//========= 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 "tier1/utlstring.h" #include "tier1/utlvector.h" #include "expressionsample.h" #include "networkvar.h" #include "localflexcontroller.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< CExpressionSample > 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< CChoreoEvent * >& 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 < CEventRelativeTag > m_RelativeTags; CUtlVector < CFlexTimingTag > m_TimingTags; CUtlVector < CEventAbsoluteTag > m_AbsoluteTags[ NUM_ABS_TAG_TYPES ]; CUtlVector < CFlexAnimationTrack * > 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< CChoreoEvent * > 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