//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #ifndef CHOREOEVENT_H #define CHOREOEVENT_H #ifdef _WIN32 #pragma once #endif class CChoreoActor; class CChoreoChannel; class CChoreoEvent; class CChoreoScene; class IChoreoEventCallback; class CAudioMixer; class CUtlBuffer; class IChoreoStringPool; #include "expressionsample.h" #include "localflexcontroller.h" #include "networkvar.h" #include "tier1/utlstring.h" #include "tier1/utlvector.h" typedef CUtlString ChoreoStr_t; //----------------------------------------------------------------------------- // Purpose: SPEAK events can have "relative tags" that other objects can // reference // to specify their start times off of //----------------------------------------------------------------------------- class CEventRelativeTag { public: DECLARE_CLASS_NOBASE(CEventRelativeTag); enum { MAX_EVENTTAG_LENGTH = 128, }; CEventRelativeTag(CChoreoEvent *owner, const char *name, float percentage); CEventRelativeTag(const CEventRelativeTag &src); const char *GetName(void); float GetPercentage(void); void SetPercentage(float percentage); // Returns the corrected time based on the owner's length and start time float GetStartTime(void); CChoreoEvent *GetOwner(void); void SetOwner(CChoreoEvent *event); protected: ChoreoStr_t m_Name; float m_flPercentage; CChoreoEvent *m_pOwner; }; //----------------------------------------------------------------------------- // Purpose: GESTURE events can have "absolute tags" (where the value is not a // percentage, but an actual timestamp from the start of the event) //----------------------------------------------------------------------------- class CEventAbsoluteTag { public: enum { MAX_EVENTTAG_LENGTH = 128, }; CEventAbsoluteTag(CChoreoEvent *owner, const char *name, float percentage); CEventAbsoluteTag(const CEventAbsoluteTag &src); const char *GetName(void); float GetPercentage(void); void SetPercentage(float percentage); float GetEventTime(void); void SetEventTime(float t); float GetAbsoluteTime(void); void SetAbsoluteTime(float t); CChoreoEvent *GetOwner(void); void SetOwner(CChoreoEvent *event); void SetLocked(bool bLocked); bool GetLocked(void); void SetLinear(bool bLinear); bool GetLinear(void); void SetEntry(bool bEntry); bool GetEntry(void); void SetExit(bool bExit); bool GetExit(void); protected: ChoreoStr_t m_Name; float m_flPercentage; bool m_bLocked : 1; bool m_bLinear : 1; bool m_bEntry : 1; bool m_bExit : 1; CChoreoEvent *m_pOwner; }; //----------------------------------------------------------------------------- // Purpose: FLEXANIMATION events can have "timing tags" that are used to align // and // manipulate flex animation curves //----------------------------------------------------------------------------- class CFlexTimingTag : public CEventRelativeTag { DECLARE_CLASS(CFlexTimingTag, CEventRelativeTag); public: CFlexTimingTag(CChoreoEvent *owner, const char *name, float percentage, bool locked); CFlexTimingTag(const CFlexTimingTag &src); bool GetLocked(void); void SetLocked(bool locked); protected: bool m_bLocked; }; //----------------------------------------------------------------------------- // Purpose: A flex controller position can be animated over a period of time //----------------------------------------------------------------------------- class CFlexAnimationTrack { public: enum { MAX_CONTROLLER_NAME = 128, }; CFlexAnimationTrack(CChoreoEvent *event); CFlexAnimationTrack(const CFlexAnimationTrack *src); virtual ~CFlexAnimationTrack(void); void SetEvent(CChoreoEvent *event); CChoreoEvent *GetEvent(void); void SetFlexControllerName(const char *name); char const *GetFlexControllerName(void); void SetComboType(bool combo); bool IsComboType(void); void SetMin(float value); void SetMax(float value); float GetMin(int type = 0); float GetMax(int type = 0); bool IsInverted(void); void SetInverted(bool isInverted); int GetNumSamples(int type = 0); CExpressionSample *GetSample(int index, int type = 0); bool IsTrackActive(void); void SetTrackActive(bool active); // returns scaled value for absolute time per left/right side float GetIntensity(float time, int side = 0); CExpressionSample *AddSample(float time, float value, int type = 0); void RemoveSample(int index, int type = 0); void Clear(void); void Resort(int type = 0); // Puts in dummy start/end samples to spline to zero ( or 0.5 for // left/right data) at the origins CExpressionSample *GetBoundedSample(int number, bool &bClamped, int type = 0); int GetFlexControllerIndex(int side = 0); LocalFlexController_t GetRawFlexControllerIndex(int side = 0); void SetFlexControllerIndex(LocalFlexController_t raw, int index, int side = 0); // returns 0..1 value for 0..1 time fraction per mag/balance float GetFracIntensity(float time, int type); // retrieves raw intensity values (for mag vs. left/right slider setting) float GetSampleIntensity(float time); float GetBalanceIntensity(float time); void SetEdgeInfo(bool leftEdge, int curveType, float zero); void GetEdgeInfo(bool leftEdge, int &curveType, float &zero) const; void SetEdgeActive(bool leftEdge, bool state); bool IsEdgeActive(bool leftEdge) const; int GetEdgeCurveType(bool leftEdge) const; float GetEdgeZeroValue(bool leftEdge) const; float GetDefaultEdgeZeroPos() const; void SetServerSide(bool state); bool IsServerSide() const; private: // remove any samples after endtime void RemoveOutOfRangeSamples(int type); // returns scaled value for absolute time per mag/balance float GetIntensityInternal(float time, int type); public: // returns the fractional (0..1) value for "zero" based on Min/Max ranges float GetZeroValue(int type, bool leftSide); private: char *m_pControllerName; // base track has range, combo is always 0..1 float m_flMin; float m_flMax; // 0 == magnitude // 1 == left/right CUtlVector m_Samples[2]; int m_nFlexControllerIndex[2]; LocalFlexController_t m_nFlexControllerIndexRaw[2]; // For left and right edge of type 0 flex data ( magnitude track ) EdgeInfo_t m_EdgeInfo[2]; CChoreoEvent *m_pEvent; // Is track active bool m_bActive : 1; // Is this a combo (magnitude + stereo) track bool m_bCombo : 1; bool m_bServerSide : 1; bool m_bInverted; // track is displayed 1..0 instead of 0..1 }; //----------------------------------------------------------------------------- // Purpose: The generic scene event type //----------------------------------------------------------------------------- class CChoreoEvent : public ICurveDataAccessor { public: // Type of event this object represents typedef enum { // Don't know yet UNSPECIFIED = 0, // Section start/end SECTION, // Play an expression EXPRESSION, // Look at another actor LOOKAT, // Move to a location MOVETO, // Speak/visemes a wave file SPEAK, // Play a gesture GESTURE, // Play a sequence SEQUENCE, // Face another actor FACE, // Fire a trigger FIRETRIGGER, // One or more flex sliders animated over the course of the event time // period FLEXANIMATION, // A contained .vcd file SUBSCENE, // Loop back to previous time (forever or up to N times) LOOP, // A time span during which the scene may be temporarily interrupted INTERRUPT, // A dummy event that is used to mark the .vcd end time STOPPOINT, // A time span during which this actor can respond to events happening // in the world, etc. PERMIT_RESPONSES, // A string passed to the game code for interpretation GENERIC, // THIS MUST BE LAST!!! NUM_TYPES, } EVENTTYPE; enum { MAX_TAGNAME_STRING = 128, MAX_CCTOKEN_STRING = 64, }; typedef enum { DEFAULT = 0, SIMULATION, DISPLAY, } TIMETYPE; typedef enum { CC_MASTER = 0, // default, implied CC_SLAVE, CC_DISABLED, NUM_CC_TYPES, } CLOSECAPTION; static int s_nGlobalID; // Construction CChoreoEvent(CChoreoScene *scene); CChoreoEvent(CChoreoScene *scene, EVENTTYPE type, const char *name); CChoreoEvent(CChoreoScene *scene, EVENTTYPE type, const char *name, const char *param); // Assignment CChoreoEvent &operator=(const CChoreoEvent &src); ~CChoreoEvent(void); // ICurveDataAccessor methods virtual bool CurveHasEndTime(); virtual int GetDefaultCurveType(); // Binary serialization void SaveToBuffer(CUtlBuffer &buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool); bool RestoreFromBuffer(CUtlBuffer &buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool); // Accessors EVENTTYPE GetType(void); void SetType(EVENTTYPE type); void SetName(const char *name); const char *GetName(void); void SetParameters(const char *target); const char *GetParameters(void); void SetParameters2(const char *target); const char *GetParameters2(void); void SetParameters3(const char *target); const char *GetParameters3(void); void SetStartTime(float starttime); float GetStartTime(void); void SetEndTime(float endtime); float GetEndTime(void); float GetDuration(void); void SetResumeCondition(bool resumecondition); bool IsResumeCondition(void); void SetLockBodyFacing(bool lockbodyfacing); bool IsLockBodyFacing(void); void SetDistanceToTarget(float distancetotarget); float GetDistanceToTarget(void); void SetForceShortMovement(bool bForceShortMovement); bool GetForceShortMovement(void); void SetSyncToFollowingGesture(bool bSyncToFollowingGesture); bool GetSyncToFollowingGesture(void); void SetPlayOverScript(bool bPlayOverScript); bool GetPlayOverScript(void); int GetRampCount(void) { return m_Ramp.GetCount(); }; CExpressionSample *GetRamp(int index) { return m_Ramp.Get(index); }; CExpressionSample *AddRamp(float time, float value, bool selected) { return m_Ramp.Add(time, value, selected); }; void DeleteRamp(int index) { m_Ramp.Delete(index); }; void ClearRamp(void) { m_Ramp.Clear(); }; void ResortRamp(void) { m_Ramp.Resort(this); }; CCurveData *GetRamp(void) { return &m_Ramp; }; float GetRampIntensity(float time) { return m_Ramp.GetIntensity(this, time); }; // Calculates weighting for a given time float GetIntensity(float scenetime); float GetIntensityArea(float scenetime); // Calculates 0..1 completion for a given time float GetCompletion(float time); // An end time of -1.0f means that the events is just triggered at the // leading edge bool HasEndTime(void); // Is the event something that can be sized ( a wave file, e.g. ) bool IsFixedLength(void); void SetFixedLength(bool isfixedlength); // Move the start/end/both times by the specified dt (fixes up -1.0f // endtimes) void OffsetStartTime(float dt); void OffsetEndTime(float dt); void OffsetTime(float dt); // Snap to scene framerate void SnapTimes(void); float SnapTime(float t); CChoreoScene *GetScene(void); void SetScene(CChoreoScene *scene); // The actor the event is associated with void SetActor(CChoreoActor *actor); CChoreoActor *GetActor(void); // The channel the event is associated with void SetChannel(CChoreoChannel *channel); CChoreoChannel *GetChannel(void); // Get a more involved description of the event const char *GetDescription(void); void ClearAllRelativeTags(void); int GetNumRelativeTags(void); CEventRelativeTag *GetRelativeTag(int tagnum); CEventRelativeTag *FindRelativeTag(const char *tagname); void AddRelativeTag(const char *tagname, float percentage); void RemoveRelativeTag(const char *tagname); bool IsUsingRelativeTag(void); void SetUsingRelativeTag(bool usetag, const char *tagname = 0, const char *wavname = 0); const char *GetRelativeTagName(void); const char *GetRelativeWavName(void); // Absolute tags typedef enum { PLAYBACK = 0, // new timeline - FIXME: should be stored as an // absolute time ORIGINAL, // original timeline - FIXME: should be stored at a fixed // percentage of event NUM_ABS_TAG_TYPES, } AbsTagType; void SetGestureSequenceDuration(float duration); bool GetGestureSequenceDuration(float &duration); void ClearAllAbsoluteTags(AbsTagType type); int GetNumAbsoluteTags(AbsTagType type); CEventAbsoluteTag *GetAbsoluteTag(AbsTagType type, int tagnum); CEventAbsoluteTag *FindAbsoluteTag(AbsTagType type, const char *tagname); void AddAbsoluteTag(AbsTagType type, const char *tagname, float t); void RemoveAbsoluteTag(AbsTagType type, const char *tagname); bool VerifyTagOrder(void); float GetOriginalPercentageFromPlaybackPercentage(float t); float GetPlaybackPercentageFromOriginalPercentage(float t); static const char *NameForAbsoluteTagType(AbsTagType t); static AbsTagType TypeForAbsoluteTagName(const char *name); void RescaleGestureTimes(float newstart, float newend, bool bMaintainAbsoluteTagPositions); bool PreventTagOverlap(void); CEventAbsoluteTag *FindEntryTag(AbsTagType type); CEventAbsoluteTag *FindExitTag(AbsTagType type); // Flex animation type int GetNumFlexAnimationTracks(void); CFlexAnimationTrack *GetFlexAnimationTrack(int index); CFlexAnimationTrack *AddTrack(const char *controllername); CFlexAnimationTrack *FindTrack(const char *controllername); void RemoveTrack(int index); void RemoveAllTracks(void); void OnEndTimeChanged(void); bool GetTrackLookupSet(void); void SetTrackLookupSet(bool set); // Flex Timing Tags (used by editor only) void ClearAllTimingTags(void); int GetNumTimingTags(void); CFlexTimingTag *GetTimingTag(int tagnum); CFlexTimingTag *FindTimingTag(const char *tagname); void AddTimingTag(const char *tagname, float percentage, bool locked); void RemoveTimingTag(const char *tagname); // Subscene ( embedded .vcd ) support void SetSubScene(CChoreoScene *scene); CChoreoScene *GetSubScene(void); bool IsProcessing(void) const; void StartProcessing(IChoreoEventCallback *cb, CChoreoScene *scene, float t); void ContinueProcessing(IChoreoEventCallback *cb, CChoreoScene *scene, float t); void StopProcessing(IChoreoEventCallback *cb, CChoreoScene *scene, float t); bool CheckProcessing(IChoreoEventCallback *cb, CChoreoScene *scene, float t); void ResetProcessing(void); void SetMixer(CAudioMixer *mixer); CAudioMixer *GetMixer(void) const; // Hack for LOOKAT in editor int GetPitch(void) const; void SetPitch(int pitch); int GetYaw(void) const; void SetYaw(int yaw); // For LOOP events void SetLoopCount(int numloops); int GetLoopCount(void); int GetNumLoopsRemaining(void); void SetNumLoopsRemaining(int loops); bool IsMarkedForSave() const { return m_bMarkedForSave; } void SetMarkedForSave(bool mark) { m_bMarkedForSave = mark; } void GetMovementStyle(char *style, int maxlen); void GetDistanceStyle(char *style, int maxlen); int GetGlobalID() const { return m_nGlobalID; } // Localization/CC support (close captioning and multiple wave file // recombination) void SetCloseCaptionType(CLOSECAPTION type); CLOSECAPTION GetCloseCaptionType() const; void SetCloseCaptionToken(char const *token); char const *GetCloseCaptionToken() const; void SetUsingCombinedFile(bool isusing); bool IsUsingCombinedFile() const; void SetRequiredCombinedChecksum(unsigned int checksum); unsigned int GetRequiredCombinedChecksum(); void SetNumSlaves(int num); int GetNumSlaves() const; void SetLastSlaveEndTime(float t); float GetLastSlaveEndTime() const; void SetCloseCaptionTokenValid(bool valid); bool GetCloseCaptionTokenValid() const; bool ComputeCombinedBaseFileName(char *dest, int destlen, bool creategenderwildcard); bool IsCombinedUsingGenderToken() const; void SetCombinedUsingGenderToken(bool using_gender); bool IsSuppressingCaptionAttenuation() const; void SetSuppressingCaptionAttenuation(bool suppress); int ValidateCombinedFile(); // This returns false if the wave is CC_DISABLED or is a CC_SLAVE, // otherwise it returns the actual m_szCCToken value, or if that's // blank it'll return the sounds.txt entry name (m_szParameters) bool GetPlaybackCloseCaptionToken(char *dest, int destlen); void ClearEventDependencies(); void AddEventDependency(CChoreoEvent *other); void GetEventDependencies(CUtlVector &list); void SetActive(bool state); bool GetActive() const; void SetDefaultCurveType(int nCurveType); // Turn enum into string and vice versa static EVENTTYPE TypeForName(const char *name); static const char *NameForType(EVENTTYPE type); // Turn enum into string and vice versa static CLOSECAPTION CCTypeForName(const char *name); static const char *NameForCCType(CLOSECAPTION type); private: // Declare copy constructor private to prevent accidental usage... CChoreoEvent(const CChoreoEvent &src); void SaveFlexAnimationsToBuffer(CUtlBuffer &buf, IChoreoStringPool *pStringPool); bool RestoreFlexAnimationsFromBuffer(CUtlBuffer &buf, IChoreoStringPool *pStringPool); float GetBoundedAbsoluteTagPercentage(AbsTagType type, int tagnum); float _GetIntensity(float time); // String bounds enum { MAX_CHOREOEVENT_NAME = 128, MAX_PARAMETERS_STRING = 128, }; // Base initialization void Init(CChoreoScene *scene); // Type of event byte m_fType; // Close caption type byte m_ccType; // Name of event ChoreoStr_t m_Name; // Event parameters ChoreoStr_t m_Parameters; ChoreoStr_t m_Parameters2; ChoreoStr_t m_Parameters3; // Event start time float m_flStartTime; // Event end time ( -1.0f means no ending, just leading edge triggered ) float m_flEndTime; // Duration of underlying gesture sequence float m_flGestureSequenceDuration; // For CChoreoEvent::LOOP int m_nNumLoops; // -1 == no limit int m_nLoopsRemaining; // Overall intensity curve CCurveData m_Ramp; // Start time is computed based on length of item referenced by tagged name ChoreoStr_t m_TagName; ChoreoStr_t m_TagWavName; // Associated actor CChoreoActor *m_pActor; // Associated channel CChoreoChannel *m_pChannel; CUtlVector m_RelativeTags; CUtlVector m_TimingTags; CUtlVector m_AbsoluteTags[NUM_ABS_TAG_TYPES]; CUtlVector m_FlexAnimationTracks; CChoreoScene *m_pSubScene; CAudioMixer *m_pMixer; // Scene which owns this event CChoreoScene *m_pScene; int m_nPitch; int m_nYaw; float m_flDistanceToTarget; int m_nGlobalID; ChoreoStr_t m_CCToken; unsigned int m_uRequiredCombinedChecksum; // on master only, the combined file must have the same checksum to be // useable int m_nNumSlaves; // Only set on master, helps UI draw underbar float m_flLastSlaveEndTime; // true if the cc token was found in the cc manager's database CUtlVector m_Dependencies; int m_nDefaultCurveType; public: // used only during scrubbing of looping sequences float m_flPrevCycle; float m_flPrevTime; // Flags bool m_bFixedLength : 1; // True if this event must be "finished" before the next section can be // started // after playback is paused from a globalevent bool m_bResumeCondition : 1; bool m_bUsesTag : 1; bool m_bTrackLookupSet : 1; bool m_bProcessing : 1; bool m_bLockBodyFacing : 1; // Purely for save/load bool m_bMarkedForSave : 1; bool m_bUsingCombinedSoundFile : 1; bool m_bCCTokenValid : 1; bool m_bCombinedUsingGenderToken : 1; bool m_bSuppressCaptionAttenuation : 1; bool m_bForceShortMovement : 1; bool m_bSyncToFollowingGesture : 1; bool m_bActive : 1; bool m_bPlayOverScript : 1; }; #endif // CHOREOEVENT_H