Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

918 lines
36 KiB

//========= 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 &params, CDmeLogLayer *savedLayer ) = 0;
virtual void BlendLayersUsingTimeSelection( const DmeLog_TimeSelection_t &params ) = 0;
virtual void BlendLayersUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t &params, bool bUseBaseLayerSamples, DmeTime_t tStartOffset ) = 0;
virtual void BlendTimesUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t &params, 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 &params, CDmeLogLayer *savedLayer );
void BlendLayersUsingTimeSelection( const DmeLog_TimeSelection_t &params );
void BlendLayersUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t &params, bool bUseBaseLayerSamples, DmeTime_t tStartOffset );
void BlendTimesUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t &params, 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 &params, 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