//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #ifndef CHOREOSCENE_H #define CHOREOSCENE_H #ifdef _WIN32 #pragma once #endif class CChoreoEvent; class CChoreoChannel; class CChoreoActor; class IChoreoEventCallback; class CEventRelativeTag; class CUtlBuffer; class CFlexAnimationTrack; class ISceneTokenProcessor; class IChoreoStringPool; #include "bitvec.h" #include "choreoevent.h" #include "expressionsample.h" #include "tier1/utldict.h" #include "tier1/utlvector.h" #define DEFAULT_SCENE_FPS 60 #define MIN_SCENE_FPS 10 #define MAX_SCENE_FPS 240 #define SCENE_BINARY_TAG MAKEID('b', 'v', 'c', 'd') #define SCENE_BINARY_VERSION 0x04 //----------------------------------------------------------------------------- // Purpose: Container for choreographed scene of events for actors //----------------------------------------------------------------------------- class CChoreoScene : public ICurveDataAccessor { typedef enum { PROCESSING_TYPE_IGNORE = 0, PROCESSING_TYPE_START, PROCESSING_TYPE_START_RESUMECONDITION, PROCESSING_TYPE_CONTINUE, PROCESSING_TYPE_STOP, } PROCESSING_TYPE; struct ActiveList { PROCESSING_TYPE pt; CChoreoEvent *e; }; public: // Construction CChoreoScene(IChoreoEventCallback *callback); ~CChoreoScene(void); // Assignment CChoreoScene &operator=(const CChoreoScene &src); // ICurveDataAccessor methods virtual float GetDuration() { return FindStopTime(); }; virtual bool CurveHasEndTime(); virtual int GetDefaultCurveType(); // Binary serialization bool SaveBinary(char const *pszBinaryFileName, char const *pPathID, unsigned int nTextVersionCRC, IChoreoStringPool *pStringPool); void SaveToBinaryBuffer(CUtlBuffer &buf, unsigned int nTextVersionCRC, IChoreoStringPool *pStringPool); bool RestoreFromBinaryBuffer(CUtlBuffer &buf, char const *filename, IChoreoStringPool *pStringPool); static bool GetCRCFromBinaryBuffer(CUtlBuffer &buf, unsigned int &crc); // We do some things differently while restoring from a save. inline void SetRestoring(bool bRestoring); inline bool IsRestoring(); enum { MAX_SCENE_FILENAME = 128, }; // Event callback handler void SetEventCallbackInterface(IChoreoEventCallback *callback); // Loading bool ParseFromBuffer(char const *pFilename, ISceneTokenProcessor *tokenizer); void SetPrintFunc(void (*pfn)(PRINTF_FORMAT_STRING const char *fmt, ...)); // Saving bool SaveToFile(const char *filename); bool ExportMarkedToFile(const char *filename); void MarkForSaveAll(bool mark); // Merges two .vcd's together, returns true if any data was merged bool Merge(CChoreoScene *other); static void FileSaveFlexAnimationTrack(CUtlBuffer &buf, int level, CFlexAnimationTrack *track, int nDefaultCurveType); static void FileSaveFlexAnimations(CUtlBuffer &buf, int level, CChoreoEvent *e); static void FileSaveRamp(CUtlBuffer &buf, int level, CChoreoEvent *e); void FileSaveSceneRamp(CUtlBuffer &buf, int level); static void FileSaveScaleSettings(CUtlBuffer &buf, int level, CChoreoScene *scene); static void ParseFlexAnimations(ISceneTokenProcessor *tokenizer, CChoreoEvent *e, bool removeold = true); static void ParseRamp(ISceneTokenProcessor *tokenizer, CChoreoEvent *e); static void ParseSceneRamp(ISceneTokenProcessor *tokenizer, CChoreoScene *scene); static void ParseScaleSettings(ISceneTokenProcessor *tokenizer, CChoreoScene *scene); static void ParseEdgeInfo(ISceneTokenProcessor *tokenizer, EdgeInfo_t *edgeinfo); // Debugging void SceneMsg(PRINTF_FORMAT_STRING const char *pFormat, ...); void Print(void); // Sound system needs to have sounds pre-queued by this much time void SetSoundFileStartupLatency(float time); // Simulation void Think(float curtime); float LoopThink(float curtime); void ProcessActiveListEntry(ActiveList *entry); // Retrieves time in simulation float GetTime(void); // Retrieves start/stop time for looped/debug scene void GetSceneTimes(float &start, float &end); void SetTime(float t); void LoopToTime(float t); // Has simulation finished bool SimulationFinished(void); // Reset simulation void ResetSimulation(bool forward = true, float starttime = 0.0f, float endtime = 0.0f); // Find time at which last simulation event is triggered float FindStopTime(void); void ResumeSimulation(void); // Have all the pause events happened bool CheckEventCompletion(void); // Find named actor in scene data CChoreoActor *FindActor(const char *name); // Remove actor from scene void RemoveActor(CChoreoActor *actor); // Find index for actor int FindActorIndex(CChoreoActor *actor); // Swap actors in the data void SwapActors(int a1, int a2); // General data access int GetNumEvents(void); CChoreoEvent *GetEvent(int event); int GetNumActors(void); CChoreoActor *GetActor(int actor); int GetNumChannels(void); CChoreoChannel *GetChannel(int channel); // Object allocation/destruction void DeleteReferencedObjects(CChoreoActor *actor); void DeleteReferencedObjects(CChoreoChannel *channel); void DeleteReferencedObjects(CChoreoEvent *event); CChoreoActor *AllocActor(void); CChoreoChannel *AllocChannel(void); CChoreoEvent *AllocEvent(void); void AddEventToScene(CChoreoEvent *event); void AddActorToScene(CChoreoActor *actor); void AddChannelToScene(CChoreoChannel *channel); // Fixup simulation times for channel gestures void ReconcileGestureTimes(void); // Go through all elements and update relative tags, removing any orphaned // tags and updating the timestamp of normal tags void ReconcileTags(void); CEventRelativeTag *FindTagByName(const char *wavname, const char *name); CChoreoEvent *FindTargetingEvent(const char *wavname, const char *name); // Used by UI to provide target actor names char const *GetMapname(void); void SetMapname(const char *name); void ExportEvents(const char *filename, CUtlVector &events); void ImportEvents(ISceneTokenProcessor *tokenizer, CChoreoActor *actor, CChoreoChannel *channel); // Subscene support void SetSubScene(bool sub); bool IsSubScene(void) const; int GetSceneFPS(void) const; void SetSceneFPS(int fps); bool IsUsingFrameSnap(void) const; void SetUsingFrameSnap(bool snap); float SnapTime(float t); int GetSceneRampCount(void) { return m_SceneRamp.GetCount(); }; CExpressionSample *GetSceneRamp(int index) { return m_SceneRamp.Get(index); }; CExpressionSample *AddSceneRamp(float time, float value, bool selected) { return m_SceneRamp.Add(time, value, selected); }; void DeleteSceneRamp(int index) { m_SceneRamp.Delete(index); }; void ClearSceneRamp(void) { m_SceneRamp.Clear(); }; void ResortSceneRamp(void) { m_SceneRamp.Resort(this); }; CCurveData *GetSceneRamp(void) { return &m_SceneRamp; }; // Global intensity for scene float GetSceneRampIntensity(float time) { return m_SceneRamp.GetIntensity(this, time); } int GetTimeZoom(char const *tool); void SetTimeZoom(char const *tool, int tz); int TimeZoomFirst(); int TimeZoomNext(int i); int TimeZoomInvalid() const; char const *TimeZoomName(int i); void ReconcileCloseCaption(); char const *GetFilename() const; void SetFileName(char const *fn); bool GetPlayingSoundName(char *pchBuff, int iBuffLength); bool HasUnplayedSpeech(); bool HasFlexAnimation(); void SetBackground(bool bIsBackground); bool IsBackground(void); void ClearPauseEventDependencies(); bool HasEventsOfType(CChoreoEvent::EVENTTYPE type) const; void RemoveEventsExceptTypes(int *typeList, int count); void IgnorePhonemes(bool bIgnore); bool ShouldIgnorePhonemes() const; // This is set by the engine to signify that we're not modifying the data // and // therefore we can precompute the end time static bool s_bEditingDisabled; private: // Simulation stuff enum { IN_RANGE = 0, BEFORE_RANGE, AFTER_RANGE }; int IsTimeInRange(float t, float starttime, float endtime); static bool EventLess(const CChoreoScene::ActiveList &al0, const CChoreoScene::ActiveList &al1); int EventThink(CChoreoEvent *e, float frame_start_time, float frame_end_time, bool playing_forward, PROCESSING_TYPE &disposition); // Prints to debug console, etc void choreoprintf(int level, PRINTF_FORMAT_STRING const char *fmt, ...); // Initialize scene void Init(IChoreoEventCallback *callback); float FindAdjustedStartTime(void); float FindAdjustedEndTime(void); CChoreoEvent *FindPauseBetweenTimes(float starttime, float endtime); // Parse scenes from token buffer CChoreoEvent *ParseEvent(CChoreoActor *actor, CChoreoChannel *channel); CChoreoChannel *ParseChannel(CChoreoActor *actor); CChoreoActor *ParseActor(void); void ParseFPS(void); void ParseSnap(void); void ParseIgnorePhonemes(void); // Map file for retrieving named objects void ParseMapname(void); // When previewing actor in hlfaceposer, this is the model to associate void ParseFacePoserModel(CChoreoActor *actor); // Print to printfunc void PrintEvent(int level, CChoreoEvent *e); void PrintChannel(int level, CChoreoChannel *c); void PrintActor(int level, CChoreoActor *a); // File I/O public: static void FilePrintf(CUtlBuffer &buf, int level, PRINTF_FORMAT_STRING const char *fmt, ...); private: void FileSaveEvent(CUtlBuffer &buf, int level, CChoreoEvent *e); void FileSaveChannel(CUtlBuffer &buf, int level, CChoreoChannel *c); void FileSaveActor(CUtlBuffer &buf, int level, CChoreoActor *a); void FileSaveHeader(CUtlBuffer &buf); // Object destruction void DestroyActor(CChoreoActor *actor); void DestroyChannel(CChoreoChannel *channel); void DestroyEvent(CChoreoEvent *event); void AddPauseEventDependency(CChoreoEvent *pauseEvent, CChoreoEvent *suppressed); void InternalDetermineEventTypes(); // Global object storage CUtlVector m_Events; CUtlVector m_Actors; CUtlVector m_Channels; // These are just pointers, the actual objects are in m_Events CUtlVector m_ResumeConditions; // These are just pointers, the actual objects are in m_Events CUtlVector m_ActiveResumeConditions; // These are just pointers, the actual objects are in m_Events CUtlVector m_PauseEvents; // Current simulation time float m_flCurrentTime; float m_flStartLoopTime; float m_flStartTime; float m_flEndTime; float m_flEarliestTime; float m_flLatestTime; int m_nActiveEvents; // Wave file playback needs to issue play commands a bit ahead of time // in order to hit exact marks float m_flSoundSystemLatency; // Scene's linger a bit after finishing to let blends reset themselves float m_flLastActiveTime; // Print callback function void (*m_pfnPrint)(PRINTF_FORMAT_STRING const char *fmt, ...); IChoreoEventCallback *m_pIChoreoEventCallback; ISceneTokenProcessor *m_pTokenizer; enum { MAX_MAPNAME = 128 }; char m_szMapname[MAX_MAPNAME]; int m_nSceneFPS; CCurveData m_SceneRamp; CUtlDict m_TimeZoomLookup; char m_szFileName[MAX_SCENE_FILENAME]; CBitVec m_bitvecHasEventOfType; // tag to suppress vcd when others are playing bool m_bIsBackground : 1; bool m_bIgnorePhonemes : 1; bool m_bSubScene : 1; bool m_bUseFrameSnap : 1; bool m_bRestoring : 1; int m_nLastPauseEvent; // This only gets updated if it's loaded from a buffer which means we're not // in an editor float m_flPrecomputedStopTime; }; bool CChoreoScene::IsRestoring() { return m_bRestoring; } void CChoreoScene::SetRestoring(bool bRestoring) { m_bRestoring = bRestoring; } abstract_class IChoreoStringPool { public: virtual short FindOrAddString(const char *pString) = 0; virtual bool GetString(short stringId, char *buff, int buffSize) = 0; }; CChoreoScene *ChoreoLoadScene(char const *filename, IChoreoEventCallback *callback, ISceneTokenProcessor *tokenizer, void (*pfn)(PRINTF_FORMAT_STRING const char *fmt, ...)); bool IsBufferBinaryVCD(char *pBuffer, int bufferSize); #endif // CHOREOSCENE_H