You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
9.1 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLayerInterface_inc
#define plLayerInterface_inc
#include "pnNetCommon/plSynchedValue.h"
#include "pnNetCommon/plSynchedObject.h"
#include "hsGMatState.h"
struct hsMatrix44;
struct hsColorRGBA;
class plBitmap;
class plMessage;
class hsGMatState;
class plShader;
class plLayerInterface : public plSynchedObject
{
friend class plLayerSDLModifier;
public:
enum plLayerDirtyBits {
kTransform = 0x1,
kPreshadeColor = 0x2,
kAmbientColor = 0x4,
kOpacity = 0x8,
kTexture = 0x10,
kState = 0x20,
kUVWSrc = 0x40,
kLODBias = 0x80,
kSpecularColor = 0x100,
kSpecularPower = 0x200,
kRuntimeColor = 0x400,
kVertexShader = 0x800,
kPixelShader = 0x1000,
kBumpEnvXfm = 0x2000,
kAllDirty = 0xffffffff
};
enum plUVWSrcModifiers {
kUVWPassThru = 0x00000000,
kUVWIdxMask = 0x0000ffff,
kUVWNormal = 0x00010000,
kUVWPosition = 0x00020000,
kUVWReflect = 0x00030000
};
protected:
plLayerInterface* fUnderLay;
plLayerInterface* fOverLay;
// NEVER MODIFY A FIELD THAT ISN'T
// YOUR OWN PERSONAL COPY.
// These are accessible so that if you're interface doesn't touch a field,
// it can set it's pointer to the previous interfaces pointer to that field
// and never even do a copy. For any fields this interface will alter, you
// need to alloc your own copy, and in your eval get the previous interface's
// value, modify it, and write it to your copy.
// So, if you don't touch a field, copy the pointer from prev into your channel pointer,
// else alloc your own and set the value to whatever you like.
// Then you only need to update your value when the source value changes (you'll know
// from dirty bits), or when you want to (you'll know from secs/frame).
// fOwnedChannels specifies which channels you have allocated and own (and will delete)
UInt32 fOwnedChannels;
// fPassThruChannels are channels which we need to pass through our underlay's values,
// even if we have a differing opinion on what the value should be. This let's us arbitrate
// between different layers that control the same channels. A layer can claim control of
// a channel by telling all other layers to pass through that channel via the
// ClaimChannels(UInt32 chans) member function. See .cpp for arbitration rules.
UInt32 fPassThruChannels;
hsMatrix44* fTransform;
hsColorRGBA* fPreshadeColor;
hsColorRGBA* fRuntimeColor; // Diffuse color to be used with runtime lights vs. static preshading
hsColorRGBA* fAmbientColor;
hsColorRGBA* fSpecularColor;
hsScalar* fOpacity;
// Would like to abstract out the mipmap, but we'll bring it
// along for now.
plBitmap** fTexture;
// (Currently) unanimatables.
hsGMatState* fState;
UInt32* fUVWSrc;
hsScalar* fLODBias;
hsScalar* fSpecularPower;
plShader** fVertexShader;
plShader** fPixelShader;
hsMatrix44* fBumpEnvXfm;
void IUnthread();
void ISetPassThru(UInt32 chans);
public:
plLayerInterface();
virtual ~plLayerInterface();
CLASSNAME_REGISTER( plLayerInterface );
GETINTERFACE_ANY( plLayerInterface, plSynchedObject );
plLayerInterface* BottomOfStack() { return fUnderLay ? fUnderLay->BottomOfStack() : this; }
plLayerInterface* TopOfStack() { return fOverLay ? fOverLay->TopOfStack() : this; }
// Used by debug code.
plLayerInterface* GetUnderLay() { return fUnderLay; }
plLayerInterface* GetOverLay() { return fOverLay; }
const hsMatrix44& GetTransform() const { return *fTransform; }
const hsColorRGBA& GetPreshadeColor() const { return *fPreshadeColor; }
const hsColorRGBA& GetRuntimeColor() const { return *fRuntimeColor; }
const hsColorRGBA& GetAmbientColor() const { return *fAmbientColor; }
const hsColorRGBA& GetSpecularColor() const { return *fSpecularColor; }
hsScalar GetOpacity() const { return *fOpacity; }
plBitmap* GetTexture() const { return *fTexture; }
// (Currently) unanimatables
UInt32 GetUVWSrc() const { return *fUVWSrc; }
hsScalar GetLODBias() const { return *fLODBias; }
hsScalar GetSpecularPower() const { return *fSpecularPower; }
const hsGMatState& GetState() const { return *fState; }
UInt32 GetBlendFlags() const { return fState->fBlendFlags; }
UInt32 GetClampFlags() const { return fState->fClampFlags; }
UInt32 GetShadeFlags() const { return fState->fShadeFlags; }
UInt32 GetZFlags() const { return fState->fZFlags; }
UInt32 GetMiscFlags() const { return fState->fMiscFlags; }
plShader* GetVertexShader() const { return *fVertexShader; }
plShader* GetPixelShader() const { return *fPixelShader; }
const hsMatrix44& GetBumpEnvMatrix() const { return *fBumpEnvXfm; }
// ClaimChannels will tell every other layer on this stack (besides this) to
// pass through the value, giving this layer the final say on it's value
void ClaimChannels(UInt32 chans);
// Eval may be called multiple times per frame, or even multiple times per render (for multiple
// renders per frame). The burden of deciding whether any update is necessary falls to the
// derived interface, but here's some info to go on.
// secs - world time. Time dependent effects (like time of day) look mostly at this.
// frame - incremented each time the camera moves. View dependent effects look at this.
// ignore - fields marked ignore will be overwritten (not modified) by an downstream layer, so don't bother computing.
// return value of fUnderLay->Eval() - bits are true for fields that an interface earlier in the chain dirtied. A field
// flagged dirty that you modify (as opposed to overwrite) should be updated regardless of secs and frame.
//
virtual UInt32 Eval(double secs, UInt32 frame, UInt32 ignore);
// Attach gives you a chance to decide whether you want to pass through fields from prev (by copying
// the pointers which you then sooner put long pins through your own eyes than modify). Alloc
// your own fields before Attach, and you can play with them at will. Base class will pass through
// (via pointer copy) all nil fields. Detach nils out any fields that are just pass through, and
// unthreads the requested layer from the stack, returning new top-of-stack.
//
// Given two stacks A->B and C->D, A->Attach(C) makes A->B->C->D
virtual plLayerInterface* Attach(plLayerInterface* prev);
// Given stack A->B->C->D, A->Detach(C) gives two stacks, A->B and C->D (returned value is A)
// If A == C (A->B->C && A->Remove(A)), it returns nil, since the it's removed A from the stack,
// so the two stacks are now nil and A->B->C
virtual plLayerInterface* Detach(plLayerInterface* nuke);
// Given stack A->B->C->D, A->Remove(C) gives two stacks, A->B->D and C. It returns the stack with C removed.
// If A==C (A->B->C && A->Remove(A)), it returns B->C.
virtual plLayerInterface* Remove(plLayerInterface* nuke);
plLayerInterface* GetAttached();
void AttachViaNotify(plLayerInterface *prev); // Export only
hsBool OwnChannel(UInt32 which) const { return 0 != (fOwnedChannels & which); }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plLayerInterface_inc