diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /public/movieobjects/dmelog.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'public/movieobjects/dmelog.h')
| -rw-r--r-- | public/movieobjects/dmelog.h | 918 |
1 files changed, 918 insertions, 0 deletions
diff --git a/public/movieobjects/dmelog.h b/public/movieobjects/dmelog.h new file mode 100644 index 0000000..a0e85b0 --- /dev/null +++ b/public/movieobjects/dmelog.h @@ -0,0 +1,918 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef DMELOG_H +#define DMELOG_H +#ifdef _WIN32 +#pragma once +#endif + +#include "datamodel/dmelement.h" +#include "datamodel/dmattribute.h" +#include "datamodel/dmattributevar.h" +#include "datamodel/dmehandle.h" +#include "interpolatortypes.h" +#include "movieobjects/timeutils.h" +#include "movieobjects/dmetimeselectiontimes.h" + +class IUniformRandomStream; + +template < class T > class CDmeTypedLog; + +enum +{ + FILTER_SMOOTH = 0, + FILTER_JITTER, + FILTER_SHARPEN, + FILTER_SOFTEN, + + NUM_FILTERS +}; + +enum RecordingMode_t +{ + RECORD_PRESET = 0, // Preset/fader slider being dragged + RECORD_ATTRIBUTESLIDER, // Single attribute slider being dragged +}; + +#define DMELOG_DEFAULT_THRESHHOLD 0.0001f + +class DmeLog_TimeSelection_t +{ +public: + DmeLog_TimeSelection_t() : + m_flIntensity( 1.0f ), + m_bAttachedMode( true ), + m_bTimeAdvancing( false ), + m_bResampleMode( true ), + m_nResampleInterval( DmeTime_t( .05f ) ),// 50 msec sampling interval by default + m_flThreshold( DMELOG_DEFAULT_THRESHHOLD ), + m_pPresetValue( 0 ), + m_RecordingMode( RECORD_PRESET ) + { + m_nTimes[ TS_LEFT_FALLOFF ] = m_nTimes[ TS_LEFT_HOLD ] = + m_nTimes[ TS_RIGHT_HOLD ] = m_nTimes[ TS_RIGHT_FALLOFF ] = DmeTime_t( 0 ); + m_nFalloffInterpolatorTypes[ 0 ] = m_nFalloffInterpolatorTypes[ 1 ] = INTERPOLATE_LINEAR_INTERP; + } + + inline void ResetTimeAdvancing() + { + // Reset the time advancing flag + m_bTimeAdvancing = false; + } + + inline void StartTimeAdvancing() + { + m_bTimeAdvancing = true; + } + + inline bool IsTimeAdvancing() const + { + return m_bTimeAdvancing; + } + + inline RecordingMode_t GetRecordingMode() const + { + return m_RecordingMode; + } + + void SetRecordingMode( RecordingMode_t mode ) + { + m_RecordingMode = mode; + } + + float GetAmountForTime( DmeTime_t curtime ) const; + float AdjustFactorForInterpolatorType( float factor, int side ) const; + + // NOTE: See DmeTimeSelectionTimes_t for return values, 0 means before, 1= left fallof, 2=hold, 3=right falloff, 4=after + int ComputeRegionForTime( DmeTime_t curtime ) const; + + DmeTime_t m_nTimes[ TS_TIME_COUNT ]; + int m_nFalloffInterpolatorTypes[ 2 ]; + DmeTime_t m_nResampleInterval; // Only used if m_bResampleMode is true + float m_flIntensity; // How much to drive values toward m_HeadValue (generally 1.0f) + float m_flThreshold; + CDmAttribute* m_pPresetValue; + + bool m_bAttachedMode : 1; // Is the current time "attached" to the head position + + // Adds new, evenly spaced samples based on m_nResampleInterval + // Also adds zero intensity samples at the falloff edges + bool m_bResampleMode : 1; + +private: + bool m_bTimeAdvancing : 1; // Has time ever been advancing + RecordingMode_t m_RecordingMode; +}; + +class CDmeChannel; +class CDmeChannelsClip; +class CDmeFilmClip; +class CDmeLog; +class CDmeLogLayer; + +struct LayerSelectionData_t +{ + LayerSelectionData_t(); + void Release(); + + CDmeHandle< CDmeChannel > m_hChannel; + CDmeHandle< CDmeChannelsClip > m_hOwner; + CDmeHandle< CDmeFilmClip > m_hShot; + CDmeHandle< CDmeLog > m_hLog; + DmAttributeType_t m_DataType; + int m_nDuration; + int m_nHoldTimes[ 2 ]; + DmeTime_t m_tStartOffset; + + // This is dynamic and needs to be released + struct DataLayer_t + { + DataLayer_t( float frac, CDmeLogLayer *layer ); + + float m_flStartFraction; + CDmeHandle< CDmeLogLayer, true > m_hData; + }; + + CUtlVector< DataLayer_t > m_vecData; +}; + +//----------------------------------------------------------------------------- +// CDmeLogLayer - abstract base class +//----------------------------------------------------------------------------- +abstract_class CDmeLogLayer : public CDmElement +{ + friend class CDmeLog; + + DEFINE_ELEMENT( CDmeLogLayer, CDmElement ); + +public: + virtual void CopyLayer( const CDmeLogLayer *src ) = 0; + virtual void CopyPartialLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps ) = 0; + virtual void ExplodeLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps, DmeTime_t tResampleInterval ) = 0; + virtual void InsertKeyFromLayer( DmeTime_t keyTime, const CDmeLogLayer *src, DmeTime_t srcKeyTime ) = 0; + + DmeTime_t GetBeginTime() const; + DmeTime_t GetEndTime() const; + int GetKeyCount() const; + + // Returns the index of a key closest to this time, within tolerance + // NOTE: Insertion or removal may change this index! + // Returns -1 if the time isn't within tolerance. + int FindKeyWithinTolerance( DmeTime_t time, DmeTime_t nTolerance ); + + // Returns the type of attribute being logged + virtual DmAttributeType_t GetDataType() const = 0; + + // Sets a key, removes all keys after this time + virtual void SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index = 0, int curveType = CURVE_DEFAULT ) = 0; + virtual bool SetDuplicateKeyAtTime( DmeTime_t time ) = 0; + // This inserts a key using the current values to construct the proper value for the time + virtual int InsertKeyAtTime( DmeTime_t nTime, int curveType = CURVE_DEFAULT ) = 0; + + // Sets the interpolated value of the log at the specified time into the attribute + virtual void GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const = 0; + + virtual float GetComponent( DmeTime_t time, int componentIndex ) const = 0; + + // Returns the time at which a particular key occurs + DmeTime_t GetKeyTime( int nKeyIndex ) const; + void SetKeyTime( int nKeyIndex, DmeTime_t keyTime ); + + // Scale + bias key times + void ScaleBiasKeyTimes( double flScale, DmeTime_t nBias ); + + // Removes a single key by index + virtual void RemoveKey( int nKeyIndex, int nNumKeysToRemove = 1 ) = 0; + + // Removes all keys + virtual void ClearKeys() = 0; + + virtual bool IsConstantValued() const = 0; + virtual void RemoveRedundantKeys() = 0; + virtual void RemoveRedundantKeys( float threshold ) = 0; + + // resampling and filtering + virtual void Resample( DmeFramerate_t samplerate ) = 0; + virtual void Filter( int nSampleRadius ) = 0; + virtual void Filter2( DmeTime_t sampleRadius ) = 0; + + virtual void SetOwnerLog( CDmeLog *owner ) = 0; + CDmeLog *GetOwnerLog(); + const CDmeLog *GetOwnerLog() const; + + bool IsUsingCurveTypes() const; + int GetDefaultCurveType() const; + + // Override curvetype for specific key + void SetKeyCurveType( int nKeyIndex, int curveType ); + int GetKeyCurveType( int nKeyIndex ) const; + + // Validates that all keys are correctly sorted in time + bool ValidateKeys() const; + + // Removes all keys outside the specified time range + void RemoveKeysOutsideRange( DmeTime_t tStart, DmeTime_t tEnd ); + +protected: + int FindKey( DmeTime_t time ) const; + + void OnUsingCurveTypesChanged(); + + CDmeLog *m_pOwnerLog; + + mutable int m_lastKey; + CDmaArray< int > m_times; + CDmaArray< int > m_CurveTypes; +}; + +template< class T > +CDmeLogLayer *CreateLayer( CDmeTypedLog< T > *ownerLog ); + + +//----------------------------------------------------------------------------- +// CDmeLogLayer - abstract base class +//----------------------------------------------------------------------------- +abstract_class CDmeCurveInfo : public CDmElement +{ + DEFINE_ELEMENT( CDmeCurveInfo, CDmElement ); + +public: + // Global override for all keys unless overriden by specific key + void SetDefaultCurveType( int curveType ); + int GetDefaultCurveType() const; + + void SetMinValue( float val ); + float GetMinValue() const; + void SetMaxValue( float val ); + float GetMaxValue() const; + +protected: + CDmaVar< int > m_DefaultCurveType; + + CDmaVar< float > m_MinValue; + CDmaVar< float > m_MaxValue; +}; + +template <class T > class CDmeTypedLogLayer; + +//----------------------------------------------------------------------------- +// CDmeLog - abstract base class +//----------------------------------------------------------------------------- +abstract_class CDmeLog : public CDmElement +{ + DEFINE_ELEMENT( CDmeLog, CDmElement ); + +public: + int FindLayerForTime( DmeTime_t time ) const; + int FindLayerForTimeSkippingTopmost( DmeTime_t time ) const; + void FindLayersForTime( DmeTime_t time, CUtlVector< int >& list ) const; + + virtual void FinishTimeSelection( DmeTime_t tHeadPosition, DmeLog_TimeSelection_t& params ) = 0; // in attached, timeadvancing mode, we need to blend out of the final sample over the fadeout interval + virtual void StampKeyAtHead( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index = 0 ) = 0; + virtual void FilterUsingTimeSelection( IUniformRandomStream *random, float flScale, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer ) = 0; + virtual void FilterUsingTimeSelection( IUniformRandomStream *random, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff ) = 0; + virtual void StaggerUsingTimeSelection( const DmeLog_TimeSelection_t& params, DmeTime_t tStaggerAmount, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer ) = 0; + virtual void RevealUsingTimeSelection( const DmeLog_TimeSelection_t ¶ms, CDmeLogLayer *savedLayer ) = 0; + virtual void BlendLayersUsingTimeSelection( const DmeLog_TimeSelection_t ¶ms ) = 0; + virtual void BlendLayersUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t ¶ms, bool bUseBaseLayerSamples, DmeTime_t tStartOffset ) = 0; + virtual void BlendTimesUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t ¶ms, DmeTime_t tStartOffset ) = 0; + virtual void PasteAndRescaleSamples( const CDmeLogLayer *src, const DmeLog_TimeSelection_t& srcParams, const DmeLog_TimeSelection_t& destParams, bool bBlendAreaInFalloffRegion ) = 0; + virtual void PasteAndRescaleSamples( const CDmeLogLayer *pBaseLayer, const CDmeLogLayer *pDataLayer, CDmeLogLayer *pOutputLayer, const DmeLog_TimeSelection_t& srcParams, const DmeLog_TimeSelection_t& destParams, bool bBlendAreaInFalloffRegion ) = 0; + virtual void BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ) = 0; + virtual void BuildCorrespondingLayer( const CDmeLogLayer *pReferenceLayer, const CDmeLogLayer *pDataLayer, CDmeLogLayer *pOutputLayer ) = 0; + + int GetTopmostLayer() const; + int GetNumLayers() const; + CDmeLogLayer *GetLayer( int index ); + const CDmeLogLayer *GetLayer( int index ) const; + + DmeTime_t GetBeginTime() const; + DmeTime_t GetEndTime() const; + int GetKeyCount() const; + + bool IsEmpty() const; + + // Returns the index of a key closest to this time, within tolerance + // NOTE: Insertion or removal may change this index! + // Returns -1 if the time isn't within tolerance. + virtual int FindKeyWithinTolerance( DmeTime_t time, DmeTime_t nTolerance ) = 0; + + // Returns the type of attribute being logged + virtual DmAttributeType_t GetDataType() const = 0; + + // Sets a key, removes all keys after this time + virtual void SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index = 0, int curveType = CURVE_DEFAULT ) = 0; + virtual bool SetDuplicateKeyAtTime( DmeTime_t time ) = 0; + virtual int InsertKeyAtTime( DmeTime_t nTime, int curveType = CURVE_DEFAULT ) = 0; + // Sets the interpolated value of the log at the specified time into the attribute + virtual void GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const = 0; + virtual void GetValueSkippingTopmostLayer( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const = 0; + + virtual float GetComponent( DmeTime_t time, int componentIndex ) const = 0; + + // Returns the time at which a particular key occurs + virtual DmeTime_t GetKeyTime( int nKeyIndex ) const = 0; + virtual void SetKeyTime( int nKeyIndex, DmeTime_t keyTime ) = 0; + + // Override curvetype for specific key + void SetKeyCurveType( int nKeyIndex, int curveType ); + int GetKeyCurveType( int nKeyIndex ) const; + + // Removes a single key by index + virtual void RemoveKey( int nKeyIndex, int nNumKeysToRemove = 1 ) = 0; + + // Removes all keys within the time range, returns true if keys were removed + bool RemoveKeys( DmeTime_t tStartTime, DmeTime_t tEndTime ); + + // Removes all keys + virtual void ClearKeys() = 0; + + // Scale + bias key times + void ScaleBiasKeyTimes( double flScale, DmeTime_t nBias ); + + virtual float GetValueThreshold() const = 0; + virtual void SetValueThreshold( float thresh ) = 0; + virtual bool IsConstantValued() const = 0; + virtual void RemoveRedundantKeys() = 0; + virtual void RemoveRedundantKeys( float threshold ) = 0; + + // resampling and filtering + virtual void Resample( DmeFramerate_t samplerate ) = 0; + virtual void Filter( int nSampleRadius ) = 0; + virtual void Filter2( DmeTime_t sampleRadius ) = 0; + + // Creates a log of a requested type + static CDmeLog *CreateLog( DmAttributeType_t type, DmFileId_t fileid ); + + virtual CDmeLogLayer *AddNewLayer() = 0; + enum + { + FLATTEN_NODISCONTINUITY_FIXUP = (1<<0), // Don't add "helper" samples to preserve discontinuities. This occurs when the time selection is "detached" from the head position + FLATTEN_SPEW = (1<<1), + }; + virtual void FlattenLayers( float threshold, int flags ) = 0; + + // Only used by undo system!!! + virtual void AddLayerToTail( CDmeLogLayer *layer ) = 0; + virtual CDmeLogLayer *RemoveLayerFromTail() = 0; + virtual CDmeLogLayer *RemoveLayer( int iLayer ) = 0; + + + // Resolve + virtual void Resolve(); + + // curve info helpers + bool IsUsingCurveTypes() const; + const CDmeCurveInfo *GetCurveInfo() const; + CDmeCurveInfo *GetCurveInfo(); + virtual CDmeCurveInfo *GetOrCreateCurveInfo() = 0; + virtual void SetCurveInfo( CDmeCurveInfo *pCurveInfo ) = 0; + + // accessors for CurveInfo data + int GetDefaultCurveType() const; + + // FIXME - this should really be in the CurveInfo + // but the animset editor currently asks for these, without having set a curveinfo... + void SetMinValue( float val ); + void SetMaxValue( float val ); + float GetMinValue() const; + float GetMaxValue() const; + + virtual bool HasDefaultValue() const = 0; + + +protected: +// int FindKey( DmeTime_t time ) const; + + void OnUsingCurveTypesChanged(); + + virtual void OnAttributeChanged( CDmAttribute *pAttribute ); + + CDmaElementArray< CDmeLogLayer > m_Layers; + CDmaElement< CDmeCurveInfo > m_CurveInfo; +}; + + + +//----------------------------------------------------------------------------- +// CDmeTypedCurveInfo - implementation class for all logs +//----------------------------------------------------------------------------- +template< class T > +class CDmeTypedCurveInfo : public CDmeCurveInfo +{ + DEFINE_ELEMENT( CDmeTypedCurveInfo, CDmeCurveInfo ); + +public: + // For "faceposer" style left/right edges, this controls whether interpolators try to mimic faceposer left/right edge behavior + void SetUseEdgeInfo( bool state ); + bool IsUsingEdgeInfo() const; + + void SetEdgeInfo( int edge, bool active, const T& val, int curveType ); + void GetEdgeInfo( int edge, bool& active, T& val, int& curveType ) const; + + void SetDefaultEdgeZeroValue( const T& val ); + const T& GetDefaultEdgeZeroValue() const; + + void SetRightEdgeTime( DmeTime_t time ); + DmeTime_t GetRightEdgeTime() const; + + bool IsEdgeActive( int edge ) const; + void GetEdgeValue( int edge, T& value ) const; + + int GetEdgeCurveType( int edge ) const; + void GetZeroValue( int side, T& val ) const; + +protected: + CDmaVar< bool > m_bUseEdgeInfo; + // Array of 2 for left/right edges... + CDmaVar< bool > m_bEdgeActive[ 2 ]; + CDmaVar< T > m_EdgeValue[ 2 ]; + CDmaVar< int > m_EdgeCurveType[ 2 ]; + CDmaVar< int > m_RightEdgeTime; + CDmaVar< T > m_DefaultEdgeValue; +}; + + +// forward declaration +template< class T > class CDmeTypedLog; + + +//----------------------------------------------------------------------------- +// CDmeTypedLogLayer - implementation class for all logs +//----------------------------------------------------------------------------- +template< class T > +class CDmeTypedLogLayer : public CDmeLogLayer +{ + DEFINE_ELEMENT( CDmeTypedLogLayer, CDmeLogLayer ); + +public: + virtual void CopyLayer( const CDmeLogLayer *src ); + virtual void CopyPartialLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps ); + virtual void ExplodeLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps, DmeTime_t tResampleInterval ); + virtual void InsertKeyFromLayer( DmeTime_t keyTime, const CDmeLogLayer *src, DmeTime_t srcKeyTime ); + + // Finds a key within tolerance, or adds one. Unlike SetKey, this will *not* delete keys after the specified time + int FindOrAddKey( DmeTime_t nTime, DmeTime_t nTolerance, const T& value, int curveType = CURVE_DEFAULT ); + + // Sets a key, removes all keys after this time + void SetKey( DmeTime_t time, const T& value, int curveType = CURVE_DEFAULT ); + // This inserts a key using the current values to construct the proper value for the time + virtual int InsertKeyAtTime( DmeTime_t nTime, int curveType = CURVE_DEFAULT ); + + void SetKeyValue( int nKey, const T& value ); + + const T& GetValue( DmeTime_t time ) const; + + const T& GetKeyValue( int nKeyIndex ) const; + const T& GetValueSkippingKey( int nKeyToSkip ) const; + + // This inserts a key. Unlike SetKey, this will *not* delete keys after the specified time + int InsertKey( DmeTime_t nTime, const T& value, int curveType = CURVE_DEFAULT ); + + // inherited from CDmeLog + virtual void ClearKeys(); + virtual void SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index = 0, int curveType = CURVE_DEFAULT ); + virtual bool SetDuplicateKeyAtTime( DmeTime_t time ); + virtual void GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const; + virtual float GetComponent( DmeTime_t time, int componentIndex ) const; + virtual DmAttributeType_t GetDataType() const; + virtual bool IsConstantValued() const; + virtual void RemoveRedundantKeys(); + virtual void RemoveRedundantKeys( float threshold ); + + virtual void RemoveKey( int nKeyIndex, int nNumKeysToRemove = 1 ); + virtual void Resample( DmeFramerate_t samplerate ); + virtual void Filter( int nSampleRadius ); + virtual void Filter2( DmeTime_t sampleRadius ); + + void RemoveKeys( DmeTime_t starttime ); + + // curve info helpers + const CDmeTypedCurveInfo< T > *GetTypedCurveInfo() const; + CDmeTypedCurveInfo< T > *GetTypedCurveInfo(); + + bool IsUsingEdgeInfo() const; + void GetEdgeInfo( int edge, bool& active, T& val, int& curveType ) const; + const T& GetDefaultEdgeZeroValue() const; + DmeTime_t GetRightEdgeTime() const; + + void SetOwnerLog( CDmeLog *owner ); + + CDmeTypedLog< T > *GetTypedOwnerLog(); + const CDmeTypedLog< T > *GetTypedOwnerLog() const; + +protected: + + int GetEdgeCurveType( int edge ) const; + void GetZeroValue( int side, T& val ) const; + + void GetValueUsingCurveInfo( DmeTime_t time, T& out ) const; + void GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, T& out ) const; + void GetBoundedSample( int keyindex, DmeTime_t& time, T& val, int& curveType ) const; + + void CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< T > *output ); + + friend CDmeTypedLog< T >; + +protected: + CDmaArray< T > m_values; +}; + + +//----------------------------------------------------------------------------- +// CDmeTypedLog - implementation class for all logs +//----------------------------------------------------------------------------- +template< class T > +class CDmeTypedLog : public CDmeLog +{ + DEFINE_ELEMENT( CDmeTypedLog, CDmeLog ); + +public: + + virtual void OnAttributeArrayElementAdded( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ); + + CDmeTypedLogLayer< T > *GetLayer( int index ); + const CDmeTypedLogLayer< T > *GetLayer( int index ) const; + + void StampKeyAtHead( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t& params, const T& value ); + void StampKeyAtHead( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index = 0 ); + void FinishTimeSelection( DmeTime_t tHeadPosition, DmeLog_TimeSelection_t& params ); // in attached, timeadvancing mode, we need to blend out of the final sample over the fadeout interval + void FilterUsingTimeSelection( IUniformRandomStream *random, float flScale, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer ); + void FilterUsingTimeSelection( IUniformRandomStream *random, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff ); + void StaggerUsingTimeSelection( const DmeLog_TimeSelection_t& params, DmeTime_t tStaggerAmount, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer ); + void RevealUsingTimeSelection( const DmeLog_TimeSelection_t ¶ms, CDmeLogLayer *savedLayer ); + void BlendLayersUsingTimeSelection( const DmeLog_TimeSelection_t ¶ms ); + void BlendLayersUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t ¶ms, bool bUseBaseLayerSamples, DmeTime_t tStartOffset ); + void BlendTimesUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t ¶ms, DmeTime_t tStartOffset ); + + virtual void PasteAndRescaleSamples( const CDmeLogLayer *src, const DmeLog_TimeSelection_t& srcParams, const DmeLog_TimeSelection_t& destParams, bool bBlendAreaInFalloffRegion ); + virtual void PasteAndRescaleSamples( const CDmeLogLayer *pBaseLayer, const CDmeLogLayer *pDataLayer, CDmeLogLayer *pOutputLayer, const DmeLog_TimeSelection_t& srcParams, const DmeLog_TimeSelection_t& destParams, bool bBlendAreaInFalloffRegion ); + virtual void BuildCorrespondingLayer( const CDmeLogLayer *pReferenceLayer, const CDmeLogLayer *pDataLayer, CDmeLogLayer *pOutputLayer ); + + virtual void BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); + + // Finds a key within tolerance, or adds one. Unlike SetKey, this will *not* delete keys after the specified time + int FindOrAddKey( DmeTime_t nTime, DmeTime_t nTolerance, const T& value, int curveType = CURVE_DEFAULT ); + + // Sets a key, removes all keys after this time + void SetKey( DmeTime_t time, const T& value, int curveType = CURVE_DEFAULT ); + int InsertKeyAtTime( DmeTime_t nTime, int curveType = CURVE_DEFAULT ); + bool ValuesDiffer( const T& a, const T& b ) const; + const T& GetValue( DmeTime_t time ) const; + const T& GetValueSkippingTopmostLayer( DmeTime_t time ) const; + + const T& GetKeyValue( int nKeyIndex ) const; + + // This inserts a key. Unlike SetKey, this will *not* delete keys after the specified time + int InsertKey( DmeTime_t nTime, const T& value, int curveType = CURVE_DEFAULT ); + + // inherited from CDmeLog + virtual void ClearKeys(); + virtual void SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index = 0, int curveType = CURVE_DEFAULT ); + virtual bool SetDuplicateKeyAtTime( DmeTime_t time ); + virtual void GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const; + virtual void GetValueSkippingTopmostLayer( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const; + virtual float GetComponent( DmeTime_t time, int componentIndex ) const; + virtual DmAttributeType_t GetDataType() const; + virtual float GetValueThreshold() const { return m_threshold; } + virtual void SetValueThreshold( float thresh ); + virtual bool IsConstantValued() const; + virtual void RemoveRedundantKeys(); + virtual void RemoveRedundantKeys( float threshold ); + virtual void RemoveKey( int nKeyIndex, int nNumKeysToRemove = 1 ); + virtual void Resample( DmeFramerate_t samplerate ); + virtual void Filter( int nSampleRadius ); + virtual void Filter2( DmeTime_t sampleRadius ); + + virtual int FindKeyWithinTolerance( DmeTime_t time, DmeTime_t nTolerance ); + virtual DmeTime_t GetKeyTime( int nKeyIndex ) const; + virtual void SetKeyTime( int nKeyIndex, DmeTime_t keyTime ); + + virtual CDmeLogLayer *AddNewLayer(); + virtual void FlattenLayers( float threshhold, int flags ); + + // Only used by undo system!!! + virtual void AddLayerToTail( CDmeLogLayer *layer ); + virtual CDmeLogLayer *RemoveLayerFromTail(); + virtual CDmeLogLayer *RemoveLayer( int iLayer ); + + // curve info helpers + const CDmeTypedCurveInfo< T > *GetTypedCurveInfo() const; + CDmeTypedCurveInfo< T > *GetTypedCurveInfo(); + virtual CDmeCurveInfo *GetOrCreateCurveInfo(); + virtual void SetCurveInfo( CDmeCurveInfo *pCurveInfo ); + + // For "faceposer" style left/right edges, this controls whether interpolators try to mimic faceposer left/right edge behavior + void SetUseEdgeInfo( bool state ); + bool IsUsingEdgeInfo() const; + + void SetEdgeInfo( int edge, bool active, const T& val, int curveType ); + void GetEdgeInfo( int edge, bool& active, T& val, int& curveType ) const; + + void SetDefaultEdgeZeroValue( const T& val ); + const T& GetDefaultEdgeZeroValue() const; + + void SetRightEdgeTime( DmeTime_t time ); + DmeTime_t GetRightEdgeTime() const; + + bool IsEdgeActive( int edge ) const; + void GetEdgeValue( int edge, T& value ) const; + + int GetEdgeCurveType( int edge ) const; + void GetZeroValue( int side, T& val ) const; + + T ClampValue( const T& value ); + + void SetDefaultValue( const T& value ); + const T& GetDefaultValue() const; + bool HasDefaultValue() const; + void ClearDefaultValue(); + + static void SetDefaultValueThreshold( float thresh ); + static float GetDefaultValueThreshold(); + + static float s_defaultThreshold; + +protected: + void RemoveKeys( DmeTime_t starttime ); + + void _StampKeyAtHeadResample( DmeTime_t tHeadPosition, const DmeLog_TimeSelection_t & params, const T& value, bool bSkipToHead, bool bClearPreviousKeys ); + void _StampKeyAtHeadFilteredByTimeSelection( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t & params, const T& value ); + void _StampKeyFilteredByTimeSelection( CDmeTypedLogLayer< T > *pWriteLayer, DmeTime_t t, const DmeLog_TimeSelection_t ¶ms, const T& value, bool bForce = false ); + +protected: + // this really only makes sense for some of our subclasses, basically those which have float data + // anything else's threshhold is almost certainly 0, and that class just ignores m_threshold + float m_threshold; + + CDmaVar< bool > m_UseDefaultValue; + CDmaVar< T > m_DefaultValue; +}; + + +//----------------------------------------------------------------------------- +// Template methods +//----------------------------------------------------------------------------- +template< class T > +DmAttributeType_t CDmeTypedLogLayer<T>::GetDataType() const +{ + return CDmAttributeInfo< T >::AttributeType(); +} + +template< class T > +bool CDmeTypedLogLayer<T>::IsConstantValued() const +{ + if ( m_values.Count() < 2 ) + return true; + + if ( m_values.Count() == 2 && !GetTypedOwnerLog()->ValuesDiffer( m_values[ 0 ], m_values[ 1 ] ) ) + return true; + + // we're throwing away duplicate values during recording, so this is generally correct + // although there are paths to set keys that don't use the duplicate test, so it's not 100% + return false; +} + +//----------------------------------------------------------------------------- +// Template methods +//----------------------------------------------------------------------------- +template< class T > +DmAttributeType_t CDmeTypedLog<T>::GetDataType() const +{ + return CDmAttributeInfo< T >::AttributeType(); +} + +template< class T > +void CDmeTypedLog<T>::SetDefaultValueThreshold( float thresh ) +{ + s_defaultThreshold = thresh; +} + +template< class T > +float CDmeTypedLog<T>::GetDefaultValueThreshold() +{ + return s_defaultThreshold; +} + +template< class T > +void CDmeTypedLog<T>::SetValueThreshold( float thresh ) +{ + m_threshold = thresh; +} + +template< class T > +bool CDmeTypedLog<T>::IsConstantValued() const +{ + int c = m_Layers.Count(); + for ( int i = 0; i < c; ++i ) + { + if ( !GetLayer( i )->IsConstantValued() ) + return false; + } + + return true; +} + +template< class T > +void CDmeTypedLog<T>::RemoveRedundantKeys() +{ + int bestLayer = GetTopmostLayer(); + if ( bestLayer < 0 ) + return; + + GetLayer( bestLayer )->RemoveRedundantKeys(); +} + +template< class T > +inline float Normalize( const T& val ) +{ + Assert( 0 ); + return 0.5f; +} + +// AT_INT +// AT_FLOAT +// AT_VECTOR* + +template<> +inline float Normalize( const bool& val ) +{ + return val ? 1.0f : 0.0f; +} + +template<> +inline float Normalize( const Color& val ) +{ + float sum = 0.0f; + for ( int i = 0 ; i < 4; ++i ) + { + sum += val[ i ]; + } + sum /= 4.0f; + return clamp( sum / 255.0f, 0.0f, 1.0f ); +} + +template<> +inline float Normalize( const QAngle& val ) +{ + float sum = 0.0f; + for ( int i = 0 ; i < 3; ++i ) + { + float ang = val[ i ]; + if ( ang < 0.0f ) + { + ang += 360.0f; + } + + sum += ang; + } + return clamp( ( sum / 3.0f ) / 360.0f, 0.0f, 1.0f ); +} + +template<> +inline float Normalize( const Quaternion& val ) +{ + QAngle angle; + QuaternionAngles( val, angle ); + return Normalize( angle ); +} + +template< class T > +inline void CDmeTypedLog< T >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *pTarget ) +{ + Assert( pTarget ); + Assert( GetDataType() != AT_FLOAT ); + + CDmeTypedLogLayer< T > *pBaseLayer = static_cast< CDmeTypedLogLayer< T > * >( GetLayer( 0 ) ); + if ( !pBaseLayer ) + return; + + int kc = pBaseLayer->GetKeyCount(); + for ( int i = 0; i < kc; ++i ) + { + DmeTime_t tKeyTime = pBaseLayer->GetKeyTime( i ); + T keyValue = pBaseLayer->GetKeyValue( i ); + float flNormalized = Normalize( keyValue ); + + pTarget->InsertKey( tKeyTime, flNormalized ); + } + + if ( HasDefaultValue() ) + { + pTarget->GetTypedOwnerLog()->SetDefaultValue( Normalize( GetDefaultValue() ) ); + } +} + +// Generic implementations all stubbed +// Forward declare specific typed instantiations for float types + +template< class T > T CDmeTypedLog< T >::ClampValue( const T& value ) { return value; } +template<> float CDmeTypedLog< float >::ClampValue( const float& value ); + + +template< class T > void CDmeTypedCurveInfo< T >::GetZeroValue( int side, T& val ) const{ Assert( 0 ); } +template< class T > bool CDmeTypedCurveInfo< T >::IsEdgeActive( int edge ) const{ Assert( 0 ); return false; } +template< class T > void CDmeTypedCurveInfo< T >::GetEdgeValue( int edge, T &value ) const{ Assert( 0 ); } + +template<> void CDmeTypedCurveInfo< float >::GetZeroValue( int side, float& val ) const; +template<> bool CDmeTypedCurveInfo< float >::IsEdgeActive( int edge ) const; +template<> void CDmeTypedCurveInfo< float >::GetEdgeValue( int edge, float &value ) const; + +template<> void CDmeTypedCurveInfo< Vector >::GetZeroValue( int side, Vector& val ) const; +template<> void CDmeTypedCurveInfo< Quaternion >::GetZeroValue( int side, Quaternion& val ) const; + +template< class T > void CDmeTypedLogLayer< T >::GetValueUsingCurveInfo( DmeTime_t time, T& out ) const { Assert( 0 ); } +template< class T > void CDmeTypedLogLayer< T >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, T& out ) const { Assert( 0 ); } +template<> void CDmeTypedLogLayer< float >::GetValueUsingCurveInfo( DmeTime_t time, float& out ) const; +template<> void CDmeTypedLogLayer< float >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, float& out ) const; + +template<> void CDmeTypedLogLayer< Vector >::GetValueUsingCurveInfo( DmeTime_t time, Vector& out ) const; +template<> void CDmeTypedLogLayer< Vector >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, Vector& out ) const; + +template<> void CDmeTypedLogLayer< Quaternion >::GetValueUsingCurveInfo( DmeTime_t time, Quaternion& out ) const; +template<> void CDmeTypedLogLayer< Quaternion >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, Quaternion& out ) const; + +template<class T> void CDmeTypedLogLayer< T >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< T > *output ); +template<> void CDmeTypedLogLayer< bool >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< bool > *output ); +template<> void CDmeTypedLogLayer< int >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< int > *output ); +template<> void CDmeTypedLogLayer< Color >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< Color > *output ); +template<> void CDmeTypedLogLayer< Quaternion >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< Quaternion > *output ); +template<> void CDmeTypedLogLayer< VMatrix >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< VMatrix > *output ); + +template<> void CDmeTypedLog< Vector >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); +template<> void CDmeTypedLog< Vector2D >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); +template<> void CDmeTypedLog< Vector4D >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); +template<> void CDmeTypedLog< float >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); +template<> void CDmeTypedLog< int >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); + +//template<> void CDmeTypedLog< float >::FinishTimeSelection( DmeTime_t tHeadPosition, DmeLog_TimeSelection_t& params ); +//template<> void CDmeTypedLog< bool >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const bool& value ) { Assert( 0 ); } + +//----------------------------------------------------------------------------- +// typedefs for convenience (and so the user-supplied names match the programmer names) +//----------------------------------------------------------------------------- +typedef CDmeTypedLog<int> CDmeIntLog; +typedef CDmeTypedLog<float> CDmeFloatLog; +typedef CDmeTypedLog<bool> CDmeBoolLog; +typedef CDmeTypedLog<Color> CDmeColorLog; +typedef CDmeTypedLog<Vector2D> CDmeVector2Log; +typedef CDmeTypedLog<Vector> CDmeVector3Log; +typedef CDmeTypedLog<Vector4D> CDmeVector4Log; +typedef CDmeTypedLog<QAngle> CDmeQAngleLog; +typedef CDmeTypedLog<Quaternion> CDmeQuaternionLog; +typedef CDmeTypedLog<VMatrix> CDmeVMatrixLog; +typedef CDmeTypedLog<CUtlString> CDmeStringLog; + +//----------------------------------------------------------------------------- +// typedefs for convenience (and so the user-supplied names match the programmer names) +//----------------------------------------------------------------------------- +typedef CDmeTypedLogLayer<int> CDmeIntLogLayer; +typedef CDmeTypedLogLayer<float> CDmeFloatLogLayer; +typedef CDmeTypedLogLayer<bool> CDmeBoolLogLayer; +typedef CDmeTypedLogLayer<Color> CDmeColorLogLayer; +typedef CDmeTypedLogLayer<Vector2D> CDmeVector2LogLayer; +typedef CDmeTypedLogLayer<Vector> CDmeVector3LogLayer; +typedef CDmeTypedLogLayer<Vector4D> CDmeVector4LogLayer; +typedef CDmeTypedLogLayer<QAngle> CDmeQAngleLogLayer; +typedef CDmeTypedLogLayer<Quaternion> CDmeQuaternionLogLayer; +typedef CDmeTypedLogLayer<VMatrix> CDmeVMatrixLogLayer; +typedef CDmeTypedLogLayer<CUtlString> CDmeStringLogLayer; + +//----------------------------------------------------------------------------- +// typedefs for convenience (and so the user-supplied names match the programmer names) +//----------------------------------------------------------------------------- +typedef CDmeTypedCurveInfo<int> CDmeIntCurveInfo; +typedef CDmeTypedCurveInfo<float> CDmeFloatCurveInfo; +typedef CDmeTypedCurveInfo<bool> CDmeBoolCurveInfo; +typedef CDmeTypedCurveInfo<Color> CDmeColorCurveInfo; +typedef CDmeTypedCurveInfo<Vector2D> CDmeVector2CurveInfo; +typedef CDmeTypedCurveInfo<Vector> CDmeVector3CurveInfo; +typedef CDmeTypedCurveInfo<Vector4D> CDmeVector4CurveInfo; +typedef CDmeTypedCurveInfo<QAngle> CDmeQAngleCurveInfo; +typedef CDmeTypedCurveInfo<Quaternion> CDmeQuaternionCurveInfo; +typedef CDmeTypedCurveInfo<VMatrix> CDmeVMatrixCurveInfo; +typedef CDmeTypedCurveInfo<CUtlString> CDmeStringCurveInfo; + +// the following types are not supported +// AT_ELEMENT, +// AT_VOID, +// AT_OBJECTID, +// <all array types> + +//----------------------------------------------------------------------------- +// Helpers for particular types of log layers +//----------------------------------------------------------------------------- +void GenerateRotationLog( CDmeQuaternionLogLayer *pLayer, const Vector &vecAxis, DmeTime_t pTime[4], float pRevolutionsPerSec[4] ); + +// rotates a position log +void RotatePositionLog( CDmeVector3LogLayer *pPositionLog, const matrix3x4_t& matrix ); + +// rotates an orientation log +void RotateOrientationLog( CDmeQuaternionLogLayer *pOrientationLog, const matrix3x4_t& matrix, bool bPreMultiply ); + + +#endif // DMELOG_H |