/*==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 . 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 plCoordinateInterface_inc #define plCoordinateInterface_inc #include "plObjInterface.h" #include "hsTemplates.h" #include "hsMatrix44.h" #include "../pnNetCommon/plSynchedValue.h" class hsStream; class hsResMgr; class plCoordinateInterface : public plObjInterface { public: enum plCoordinateProperties { kDisable = 0, // prop 0 is always disable, declared in plObjInterface kCanEverDelayTransform = 1, // we can sometimes delay our transform eval (i.e. we're on a physics object) kDelayedTransformEval = 2, // we're currently registering for the DelayedTransformMsg (we, and all our // descendants, have the kCanEverDelayTransform prop) kNumProps // last in the list }; enum plCoordinateTransformPhases { kTransformPhaseNormal, kTransformPhaseDelayed, }; protected: enum { kTransformDirty = 0x1, kWarp = 0x2, kMaxState = 0xffff }; enum plAttachFlags { kMaintainWorldPosition = 0x1, kMaintainSceneNode = 0x2, kAboutToAttach = 0x4 }; enum Reason { kReasonUnknown = 0x1, // somebody moved us kReasonPhysics = 0x2, // physics moved us kMaxReasons = 0xffff // sixteen bits }; // Set by the client in IUpdate(). This tells us where we are in the update loop so that we know // which transform message to register for when our transform is dirtied. static UInt8 fTransformPhase; // Temp debugging tool, so we can quickly (dis/en)able delayed transforms at runtime. static hsBool fDelayedTransformsEnabled; UInt16 fState; UInt16 fReason; // why we've changed position (if we have) hsTArray fChildren; plCoordinateInterface* fParent; // if this changes, marks us as dirty hsMatrix44 fLocalToParent; hsMatrix44 fParentToLocal; hsMatrix44 fLocalToWorld; hsMatrix44 fWorldToLocal; virtual void ISetOwner(plSceneObject* so); virtual void ISetParent(plCoordinateInterface* par); // don't use, use AddChild on parent virtual void ISetSceneNode(plKey newNode); // objectToo moves the sceneObject to the new room, else just move the data and remove // the object from whatever room he's in. // Network only strange functions. Do not emulate or generalize this functionality. void ISetNetGroupRecur(plNetGroupId netGroup); virtual void ISetChild(plSceneObject* child, int which); // sets parent on child virtual void IAddChild(plSceneObject* child); // sets parent on child virtual void IRemoveChild(plSceneObject* child); // removes this as parent of child virtual void IRemoveChild(int i); // removes this as parent of child virtual void IAttachChild(plSceneObject* child, UInt8 flags); // physically attaches child to us virtual void IDetachChild(plSceneObject* child, UInt8 flags); // physically detach this child from us virtual void IUpdateDelayProp(); // Called whenever a child is added/removed virtual void IRecalcTransforms(); // Called by ITransformChanged when we need to re-examine our relationship with our parent. virtual void ITransformChanged(hsBool force, UInt16 reasons, hsBool checkForDelay); // called by SceneObject on TransformChanged messsage void IDirtyTransform(); void IRegisterForTransformMessage(hsBool delayed); void IUnRegisterForTransformMessage(); plCoordinateInterface* IGetRoot(); friend class plSceneObject; public: plCoordinateInterface(); ~plCoordinateInterface(); CLASSNAME_REGISTER( plCoordinateInterface ); GETINTERFACE_ANY( plCoordinateInterface, plObjInterface ); virtual void Read(hsStream* stream, hsResMgr* mgr); virtual void Write(hsStream* stream, hsResMgr* mgr); virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual void SetLocalToParent(const hsMatrix44& l2p, const hsMatrix44& p2l); // special version for setting transform from physics. // separate to keep from changing interface to add "reason" parameter virtual void SetTransformPhysical(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual void MultTransformLocal(const hsMatrix44& move, const hsMatrix44& invMove); virtual void WarpToWorld(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual void WarpToLocal(const hsMatrix44& l2p, const hsMatrix44& p2l); // Force an immediate re-sync of the transforms in the hierarchy this object belongs to, // as opposed to waiting for the plTransformMsg to resync. // There are two uses for this: // a) You need the transforms for this object to be valid NOW, can't wait till after a TransforMsg // In this case, you want to flush from the root, because something higher up the hierarchy // may be dirty, which invalidates this object's transforms // b) You've just dirtied this object's transform, and need it to propagate downward from here NOW // In this case, fromRoot should be false, because you haven't dirtied anything higher up // the hierarchy. // Another way to look at it is, if the transforms for the tree were correct before you messed with // this object, you only need to flush the transforms for this object and its recursive children, // so fromRoot=false. // If the entire tree is potentially dirty and you need to read from it, you want the entire tree // synced up, so fromRoot=true. // fromRoot=true is always safe, just potentially wasteful, so if you don't know, use fromRoot=true or // preferably, don't use this function. void FlushTransform(hsBool fromRoot=true); virtual const hsMatrix44& GetLocalToParent() const { return fLocalToParent; } virtual const hsMatrix44& GetParentToLocal() const { return fParentToLocal; } virtual const hsMatrix44& GetLocalToWorld() const { return fLocalToWorld; } virtual const hsMatrix44& GetWorldToLocal() const { return fWorldToLocal; } virtual const hsPoint3 GetWorldPos() const { return fLocalToWorld.GetTranslate(); } virtual int GetNumChildren() const { return fChildren.GetCount(); } virtual plCoordinateInterface* GetChild(int i) const; virtual plCoordinateInterface* GetParent() const { return fParent; } virtual hsBool MsgReceive(plMessage* msg); UInt16 GetReasons(); void ClearReasons(); Int32 GetNumProperties() const { return kNumProps; } static UInt8 GetTransformPhase() { return fTransformPhase; } static void SetTransformPhase(UInt8 phase) { fTransformPhase = phase; } static hsBool GetDelayedTransformsEnabled() { return fDelayedTransformsEnabled; } static void SetDelayedTransformsEnabled(hsBool val) { fDelayedTransformsEnabled = val; } }; #endif // plCoordinateInterface_inc