Files
FC1/CryAnimation/ControllerManager.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

189 lines
6.7 KiB
C++

/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Crytek Character Animation source code
//
// History:
// Created by Sergiy Migdalskiy
//
// Notes:
// CControllerManager class declaration extracted from File:CryModelState.h
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _CRYTEK_CONTROLLER_MANAGER_HEADER_
#define _CRYTEK_CONTROLLER_MANAGER_HEADER_
#include "Controller.h"
#include "CryAnimationInfo.h"
#include "FileMapping.h"
#include "IStreamEngine.h"
class CryModelAnimationContainer;
/////////////////////////////////////////////////////////////////////////////////////////////////////
// class CControllerManager
// Responsible for creation of multiple animations, subsequently bind to the character bones
// There is one instance of this class per a game.
/////////////////////////////////////////////////////////////////////////////////////////////////////
class CControllerManager : public IStreamCallback
{
public:
// array of animations, each animation having its name and id
// Animation is an array of controllers. Animation id is an index in the array
typedef GlobalAnimation Animation;
struct AnimationIdPred
{
const std::vector<Animation>& m_arrAnims;
AnimationIdPred(const std::vector<Animation>& arrAnims):
m_arrAnims(arrAnims)
{
}
bool operator () (int left, int right)const
{
return stricmp(m_arrAnims[left].strFileName.c_str(), m_arrAnims[right].strFileName.c_str()) < 0;
}
bool operator () (int left, const char* right)const
{
return stricmp(m_arrAnims[left].strFileName.c_str(), right)<0;
}
bool operator () (const char* left, int right)const
{
return stricmp(left, m_arrAnims[right].strFileName.c_str())<0;
}
};
// returns the structure describing the animation data, given the global anim id
Animation& GetAnimation (int nAnimID);
CControllerManager();
// loads the animation with the specified name; if the animation is already loaded,
// then just returns its id
// The caller MUST TAKE CARE to bind the animation if it's already loaded before it has registered itself within this manager
int StartLoadAnimation (const string& strFileName, float fScale, unsigned nFlags = Animation::FLAGS_DEFAULT_FLAGS);
// unreferences the controllers and makes the animation unloaded
// before this operation, all bones must be unbound
bool UnloadAnimation (int nGlobAnimId);
// loads existing animation record, returns false on error
bool LoadAnimation(int nGlobalAnimId);
// loads the animation info, if not loaded yet
bool LoadAnimationInfo(int nGlobalAnimId);
// updates the animation from the chunk of AnimInfo
bool UpdateAnimation (int nGlobalAnimId, const struct CCFAnimInfo* pAnimInfo);
// notifies the controller manager that another client uses the given animation.
// these calls must be balanced with AnimationRelease() calls
void AnimationAddRef (int nGlobalAnimId, CryModelAnimationContainer* pClient);
// notifies the controller manager that this client doesn't use the given animation any more.
// these calls must be balanced with AnimationAddRef() calls
void AnimationRelease (int nGlobalAnimId, CryModelAnimationContainer* pClient);
void OnStartAnimation (int nGlobalAnimId);
void OnTickAnimation(int nGlobalAnimId);
void OnApplyAnimation(int nGlobalAnimId);
// returns the total number of animations hold in memory (for statistics)
unsigned NumAnimations();
// finds controller with the given nControllerID among controller in the animation
// identified by nGlobalAnimID
IController* GetController (int nGlobalAnimID, unsigned nControllerID);
~CControllerManager();
// logs controller usage statistics
void LogUsageStats();
// puts the size of the whole subsystem into this sizer object, classified,
// according to the flags set in the sizer
void GetSize(class ICrySizer* pSizer);
// dumps the used animations
void DumpAnims();
void Update();
void Register (CryModelAnimationContainer* pClient)
{
m_arrClients.insert (std::lower_bound(m_arrClients.begin(), m_arrClients.end(), pClient), pClient);
}
void Unregister (CryModelAnimationContainer* pClient)
{
std::vector<CryModelAnimationContainer*>::iterator it = std::lower_bound(m_arrClients.begin(), m_arrClients.end(), pClient);
if(it != m_arrClients.end() && *it == pClient)
m_arrClients.erase (it);
else
assert (0); // the unregistered client tries to unregister
}
// finds the animation by name. Returns -1 if no animation was found
// Returns the animation ID if it was found
int FindAnimationByFile(const string& sAnimFileName);
protected:
// notifies all clients that the animation or its info has been loaded
void FireAnimationGlobalLoad (int nAnimId);
// immediately load the given animation from the already opened reader
bool LoadAnimation(int nAnimId, class CChunkFileReader* pReader);
// these two are called back when an asynchronous IO operation has finished
void StreamOnComplete (IReadStream* pStream, unsigned nError);
// this structure describes the pending animation load request: it exists as long as the animation
// is being loaded (asynchronously)
struct PendingAnimLoad:public _reference_target_t
{
public:
PendingAnimLoad (int animId){nAnimId = animId;}
PendingAnimLoad (){}
// the data that's being loaded
CFileMapping_AutoPtr pFile;
// the animation for which the data is loaded
int nAnimId;
// the frame at which the animation load was started
int nFrameId;
// the stream that loads the data
IReadStreamPtr pStream;
};
TYPEDEF_AUTOPTR(PendingAnimLoad);
// the set of pending animation load requests; they get deleted as soon as the IO operation is completed
std::set<PendingAnimLoad_AutoPtr> m_setPendingAnimLoads;
// Loads the controller from the chunk, returns the result in the autopointer
// It is important that the return type is autoptr: it lets the procedure gracefully destruct
// half-constructed animation in case of an error.
IController_AutoPtr LoadController(float fScale, const CONTROLLER_CHUNK_DESC_0826*pChunk, int nSize);
// array of animations
// since the number of animations dynamically changes and STL vector has good balanced
// reallocation properties, we use it here
typedef std::vector<Animation> AnimationArray;
AnimationArray m_arrAnims;
// index array for the animation indices sorted by file name
std::vector<int>m_arrAnimByFile;
void selfValidate();
size_t m_nCachedSizeofThis;
// the sorted list of pointers to the clients that use the services of this manager
std::vector<CryModelAnimationContainer*> m_arrClients;
// this scans through all animations cyclicly each frame and checks which ones should be unloaded
// due to not being used
unsigned m_nLastCheckedUnloadCandidate;
};
#endif