This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

719 lines
21 KiB
C++

//========= 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<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