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.

221 lines
8.8 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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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