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.
488 lines
17 KiB
488 lines
17 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==*/ |
|
/** \file plArmatureMod.h |
|
A modifier which manages multi-channel animation and has a physical body. |
|
Designed for avatars; also good for vehicles, creatures, etc. |
|
*/ |
|
|
|
// PLARMATUREMOD |
|
// |
|
// An armature is an object with both a physical presence (physics behavior) and articulated animated parts. |
|
// (The parts are not themselves physical) |
|
// An avatar is a type of armature, as is a critter, and anything else that moves around. |
|
// |
|
// This modifier combines multi-channel animation with blending (inherited from plAGMasterMod) |
|
// with convenience functions for moving a physical body around and some specialized animation support |
|
|
|
#ifndef plArmatureMod_inc |
|
#define plArmatureMod_inc |
|
|
|
#include "plAGMasterMod.h" |
|
|
|
// other local |
|
#include "plAvDefs.h" |
|
|
|
#include "../pnSceneObject/plSimulationInterface.h" |
|
|
|
#include "hsMatrix44.h" |
|
#include "../plNetCommon/plNetCommon.h" |
|
|
|
#include <float.h> |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// FORWARDS |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
class hsQuat; |
|
class plMatrixChannel; |
|
class plAGModifier; |
|
class plAGMasterMod; |
|
class plAGChannel; |
|
class plClothingOutfit; |
|
class plClothingSDLModifier; |
|
class plAvatarSDLModifier; |
|
class plMatrixDelayedCorrectionApplicator; |
|
class plMatrixDifferenceApp; |
|
class plDebugText; |
|
class plArmatureEffectsMgr; |
|
class plAvBoneMap; // below |
|
class plDrawable; |
|
class plControlEventMsg; |
|
class plAvatarInputStateMsg; |
|
class plLayerLinkAnimation; |
|
class plPipeline; |
|
class plArmatureBrain; |
|
class plArmatureUpdateMsg; |
|
class plPhysicalControllerCore; |
|
|
|
typedef std::vector<plKey> plKeyVector; |
|
typedef std::vector<plArmatureBrain*> plBrainStack; |
|
|
|
class plArmatureModBase : public plAGMasterMod |
|
{ |
|
public: |
|
plArmatureModBase(); |
|
virtual ~plArmatureModBase(); |
|
|
|
CLASSNAME_REGISTER( plArmatureModBase ); |
|
GETINTERFACE_ANY( plArmatureModBase, plAGMasterMod ); |
|
|
|
virtual hsBool MsgReceive(plMessage* msg); |
|
virtual void AddTarget(plSceneObject* so); |
|
virtual void RemoveTarget(plSceneObject* so); |
|
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty); |
|
virtual void Read(hsStream *stream, hsResMgr *mgr); |
|
virtual void Write(hsStream *stream, hsResMgr *mgr); |
|
|
|
plMatrixDifferenceApp *GetRootAnimator() { return fRootAnimator; } |
|
plPhysicalControllerCore* GetController() const { return fController; } |
|
plKey GetWorldKey() const; |
|
virtual hsBool ValidatePhysics(); |
|
virtual hsBool ValidateMesh(); |
|
virtual void PushBrain(plArmatureBrain *brain); |
|
virtual void PopBrain(); |
|
plArmatureBrain *GetCurrentBrain() const; |
|
plDrawable *FindDrawable() const; |
|
virtual void LeaveAge(); |
|
virtual hsBool IsFinal(); |
|
|
|
// LOD stuff |
|
void AdjustLOD(); // see if we need to switch to a different resolution |
|
hsBool SetLOD(int newLOD); // switch to a different resolution |
|
void RefreshTree(); // Resend an LOD update to all our nodes (for when geometry changes) |
|
int AppendMeshKey(plKey meshKey); |
|
int AppendBoneVec(plKeyVector *boneVec); |
|
UInt8 GetNumLOD() const; |
|
|
|
// A collection of reasons (flags) that things might be disabled. When all flags are gone |
|
// The object is re-enabled. |
|
enum |
|
{ |
|
kDisableReasonUnknown = 0x0001, |
|
kDisableReasonRelRegion = 0x0002, |
|
kDisableReasonLinking = 0x0004, |
|
kDisableReasonCCR = 0x0008, |
|
kDisableReasonVehicle = 0x0010, |
|
kDisableReasonGenericBrain = 0x0020, |
|
kDisableReasonKinematic = 0x0040 |
|
}; |
|
void EnablePhysics(hsBool status, UInt16 reason = kDisableReasonUnknown); |
|
void EnablePhysicsKinematic(hsBool status); |
|
void EnableDrawing(hsBool status, UInt16 reason = kDisableReasonUnknown); |
|
hsBool IsPhysicsEnabled() { return fDisabledPhysics == 0; } |
|
hsBool IsDrawEnabled() { return fDisabledDraw == 0; } |
|
|
|
|
|
static void AddressMessageToDescendants(const plCoordinateInterface * CI, plMessage *msg); |
|
static void EnableDrawingTree(const plSceneObject *object, hsBool status); |
|
|
|
static int fMinLOD; // throttle for lowest-indexed LOD |
|
static double fLODDistance; // Distance for first LOD switch 2nd is 2x this distance (for now) |
|
|
|
protected: |
|
virtual void IFinalize(); |
|
virtual void ICustomizeApplicator(); |
|
void IEnableBones(int lod, hsBool enable); |
|
|
|
// Some of these flags are only needed by derived classes, but I just want |
|
// the one waitFlags variable. |
|
enum |
|
{ |
|
kNeedMesh = 0x01, |
|
kNeedPhysics = 0x02, |
|
kNeedAudio = 0x04, |
|
kNeedCamera = 0x08, |
|
kNeedSpawn = 0x10, |
|
kNeedApplicator = 0x20, |
|
kNeedBrainActivation = 0x40, |
|
}; |
|
UInt16 fWaitFlags; |
|
|
|
int fCurLOD; |
|
plPhysicalControllerCore* fController; |
|
plKeyVector fMeshKeys; |
|
plBrainStack fBrains; |
|
plMatrixDifferenceApp *fRootAnimator; |
|
std::vector<plKeyVector*> fUnusedBones; |
|
UInt16 fDisabledPhysics; |
|
UInt16 fDisabledDraw; |
|
}; |
|
|
|
class plArmatureMod : public plArmatureModBase |
|
{ |
|
friend class plHBehavior; |
|
friend class plAvatarSDLModifier; |
|
friend class plAvatarPhysicalSDLModifier; |
|
friend class plClothingSDLModifier; |
|
friend class plAvOneShotLinkTask; |
|
|
|
public: |
|
plArmatureMod(); |
|
virtual ~plArmatureMod(); |
|
|
|
CLASSNAME_REGISTER( plArmatureMod ); |
|
GETINTERFACE_ANY( plArmatureMod, plArmatureModBase ); |
|
|
|
virtual hsBool MsgReceive(plMessage* msg); |
|
virtual void AddTarget(plSceneObject* so); |
|
virtual void RemoveTarget(plSceneObject* so); |
|
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty); |
|
virtual void Read(hsStream *stream, hsResMgr *mgr); |
|
virtual void Write(hsStream *stream, hsResMgr *mgr); |
|
|
|
virtual hsBool ValidatePhysics(); |
|
virtual hsBool ValidateMesh(); |
|
|
|
// Get or set the position of the avatar in simulation space. Set any |
|
// arguments you don't care about to nil. |
|
void SetPositionAndRotationSim(const hsPoint3* position, const hsQuat* rotation); |
|
void GetPositionAndRotationSim(hsPoint3* position, hsQuat* rotation); |
|
|
|
hsBool IsLocalAvatar(); |
|
hsBool IsLocalAI() const; |
|
virtual const plSceneObject *FindBone(const char * name) const; |
|
virtual const plSceneObject *FindBone(UInt32 id) const; // use an id from an appropriate taxonomy, such as plAvBrainHuman::BoneID |
|
virtual void AddBoneMapping(UInt32 id, const plSceneObject *bone); |
|
plAGModifier *GetRootAGMod(); |
|
plAGAnim *FindCustomAnim(const char *baseName) const; |
|
|
|
virtual void Spawn(double timeNow); |
|
virtual void SpawnAt(int which, double timeNow); |
|
virtual void EnterAge(hsBool reSpawn); |
|
virtual void LeaveAge(); |
|
virtual void PanicLink(hsBool playLinkOutAnim = true); |
|
virtual void PersonalLink(); |
|
|
|
virtual bool ToggleDontPanicLinkFlag() { fDontPanicLink = fDontPanicLink ? false : true; return fDontPanicLink; } |
|
|
|
int GetBrainCount(); |
|
plArmatureBrain *GetNextBrain(plArmatureBrain *brain); |
|
plArmatureBrain *GetBrain(int index) { if(index <= fBrains.size()) return fBrains.at(index); else return nil; } |
|
plArmatureBrain *FindBrainByClass(UInt32 classID) const; |
|
|
|
void TurnToPoint(hsPoint3 &point); |
|
void SuspendInput(); |
|
void ResumeInput(); |
|
|
|
UInt8 IsInputSuspended() { return fSuspendInputCount; } |
|
void IProcessQueuedInput(); |
|
void PreserveInputState(); |
|
void RestoreInputState(); |
|
hsBool GetInputFlag(int f) const; |
|
void SetInputFlag(int which, hsBool status); |
|
void ClearInputFlags(bool saveAlwaysRun, bool clearBackup); |
|
hsBool HasMovementFlag() const; // Is any *movement* input flag on? |
|
hsScalar GetTurnStrength() const; |
|
hsScalar GetKeyTurnStrength() const; |
|
hsScalar GetAnalogTurnStrength() const; |
|
void SetReverseFBOnIdle(bool val); |
|
hsBool IsFBReversed(); |
|
|
|
bool ForwardKeyDown() const; |
|
bool BackwardKeyDown() const; |
|
bool StrafeLeftKeyDown() const; |
|
bool StrafeRightKeyDown() const; |
|
bool StrafeKeyDown() const; |
|
bool FastKeyDown() const; |
|
bool TurnLeftKeyDown() const; |
|
bool TurnRightKeyDown() const; |
|
bool JumpKeyDown() const; |
|
bool ExitModeKeyDown() const; |
|
void SetForwardKeyDown(); |
|
void SetBackwardKeyDown(); |
|
void SetStrafeLeftKeyDown(bool on = true); |
|
void SetStrafeRightKeyDown(bool on = true); |
|
void SetFastKeyDown(); |
|
void SetTurnLeftKeyDown(bool status = true); |
|
void SetTurnRightKeyDown(bool status = true); |
|
void SetJumpKeyDown(); |
|
void DebugDumpMoveKeys(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt); |
|
void GetMoveKeyString(char *buff); |
|
|
|
void SynchIfLocal(double timeNow, int force); // Just physical state |
|
void SynchInputState(UInt32 rcvID = kInvalidPlayerID); |
|
hsBool DirtySynchState(const char* SDLStateName, UInt32 synchFlags ); |
|
hsBool DirtyPhysicalSynchState(UInt32 synchFlags); |
|
plClothingOutfit *GetClothingOutfit() const { return fClothingOutfit; } |
|
plClothingSDLModifier *GetClothingSDLMod() const { return fClothingSDLMod; } |
|
const plSceneObject *GetClothingSO(UInt8 lod) const; |
|
plArmatureEffectsMgr *GetArmatureEffects() const { return fEffects; } |
|
|
|
enum |
|
{ |
|
kWalk, |
|
kRun, |
|
kTurn, |
|
kImpact, |
|
kSwim, |
|
}; |
|
|
|
const char *plArmatureMod::GetAnimRootName(const char *name); |
|
Int8 AnimNameToIndex(const char *name); |
|
void SetBodyType(int type) { fBodyType = type; } |
|
int GetBodyType(int type) { return fBodyType; } |
|
int GetCurrentGenericType(); |
|
bool FindMatchingGenericBrain(const char *names[], int count); |
|
char *MakeAnimationName(const char * baseName) const; |
|
char *GetRootName(); |
|
void SetRootName(const char *name); |
|
|
|
int RefreshDebugDisplay(); |
|
void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt); |
|
void SetDebugState(hsBool state) { fDebugOn = (state != 0); } |
|
bool GetDebugState() { return fDebugOn; } |
|
|
|
virtual void RefreshTree() {} |
|
hsBool IsInStealthMode() const; |
|
int GetStealthLevel() const { return fStealthLevel; } |
|
|
|
bool IsOpaque(); |
|
bool IsLinkedIn(); |
|
bool IsMidLink(); |
|
hsBool ConsumeJump(); // returns true if the jump keypress was available to consume |
|
|
|
void SendBehaviorNotify(UInt32 type, hsBool start = true) { IFireBehaviorNotify(type,start); } |
|
// Discovered a bug which makes these values horribly out of scale. So we do the rescale |
|
// in the Get/Set functions for backwards compatability. |
|
static void SetMouseTurnSensitivity(hsScalar val) { fMouseTurnSensitivity = val / 150.f; } |
|
static hsScalar GetMouseTurnSensitivity() { return fMouseTurnSensitivity * 150.f; } |
|
|
|
static void SetSpawnPointOverride( const char *overrideObjName ); |
|
static void WindowActivate(bool active); |
|
void SetFollowerParticleSystemSO(plSceneObject *follower); |
|
plSceneObject *GetFollowerParticleSystemSO(); |
|
void RegisterForBehaviorNotify(plKey key); |
|
void UnRegisterForBehaviorNotify(plKey key); |
|
const hsBitVector& GetRelRegionCareAbout() const { return fRegionsICareAbout; } |
|
const hsBitVector& GetRelRegionImIn() const { return fRegionsImIn; } |
|
|
|
bool IsKILowestLevel(); |
|
int GetKILevel(); |
|
void SetLinkInAnim(const char *animName); |
|
plKey GetLinkInAnimKey() const; |
|
|
|
enum |
|
{ |
|
kSwapTargetShadow, |
|
kMaxSwapType |
|
}; |
|
enum |
|
{ |
|
kBoneBaseMale = 0, |
|
kBoneBaseFemale, |
|
kBoneBaseCritter, // AI controlled avatar |
|
kBoneBaseActor, // human controlled, non human avatar |
|
kMaxBoneBase |
|
}; |
|
enum |
|
{ |
|
kAvatarLOSGround, |
|
kAvatarLOSSwimSurface, |
|
}; |
|
plMatrixDelayedCorrectionApplicator *fBoneRootAnimator; |
|
|
|
static const hsScalar kAvatarInputSynchThreshold; |
|
static hsBool fClickToTurn; |
|
static const char *BoneStrings[]; |
|
|
|
void SetPhysicalDims(hsScalar height, hsScalar width) { fPhysHeight = height; fPhysWidth = width; } |
|
|
|
void SetBodyAgeName(const char* ageName) {if (ageName) fBodyAgeName = ageName; else fBodyAgeName = "";} |
|
void SetBodyFootstepSoundPage(const char* pageName) {if (pageName) fBodyFootstepSoundPage = pageName; else fBodyFootstepSoundPage = "";} |
|
void SetAnimationPrefix(const char* prefix) {if (prefix) fAnimationPrefix = prefix; else fAnimationPrefix = "";} |
|
|
|
const char* GetUserStr() {return fUserStr.c_str();} |
|
|
|
protected: |
|
void IInitDefaults(); |
|
virtual void IFinalize(); |
|
virtual void ICustomizeApplicator(); |
|
virtual void ISetupMarkerCallbacks(plATCAnim *anim, plAnimTimeConvert *atc); |
|
|
|
void NetworkSynch(double timeNow, int force = 0); |
|
hsBool IHandleControlMsg(plControlEventMsg* pMsg); |
|
void IFireBehaviorNotify(UInt32 type, hsBool behaviorStart = true); |
|
void IHandleInputStateMsg(plAvatarInputStateMsg *msg); |
|
void ILinkToPersonalAge(); |
|
int IFindSpawnOverride(void); |
|
void ISetTransparentDrawOrder(bool val); |
|
plLayerLinkAnimation *IFindLayerLinkAnim(); |
|
|
|
char *fRootName; // the name of the player root (from the max file) |
|
hsBitVector fMoveFlags; // which keys/buttons are currently pressed |
|
hsBitVector fMoveFlagsBackup; // a copy of fMoveFlags |
|
typedef std::vector<plControlEventMsg*> CtrlMessageVec; |
|
CtrlMessageVec fQueuedCtrlMessages; // input messages we haven't processed |
|
hsScalar fMouseFrameTurnStrength; // Sum turnage from mouse delta messages since last eval. |
|
plKey fFootSoundSOKey; // The Scene Object we attach to targets for footstep sounds |
|
plKey fLinkSoundSOKey; // Same thing for linking... wwwwawAWAWAwawa... |
|
plKey fLinkInAnimKey; // Set when we link out, this is the anim to play (backwards) when we link in. |
|
static hsScalar fMouseTurnSensitivity; |
|
plArmatureUpdateMsg *fUpdateMsg; |
|
|
|
// Trying to be a good lad here and align all our bools and UInt8s... |
|
bool fIsLinkedIn; // We have finished playing the LinkEffects and are properly in the age |
|
bool fMidLink; // We're in between a LeaveAge and an EnterAge |
|
bool fAlreadyPanicLinking; // Cleared when you enter an age. Prevents spamming the server with panic link requests. |
|
bool fUnconsumedJump; // We've pressed the jump key, but haven't jumped yet |
|
bool fReverseFBOnIdle; // see set/getters for comments |
|
bool fPendingSynch; |
|
bool fDebugOn; |
|
bool fOpaque; |
|
UInt8 fSuspendInputCount; |
|
UInt8 fStealthMode; |
|
int fStealthLevel; // you are invisible to other players/CCRs of lower stealthLevel |
|
|
|
double fLastInputSynch; |
|
plAGModifier * fRootAGMod; |
|
plAvBoneMap * fBoneMap; // uses id codes to look up bones. set up by the brain as needed. |
|
double fLastSynch; |
|
int fBodyType; |
|
plClothingOutfit *fClothingOutfit; |
|
plClothingSDLModifier *fClothingSDLMod; |
|
plAvatarSDLModifier *fAvatarSDLMod; |
|
plAvatarPhysicalSDLModifier *fAvatarPhysicalSDLMod; |
|
hsTArray<const plSceneObject*> fClothToSOMap; |
|
plArmatureEffectsMgr *fEffects; |
|
plSceneObject *fFollowerParticleSystemSO; |
|
static char *fSpawnPointOverride; |
|
|
|
// These vectors are used with relevance regions for culling out other objects |
|
hsBitVector fRegionsImIn; |
|
hsBitVector fRegionsICareAbout; |
|
hsBitVector fOldRegionsImIn; |
|
hsBitVector fOldRegionsICareAbout; |
|
|
|
hsTArray<plKey> fNotifyKeys; |
|
|
|
// Extra info for creating our special physical at runtime |
|
float fPhysHeight; |
|
float fPhysWidth; |
|
|
|
bool fDontPanicLink; |
|
|
|
// strings for animations, age names, footstep sounds, etc |
|
std::string fBodyAgeName; |
|
std::string fBodyFootstepSoundPage; |
|
std::string fAnimationPrefix; |
|
|
|
// user-defined string assigned to this avatar |
|
std::string fUserStr; |
|
}; |
|
|
|
// PLARMATURELOD |
|
// This class has been phased into plArmatureModBase. It's left behind |
|
// for backwards compatability. |
|
class plArmatureLODMod : public plArmatureMod |
|
{ |
|
public: |
|
// tors |
|
plArmatureLODMod(); |
|
plArmatureLODMod(const char * root_name); |
|
virtual ~plArmatureLODMod(); |
|
|
|
CLASSNAME_REGISTER( plArmatureLODMod ); |
|
GETINTERFACE_ANY( plArmatureLODMod, plArmatureMod ); |
|
|
|
virtual void Read(hsStream *stream, hsResMgr *mgr); |
|
virtual void Write(hsStream *stream, hsResMgr *mgr); |
|
}; |
|
|
|
class plAvBoneMap |
|
{ |
|
public: |
|
plAvBoneMap(); |
|
virtual ~plAvBoneMap(); |
|
|
|
const plSceneObject * FindBone(UInt32 boneID); // you probably want to use plAvBrainHuman::BoneID; |
|
void AddBoneMapping(UInt32 boneID, const plSceneObject *SO); |
|
|
|
protected: |
|
class BoneMapImp; // forward declaration to keep the header clean: see .cpp for implementation |
|
BoneMapImp *fImp; // the thing that actually holds our map |
|
}; |
|
|
|
#define TWO_PI (hsScalarPI * 2) |
|
|
|
#endif plArmatureMod_inc
|
|
|