Counter Strike : Global Offensive Source Code
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.

9266 lines
272 KiB

  1. //====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "movieobjects/dmelog.h"
  7. #include "movieobjects/dmeclip.h"
  8. #include "movieobjects/dmechannel.h"
  9. #include "datamodel/dmelementfactoryhelper.h"
  10. #include "datamodel/dmehandle.h"
  11. #include "vstdlib/random.h"
  12. #include "tier0/dbg.h"
  13. #include <limits.h>
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. union compressed_value_t
  17. {
  18. struct
  19. {
  20. byte valid;
  21. byte total;
  22. } num;
  23. short value;
  24. };
  25. struct compressed_stream_t
  26. {
  27. const compressed_value_t *Get( int index ) const
  28. {
  29. // the offset for data 0 is right after the structure, so no need to store/retrieve it
  30. unsigned int offset;
  31. if ( index == 0 )
  32. {
  33. offset = sizeof( compressed_stream_t );
  34. }
  35. else
  36. {
  37. offset = m_Offset[ index - 1 ];
  38. }
  39. return (compressed_value_t *)((byte *)this + offset );
  40. }
  41. Vector m_vecScale;
  42. Vector m_vecBaseValue;
  43. unsigned int m_Offset[ 2 ]; // x (implied), y, z or pitch (implied), yaw, roll if EulerAngles
  44. };
  45. LayerSelectionData_t::DataLayer_t::DataLayer_t( float frac, CDmeLogLayer *layer ) :
  46. m_flStartFraction( frac )
  47. {
  48. m_hData = layer;
  49. }
  50. LayerSelectionData_t::LayerSelectionData_t() :
  51. m_DataType( AT_UNKNOWN )
  52. {
  53. m_nTimes[ 0 ] = DMETIME_ZERO;
  54. m_nTimes[ 1 ] = DMETIME_ZERO;
  55. m_nTimes[ 2 ] = DMETIME_ZERO;
  56. m_nTimes[ 3 ] = DMETIME_ZERO;
  57. }
  58. void LayerSelectionData_t::Release()
  59. {
  60. for ( int i = 0; i < m_vecData.Count(); ++i )
  61. {
  62. DataLayer_t *dl = &m_vecData[ i ];
  63. if ( dl->m_hData.Get() )
  64. {
  65. g_pDataModel->DestroyElement( dl->m_hData->GetHandle() );
  66. }
  67. }
  68. m_vecData.Purge();
  69. }
  70. //-----------------------------------------------------------------------------
  71. // Interpolatable types
  72. //-----------------------------------------------------------------------------
  73. inline bool IsInterpolableType( DmAttributeType_t type )
  74. {
  75. return ( type == AT_FLOAT ) ||
  76. ( type == AT_TIME ) ||
  77. ( type == AT_COLOR ) ||
  78. ( type == AT_VECTOR2 ) ||
  79. ( type == AT_VECTOR3 ) ||
  80. ( type == AT_QANGLE ) ||
  81. ( type == AT_QUATERNION );
  82. }
  83. float DmeLog_TimeSelection_t::AdjustFactorForInterpolatorType( float flFactor, int nSide ) const
  84. {
  85. return ComputeInterpolationFactor( flFactor, m_nFalloffInterpolatorTypes[ nSide ] );
  86. }
  87. //-----------------------------------------------------------------------------
  88. // NOTE: See TimeSelectionTimes_t for return values, -1 means before, TS_TIME_COUNT means after
  89. //-----------------------------------------------------------------------------
  90. static inline int ComputeRegionForTime( DmeTime_t t, TimeSelection_t regionTimes )
  91. {
  92. if ( t >= regionTimes[TS_LEFT_HOLD] )
  93. {
  94. if ( t <= regionTimes[TS_RIGHT_HOLD] )
  95. return 2;
  96. return ( t <= regionTimes[TS_RIGHT_FALLOFF] ) ? 3 : 4;
  97. }
  98. return ( t >= regionTimes[TS_LEFT_FALLOFF] ) ? 1 : 0;
  99. }
  100. //-----------------------------------------------------------------------------
  101. // NOTE: See TimeSelectionTimes_t for return values, -1 means before, TS_TIME_COUNT means after
  102. //-----------------------------------------------------------------------------
  103. int DmeLog_TimeSelection_t::ComputeRegionForTime( DmeTime_t curtime ) const
  104. {
  105. return ::ComputeRegionForTime( curtime, m_nTimes );
  106. }
  107. //-----------------------------------------------------------------------------
  108. // per-type averaging methods
  109. //-----------------------------------------------------------------------------
  110. float DmeLog_TimeSelection_t::GetAmountForTime( DmeTime_t dmetime ) const
  111. {
  112. return ::GetAmountForTime( dmetime, m_nTimes, m_nFalloffInterpolatorTypes );
  113. }
  114. // catch-all for non-interpolable types - just holds first value
  115. template < class T >
  116. T Average( const T *pValues, int nValues)
  117. {
  118. if ( IsInterpolableType( CDmAttributeInfo< T >::AttributeType() ) )
  119. {
  120. static bool first = true;
  121. if ( first )
  122. {
  123. first = false;
  124. Warning( "CDmeLog: interpolable type %s doesn't have an averaging function!", CDmAttributeInfo< T >::AttributeTypeName() );
  125. }
  126. }
  127. Assert( nValues > 0 );
  128. if ( nValues <= 0 )
  129. return T(); // uninitialized for most value classes!!!
  130. return pValues[ 0 ];
  131. }
  132. // float version
  133. template <>
  134. float Average( const float *pValues, int nValues )
  135. {
  136. Assert( nValues > 0 );
  137. if ( nValues <= 0 )
  138. return 0.0f;
  139. float sum = 0.0f;
  140. for ( int i = 0; i < nValues; ++i )
  141. {
  142. sum += pValues[ i ];
  143. }
  144. return sum / nValues;
  145. }
  146. // Color version
  147. template <>
  148. Color Average( const Color *pValues, int nValues )
  149. {
  150. Assert( nValues > 0 );
  151. if ( nValues <= 0 )
  152. return Color( 0, 0, 0, 0 );
  153. float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f;
  154. for ( int i = 0; i < nValues; ++i )
  155. {
  156. r += pValues[ i ].r();
  157. g += pValues[ i ].g();
  158. b += pValues[ i ].b();
  159. a += pValues[ i ].a();
  160. }
  161. float inv = nValues;
  162. return Color( r * inv, g * inv, b * inv, a * inv );
  163. }
  164. // Vector2 version
  165. template <>
  166. Vector2D Average( const Vector2D *pValues, int nValues )
  167. {
  168. Assert( nValues > 0 );
  169. if ( nValues <= 0 )
  170. return Vector2D( 0.0f, 0.0f );
  171. Vector2D sum( 0.0f, 0.0f );
  172. for ( int i = 0; i < nValues; ++i )
  173. {
  174. sum += pValues[ i ];
  175. }
  176. return sum / nValues;
  177. }
  178. // Vector3 version
  179. template <>
  180. Vector Average( const Vector *pValues, int nValues )
  181. {
  182. Assert( nValues > 0 );
  183. if ( nValues <= 0 )
  184. return Vector( 0.0f, 0.0f, 0.0f );
  185. Vector sum( 0.0f, 0.0f, 0.0f );
  186. for ( int i = 0; i < nValues; ++i )
  187. {
  188. sum += pValues[ i ];
  189. }
  190. return sum / nValues;
  191. }
  192. // QAngle version
  193. template <>
  194. QAngle Average( const QAngle *pValues, int nValues )
  195. {
  196. Assert( nValues > 0 );
  197. if ( nValues <= 0 )
  198. return QAngle( 0.0f, 0.0f, 0.0f );
  199. Quaternion ave;
  200. AngleQuaternion( pValues[ 0 ], ave );
  201. // this is calculating the average by slerping with decreasing weights
  202. // for example: ave = 1/3 * q2 + 2/3 ( 1/2 * q1 + 1/2 * q0 )
  203. for ( int i = 1; i < nValues; ++i )
  204. {
  205. Quaternion quat;
  206. AngleQuaternion( pValues[ i ], quat );
  207. QuaternionSlerp( ave, quat, 1 / float( i + 1 ), ave );
  208. }
  209. QAngle qangle;
  210. QuaternionAngles( ave, qangle );
  211. return qangle;
  212. }
  213. // Quaternion version
  214. template <>
  215. Quaternion Average( const Quaternion *pValues, int nValues )
  216. {
  217. Assert( nValues > 0 );
  218. if ( nValues <= 0 )
  219. return Quaternion( 0.0f, 0.0f, 0.0f, 1.0f );
  220. Quaternion ave = pValues[ 0 ];
  221. // this is calculating the average by slerping with decreasing weights
  222. // for example: ave = 1/3 * q2 + 2/3 ( 1/2 * q1 + 1/2 * q0 )
  223. for ( int i = 1; i < nValues; ++i )
  224. {
  225. QuaternionSlerp( ave, pValues[ i ], 1 / float( i + 1 ), ave );
  226. }
  227. return ave;
  228. }
  229. // DmeTime_t version
  230. template <>
  231. DmeTime_t Average( const DmeTime_t *pValues, int nValues )
  232. {
  233. Assert( nValues > 0 );
  234. if ( nValues <= 0 )
  235. return DMETIME_ZERO;
  236. double sum = pValues[ 0 ].GetTenthsOfMS();
  237. for ( int i = 1; i < nValues; ++i )
  238. {
  239. sum += pValues[ i ].GetTenthsOfMS();
  240. }
  241. return DmeTime_t( ( int )( sum / nValues ) );
  242. }
  243. //-----------------------------------------------------------------------------
  244. // per-type interpolation methods
  245. //-----------------------------------------------------------------------------
  246. // catch-all for non-interpolable types - just holds first value
  247. template < class T >
  248. T Interpolate( float t, const T& ti, const T& tj, LogComponents_t componentFlags = LOG_COMPONENTS_ALL )
  249. {
  250. if ( IsInterpolableType( CDmAttributeInfo< T >::AttributeType() ) )
  251. {
  252. static bool first = true;
  253. if ( first )
  254. {
  255. first = false;
  256. Warning( "CDmeLog: interpolable type %s doesn't have an interpolation function!", CDmAttributeInfo< T >::AttributeTypeName() );
  257. }
  258. }
  259. return ti;
  260. }
  261. // float version
  262. template <>
  263. float Interpolate( float t, const float& ti, const float& tj, LogComponents_t componentFlags )
  264. {
  265. return t * tj + (1.0f - t) * ti;
  266. }
  267. // Color version
  268. template <>
  269. Color Interpolate( float t, const Color& ti, const Color& tj, LogComponents_t componentFlags )
  270. {
  271. int ri, gi, bi, ai;
  272. int rj, gj, bj, aj;
  273. ti.GetColor( ri, gi, bi, ai );
  274. tj.GetColor( rj, gj, bj, aj );
  275. return Color( t * rj + (1.0f - t) * ri,
  276. t * gj + (1.0f - t) * gi,
  277. t * bj + (1.0f - t) * bi,
  278. t * aj + (1.0f - t) * ai);
  279. }
  280. // Vector2 version
  281. template <>
  282. Vector2D Interpolate( float t, const Vector2D& ti, const Vector2D& tj, LogComponents_t componentFlags )
  283. {
  284. return t * tj + (1.0f - t) * ti;
  285. }
  286. // Vector3 version
  287. template <>
  288. Vector Interpolate( float t, const Vector& ti, const Vector& tj, LogComponents_t componentFlags )
  289. {
  290. Vector result = t * tj + (1.0f - t) * ti;
  291. if ( ( componentFlags & LOG_COMPONENTS_ALL ) != LOG_COMPONENTS_ALL )
  292. {
  293. result.x = ( componentFlags & LOG_COMPONENTS_X ) ? result.x : ti.x;
  294. result.y = ( componentFlags & LOG_COMPONENTS_Y ) ? result.y : ti.y;
  295. result.z = ( componentFlags & LOG_COMPONENTS_Z ) ? result.z : ti.z;
  296. }
  297. return result;
  298. }
  299. // QAngle version
  300. template <>
  301. QAngle Interpolate( float t, const QAngle& ti, const QAngle& tj, LogComponents_t componentFlags )
  302. {
  303. QAngle qaResult;
  304. Quaternion q, qi, qj; // Some Quaternion temps for doing the slerp
  305. AngleQuaternion( ti, qi ); // Convert QAngles to Quaternions
  306. AngleQuaternion( tj, qj );
  307. QuaternionSlerp( qi, qj, t, q ); // Do a slerp as Quaternions
  308. QuaternionAngles( q, qaResult ); // Convert back to QAngles
  309. return qaResult;
  310. }
  311. // Quaternion version
  312. template <>
  313. Quaternion Interpolate( float t, const Quaternion& ti, const Quaternion& tj, LogComponents_t componentFlags )
  314. {
  315. static Quaternion s_value;
  316. QuaternionSlerp( ti, tj, t, s_value );
  317. QuaternionNormalize( s_value );
  318. return s_value;
  319. }
  320. // DmeTime_t version
  321. template <>
  322. DmeTime_t Interpolate( float t, const DmeTime_t& ti, const DmeTime_t& tj, LogComponents_t componentFlags )
  323. {
  324. double a = ti.GetTenthsOfMS();
  325. double b = tj.GetTenthsOfMS();
  326. return DmeTime_t( ( int )( t * b + (1.0f - t) * a ) );
  327. }
  328. // catch-all for non-interpolable types - just holds first value
  329. template < class T >
  330. T Curve_Interpolate( float t, DmeTime_t times[ 4 ], const T values[ 4 ], int curveTypes[ 4 ], float fmin, float fmax )
  331. {
  332. if ( IsInterpolableType( CDmAttributeInfo< T >::AttributeType() ) )
  333. {
  334. static bool first = true;
  335. if ( first )
  336. {
  337. first = false;
  338. Warning( "CDmeLog: interpolable type %s doesn't have an interpolation function!", CDmAttributeInfo< T >::AttributeTypeName() );
  339. }
  340. }
  341. return values[ 1 ];
  342. }
  343. // float version
  344. template <>
  345. float Curve_Interpolate( float t, DmeTime_t times[ 4 ], const float values[ 4 ], int curveTypes[ 4 ], float fmin, float fmax )
  346. {
  347. Vector args[ 4 ];
  348. for ( int i = 0; i < 4; ++i )
  349. {
  350. args[ i ].Init( times[ i ].GetSeconds(), values[ i ], 0.0f );
  351. }
  352. Vector vOut;
  353. int dummy;
  354. int earlypart, laterpart;
  355. // Not holding out value of previous curve...
  356. Interpolator_CurveInterpolatorsForType( curveTypes[ 1 ], dummy, earlypart );
  357. Interpolator_CurveInterpolatorsForType( curveTypes[ 2 ], laterpart, dummy );
  358. if ( earlypart == INTERPOLATE_HOLD )
  359. {
  360. // Hold "out" of previous sample (can cause a discontinuity)
  361. VectorLerp( args[ 1 ], args[ 2 ], t, vOut );
  362. vOut.y = args[ 1 ].y;
  363. }
  364. else if ( laterpart == INTERPOLATE_HOLD )
  365. {
  366. // Hold "out" of previous sample (can cause a discontinuity)
  367. VectorLerp( args[ 1 ], args[ 2 ], t, vOut );
  368. vOut.y = args[ 2 ].y;
  369. }
  370. else
  371. {
  372. bool sameCurveType = earlypart == laterpart ? true : false;
  373. if ( sameCurveType )
  374. {
  375. Interpolator_CurveInterpolate( laterpart, args[ 0 ], args[ 1 ], args[ 2 ], args[ 3 ], t, vOut );
  376. }
  377. else // curves differ, sigh
  378. {
  379. Vector vOut1, vOut2;
  380. Interpolator_CurveInterpolate( earlypart, args[ 0 ], args[ 1 ], args[ 2 ], args[ 3 ], t, vOut1 );
  381. Interpolator_CurveInterpolate( laterpart, args[ 0 ], args[ 1 ], args[ 2 ], args[ 3 ], t, vOut2 );
  382. VectorLerp( vOut1, vOut2, t, vOut );
  383. }
  384. }
  385. // FIXME: This means we can only work with curves that range from 0.0 to 1.0f!!!
  386. float retval = clamp( vOut.y, fmin, fmax );
  387. return retval;
  388. }
  389. // this is necessary to work around the weirdness of the interpolation schemes
  390. // they all ignore time, except for CR's NormalizeX, and that assumes that time is in the x component of the vector!
  391. void CurveInterpolateVectorHelper( float t, DmeTime_t times[ 4 ], const Vector values[ 4 ], int curveType, Vector &vOut )
  392. {
  393. if ( curveType != INTERPOLATE_CATMULL_ROM_NORMALIZEX )
  394. return Interpolator_CurveInterpolate_NonNormalized( curveType, values[ 0 ], values[ 1 ], values[ 2 ], values[ 3 ], t, vOut );
  395. Vector xArgs[ 4 ], yArgs[ 4 ], zArgs[ 4 ];
  396. for ( int i = 0; i < 4; ++i )
  397. {
  398. xArgs[ i ].Init( times[ i ].GetSeconds(), values[ i ].x, 0.0f );
  399. yArgs[ i ].Init( times[ i ].GetSeconds(), values[ i ].y, 0.0f );
  400. zArgs[ i ].Init( times[ i ].GetSeconds(), values[ i ].z, 0.0f );
  401. }
  402. Vector xOut, yOut, zOut;
  403. Interpolator_CurveInterpolate( curveType, xArgs[ 0 ], xArgs[ 1 ], xArgs[ 2 ], xArgs[ 3 ], t, xOut );
  404. Interpolator_CurveInterpolate( curveType, yArgs[ 0 ], yArgs[ 1 ], yArgs[ 2 ], yArgs[ 3 ], t, yOut );
  405. Interpolator_CurveInterpolate( curveType, zArgs[ 0 ], zArgs[ 1 ], zArgs[ 2 ], zArgs[ 3 ], t, zOut );
  406. vOut.Init( xOut.y, yOut.y, zOut.y ); // .y is intentional across all three inputs
  407. }
  408. // Vector version
  409. template <>
  410. Vector Curve_Interpolate( float t, DmeTime_t times[ 4 ], const Vector values[ 4 ], int curveTypes[ 4 ], float fmin, float fmax )
  411. {
  412. Vector vOut;
  413. int dummy;
  414. int earlypart, laterpart;
  415. // Not holding out value of previous curve...
  416. Interpolator_CurveInterpolatorsForType( curveTypes[ 1 ], dummy, earlypart );
  417. Interpolator_CurveInterpolatorsForType( curveTypes[ 2 ], laterpart, dummy );
  418. if ( earlypart == INTERPOLATE_HOLD )
  419. {
  420. // Hold "out" of previous sample (can cause a discontinuity)
  421. vOut = values[ 1 ];
  422. }
  423. else if ( laterpart == INTERPOLATE_HOLD )
  424. {
  425. // Hold "out" of previous sample (can cause a discontinuity)
  426. vOut = values[ 2 ];
  427. }
  428. else
  429. {
  430. bool sameCurveType = earlypart == laterpart;
  431. if ( sameCurveType )
  432. {
  433. CurveInterpolateVectorHelper( t, times, values, laterpart, vOut );
  434. }
  435. else // curves differ, sigh
  436. {
  437. Vector vOut1, vOut2;
  438. CurveInterpolateVectorHelper( t, times, values, earlypart, vOut1 );
  439. CurveInterpolateVectorHelper( t, times, values, laterpart, vOut2 );
  440. VectorLerp( vOut1, vOut2, t, vOut );
  441. }
  442. }
  443. return vOut;
  444. }
  445. // Quaternion version
  446. template <>
  447. Quaternion Curve_Interpolate( float t, DmeTime_t times[ 4 ], const Quaternion values[ 4 ], int curveTypes[ 4 ], float fmin, float fmax )
  448. {
  449. Quaternion vOut;
  450. int dummy;
  451. int earlypart, laterpart;
  452. // Not holding out value of previous curve...
  453. Interpolator_CurveInterpolatorsForType( curveTypes[ 1 ], dummy, earlypart );
  454. Interpolator_CurveInterpolatorsForType( curveTypes[ 2 ], laterpart, dummy );
  455. if ( earlypart == INTERPOLATE_HOLD )
  456. {
  457. // Hold "out" of previous sample (can cause a discontinuity)
  458. vOut = values[ 1 ];
  459. }
  460. else if ( laterpart == INTERPOLATE_HOLD )
  461. {
  462. // Hold "out" of previous sample (can cause a discontinuity)
  463. vOut = values[ 2 ];
  464. }
  465. else
  466. {
  467. bool sameCurveType = ( earlypart == laterpart ) ? true : false;
  468. if ( sameCurveType )
  469. {
  470. Interpolator_CurveInterpolate_NonNormalized( laterpart, values[ 0 ], values[ 1 ], values[ 2 ], values[ 3 ], t, vOut );
  471. }
  472. else // curves differ, sigh
  473. {
  474. Quaternion vOut1, vOut2;
  475. Interpolator_CurveInterpolate_NonNormalized( earlypart, values[ 0 ], values[ 1 ], values[ 2 ], values[ 3 ], t, vOut1 );
  476. Interpolator_CurveInterpolate_NonNormalized( laterpart, values[ 0 ], values[ 1 ], values[ 2 ], values[ 3 ], t, vOut2 );
  477. QuaternionSlerp( vOut1, vOut2, t, vOut );
  478. }
  479. }
  480. return vOut;
  481. }
  482. template< class T >
  483. T ScaleValue( const T& value, float scale )
  484. {
  485. return value * scale;
  486. }
  487. template<>
  488. bool ScaleValue( const bool& value, float scale )
  489. {
  490. Assert( 0 );
  491. return value;
  492. }
  493. template<>
  494. Color ScaleValue( const Color& value, float scale )
  495. {
  496. Assert( 0 );
  497. return value;
  498. }
  499. template<>
  500. Vector4D ScaleValue( const Vector4D& value, float scale )
  501. {
  502. return Vector4D( value.x * scale, value.y * scale, value.z * scale, value.w * scale );
  503. }
  504. template<>
  505. Quaternion ScaleValue( const Quaternion& value, float scale )
  506. {
  507. Quaternion q;
  508. QuaternionScale( value, scale, q );
  509. return q;
  510. }
  511. template<>
  512. VMatrix ScaleValue( const VMatrix& value, float scale )
  513. {
  514. Assert( 0 );
  515. return value;
  516. }
  517. template<>
  518. CUtlSymbolLarge ScaleValue( const CUtlSymbolLarge& value, float scale )
  519. {
  520. Assert( 0 );
  521. return value;
  522. }
  523. template<>
  524. DmeTime_t ScaleValue( const DmeTime_t& value, float scale )
  525. {
  526. return DmeTime_t( ( int )( value.GetTenthsOfMS() * scale ) );
  527. }
  528. template< class T >
  529. float LengthOf( const T& value )
  530. {
  531. Assert( 0 );
  532. return 0.0f;
  533. }
  534. template<>
  535. float LengthOf( const float& value )
  536. {
  537. return fabs( value );
  538. }
  539. template<>
  540. float LengthOf( const bool& value )
  541. {
  542. return value ? 1.0f : 0.0f;
  543. }
  544. template<>
  545. float LengthOf( const int& value )
  546. {
  547. return fabs( ( float ) value );
  548. }
  549. template<>
  550. float LengthOf( const Color& value )
  551. {
  552. return (float)sqrt( (float)( value.r() * value.r() +
  553. value.g() * value.g() +
  554. value.b() * value.b() +
  555. value.a() * value.a()) );
  556. }
  557. template<>
  558. float LengthOf( const Vector4D& value )
  559. {
  560. return sqrt( value.x * value.x +
  561. value.y * value.y +
  562. value.z * value.z +
  563. value.w * value.w );
  564. }
  565. template<>
  566. float LengthOf( const Quaternion& value )
  567. {
  568. return sqrt( value.x * value.x +
  569. value.y * value.y +
  570. value.z * value.z );
  571. }
  572. template<>
  573. float LengthOf( const VMatrix& value )
  574. {
  575. return 0.0f;
  576. }
  577. template<>
  578. float LengthOf( const CUtlSymbolLarge& value )
  579. {
  580. return 0.0f;
  581. }
  582. template<>
  583. float LengthOf( const Vector2D& value )
  584. {
  585. return value.Length();
  586. }
  587. template<>
  588. float LengthOf( const Vector& value )
  589. {
  590. return value.Length();
  591. }
  592. template<>
  593. float LengthOf( const QAngle& value )
  594. {
  595. return value.Length();
  596. }
  597. template<>
  598. float LengthOf( const DmeTime_t& value )
  599. {
  600. return value.GetSeconds();
  601. }
  602. template< class T >
  603. T Subtract( const T& v1, const T& v2 )
  604. {
  605. return v1 - v2;
  606. }
  607. template<>
  608. bool Subtract( const bool& v1, const bool& v2 )
  609. {
  610. return v1;
  611. }
  612. template<>
  613. CUtlSymbolLarge Subtract( const CUtlSymbolLarge& v1, const CUtlSymbolLarge& v2 )
  614. {
  615. return v1;
  616. }
  617. template<>
  618. Color Subtract( const Color& v1, const Color& v2 )
  619. {
  620. Color ret;
  621. for ( int i = 0; i < 4; ++i )
  622. {
  623. ret[ i ] = clamp( v1[ i ] - v2[ i ], 0, 255 );
  624. }
  625. return ret;
  626. }
  627. template<>
  628. Vector4D Subtract( const Vector4D& v1, const Vector4D& v2 )
  629. {
  630. Vector4D ret;
  631. for ( int i = 0; i < 4; ++i )
  632. {
  633. ret[ i ] = v1[ i ] - v2[ i ];
  634. }
  635. return ret;
  636. }
  637. template<>
  638. Quaternion Subtract( const Quaternion& v1, const Quaternion& v2 )
  639. {
  640. Quaternion ret;
  641. for ( int i = 0; i < 4; ++i )
  642. {
  643. ret[ i ] = v1[ i ];
  644. }
  645. return ret;
  646. }
  647. template< class T >
  648. T Add( const T& v1, const T& v2 )
  649. {
  650. return v1 + v2;
  651. }
  652. template<>
  653. bool Add( const bool& v1, const bool& v2 )
  654. {
  655. return v1;
  656. }
  657. template<>
  658. CUtlSymbolLarge Add( const CUtlSymbolLarge& v1, const CUtlSymbolLarge& v2 )
  659. {
  660. return v1;
  661. }
  662. template<>
  663. Color Add( const Color& v1, const Color& v2 )
  664. {
  665. Color ret;
  666. for ( int i = 0; i < 4; ++i )
  667. {
  668. ret[ i ] = clamp( v1[ i ] + v2[ i ], 0, 255 );
  669. }
  670. return ret;
  671. }
  672. template<>
  673. Vector4D Add( const Vector4D& v1, const Vector4D& v2 )
  674. {
  675. Vector4D ret;
  676. for ( int i = 0; i < 4; ++i )
  677. {
  678. ret[ i ] = v1[ i ] + v2[ i ];
  679. }
  680. return ret;
  681. }
  682. template<>
  683. Quaternion Add( const Quaternion& v1, const Quaternion& v2 )
  684. {
  685. Quaternion ret;
  686. QuaternionMult( v2, v1, ret );
  687. return ret;
  688. }
  689. template < class T >
  690. T Difference( const T &v1, const T &v2 )
  691. {
  692. return Subtract< T >( v1, v2 );
  693. }
  694. template <>
  695. Quaternion Difference( const Quaternion &v1, const Quaternion &v2 )
  696. {
  697. Quaternion inv;
  698. QuaternionInvert( v2, inv );
  699. Quaternion ret;
  700. QuaternionMult( v1, inv, ret );
  701. return ret;
  702. }
  703. template < class T >
  704. T TransformRelative( const matrix3x4_t &transformMatrix, const T &value )
  705. {
  706. return value;
  707. }
  708. template <>
  709. Vector TransformRelative( const matrix3x4_t &transformMatrix, const Vector &value )
  710. {
  711. Vector result;
  712. VectorRotate( value, transformMatrix, result );
  713. return result;
  714. }
  715. template <>
  716. Quaternion TransformRelative( const matrix3x4_t &transformMatrix, const Quaternion &rotation )
  717. {
  718. Quaternion result;
  719. Vector newAxis;
  720. Vector axis( rotation.x, rotation.y, rotation.z );
  721. float sa = VectorNormalize( axis );
  722. VectorRotate( axis, transformMatrix, newAxis );
  723. result.x = newAxis.x * sa;
  724. result.y = newAxis.y * sa;
  725. result.z = newAxis.z * sa;
  726. result.w = rotation.w;
  727. return result;
  728. }
  729. template <>
  730. matrix3x4_t TransformRelative( const matrix3x4_t &transformMatrix, const matrix3x4_t &value )
  731. {
  732. // result = transform * value * transform-1
  733. matrix3x4_t transformInv, temp, result;
  734. MatrixInvert( transformMatrix, transformInv );
  735. ConcatTransforms( value, transformInv, temp );
  736. ConcatTransforms( transformMatrix, temp, result );
  737. return result;
  738. }
  739. template < class T >
  740. T TransformAbsolute( const matrix3x4_t &transformMatrix, const T &value )
  741. {
  742. return value;
  743. }
  744. template <>
  745. Vector TransformAbsolute( const matrix3x4_t &transformMatrix, const Vector &value )
  746. {
  747. Vector result;
  748. VectorTransform( value, transformMatrix, result );
  749. return result;
  750. }
  751. template <>
  752. Quaternion TransformAbsolute( const matrix3x4_t &transformMatrix, const Quaternion &rotation )
  753. {
  754. Quaternion quat, result;
  755. MatrixQuaternion( transformMatrix, quat );
  756. QuaternionMult( quat, rotation, result );
  757. return result;
  758. }
  759. template <>
  760. matrix3x4_t TransformAbsolute( const matrix3x4_t &transformMatrix, const matrix3x4_t &value )
  761. {
  762. matrix3x4_t result;
  763. ConcatTransforms( transformMatrix, value, result );
  764. return result;
  765. }
  766. //-----------------------------------------------------------------------------
  767. // Purpose: Generic type rotation function, provides stub for types to which
  768. // rotation does not apply, simply returns the original value.
  769. //-----------------------------------------------------------------------------
  770. template < class T >
  771. T Rotate( const Quaternion &rotation, const Vector &pivot, const T &value, const Quaternion &curRotation, bool local = true );
  772. template < class T >
  773. T Rotate( const Quaternion &rotation, const Vector &pivot, const T &value, const Quaternion &curRotation, bool local )
  774. {
  775. return value;
  776. }
  777. //-----------------------------------------------------------------------------
  778. // Purpose: Rotate a position value around the specified pivot in the current
  779. // local space. The local space is constructed from the provided current
  780. // position and rotation.
  781. //-----------------------------------------------------------------------------
  782. template <>
  783. Vector Rotate( const Quaternion &rotation, const Vector &pivot, const Vector &value, const Quaternion &currentRotation, bool local )
  784. {
  785. Quaternion deltaRotation = rotation;
  786. // Construct a matrix with the current rotation
  787. matrix3x4_t currentTransform;
  788. QuaternionMatrix( currentRotation, value, currentTransform );
  789. // Convert the parent space rotation into local space
  790. if ( !local )
  791. {
  792. matrix3x4_t invTransform;
  793. MatrixInvert( currentTransform, invTransform );
  794. deltaRotation = TransformRelative( invTransform, rotation );
  795. }
  796. // Construct the transform matrix for the delta rotation
  797. matrix3x4_t xform;
  798. AngleMatrix( RadianEuler( deltaRotation ), xform );
  799. // Apply the pivot offset to the rotation matrix
  800. matrix3x4_t temp = xform;
  801. temp[0][3] += pivot.x;
  802. temp[1][3] += pivot.y;
  803. temp[2][3] += pivot.z;
  804. matrix3x4_t pivotOffset;
  805. SetIdentityMatrix( pivotOffset );
  806. PositionMatrix( -pivot, pivotOffset );
  807. ConcatTransforms( temp, pivotOffset, xform );
  808. // Construct the current transform matrix and apply the rotation transform to it to.
  809. ConcatTransforms( currentTransform, xform, xform );
  810. Vector ret;
  811. MatrixPosition( xform, ret );
  812. return ret;
  813. }
  814. //-----------------------------------------------------------------------------
  815. // Purpose: Apply a relative rotation to the input quaternion rotation value
  816. //-----------------------------------------------------------------------------
  817. template <>
  818. Quaternion Rotate( const Quaternion &rotation, const Vector &pivot, const Quaternion &value, const Quaternion &curRotation, bool local )
  819. {
  820. Quaternion ret;
  821. if ( local )
  822. {
  823. QuaternionMult( value, rotation, ret );
  824. }
  825. else
  826. {
  827. QuaternionMult( rotation, value, ret );
  828. }
  829. return ret;
  830. }
  831. //-----------------------------------------------------------------------------
  832. // Purpose: Scale the provided quaternion by its rotation around an axis in
  833. // such a way that the direction of the rotation is maintained. For example, a
  834. // quaternion with rotation of 270 degrees around an axis scaled by 0.5 will
  835. // have a 135 degree rotation around the same axis, instead of 315 degree
  836. // rotation that the standard QuaternionScale() function would return.
  837. //-----------------------------------------------------------------------------
  838. void ScaleRotationQuaternion( const Quaternion &p, float scale, Quaternion &q )
  839. {
  840. // Construct the axis from the input quaternion
  841. Vector axis;
  842. axis.x = p.x;
  843. axis.y = p.y;
  844. axis.z = p.z;
  845. VectorNormalize( axis );
  846. // Calculate the angle of rotation, note that the QuaternionAxisAngle() function is
  847. // not used because it will force the angle to be between -180 and 180, losing the
  848. // complete rotation information this function is specifically trying to maintain.
  849. float angle;
  850. angle = RAD2DEG( 2 * acos( p.w ) );
  851. // Scale the angle by the specified amount and construct the new quaternion
  852. // with the same axis as the original but with the new scaled rotation angle.
  853. angle = angle * scale;
  854. AxisAngleQuaternion( axis, angle, q );
  855. }
  856. IMPLEMENT_ABSTRACT_ELEMENT( DmeLogLayer, CDmeLogLayer );
  857. IMPLEMENT_ELEMENT_FACTORY( DmeIntLogLayer, CDmeIntLogLayer );
  858. IMPLEMENT_ELEMENT_FACTORY( DmeFloatLogLayer, CDmeFloatLogLayer );
  859. IMPLEMENT_ELEMENT_FACTORY( DmeBoolLogLayer, CDmeBoolLogLayer );
  860. IMPLEMENT_ELEMENT_FACTORY( DmeColorLogLayer, CDmeColorLogLayer );
  861. IMPLEMENT_ELEMENT_FACTORY( DmeVector2LogLayer, CDmeVector2LogLayer );
  862. IMPLEMENT_ELEMENT_FACTORY( DmeVector3LogLayer, CDmeVector3LogLayer );
  863. IMPLEMENT_ELEMENT_FACTORY( DmeVector4LogLayer, CDmeVector4LogLayer );
  864. IMPLEMENT_ELEMENT_FACTORY( DmeQAngleLogLayer, CDmeQAngleLogLayer );
  865. IMPLEMENT_ELEMENT_FACTORY( DmeQuaternionLogLayer, CDmeQuaternionLogLayer );
  866. IMPLEMENT_ELEMENT_FACTORY( DmeVMatrixLogLayer, CDmeVMatrixLogLayer );
  867. IMPLEMENT_ELEMENT_FACTORY( DmeStringLogLayer, CDmeStringLogLayer );
  868. IMPLEMENT_ELEMENT_FACTORY( DmeTimeLogLayer, CDmeTimeLogLayer );
  869. //-----------------------------------------------------------------------------
  870. // explicit template instantiation
  871. //-----------------------------------------------------------------------------
  872. template class CDmeTypedLogLayer<int>;
  873. template class CDmeTypedLogLayer<float>;
  874. template class CDmeTypedLogLayer<bool>;
  875. template class CDmeTypedLogLayer<Color>;
  876. template class CDmeTypedLogLayer<Vector2D>;
  877. template class CDmeTypedLogLayer<Vector>;
  878. template class CDmeTypedLogLayer<Vector4D>;
  879. template class CDmeTypedLogLayer<QAngle>;
  880. template class CDmeTypedLogLayer<Quaternion>;
  881. template class CDmeTypedLogLayer<VMatrix>;
  882. template class CDmeTypedLogLayer<CUtlSymbolLarge>;
  883. template class CDmeTypedLogLayer<DmeTime_t>;
  884. IMPLEMENT_ABSTRACT_ELEMENT( DmeCurveInfo, CDmeCurveInfo );
  885. IMPLEMENT_ELEMENT_FACTORY( DmeIntCurveInfo, CDmeIntCurveInfo );
  886. IMPLEMENT_ELEMENT_FACTORY( DmeFloatCurveInfo, CDmeFloatCurveInfo );
  887. IMPLEMENT_ELEMENT_FACTORY( DmeBoolCurveInfo, CDmeBoolCurveInfo );
  888. IMPLEMENT_ELEMENT_FACTORY( DmeColorCurveInfo, CDmeColorCurveInfo );
  889. IMPLEMENT_ELEMENT_FACTORY( DmeVector2CurveInfo, CDmeVector2CurveInfo );
  890. IMPLEMENT_ELEMENT_FACTORY( DmeVector3CurveInfo, CDmeVector3CurveInfo );
  891. IMPLEMENT_ELEMENT_FACTORY( DmeVector4CurveInfo, CDmeVector4CurveInfo );
  892. IMPLEMENT_ELEMENT_FACTORY( DmeQAngleCurveInfo, CDmeQAngleCurveInfo );
  893. IMPLEMENT_ELEMENT_FACTORY( DmeQuaternionCurveInfo, CDmeQuaternionCurveInfo );
  894. IMPLEMENT_ELEMENT_FACTORY( DmeVMatrixCurveInfo, CDmeVMatrixCurveInfo );
  895. IMPLEMENT_ELEMENT_FACTORY( DmeStringCurveInfo, CDmeStringCurveInfo );
  896. IMPLEMENT_ELEMENT_FACTORY( DmeTimeCurveInfo, CDmeTimeCurveInfo );
  897. //-----------------------------------------------------------------------------
  898. // explicit template instantiation
  899. //-----------------------------------------------------------------------------
  900. template class CDmeTypedCurveInfo<int>;
  901. template class CDmeTypedCurveInfo<float>;
  902. template class CDmeTypedCurveInfo<bool>;
  903. template class CDmeTypedCurveInfo<Color>;
  904. template class CDmeTypedCurveInfo<Vector2D>;
  905. template class CDmeTypedCurveInfo<Vector>;
  906. template class CDmeTypedCurveInfo<Vector4D>;
  907. template class CDmeTypedCurveInfo<QAngle>;
  908. template class CDmeTypedCurveInfo<Quaternion>;
  909. template class CDmeTypedCurveInfo<VMatrix>;
  910. template class CDmeTypedCurveInfo<CUtlSymbolLarge>;
  911. template class CDmeTypedCurveInfo<DmeTime_t>;
  912. //-----------------------------------------------------------------------------
  913. // Class factory
  914. //-----------------------------------------------------------------------------
  915. IMPLEMENT_ABSTRACT_ELEMENT( DmeLog, CDmeLog );
  916. IMPLEMENT_ELEMENT_FACTORY( DmeIntLog, CDmeIntLog );
  917. IMPLEMENT_ELEMENT_FACTORY( DmeFloatLog, CDmeFloatLog );
  918. IMPLEMENT_ELEMENT_FACTORY( DmeBoolLog, CDmeBoolLog );
  919. IMPLEMENT_ELEMENT_FACTORY( DmeColorLog, CDmeColorLog );
  920. IMPLEMENT_ELEMENT_FACTORY( DmeVector2Log, CDmeVector2Log );
  921. IMPLEMENT_ELEMENT_FACTORY( DmeVector3Log, CDmeVector3Log );
  922. IMPLEMENT_ELEMENT_FACTORY( DmeVector4Log, CDmeVector4Log );
  923. IMPLEMENT_ELEMENT_FACTORY( DmeQAngleLog, CDmeQAngleLog );
  924. IMPLEMENT_ELEMENT_FACTORY( DmeQuaternionLog, CDmeQuaternionLog );
  925. IMPLEMENT_ELEMENT_FACTORY( DmeVMatrixLog, CDmeVMatrixLog );
  926. IMPLEMENT_ELEMENT_FACTORY( DmeStringLog, CDmeStringLog );
  927. IMPLEMENT_ELEMENT_FACTORY( DmeTimeLog, CDmeTimeLog );
  928. //-----------------------------------------------------------------------------
  929. // explicit template instantiation
  930. //-----------------------------------------------------------------------------
  931. template class CDmeTypedLog<int>;
  932. template class CDmeTypedLog<float>;
  933. template class CDmeTypedLog<bool>;
  934. template class CDmeTypedLog<Color>;
  935. template class CDmeTypedLog<Vector2D>;
  936. template class CDmeTypedLog<Vector>;
  937. template class CDmeTypedLog<Vector4D>;
  938. template class CDmeTypedLog<QAngle>;
  939. template class CDmeTypedLog<Quaternion>;
  940. template class CDmeTypedLog<VMatrix>;
  941. template class CDmeTypedLog<CUtlSymbolLarge>;
  942. template class CDmeTypedLog<DmeTime_t>;
  943. //-----------------------------------------------------------------------------
  944. // instantiate and initialize static vars
  945. //-----------------------------------------------------------------------------
  946. float CDmeIntLog::s_threshold = 0.0f;
  947. float CDmeFloatLog::s_threshold = 0.0f;
  948. float CDmeBoolLog::s_threshold = 0.0f;
  949. float CDmeColorLog::s_threshold = 0.0f;
  950. float CDmeVector2Log::s_threshold = 0.0f;
  951. float CDmeVector3Log::s_threshold = 0.01f; // 0.01"
  952. float CDmeVector4Log::s_threshold = 0.0f;
  953. float CDmeQAngleLog::s_threshold = 0.001f;
  954. float CDmeQuaternionLog::s_threshold = 0.001f; // 0.001 degrees, which for a 10-joint deep skeleton w/ 1' bones, translates to 0.01"
  955. float CDmeVMatrixLog::s_threshold = 0.0f;
  956. float CDmeStringLog::s_threshold = 0.0f;
  957. float CDmeTimeLog::s_threshold = 0.0f;
  958. template< class T >
  959. class CLogTimeIterator
  960. {
  961. public:
  962. CLogTimeIterator( CDmeTypedLogLayer< T > *pLayer, bool bReverse = false );
  963. // Ways to add keys
  964. void AddInterval( DmeTime_t tStart, DmeTime_t tEnd, DmeTime_t tSampleInterval );
  965. void AddLayer( CDmeTypedLogLayer< T > *pLayer, DmeTime_t tStartingOffset );
  966. void AddLayer();
  967. void AddKeyTime( DmeTime_t t );
  968. int InvalidIndex() const;
  969. int First() const; // returns false if no samples in interval
  970. int Next( int idx ) const; // returns false after last sample
  971. DmeTime_t GetKeyTime( int idx ) const;
  972. void GetValue( int idx, T &val ) const;
  973. private:
  974. bool m_bReverse;
  975. // For layer values
  976. CDmeTypedLogLayer< T > *m_pLayer;
  977. // For combination, we build out a full list on Init
  978. CUtlRBTree< DmeTime_t > m_rbKeyTimes;
  979. };
  980. template< class T >
  981. CLogTimeIterator< T >::CLogTimeIterator( CDmeTypedLogLayer< T > *pLayer, bool bReverse /*=false*/ ) :
  982. m_bReverse( bReverse ),
  983. m_pLayer( pLayer ),
  984. m_rbKeyTimes( 0, 0, DefLessFunc( DmeTime_t ) )
  985. {
  986. }
  987. template< class T >
  988. void CLogTimeIterator< T >::AddKeyTime( DmeTime_t t )
  989. {
  990. int idx = m_rbKeyTimes.Find( t );
  991. if ( idx != m_rbKeyTimes.InvalidIndex() )
  992. return;
  993. m_rbKeyTimes.Insert( t );
  994. }
  995. template< class T >
  996. void CLogTimeIterator< T >::AddInterval( DmeTime_t tStart, DmeTime_t tEnd, DmeTime_t tSampleInterval )
  997. {
  998. if ( m_bReverse )
  999. {
  1000. swap( tStart, tEnd );
  1001. tSampleInterval = -tSampleInterval;
  1002. }
  1003. for ( DmeTime_t t = tStart; t < tEnd + tSampleInterval; t += tSampleInterval )
  1004. {
  1005. AddKeyTime( t );
  1006. }
  1007. }
  1008. template< class T >
  1009. void CLogTimeIterator< T >::AddLayer()
  1010. {
  1011. // Add m_pLayer
  1012. AddLayer( m_pLayer, DMETIME_ZERO );
  1013. }
  1014. template< class T >
  1015. void CLogTimeIterator< T >::AddLayer( CDmeTypedLogLayer< T > *pLayer, DmeTime_t tStartingOffset )
  1016. {
  1017. for ( int i = 0 ; i < pLayer->GetKeyCount(); ++i )
  1018. {
  1019. DmeTime_t tKeyTime = pLayer->GetKeyTime( i );
  1020. tKeyTime -= tStartingOffset;
  1021. AddKeyTime( tKeyTime );
  1022. }
  1023. }
  1024. template< class T >
  1025. DmeTime_t CLogTimeIterator< T >::GetKeyTime( int idx ) const
  1026. {
  1027. // Don't check idx in release since we want this to be fast as possible
  1028. Assert( m_rbKeyTimes.IsValidIndex( idx ) );
  1029. return m_rbKeyTimes[ idx ];
  1030. }
  1031. template< class T >
  1032. void CLogTimeIterator< T >::GetValue( int idx, T &val ) const
  1033. {
  1034. // Don't check idx in release since we want this to be fast as possible
  1035. Assert( m_rbKeyTimes.IsValidIndex( idx ) );
  1036. DmeTime_t tValue = m_rbKeyTimes[ idx ];
  1037. val = m_pLayer->GetValue( tValue );
  1038. }
  1039. template< class T >
  1040. int CLogTimeIterator< T >::InvalidIndex() const
  1041. {
  1042. return m_rbKeyTimes.InvalidIndex();
  1043. }
  1044. // returns false if no samples in interval
  1045. template< class T >
  1046. int CLogTimeIterator< T >::First() const
  1047. {
  1048. if ( m_rbKeyTimes.Count() <= 0 )
  1049. return m_rbKeyTimes.InvalidIndex();
  1050. return m_bReverse ? m_rbKeyTimes.LastInorder() : m_rbKeyTimes.FirstInorder();
  1051. }
  1052. // returns false after last sample
  1053. template< class T >
  1054. int CLogTimeIterator< T >::Next( int idx ) const
  1055. {
  1056. if ( m_bReverse )
  1057. {
  1058. return m_rbKeyTimes.PrevInorder( idx );
  1059. }
  1060. return m_rbKeyTimes.NextInorder( idx );
  1061. }
  1062. static DmeTime_t RemapTime( DmeTime_t tKeyTime, const TimeSelection_t &tSrcTimes, const TimeSelection_t &tDstTimes )
  1063. {
  1064. int nSrcTSI = 1;
  1065. if ( tKeyTime < tSrcTimes[ TS_LEFT_HOLD ] )
  1066. {
  1067. if ( tKeyTime < tSrcTimes[ TS_LEFT_FALLOFF ] )
  1068. {
  1069. DmeTime_t lDelta = tSrcTimes[ TS_LEFT_FALLOFF ] - tKeyTime;
  1070. tKeyTime = tDstTimes[ TS_LEFT_FALLOFF ] - lDelta;
  1071. return tKeyTime;
  1072. }
  1073. nSrcTSI = 0;
  1074. }
  1075. else if ( tKeyTime > tSrcTimes[ TS_RIGHT_HOLD ] )
  1076. {
  1077. if ( tKeyTime > tSrcTimes[ TS_RIGHT_FALLOFF ] )
  1078. {
  1079. DmeTime_t rDelta = tKeyTime - tSrcTimes[ TS_RIGHT_FALLOFF ];
  1080. tKeyTime = tDstTimes[ TS_RIGHT_FALLOFF ] + rDelta;
  1081. return tKeyTime;
  1082. }
  1083. nSrcTSI = 2;
  1084. }
  1085. int nDstTSI = nSrcTSI;
  1086. bool bHold = nSrcTSI == 1;
  1087. DmeTime_t tSrcDuration = tSrcTimes[ nSrcTSI + 1 ] - tSrcTimes[ nSrcTSI ];
  1088. DmeTime_t tDstDuration = tDstTimes[ nDstTSI + 1 ] - tDstTimes[ nDstTSI ];
  1089. if ( !bHold && tDstDuration == DMETIME_ZERO )
  1090. return tDstTimes[ nDstTSI ];
  1091. DmeTime_t tDstTime;
  1092. if ( tKeyTime == tSrcTimes[ TS_LEFT_HOLD ] )
  1093. {
  1094. tDstTime = tDstTimes[ TS_LEFT_HOLD ];
  1095. }
  1096. else if ( tKeyTime == tSrcTimes[ TS_RIGHT_HOLD ] )
  1097. {
  1098. tDstTime = tDstTimes[ TS_RIGHT_HOLD ];
  1099. }
  1100. else
  1101. {
  1102. float flRatio = MIN( 1.0f, ( tKeyTime - tSrcTimes[ nSrcTSI ] ).GetSeconds() / tSrcDuration.GetSeconds() );
  1103. tDstTime = tDstTimes[ nDstTSI ] + flRatio * tDstDuration;
  1104. }
  1105. return tDstTime;
  1106. }
  1107. void CDmeLogLayer::OnConstruction()
  1108. {
  1109. m_pOwnerLog = NULL;
  1110. m_lastKey = 0;
  1111. m_bLeftInfinite = false;
  1112. m_bRightInfinite = false;
  1113. m_times.Init( this, "times" );
  1114. m_CurveTypes.Init( this, "curvetypes" );
  1115. m_NonInterpolatedSegments.Init( this, "noninterpolatedsegments" );
  1116. }
  1117. void CDmeLogLayer::OnDestruction()
  1118. {
  1119. }
  1120. CDmeLog *CDmeLogLayer::GetOwnerLog()
  1121. {
  1122. return m_pOwnerLog;
  1123. }
  1124. const CDmeLog *CDmeLogLayer::GetOwnerLog() const
  1125. {
  1126. return m_pOwnerLog;
  1127. }
  1128. DmeTime_t CDmeLogLayer::GetBeginTime( bool bAllowInfinite ) const
  1129. {
  1130. if ( bAllowInfinite && m_bLeftInfinite )
  1131. return DmeTime_t::MinTime();
  1132. if ( m_times.Count() == 0 )
  1133. return DmeTime_t::InvalidTime();
  1134. return m_times[ 0 ];
  1135. }
  1136. DmeTime_t CDmeLogLayer::GetEndTime( bool bAllowInfinite ) const
  1137. {
  1138. if ( bAllowInfinite && m_bRightInfinite )
  1139. return DmeTime_t::MaxTime();
  1140. uint tn = m_times.Count();
  1141. if ( tn == 0 )
  1142. return DmeTime_t::InvalidTime();
  1143. return m_times[ tn - 1 ];
  1144. }
  1145. // Validates that all keys are correctly sorted in time
  1146. bool CDmeLogLayer::ValidateKeys() const
  1147. {
  1148. int nCount = m_times.Count();
  1149. for ( int i = 1; i < nCount; ++i )
  1150. {
  1151. if ( m_times[i] < m_times[i-1] )
  1152. {
  1153. Warning( "Error in log %s! Key times are out of order [keys %d->%d: %d->%d]!\n",
  1154. GetName(), i-1, i, m_times[i-1].GetTenthsOfMS(), m_times[i].GetTenthsOfMS() );
  1155. return false;
  1156. }
  1157. }
  1158. return true;
  1159. }
  1160. int CDmeLogLayer::FindKey( DmeTime_t time ) const
  1161. {
  1162. int tn = m_times.Count();
  1163. if ( m_lastKey >= 0 && m_lastKey < tn )
  1164. {
  1165. if ( time >= m_times[ m_lastKey ] )
  1166. {
  1167. // common case - playing forward
  1168. for ( ; m_lastKey < tn - 1; ++m_lastKey )
  1169. {
  1170. if ( time < m_times[ m_lastKey + 1 ] )
  1171. return m_lastKey;
  1172. }
  1173. // if time past the end, return the last key
  1174. return m_lastKey;
  1175. }
  1176. else
  1177. {
  1178. tn = m_lastKey;
  1179. }
  1180. }
  1181. for ( int ti = tn - 1; ti >= 0; --ti )
  1182. {
  1183. if ( time >= m_times[ ti ] )
  1184. {
  1185. m_lastKey = ti;
  1186. return ti;
  1187. }
  1188. }
  1189. return -1;
  1190. }
  1191. void CDmeLogLayer::ScaleSampleTimes( float scale )
  1192. {
  1193. int nCount = m_times.Count();
  1194. for ( int i = 0; i < nCount; ++i )
  1195. {
  1196. DmeTime_t t = m_times.Get( i ) * scale;
  1197. if ( i > 0 && t <= m_times.Get( i - 1 ) )
  1198. {
  1199. t = m_times.Get( i - 1 ) + DMETIME_MINDELTA;
  1200. }
  1201. m_times.Set( i, t );
  1202. }
  1203. }
  1204. //-----------------------------------------------------------------------------
  1205. // Returns the number of keys
  1206. //-----------------------------------------------------------------------------
  1207. int CDmeLogLayer::GetKeyCount() const
  1208. {
  1209. return m_times.Count();
  1210. }
  1211. //-----------------------------------------------------------------------------
  1212. // Purpose:
  1213. // Input : nKeyIndex -
  1214. // keyTime -
  1215. //-----------------------------------------------------------------------------
  1216. void CDmeLogLayer::SetKeyTime( int nKeyIndex, DmeTime_t keyTime )
  1217. {
  1218. m_times.Set( nKeyIndex, keyTime );
  1219. }
  1220. //-----------------------------------------------------------------------------
  1221. // Returns a specific key's value
  1222. //-----------------------------------------------------------------------------
  1223. DmeTime_t CDmeLogLayer::GetKeyTime( int nKeyIndex ) const
  1224. {
  1225. return m_times[ nKeyIndex ];
  1226. }
  1227. //-----------------------------------------------------------------------------
  1228. // Scale + bias key times
  1229. //-----------------------------------------------------------------------------
  1230. void CDmeLogLayer::ScaleBiasKeyTimes( double flScale, DmeTime_t nBias )
  1231. {
  1232. // Don't waste time on the identity transform
  1233. if ( ( nBias == DMETIME_ZERO ) && ( fabs( flScale - 1.0 ) < 1e-5 ) )
  1234. return;
  1235. int nCount = GetKeyCount();
  1236. for ( int i = 0; i < nCount; ++i )
  1237. {
  1238. DmeTime_t t = GetKeyTime( i );
  1239. t.SetSeconds( t.GetSeconds() * flScale );
  1240. t += nBias;
  1241. SetKeyTime( i, t );
  1242. }
  1243. }
  1244. //-----------------------------------------------------------------------------
  1245. // Scale the keys within the source time selection to fill the destination time
  1246. // selection, keys outside the time selection will be shifted
  1247. //-----------------------------------------------------------------------------
  1248. void CDmeLogLayer::RescaleSamplesInTimeSelection( const TimeSelection_t &srcTimeSelection, const TimeSelection_t & dstTimeSelection )
  1249. {
  1250. DmeTime_t srcLeftFalloff = srcTimeSelection[ TS_LEFT_FALLOFF ];
  1251. DmeTime_t srcLeftHold = srcTimeSelection[ TS_LEFT_HOLD ];
  1252. DmeTime_t srcRightHold = srcTimeSelection[ TS_RIGHT_HOLD ];
  1253. DmeTime_t srcRightFalloff = srcTimeSelection[ TS_RIGHT_FALLOFF ];
  1254. DmeTime_t dstLeftFalloff = dstTimeSelection[ TS_LEFT_FALLOFF ];
  1255. DmeTime_t dstLeftHold = dstTimeSelection[ TS_LEFT_HOLD ];
  1256. DmeTime_t dstRightHold = dstTimeSelection[ TS_RIGHT_HOLD ];
  1257. DmeTime_t dstRightFalloff = dstTimeSelection[ TS_RIGHT_FALLOFF ];
  1258. DmeTime_t preOffset = dstLeftFalloff - srcLeftFalloff;
  1259. DmeTime_t postOffset = dstRightFalloff - srcRightFalloff;
  1260. DmeTime_t leftDuration = dstLeftHold - dstLeftFalloff;
  1261. DmeTime_t holdDuration = dstRightHold - dstLeftHold;
  1262. DmeTime_t rightDuration = dstRightFalloff - dstRightHold;
  1263. int nNumKeys = GetKeyCount();
  1264. CUtlVector < DmeTime_t > newKeyTimes;
  1265. newKeyTimes.SetCount( nNumKeys );
  1266. for ( int iKey = 0; iKey < nNumKeys; ++iKey )
  1267. {
  1268. DmeTime_t keyTime = m_times[ iKey ];
  1269. if ( keyTime < srcLeftFalloff )
  1270. {
  1271. newKeyTimes[ iKey ] = keyTime + preOffset;
  1272. }
  1273. else if ( keyTime < srcLeftHold )
  1274. {
  1275. float flParam = GetFractionOfTimeBetween( keyTime, srcLeftFalloff, srcLeftHold );
  1276. newKeyTimes[ iKey ] = dstLeftFalloff + ( flParam * leftDuration );
  1277. }
  1278. else if ( keyTime < srcRightHold )
  1279. {
  1280. float flParam = GetFractionOfTimeBetween( keyTime, srcLeftHold, srcRightHold );
  1281. newKeyTimes[ iKey ] = dstLeftHold + ( flParam * holdDuration );
  1282. }
  1283. else if ( keyTime < srcRightFalloff )
  1284. {
  1285. float flParam = GetFractionOfTimeBetween( keyTime, srcRightHold, srcRightFalloff );
  1286. newKeyTimes[ iKey ] = dstRightHold + ( flParam * rightDuration );
  1287. }
  1288. else
  1289. {
  1290. newKeyTimes[ iKey] = keyTime + postOffset;
  1291. }
  1292. }
  1293. m_times = newKeyTimes;
  1294. }
  1295. //-----------------------------------------------------------------------------
  1296. // Returns the index of a particular key
  1297. //-----------------------------------------------------------------------------
  1298. int CDmeLogLayer::FindKeyWithinTolerance( DmeTime_t nTime, DmeTime_t nTolerance )
  1299. {
  1300. int nClosest = -1;
  1301. DmeTime_t nClosestTolerance = DmeTime_t::MaxTime();
  1302. DmeTime_t nCurrTolerance;
  1303. int start = 0, end = GetKeyCount() - 1;
  1304. while ( start <= end )
  1305. {
  1306. int mid = (start + end) >> 1;
  1307. DmeTime_t nDelta = nTime - m_times[mid];
  1308. if ( nDelta > DmeTime_t( 0 ) )
  1309. {
  1310. nCurrTolerance = nDelta;
  1311. start = mid + 1;
  1312. }
  1313. else if ( nDelta < DmeTime_t( 0 ) )
  1314. {
  1315. nCurrTolerance = -nDelta;
  1316. end = mid - 1;
  1317. }
  1318. else
  1319. {
  1320. return mid;
  1321. }
  1322. if ( nCurrTolerance < nClosestTolerance )
  1323. {
  1324. nClosest = mid;
  1325. nClosestTolerance = nCurrTolerance;
  1326. }
  1327. }
  1328. if ( nClosestTolerance > nTolerance )
  1329. return -1;
  1330. return nClosest;
  1331. }
  1332. void CDmeLogLayer::OnUsingCurveTypesChanged()
  1333. {
  1334. if ( g_pDataModel->IsUnserializing() )
  1335. return;
  1336. if ( !IsUsingCurveTypes() )
  1337. {
  1338. m_CurveTypes.RemoveAll();
  1339. }
  1340. else
  1341. {
  1342. m_CurveTypes.RemoveAll();
  1343. // Fill in an array with the default curve type for
  1344. int c = m_times.Count();
  1345. for ( int i = 0; i < c; ++i )
  1346. {
  1347. m_CurveTypes.AddToTail( GetDefaultCurveType() );
  1348. }
  1349. }
  1350. }
  1351. bool CDmeLogLayer::IsUsingCurveTypes() const
  1352. {
  1353. return GetOwnerLog() ? GetOwnerLog()->IsUsingCurveTypes() : false;
  1354. }
  1355. int CDmeLogLayer::GetDefaultCurveType() const
  1356. {
  1357. return GetOwnerLog()->GetDefaultCurveType();
  1358. }
  1359. void CDmeLogLayer::SetKeyCurveType( int nKeyIndex, int curveType )
  1360. {
  1361. Assert( GetOwnerLog() );
  1362. if ( !GetOwnerLog() )
  1363. return;
  1364. Assert( GetOwnerLog()->IsUsingCurveTypes() );
  1365. Assert( m_CurveTypes.IsValidIndex( nKeyIndex ) );
  1366. if ( !m_CurveTypes.IsValidIndex( nKeyIndex ) )
  1367. return;
  1368. m_CurveTypes.Set( nKeyIndex, curveType );
  1369. }
  1370. int CDmeLogLayer::GetKeyCurveType( int nKeyIndex ) const
  1371. {
  1372. Assert( GetOwnerLog() );
  1373. if ( !GetOwnerLog() )
  1374. return CURVE_DEFAULT;
  1375. Assert( GetOwnerLog()->IsUsingCurveTypes() );
  1376. Assert( m_CurveTypes.IsValidIndex( nKeyIndex ) );
  1377. if ( !m_CurveTypes.IsValidIndex( nKeyIndex ) )
  1378. return GetOwnerLog()->GetDefaultCurveType();
  1379. return m_CurveTypes[ nKeyIndex ];
  1380. }
  1381. void CDmeLogLayer::SetInfinite( bool bLeftInfinite, bool bRightInfinite )
  1382. {
  1383. m_bLeftInfinite = bLeftInfinite;
  1384. m_bRightInfinite = bRightInfinite;
  1385. }
  1386. //-----------------------------------------------------------------------------
  1387. // Removes all keys outside the specified time range
  1388. //-----------------------------------------------------------------------------
  1389. void CDmeLogLayer::RemoveKeysOutsideRange( DmeTime_t tStart, DmeTime_t tEnd )
  1390. {
  1391. int i;
  1392. int nKeysToRemove = 0;
  1393. int nKeyCount = m_times.Count();
  1394. for ( i = 0; i < nKeyCount; ++i, ++nKeysToRemove )
  1395. {
  1396. if ( m_times[i] >= tStart )
  1397. break;
  1398. }
  1399. if ( nKeysToRemove )
  1400. {
  1401. RemoveKey( 0, nKeysToRemove );
  1402. }
  1403. nKeyCount = m_times.Count();
  1404. for ( i = 0; i < nKeyCount; ++i )
  1405. {
  1406. if ( m_times[i] > tEnd )
  1407. break;
  1408. }
  1409. nKeysToRemove = nKeyCount - i;
  1410. if ( nKeysToRemove )
  1411. {
  1412. RemoveKey( i, nKeysToRemove );
  1413. }
  1414. }
  1415. SegmentInterpolation_t CDmeLogLayer::GetSegmentInterpolationSetting( int nKeyIndex ) const
  1416. {
  1417. if( m_NonInterpolatedSegments.Count() == 0 ) //We don't allocate an array until at least one non-interpolated segment exists
  1418. return SEGMENT_INTERPOLATE;
  1419. //if at least one exists, the array size keeps parity with other arrays
  1420. Assert( m_NonInterpolatedSegments.Count() == m_times.Count() );
  1421. Assert( (nKeyIndex >= 0) && (nKeyIndex < m_NonInterpolatedSegments.Count()) );
  1422. return m_NonInterpolatedSegments[ nKeyIndex ] ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  1423. }
  1424. SegmentInterpolation_t CDmeLogLayer::GetSegmentInterpolationSetting( int nStartKeyIndex, int nEndKeyIndex ) const
  1425. {
  1426. if( m_NonInterpolatedSegments.Count() == 0 ) //We don't allocate an array until at least one non-interpolated segment exists
  1427. return SEGMENT_INTERPOLATE;
  1428. //if at least one exists, the array size keeps parity with other arrays
  1429. Assert( m_NonInterpolatedSegments.Count() == m_times.Count() );
  1430. int iLastKey = m_NonInterpolatedSegments.Count();
  1431. //it's easier to bounds check here in a central location than in all bits of leaf code that want to check a (usually forward looking) range
  1432. nStartKeyIndex = MAX( nStartKeyIndex, 0 );
  1433. nStartKeyIndex = MIN( nStartKeyIndex, iLastKey );
  1434. nEndKeyIndex = MAX( nEndKeyIndex, nStartKeyIndex );
  1435. nEndKeyIndex = MIN( nEndKeyIndex, iLastKey );
  1436. for( int i = nStartKeyIndex; i <= nEndKeyIndex; ++i )
  1437. {
  1438. if( m_NonInterpolatedSegments[i] )
  1439. return SEGMENT_NOINTERPOLATE;
  1440. }
  1441. return SEGMENT_INTERPOLATE;
  1442. }
  1443. SegmentInterpolation_t CDmeLogLayer::GetSegmentInterpolationSetting( DmeTime_t time ) const
  1444. {
  1445. if( m_NonInterpolatedSegments.Count() == 0 ) //We don't allocate an array until at least one non-interpolated segment exists
  1446. return SEGMENT_INTERPOLATE;
  1447. return GetSegmentInterpolationSetting( FindKey( time ) );
  1448. }
  1449. SegmentInterpolation_t CDmeLogLayer::GetSegmentInterpolationSetting( DmeTime_t startTime, DmeTime_t endTime, bool bExcludeActualEndTimeKey ) const
  1450. {
  1451. if( m_NonInterpolatedSegments.Count() == 0 ) //We don't allocate an array until at least one non-interpolated segment exists
  1452. return SEGMENT_INTERPOLATE;
  1453. int nStartKey = (startTime == DMETIME_INVALID) ? 0 : FindKey( startTime );
  1454. int nEndKey = (endTime == DMETIME_INVALID) ? (m_NonInterpolatedSegments.Count() - 1) : FindKey( endTime );
  1455. if( bExcludeActualEndTimeKey && (nEndKey > nStartKey) && (endTime != DMETIME_INVALID) )
  1456. {
  1457. --nEndKey;
  1458. }
  1459. return GetSegmentInterpolationSetting( nStartKey, nEndKey );
  1460. }
  1461. template < class T >
  1462. class CUndoLayerAdded : public CUndoElement
  1463. {
  1464. typedef CUndoElement BaseClass;
  1465. public:
  1466. CUndoLayerAdded( const char *desc, CDmeLog *pLog ) :
  1467. BaseClass( desc ),
  1468. m_bNeedsCleanup( false ),
  1469. m_hLog( pLog )
  1470. {
  1471. Assert( pLog && pLog->GetFileId() != DMFILEID_INVALID );
  1472. }
  1473. virtual ~CUndoLayerAdded()
  1474. {
  1475. if ( m_bNeedsCleanup )
  1476. {
  1477. g_pDataModel->DestroyElement( m_hLayer );
  1478. }
  1479. }
  1480. virtual void Undo()
  1481. {
  1482. m_bNeedsCleanup = true;
  1483. CDmeLogLayer *pLayer = m_hLog->RemoveLayerFromTail();
  1484. Assert( pLayer );
  1485. m_hLayer = pLayer ? pLayer->GetHandle() : DMELEMENT_HANDLE_INVALID;
  1486. g_pDataModel->MarkHandleInvalid( m_hLayer );
  1487. }
  1488. virtual void Redo()
  1489. {
  1490. m_bNeedsCleanup = false;
  1491. g_pDataModel->MarkHandleValid( m_hLayer );
  1492. m_hLog->AddLayerToTail( GetElement< CDmeTypedLogLayer< T > >( m_hLayer ) );
  1493. }
  1494. virtual const char *GetDesc()
  1495. {
  1496. static char sz[ 512 ];
  1497. int iLayer = m_hLog->GetTopmostLayer();
  1498. if ( iLayer >= 0 )
  1499. {
  1500. CDmeLogLayer *layer = m_hLog->GetLayer( iLayer );
  1501. Q_snprintf( sz, sizeof( sz ), "addlayer: log %p lc[%d], layer %p",
  1502. m_hLog.Get(), m_hLog->GetNumLayers(), layer );
  1503. }
  1504. else
  1505. {
  1506. Q_snprintf( sz, sizeof( sz ), "addlayer: log %p lc[%d], layer NULL",
  1507. m_hLog.Get(), m_hLog->GetNumLayers() );
  1508. }
  1509. return sz;
  1510. }
  1511. private:
  1512. CDmeHandle< CDmeLog > m_hLog;
  1513. bool m_bNeedsCleanup;
  1514. CDmeUndoHandle m_hLayer;
  1515. };
  1516. template < class T >
  1517. class CUndoFlattenLayers : public CUndoElement
  1518. {
  1519. typedef CUndoElement BaseClass;
  1520. public:
  1521. CUndoFlattenLayers( const char *desc, CDmeTypedLog< T > *pLog, float threshold, int flags, int baseLayer ) :
  1522. BaseClass( desc ),
  1523. m_bNeedsCleanup( true ),
  1524. m_hLog( pLog ),
  1525. m_nFlags( flags ),
  1526. m_flThreshold( threshold ),
  1527. m_nBaseLayer( baseLayer ),
  1528. m_nLogLayers( 0 )
  1529. {
  1530. Assert( pLog && pLog->GetFileId() != DMFILEID_INVALID );
  1531. LatchCurrentLayers();
  1532. }
  1533. virtual ~CUndoFlattenLayers()
  1534. {
  1535. if ( m_bNeedsCleanup )
  1536. {
  1537. for ( int i = 0; i < m_hLayers.Count(); ++i )
  1538. {
  1539. m_hLayers[ i ] = DMELEMENT_HANDLE_INVALID;
  1540. #ifdef _DEBUG
  1541. CDmElement *pElement = g_pDataModel->GetElement( m_hLayers[ i ] );
  1542. Assert( !pElement || pElement->IsStronglyReferenced() );
  1543. #endif
  1544. }
  1545. }
  1546. }
  1547. virtual void Undo()
  1548. {
  1549. m_bNeedsCleanup = false;
  1550. int startLayerCount = m_hLog->GetNumLayers();
  1551. int undoLayerCount = m_hLayers.Count();
  1552. Assert( startLayerCount >= 1 );
  1553. Assert( undoLayerCount >= 1 );
  1554. // Calculate the number of layers the log wil have after the undo operation.
  1555. int newLayerCount = ( startLayerCount + undoLayerCount - 1 );
  1556. Assert( m_nLogLayers == newLayerCount );
  1557. if ( m_nLogLayers == newLayerCount )
  1558. {
  1559. for ( int i = 0; i < m_hLayers.Count(); ++i )
  1560. {
  1561. if ( i == 0 )
  1562. {
  1563. // Copy base layer in place so handles to the base layer remain valid
  1564. CDmeTypedLogLayer< T > *base = m_hLog->GetLayer( m_nBaseLayer );
  1565. base->CopyLayer( GetElement< CDmeTypedLogLayer< T > >( m_hLayers[ i ] ) );
  1566. // Release it since we didn't txfer it over
  1567. g_pDataModel->DestroyElement( m_hLayers[ i ] );
  1568. }
  1569. else
  1570. {
  1571. // This transfers ownership, so no Release needed
  1572. m_hLog->AddLayerToTail( GetElement< CDmeTypedLogLayer< T > >( m_hLayers[ i ] ) );
  1573. }
  1574. }
  1575. }
  1576. m_hLayers.RemoveAll();
  1577. }
  1578. virtual void Redo()
  1579. {
  1580. m_bNeedsCleanup = true;
  1581. Assert( m_hLayers.Count() == 0 );
  1582. LatchCurrentLayers();
  1583. // Flatten them again (won't create undo records since we're in undo already)
  1584. m_hLog->FlattenLayers( m_flThreshold, m_nFlags, m_nBaseLayer );
  1585. }
  1586. virtual const char *GetDesc()
  1587. {
  1588. static char sz[ 512 ];
  1589. Q_snprintf( sz, sizeof( sz ), "flatten log %p lc[%d]",
  1590. m_hLog.Get(), m_hLayers.Count() );
  1591. return sz;
  1592. }
  1593. private:
  1594. void LatchCurrentLayers()
  1595. {
  1596. CDisableUndoScopeGuard guard;
  1597. Assert( m_hLayers.Count() == 0 );
  1598. Assert( m_hLog->GetNumLayers() >= 1 );
  1599. // Save the number of layers in the log so that we can verify the
  1600. // log is in the same state when performing the undo operation.
  1601. m_nLogLayers = m_hLog->GetNumLayers();
  1602. // Start with the layer that is specified as the base layer of the flatten operation,
  1603. // and copy the contents of that layer and the of the layers above it.
  1604. for ( int i = m_nBaseLayer; i < m_hLog->GetNumLayers(); ++i )
  1605. {
  1606. CDmeTypedLogLayer< T > *pLayer = CastElement< CDmeTypedLogLayer< T > >( CreateLayer< T >( m_hLog ) );
  1607. pLayer->CopyLayer( m_hLog->GetLayer( i ) );
  1608. m_hLayers.AddToTail( pLayer->GetHandle() );
  1609. }
  1610. }
  1611. CDmeHandle< CDmeTypedLog< T > > m_hLog;
  1612. bool m_bNeedsCleanup;
  1613. CUtlVector< CDmeUndoHandle > m_hLayers;
  1614. int m_nFlags;
  1615. float m_flThreshold;
  1616. int m_nBaseLayer;
  1617. int m_nLogLayers;
  1618. };
  1619. //-----------------------------------------------------------------------------
  1620. // Purpose: return a sub frame rotation for a single bone
  1621. //-----------------------------------------------------------------------------
  1622. void ExtractAnimValue( int frame, const compressed_value_t *panimvalue, float scale, float &v1, float &v2 )
  1623. {
  1624. if ( !panimvalue )
  1625. {
  1626. v1 = v2 = 0;
  1627. return;
  1628. }
  1629. // Avoids a crash reading off the end of the data
  1630. // There is probably a better long-term solution; Ken is going to look into it.
  1631. if ( ( panimvalue->num.total == 1 ) && ( panimvalue->num.valid == 1 ) )
  1632. {
  1633. v1 = v2 = panimvalue[1].value * scale;
  1634. return;
  1635. }
  1636. int k = frame;
  1637. // find the data list that has the frame
  1638. while (panimvalue->num.total <= k)
  1639. {
  1640. k -= panimvalue->num.total;
  1641. panimvalue += panimvalue->num.valid + 1;
  1642. if ( panimvalue->num.total == 0 )
  1643. {
  1644. Assert( 0 ); // running off the end of the animation stream is bad
  1645. v1 = v2 = 0;
  1646. return;
  1647. }
  1648. }
  1649. if (panimvalue->num.valid > k)
  1650. {
  1651. // has valid animation data
  1652. v1 = panimvalue[k+1].value * scale;
  1653. if (panimvalue->num.valid > k + 1)
  1654. {
  1655. // has valid animation blend data
  1656. v2 = panimvalue[k+2].value * scale;
  1657. }
  1658. else
  1659. {
  1660. if (panimvalue->num.total > k + 1)
  1661. {
  1662. // data repeats, no blend
  1663. v2 = v1;
  1664. }
  1665. else
  1666. {
  1667. // pull blend from first data block in next list
  1668. v2 = panimvalue[panimvalue->num.valid+2].value * scale;
  1669. }
  1670. }
  1671. }
  1672. else
  1673. {
  1674. // get last valid data block
  1675. v1 = panimvalue[panimvalue->num.valid].value * scale;
  1676. if (panimvalue->num.total > k + 1)
  1677. {
  1678. // data repeats, no blend
  1679. v2 = v1;
  1680. }
  1681. else
  1682. {
  1683. // pull blend from first data block in next list
  1684. v2 = panimvalue[panimvalue->num.valid + 2].value * scale;
  1685. }
  1686. }
  1687. }
  1688. void ExtractAnimValue( int frame, const compressed_value_t *panimvalue, float scale, float &v1 )
  1689. {
  1690. if ( !panimvalue )
  1691. {
  1692. v1 = 0;
  1693. return;
  1694. }
  1695. int k = frame;
  1696. while (panimvalue->num.total <= k)
  1697. {
  1698. k -= panimvalue->num.total;
  1699. panimvalue += panimvalue->num.valid + 1;
  1700. if ( panimvalue->num.total == 0 )
  1701. {
  1702. Assert( 0 ); // running off the end of the animation stream is bad
  1703. v1 = 0;
  1704. return;
  1705. }
  1706. }
  1707. if (panimvalue->num.valid > k)
  1708. {
  1709. v1 = panimvalue[k+1].value * scale;
  1710. }
  1711. else
  1712. {
  1713. // get last valid data block
  1714. v1 = panimvalue[panimvalue->num.valid].value * scale;
  1715. }
  1716. }
  1717. template< class T >
  1718. void GetComponentValues( const T &in, Vector &out )
  1719. {
  1720. Assert( 0 );
  1721. }
  1722. template<>
  1723. void GetComponentValues( const Vector &in, Vector &out )
  1724. {
  1725. out = in;
  1726. }
  1727. template<>
  1728. void GetComponentValues( const Quaternion &in, Vector &out )
  1729. {
  1730. RadianEuler ang;
  1731. QuaternionAngles( in, ang );
  1732. for ( int i = 0; i < 3; ++i )
  1733. {
  1734. out[ i ] = ang[ i ];
  1735. while (out[ i ] >= M_PI)
  1736. out[ i ] -= M_PI * 2;
  1737. while (out[ i ] < -M_PI)
  1738. out[ i ] += M_PI * 2;
  1739. }
  1740. }
  1741. template< class T >
  1742. void InitBounds( float &mins, float &maxs )
  1743. {
  1744. Assert( 0 );
  1745. }
  1746. template<>
  1747. void InitBounds< Vector >( float &mins, float &maxs )
  1748. {
  1749. mins = -128.0f;
  1750. maxs = 128.0f;
  1751. }
  1752. template<>
  1753. void InitBounds< Quaternion >( float &mins, float &maxs )
  1754. {
  1755. mins = -M_PI / 8.0;
  1756. maxs = M_PI / 8.0;
  1757. }
  1758. template< class T >
  1759. void CDmeTypedLogLayer< T >::CompressValues( CDmaArray< T > &stream, CUtlBinaryBlock &block, float flMaxError = 0.1f )
  1760. {
  1761. // Don't bother
  1762. if ( stream.Count() <= 2 )
  1763. return;
  1764. // Allocate sufficient scratch space
  1765. size_t memsize = ALIGN_VALUE( sizeof( compressed_stream_t ) + 3 * ( 2 * stream.Count() + 1 ) * sizeof( compressed_value_t ), 4 );
  1766. byte *scratch = new byte[ memsize ];
  1767. Q_memset( scratch, 0, memsize );
  1768. compressed_stream_t *compressed = (compressed_stream_t *)scratch;
  1769. // First payload goes here
  1770. byte *pOut = (byte *)( compressed + 1 );
  1771. Vector minv, maxv;
  1772. for ( int k = 0; k < 3; ++k )
  1773. {
  1774. InitBounds< T >( minv[ k ], maxv[ k ] );
  1775. }
  1776. int nCount[ 3 ];
  1777. CUtlVector< Vector > vecComponentStream;
  1778. for ( int n = 0; n < stream.Count(); ++n )
  1779. {
  1780. Vector &compValue = vecComponentStream[ vecComponentStream.AddToTail() ];
  1781. GetComponentValues( stream[ n ], compValue );
  1782. if ( n == 0 )
  1783. {
  1784. compressed->m_vecBaseValue = compValue;
  1785. }
  1786. compValue -= compressed->m_vecBaseValue;
  1787. for ( int k = 0; k < 3; ++k )
  1788. {
  1789. if (compValue[ k ] < minv[ k ])
  1790. minv[ k ] = compValue[ k ];
  1791. if (compValue[ k ] > maxv[ k ])
  1792. maxv[ k ] = compValue[ k ];
  1793. }
  1794. }
  1795. // Per component, compute scaled values and then rle them
  1796. for ( int k = 0; k < 3; ++k )
  1797. {
  1798. float scale;
  1799. if ( minv[ k ] < maxv[ k ] )
  1800. {
  1801. if ( -minv[ k ]> maxv[ k ] )
  1802. {
  1803. scale = minv[ k ] / -32768.0f;
  1804. }
  1805. else
  1806. {
  1807. scale = maxv[ k ] / 32767.0f;
  1808. }
  1809. }
  1810. else
  1811. {
  1812. scale = 1.0f / 32.0f;
  1813. }
  1814. if ( scale > flMaxError )
  1815. {
  1816. // Dynamic range was too large
  1817. Warning( "compression error would be too large %f [%f %f]\n", scale, minv[ k ], maxv[ k ] );
  1818. delete[] scratch;
  1819. return;
  1820. }
  1821. compressed->m_vecScale[ k ] = scale;
  1822. CUtlVector< short > value;
  1823. value.EnsureCount( vecComponentStream.Count() );
  1824. // quantize the values into shorts
  1825. for ( int n = 0; n < vecComponentStream.Count(); n++ )
  1826. {
  1827. value[ n ] = (short)( vecComponentStream[ n ][ k ] / scale );
  1828. }
  1829. // initialize animation RLE block
  1830. compressed_value_t *pStart = (compressed_value_t *)pOut;
  1831. compressed_value_t *pcount, *pvalue;
  1832. pcount = pStart;
  1833. pvalue = pcount + 1;
  1834. pcount->num.valid = 1;
  1835. pcount->num.total = 1;
  1836. pvalue->value = value[0];
  1837. pvalue++;
  1838. // build a RLE of deltas from the default pose
  1839. for ( int m = 1; m < vecComponentStream.Count(); m++ )
  1840. {
  1841. if ( pcount->num.total == 255 )
  1842. {
  1843. // chain too long, force a new entry
  1844. pcount = pvalue;
  1845. pvalue = pcount + 1;
  1846. pcount->num.valid++;
  1847. pvalue->value = value[m];
  1848. pvalue++;
  1849. }
  1850. // insert value if they're not equal,
  1851. // or if we're not on a run and the run is less than 3 units
  1852. else if ((value[m] != value[m-1])
  1853. || ((pcount->num.total == pcount->num.valid) && ((m < vecComponentStream.Count() - 1) && value[m] != value[m+1])))
  1854. {
  1855. if (pcount->num.total != pcount->num.valid)
  1856. {
  1857. pcount = pvalue;
  1858. pvalue = pcount + 1;
  1859. }
  1860. pcount->num.valid++;
  1861. pvalue->value = value[m];
  1862. pvalue++;
  1863. }
  1864. pcount->num.total++;
  1865. }
  1866. nCount[ k ] = pvalue - pStart;
  1867. size_t nSize = nCount[ k ] * sizeof( compressed_value_t );
  1868. size_t offset = (byte *)pStart - (byte *)compressed;
  1869. if ( k >= 1 )
  1870. {
  1871. compressed->m_Offset[ k - 1 ] = (unsigned int)offset;
  1872. }
  1873. pOut += nSize;
  1874. }
  1875. size_t nTotalMem = pOut - scratch;
  1876. Assert( nTotalMem <= memsize );
  1877. block.Set( scratch, nTotalMem );
  1878. delete[] scratch;
  1879. }
  1880. //-----------------------------------------------------------------------------
  1881. // CDmeTypedLogLayer - a generic typed layer used by a log
  1882. //-----------------------------------------------------------------------------
  1883. template< class T >
  1884. void CDmeTypedLogLayer< T >::OnConstruction()
  1885. {
  1886. m_values.Init( this, "values" );
  1887. m_Compressed.Init( this, "compressed", FATTRIB_HIDDEN );
  1888. }
  1889. template< class T >
  1890. void CDmeTypedLogLayer< T >::Compress()
  1891. {
  1892. if ( IsCompressed() )
  1893. return;
  1894. CUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "CDmeTypedLogLayer::Compress" );
  1895. Assert( m_Compressed->Length() == 0 );
  1896. CUtlBinaryBlock block;
  1897. CompressValues( m_values, block, 0.1f );
  1898. m_Compressed = block;
  1899. if ( IsCompressed() )
  1900. {
  1901. m_values.RemoveAll();
  1902. }
  1903. }
  1904. template< class T >
  1905. void CDmeTypedLogLayer< T >::Decompress()
  1906. {
  1907. if ( !IsCompressed() )
  1908. return;
  1909. CUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "CDmeTypedLogLayer::Decompress" );
  1910. Assert( m_values.Count() == 0 );
  1911. m_values.RemoveAll();
  1912. CUtlVector< T > values;
  1913. for ( int i = 0; i < m_times.Count(); ++i )
  1914. {
  1915. T &val = values[ values.AddToTail() ];
  1916. GetCompressedValue( i, val );
  1917. }
  1918. m_values.CopyArray( values.Base(), values.Count() );
  1919. CUtlBinaryBlock empty;
  1920. m_Compressed = empty;
  1921. Assert( !IsCompressed() );
  1922. }
  1923. template< class T >
  1924. bool CDmeTypedLogLayer< T >::IsCompressed() const
  1925. {
  1926. return ( m_Compressed->Length() > 0 ) ? true : false;
  1927. }
  1928. template< class T >
  1929. size_t CDmeTypedLogLayer< T >::GetCompressedSize() const
  1930. {
  1931. return m_Compressed->Length();
  1932. }
  1933. template< class T >
  1934. size_t CDmeTypedLogLayer< T >::GetDataSize() const
  1935. {
  1936. return sizeof( T );
  1937. }
  1938. template< class T >
  1939. void CDmeTypedLogLayer< T >::SetOwnerLog( CDmeLog *owner )
  1940. {
  1941. Assert( owner );
  1942. Assert( assert_cast< CDmeTypedLog< T > * >( owner ) );
  1943. m_pOwnerLog = owner;
  1944. }
  1945. template< class T >
  1946. CDmeTypedLog< T > *CDmeTypedLogLayer< T >::GetTypedOwnerLog()
  1947. {
  1948. return assert_cast< CDmeTypedLog< T > * >( m_pOwnerLog );
  1949. }
  1950. template< class T >
  1951. const CDmeTypedLog< T > *CDmeTypedLogLayer< T >::GetTypedOwnerLog() const
  1952. {
  1953. return assert_cast< CDmeTypedLog< T > * >( m_pOwnerLog );
  1954. }
  1955. template< class T >
  1956. void CDmeTypedLogLayer< T >::OnDestruction()
  1957. {
  1958. }
  1959. template< class T >
  1960. void CDmeTypedLogLayer< T >::RemoveKeys( DmeTime_t starttime )
  1961. {
  1962. // Manipulating values will require decompressing data
  1963. Decompress();
  1964. int ti = FindKey( starttime );
  1965. if ( ti < 0 )
  1966. {
  1967. ClearKeys();
  1968. return;
  1969. }
  1970. if ( starttime > m_times[ ti ] )
  1971. ++ti;
  1972. int nKeys = m_times.Count() - ti;
  1973. if ( nKeys == 0 )
  1974. return;
  1975. m_times.RemoveMultiple( ti, nKeys );
  1976. m_values.RemoveMultiple( ti, nKeys );
  1977. if ( IsUsingCurveTypes() )
  1978. {
  1979. m_CurveTypes.RemoveMultiple( ti, nKeys );
  1980. }
  1981. if( m_NonInterpolatedSegments.Count() > 0 )
  1982. {
  1983. m_NonInterpolatedSegments.RemoveMultiple( ti, nKeys );
  1984. }
  1985. if ( m_lastKey >= ti && m_lastKey < ti + nKeys )
  1986. {
  1987. m_lastKey = ( ti > 0 ) ? ti - 1 : 0;
  1988. }
  1989. }
  1990. template< class T >
  1991. void CDmeTypedLogLayer< T >::ClearKeys()
  1992. {
  1993. // Manipulating values will require decompressing data
  1994. Decompress();
  1995. m_times.RemoveAll();
  1996. m_values.RemoveAll();
  1997. m_CurveTypes.RemoveAll();
  1998. m_NonInterpolatedSegments.RemoveAll();
  1999. m_lastKey = 0;
  2000. }
  2001. template< class T >
  2002. void CDmeTypedLogLayer< T >::RemoveKey( int nKeyIndex, int nNumKeysToRemove /*= 1*/ )
  2003. {
  2004. // Manipulating values will require decompressing data
  2005. Decompress();
  2006. m_times.RemoveMultiple( nKeyIndex, nNumKeysToRemove );
  2007. m_values.RemoveMultiple( nKeyIndex, nNumKeysToRemove );
  2008. if ( IsUsingCurveTypes() )
  2009. {
  2010. m_CurveTypes.RemoveMultiple( nKeyIndex, nNumKeysToRemove );
  2011. }
  2012. if( m_NonInterpolatedSegments.Count() > 0 )
  2013. {
  2014. m_NonInterpolatedSegments.RemoveMultiple( nKeyIndex, nNumKeysToRemove );
  2015. }
  2016. }
  2017. //-----------------------------------------------------------------------------
  2018. // Sets all of the keys on the layer from the provided array of times and
  2019. // values.
  2020. //-----------------------------------------------------------------------------
  2021. template< class T >
  2022. void CDmeTypedLogLayer< T >::SetAllKeys( const CUtlVector< DmeTime_t > &times, const CUtlVector< T > &values )
  2023. {
  2024. // Manipulating values will require decompressing data
  2025. Decompress();
  2026. // This method may not be used for logs using curve types
  2027. Assert( !IsUsingCurveTypes() );
  2028. if ( IsUsingCurveTypes() )
  2029. return;
  2030. // The provided arrays must be the same size
  2031. Assert( times.Count() == values.Count() );
  2032. if ( times.Count() != values.Count() )
  2033. return;
  2034. m_times = times;
  2035. m_values = values;
  2036. m_lastKey = 0;
  2037. if ( m_CurveTypes.Count() > 0 )
  2038. {
  2039. m_CurveTypes.RemoveAll();
  2040. }
  2041. m_NonInterpolatedSegments.RemoveAll();
  2042. }
  2043. //-----------------------------------------------------------------------------
  2044. // Copy all of the keys into the specified arrays
  2045. //-----------------------------------------------------------------------------
  2046. template< class T >
  2047. void CDmeTypedLogLayer< T >::GetAllKeys( CUtlVector< DmeTime_t > &times, CUtlVector< T > &values ) const
  2048. {
  2049. // Manipulating values will require decompressing data
  2050. const_cast< CDmeTypedLogLayer< T > * >( this )->Decompress();
  2051. // This method may not be used for logs using curve types
  2052. Assert( !IsUsingCurveTypes() );
  2053. if ( IsUsingCurveTypes() )
  2054. return;
  2055. times.CopyArray( m_times.Base(), m_times.Count() );
  2056. values.CopyArray( m_values.Base(), m_values.Count() );
  2057. }
  2058. //-----------------------------------------------------------------------------
  2059. // Sets a key, removes all keys after this time
  2060. // FIXME: This needs to account for interpolation!!!
  2061. //-----------------------------------------------------------------------------
  2062. template< class T >
  2063. void CDmeTypedLogLayer< T >::SetKey( DmeTime_t time, const T& value, SegmentInterpolation_t interpSetting /*= SEGMENT_INTERPOLATE*/, int curveType /*=CURVE_DEFAULT*/, bool removeRedundant /*=true*/ )
  2064. {
  2065. // Manipulating values will require decompressing data
  2066. Decompress();
  2067. Assert( time != DMETIME_INVALID );
  2068. Assert( m_values.Count() == m_times.Count() );
  2069. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  2070. // Remove all keys after this time
  2071. RemoveKeys( time );
  2072. // Add the key and then check to see if the penultimate key is still necessary
  2073. m_times.AddToTail( time );
  2074. m_values.AddToTail( value );
  2075. if ( IsUsingCurveTypes() )
  2076. {
  2077. m_CurveTypes.AddToTail( curveType );
  2078. }
  2079. if( m_NonInterpolatedSegments.Count() > 0 )
  2080. {
  2081. m_NonInterpolatedSegments.AddToTail( (interpSetting == SEGMENT_NOINTERPOLATE) );
  2082. Assert( m_NonInterpolatedSegments.Count() == m_times.Count() );
  2083. }
  2084. else if( interpSetting == SEGMENT_NOINTERPOLATE )
  2085. {
  2086. //first key with non-interpolation setting. Create the whole set
  2087. m_NonInterpolatedSegments.EnsureCount( m_times.Count() - 1 );
  2088. m_NonInterpolatedSegments.AddToTail( (interpSetting == SEGMENT_NOINTERPOLATE) );
  2089. Assert( m_NonInterpolatedSegments.Count() == m_times.Count() );
  2090. }
  2091. int nKeys = m_values.Count();
  2092. if ( ( nKeys < 3 ) ||
  2093. ( IsUsingCurveTypes() && ( curveType != m_CurveTypes[ nKeys -1 ] || ( curveType != m_CurveTypes[ nKeys - 2 ] ) ) )
  2094. )
  2095. {
  2096. return;
  2097. }
  2098. // Done if not removing redundant penultimate keys.
  2099. if ( !removeRedundant )
  2100. {
  2101. return;
  2102. }
  2103. // If adding the new means that the penultimate key's value was unneeded, then we will remove the penultimate key value
  2104. T check = GetValueSkippingKey( nKeys - 2 );
  2105. T oldPenultimateValue = m_values[ nKeys - 2 ];
  2106. if ( GetTypedOwnerLog()->ValuesDiffer( oldPenultimateValue, check ) )
  2107. {
  2108. return;
  2109. }
  2110. if( (interpSetting == SEGMENT_NOINTERPOLATE) ||
  2111. (GetSegmentInterpolationSetting( nKeys - 2 ) == SEGMENT_NOINTERPOLATE) ||
  2112. (GetSegmentInterpolationSetting( nKeys - 3 ) == SEGMENT_NOINTERPOLATE) )
  2113. {
  2114. return;
  2115. }
  2116. // Remove penultimate, it's not needed
  2117. m_times.Remove( nKeys - 2 );
  2118. m_values.Remove( nKeys - 2 );
  2119. if ( IsUsingCurveTypes() )
  2120. {
  2121. m_CurveTypes.Remove( nKeys - 2 );
  2122. }
  2123. if( m_NonInterpolatedSegments.Count() > 0 )
  2124. {
  2125. m_NonInterpolatedSegments.Remove( nKeys - 2 );
  2126. }
  2127. }
  2128. //-----------------------------------------------------------------------------
  2129. // Finds a key within tolerance, or adds one
  2130. //-----------------------------------------------------------------------------
  2131. template< class T >
  2132. int CDmeTypedLogLayer< T >::FindOrAddKey( DmeTime_t nTime, DmeTime_t nTolerance, const T& value, SegmentInterpolation_t interpSetting /*= SEGMENT_INTERPOLATE*/, int curveType /*=CURVE_DEFAULT*/ )
  2133. {
  2134. // Manipulating values will require decompressing data
  2135. Decompress();
  2136. Assert( m_values.Count() == m_times.Count() );
  2137. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  2138. // NOTE: This math must occur in 64bits because the max delta nDelta
  2139. // can be 33 bits large. Bleah.
  2140. int nClosest = -1;
  2141. int64 nClosestTolerance = DmeTime_t::MinTime().GetTenthsOfMS();
  2142. int64 nCurrTolerance;
  2143. int start = 0, end = GetKeyCount() - 1;
  2144. while ( start <= end )
  2145. {
  2146. int mid = (start + end) >> 1;
  2147. int64 nDelta = (int64)nTime.GetTenthsOfMS() - (int64)m_times[mid].GetTenthsOfMS();
  2148. if ( nDelta > 0 )
  2149. {
  2150. nCurrTolerance = nDelta;
  2151. start = mid + 1;
  2152. }
  2153. else if ( nDelta < 0 )
  2154. {
  2155. nCurrTolerance = -nDelta;
  2156. end = mid - 1;
  2157. }
  2158. else
  2159. {
  2160. nClosest = end = mid;
  2161. nClosestTolerance = 0;
  2162. break;
  2163. }
  2164. if ( nCurrTolerance < nClosestTolerance )
  2165. {
  2166. nClosest = mid;
  2167. nClosestTolerance = nCurrTolerance;
  2168. }
  2169. }
  2170. // At this point, end is the entry less than or equal to the entry
  2171. if ( nClosest == -1 || nTolerance.GetTenthsOfMS() < nClosestTolerance )
  2172. {
  2173. ++end;
  2174. nClosest = m_times.InsertBefore( end, nTime );
  2175. m_values.InsertBefore( end, value );
  2176. if ( IsUsingCurveTypes() )
  2177. {
  2178. m_CurveTypes.InsertBefore( end, curveType );
  2179. }
  2180. if( m_NonInterpolatedSegments.Count() > 0 )
  2181. {
  2182. m_NonInterpolatedSegments.InsertBefore( end, (interpSetting == SEGMENT_NOINTERPOLATE) || m_NonInterpolatedSegments[end - 1] );
  2183. Assert( m_NonInterpolatedSegments.Count() == m_times.Count() );
  2184. }
  2185. else if( interpSetting == SEGMENT_NOINTERPOLATE )
  2186. {
  2187. //first key with non-interpolation setting. Create the whole set
  2188. m_NonInterpolatedSegments.EnsureCount( m_times.Count() - 1 );
  2189. m_NonInterpolatedSegments.InsertBefore( end, (interpSetting == SEGMENT_NOINTERPOLATE) );
  2190. Assert( m_NonInterpolatedSegments.Count() == m_times.Count() );
  2191. }
  2192. }
  2193. return nClosest;
  2194. }
  2195. //-----------------------------------------------------------------------------
  2196. // This inserts a key. Unlike SetKey, this will *not* delete keys after the specified time
  2197. //-----------------------------------------------------------------------------
  2198. template < class T >
  2199. int CDmeTypedLogLayer< T >::InsertKey( DmeTime_t nTime, const T& value, SegmentInterpolation_t interpSetting /*= SEGMENT_INTERPOLATE*/, int curveType /*=CURVE_DEFAULT*/, bool bIgnoreTolerance /*= false*/ )
  2200. {
  2201. // Manipulating values will require decompressing data
  2202. Decompress();
  2203. int idx = FindOrAddKey( nTime, bIgnoreTolerance ? DmeTime_t( -1 ) : DmeTime_t( 0 ), value, interpSetting );
  2204. m_times .Set( idx, nTime );
  2205. m_values.Set( idx, value );
  2206. if ( IsUsingCurveTypes() )
  2207. {
  2208. m_CurveTypes.Set( idx, curveType );
  2209. }
  2210. if( interpSetting == SEGMENT_NOINTERPOLATE )
  2211. {
  2212. if( m_NonInterpolatedSegments.Count() > 0 )
  2213. {
  2214. m_NonInterpolatedSegments.Set( idx, (interpSetting == SEGMENT_NOINTERPOLATE) );
  2215. Assert( m_NonInterpolatedSegments.Count() == m_times.Count() );
  2216. }
  2217. else if( interpSetting == SEGMENT_NOINTERPOLATE )
  2218. {
  2219. //first key with non-interpolation setting. Create the whole set
  2220. m_NonInterpolatedSegments.EnsureCount( m_times.Count() );
  2221. m_NonInterpolatedSegments.Set( idx, (interpSetting == SEGMENT_NOINTERPOLATE) );
  2222. Assert( m_NonInterpolatedSegments.Count() == m_times.Count() );
  2223. }
  2224. }
  2225. return idx;
  2226. }
  2227. template< class T >
  2228. int CDmeTypedLogLayer< T >::InsertKeyAtTime( DmeTime_t nTime, int curveType /*=CURVE_DEFAULT*/ )
  2229. {
  2230. // Manipulating values will require decompressing data
  2231. Decompress();
  2232. T curVal = GetValue( nTime );
  2233. return InsertKey( nTime, curVal, GetSegmentInterpolationSetting(nTime), curveType );
  2234. }
  2235. //-----------------------------------------------------------------------------
  2236. // Add keys at tStartTime and tEndTime, and remove all keys outside the range
  2237. //-----------------------------------------------------------------------------
  2238. template< class T >
  2239. void CDmeTypedLogLayer< T >::TrimKeys( DmeTime_t tStartTime, DmeTime_t tEndTime )
  2240. {
  2241. // Manipulating values will require decompressing data
  2242. Decompress();
  2243. int idx = FindKey( tStartTime ); // the key at or before tStartTime
  2244. if ( idx >= 0 )
  2245. {
  2246. if ( m_times[ idx ] != tStartTime )
  2247. {
  2248. const T &value = GetValue( tStartTime ); // reference here only good until next GetValue()
  2249. m_times .Set( idx, tStartTime );
  2250. m_values.Set( idx, value );
  2251. }
  2252. RemoveKey( 0, idx );
  2253. }
  2254. int nKeys = m_times.Count();
  2255. idx = FindKey( tEndTime );
  2256. if ( idx >= 0 && idx + 1 < nKeys )
  2257. {
  2258. if ( m_times[ idx ] != tEndTime )
  2259. {
  2260. ++idx; // the key at or after tEndTime
  2261. const T &value = GetValue( tEndTime ); // reference here only good until next GetValue()
  2262. m_times .Set( idx, tEndTime );
  2263. m_values.Set( idx, value );
  2264. }
  2265. RemoveKey( idx + 1, nKeys - idx - 1 );
  2266. }
  2267. }
  2268. static bool CanInterpolateType( DmAttributeType_t attType )
  2269. {
  2270. switch ( attType )
  2271. {
  2272. default:
  2273. return false;
  2274. case AT_FLOAT:
  2275. case AT_VECTOR3:
  2276. case AT_QUATERNION:
  2277. case AT_TIME:
  2278. break;
  2279. }
  2280. return true;
  2281. }
  2282. template< class T >
  2283. const T& CDmeTypedLogLayer< T >::GetValue( DmeTime_t time ) const
  2284. {
  2285. // Curve Interpolation only for 1-D float data right now!!!
  2286. if ( IsUsingCurveTypes() &&
  2287. CanInterpolateType( GetDataType() ) )
  2288. {
  2289. static T out;
  2290. GetValueUsingCurveInfo( time, out );
  2291. return out;
  2292. }
  2293. int tc = m_times.Count();
  2294. Assert( IsCompressed() || m_values.Count() == tc );
  2295. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == tc ) );
  2296. int ti = FindKey( time );
  2297. if ( ti < 0 )
  2298. {
  2299. if ( tc > 0 )
  2300. return GetKeyValue( 0 );
  2301. const CDmeTypedLog< T > *pOwner = GetTypedOwnerLog();
  2302. if ( pOwner->HasDefaultValue() )
  2303. return pOwner->GetDefaultValue();
  2304. static T s_value;
  2305. CDmAttributeInfo< T >::SetDefaultValue( s_value ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  2306. return s_value;
  2307. }
  2308. // Early out if we're at the end
  2309. if ( ti >= tc - 1 )
  2310. return GetKeyValue( ti );
  2311. if( GetSegmentInterpolationSetting( ti ) == SEGMENT_NOINTERPOLATE )
  2312. return GetKeyValue( ti );
  2313. if ( !IsInterpolableType( GetDataType() ) )
  2314. return GetKeyValue( ti );
  2315. // Figure out the lerp factor
  2316. float t = GetFractionOfTimeBetween( time, m_times[ti], m_times[ti+1] );
  2317. static T s_value;
  2318. T v1, v2;
  2319. GetTwoKeyValues( ti, v1, v2 );
  2320. s_value = Interpolate( t, v1, v2 ); // Compute the lerp between ti and ti+1
  2321. return s_value;
  2322. }
  2323. template< class T >
  2324. void CDmeTypedLogLayer< T >::SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index, SegmentInterpolation_t interpSetting /*= SEGMENT_INTERPOLATE*/, int curveType /*= CURVE_DEFAULT*/ )
  2325. {
  2326. DmAttributeType_t type = ( pAttr ? pAttr->GetType() : AT_UNKNOWN );
  2327. if ( IsValueType( type ) )
  2328. {
  2329. Assert( pAttr->GetType() == GetDataType() );
  2330. SetKey( time, pAttr->GetValue< T >(), interpSetting, curveType );
  2331. }
  2332. else if ( IsArrayType( type ) )
  2333. {
  2334. Assert( ArrayTypeToValueType( type ) == GetDataType() );
  2335. CDmrArrayConst<T> array( pAttr );
  2336. SetKey( time, array[ index ], interpSetting, curveType );
  2337. }
  2338. else
  2339. {
  2340. Assert( 0 );
  2341. }
  2342. }
  2343. template< class T >
  2344. bool CDmeTypedLogLayer< T >::SetDuplicateKeyAtTime( DmeTime_t time )
  2345. {
  2346. Decompress();
  2347. int nKeys = m_times.Count();
  2348. if ( nKeys == 0 || m_times[ nKeys - 1 ] == time )
  2349. return false;
  2350. T value = GetValue( time );
  2351. SegmentInterpolation_t interpSetting = GetSegmentInterpolationSetting( time );
  2352. // these two calls need to be separated (and we need to make an extra copy here) because
  2353. // CUtlVector has an assert to try to safeguard against inserting an existing value
  2354. // therefore, m_values.AddToTail( m_values[ i ] ) is illegal (or at least, triggers the assert)
  2355. SetKey( time, value, interpSetting );
  2356. return true;
  2357. }
  2358. //-----------------------------------------------------------------------------
  2359. // Returns the key time / value pair for the specified key
  2360. //-----------------------------------------------------------------------------
  2361. template < class T >
  2362. void CDmeTypedLogLayer< T >::GetKeyValue( int nKeyIndex, LogKeyValue_t< T > &keyValue ) const
  2363. {
  2364. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  2365. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  2366. keyValue.time = m_times[ nKeyIndex ];
  2367. keyValue.value = GetKeyValue( nKeyIndex );
  2368. }
  2369. template< class T >
  2370. void CalcDecompressedAnimation( const compressed_stream_t &stream, int iFrame, T &out )
  2371. {
  2372. Assert( 0 );
  2373. }
  2374. template<>
  2375. void CalcDecompressedAnimation( const compressed_stream_t &stream, int iFrame, Vector &out )
  2376. {
  2377. ExtractAnimValue( iFrame, stream.Get( 0 ), stream.m_vecScale[0], out.x );
  2378. ExtractAnimValue( iFrame, stream.Get( 1 ), stream.m_vecScale[1], out.y );
  2379. ExtractAnimValue( iFrame, stream.Get( 2 ), stream.m_vecScale[2], out.z );
  2380. out += stream.m_vecBaseValue;
  2381. }
  2382. template<>
  2383. void CalcDecompressedAnimation( const compressed_stream_t &stream, int iFrame, Quaternion &out )
  2384. {
  2385. RadianEuler angle;
  2386. ExtractAnimValue( iFrame, stream.Get( 0 ), stream.m_vecScale[0], angle.x );
  2387. ExtractAnimValue( iFrame, stream.Get( 1 ), stream.m_vecScale[1], angle.y );
  2388. ExtractAnimValue( iFrame, stream.Get( 2 ), stream.m_vecScale[2], angle.z );
  2389. for ( int i = 0 ;i < 3; ++i )
  2390. {
  2391. angle[ i ] += stream.m_vecBaseValue[ i ];
  2392. }
  2393. AngleQuaternion( angle, out );
  2394. }
  2395. template< class T >
  2396. void CalcDecompressedAnimations( const compressed_stream_t &stream, int iFrame, T &out1, T &out2 )
  2397. {
  2398. Assert( 0 );
  2399. }
  2400. template<>
  2401. void CalcDecompressedAnimations( const compressed_stream_t &stream, int iFrame, Vector &out1, Vector &out2 )
  2402. {
  2403. ExtractAnimValue( iFrame, stream.Get( 0 ), stream.m_vecScale[0], out1.x, out2.x );
  2404. ExtractAnimValue( iFrame, stream.Get( 1 ), stream.m_vecScale[1], out1.y, out2.y );
  2405. ExtractAnimValue( iFrame, stream.Get( 2 ), stream.m_vecScale[2], out1.z, out2.z );
  2406. out1 += stream.m_vecBaseValue;
  2407. out2 += stream.m_vecBaseValue;
  2408. }
  2409. template<>
  2410. void CalcDecompressedAnimations( const compressed_stream_t &stream, int iFrame, Quaternion &out1, Quaternion &out2 )
  2411. {
  2412. RadianEuler angle1, angle2;
  2413. ExtractAnimValue( iFrame, stream.Get( 0 ), stream.m_vecScale[0], angle1.x, angle2.x );
  2414. ExtractAnimValue( iFrame, stream.Get( 1 ), stream.m_vecScale[1], angle1.y, angle2.y );
  2415. ExtractAnimValue( iFrame, stream.Get( 2 ), stream.m_vecScale[2], angle1.z, angle2.z );
  2416. for ( int i = 0 ;i < 3; ++i )
  2417. {
  2418. angle1[ i ] += stream.m_vecBaseValue[ i ];
  2419. angle2[ i ] += stream.m_vecBaseValue[ i ];
  2420. }
  2421. AngleQuaternion( angle1, out1 );
  2422. AngleQuaternion( angle2, out2 );
  2423. }
  2424. template< class T >
  2425. void CDmeTypedLogLayer< T >::GetCompressedValue( int nKeyIndex, T &value ) const
  2426. {
  2427. const compressed_stream_t *pStream = ( const compressed_stream_t * )m_Compressed->Get();
  2428. Assert( pStream );
  2429. CalcDecompressedAnimation( *pStream, nKeyIndex, value );
  2430. }
  2431. template< class T >
  2432. void CDmeTypedLogLayer< T >::GetCompressedValues( int nKeyIndex, T &value1, T &value2 ) const
  2433. {
  2434. const compressed_stream_t *pStream = ( const compressed_stream_t * )m_Compressed->Get();
  2435. Assert( pStream );
  2436. CalcDecompressedAnimations( *pStream, nKeyIndex, value1, value2 );
  2437. }
  2438. //-----------------------------------------------------------------------------
  2439. // Returns a specific key's value
  2440. //-----------------------------------------------------------------------------
  2441. template< class T >
  2442. const T& CDmeTypedLogLayer< T >::GetKeyValue( int nKeyIndex ) const
  2443. {
  2444. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  2445. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  2446. if ( !IsCompressed() )
  2447. {
  2448. return m_values[ nKeyIndex ];
  2449. }
  2450. // Get compressed value
  2451. static T value;
  2452. GetCompressedValue( nKeyIndex, value );
  2453. return value;
  2454. }
  2455. template< class T >
  2456. void CDmeTypedLogLayer< T >::GetTwoKeyValues( int keyindex, T &v1, T &v2 ) const
  2457. {
  2458. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  2459. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  2460. if ( !IsCompressed() )
  2461. {
  2462. v1 = m_values[ keyindex ];
  2463. v2 = m_values[ keyindex + 1 ];
  2464. return;
  2465. }
  2466. // Get compressed value
  2467. GetCompressedValues( keyindex, v1, v2 );
  2468. }
  2469. template< class T >
  2470. void CDmeTypedLogLayer< T >::GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index ) const
  2471. {
  2472. DmAttributeType_t attrtype = pAttr->GetType();
  2473. if ( IsValueType( attrtype ) )
  2474. {
  2475. Assert( attrtype == GetDataType() );
  2476. pAttr->SetValue( GetValue( time ) );
  2477. }
  2478. else if ( IsArrayType( attrtype ) )
  2479. {
  2480. Assert( ArrayTypeToValueType( attrtype ) == GetDataType() );
  2481. CDmrArray<T> array( pAttr );
  2482. array.Set( index, GetValue( time ) );
  2483. }
  2484. else
  2485. {
  2486. Assert( 0 );
  2487. }
  2488. }
  2489. template< class T >
  2490. float CDmeTypedLogLayer< T >::GetComponent( DmeTime_t time, int componentIndex ) const
  2491. {
  2492. return ::GetComponent( GetValue( time ), componentIndex );
  2493. }
  2494. template< class T >
  2495. void CDmeTypedLogLayer< T >::SetKeyValue( int nKey, const T& value )
  2496. {
  2497. Decompress();
  2498. Assert( nKey >= 0 );
  2499. Assert( nKey < m_values.Count() );
  2500. m_values.Set( nKey, value );
  2501. }
  2502. //-----------------------------------------------------------------------------
  2503. // resampling and filtering
  2504. //-----------------------------------------------------------------------------
  2505. template< class T >
  2506. void CDmeTypedLogLayer< T >::Resample( DmeFramerate_t samplerate )
  2507. {
  2508. Decompress();
  2509. // FIXME: Might have to revisit how to determine "curve types" for "resampled points...
  2510. Assert( !IsUsingCurveTypes() );
  2511. // make sure we resample to include _at_least_ the existing time range
  2512. DmeTime_t begin = GetBeginTime( false );
  2513. DmeTime_t end = GetEndTime( false );
  2514. int nSamples = 2 + FrameForTime( end - begin, samplerate );
  2515. CUtlVector< DmeTime_t > resampledTimes;
  2516. CUtlVector< T > resampledValues;
  2517. CUtlVector< int > resampledCurveTypes;
  2518. CUtlVector< bool > resampledNoInterpSegments;
  2519. resampledValues.EnsureCapacity( nSamples );
  2520. resampledTimes.EnsureCapacity( nSamples );
  2521. bool bHasNonInterpSegments = (m_NonInterpolatedSegments.Count() > 0);
  2522. if( bHasNonInterpSegments )
  2523. {
  2524. resampledNoInterpSegments.EnsureCapacity( nSamples );
  2525. }
  2526. DmeTime_t time( begin );
  2527. DmeTime_t lastInterpSampleTime = time;
  2528. for ( int i = 0; i < nSamples; ++i )
  2529. {
  2530. resampledTimes.AddToTail( time );
  2531. resampledValues.AddToTail( GetValue( time ) );
  2532. if ( IsUsingCurveTypes() )
  2533. {
  2534. resampledCurveTypes.AddToTail( CURVE_DEFAULT );
  2535. }
  2536. time = time.TimeAtNextFrame( samplerate );
  2537. if ( bHasNonInterpSegments )
  2538. {
  2539. //disable interpolation if we're about to pass through a non-interpolated segment.
  2540. //non-interpolated segments keep their beginning value for the entire segment, so they must be front-loaded
  2541. resampledNoInterpSegments.AddToTail( (GetSegmentInterpolationSetting( lastInterpSampleTime, time, true ) == SEGMENT_NOINTERPOLATE) );
  2542. lastInterpSampleTime = time;
  2543. }
  2544. }
  2545. m_times.SwapArray( resampledTimes );
  2546. m_values.SwapArray( resampledValues );
  2547. if ( IsUsingCurveTypes() )
  2548. {
  2549. m_CurveTypes.SwapArray( resampledCurveTypes );
  2550. }
  2551. if( bHasNonInterpSegments )
  2552. {
  2553. m_NonInterpolatedSegments.SwapArray( resampledNoInterpSegments );
  2554. }
  2555. }
  2556. template< class T >
  2557. void CDmeTypedLogLayer< T >::Filter( int nSampleRadius )
  2558. {
  2559. Decompress();
  2560. // Doesn't mess with curvetypes!!!
  2561. const CUtlVector< T > &values = m_values.Get();
  2562. CUtlVector< T > filteredValues;
  2563. int nValues = values.Count();
  2564. filteredValues.EnsureCapacity( nValues );
  2565. for ( int i = 0; i < nValues; ++i )
  2566. {
  2567. int nSamples = MIN( nSampleRadius, MIN( i, nValues - i - 1 ) );
  2568. filteredValues.AddToTail( Average( values.Base() + i - nSamples, 2 * nSamples + 1 ) );
  2569. }
  2570. m_values.SwapArray( filteredValues );
  2571. }
  2572. template< class T >
  2573. void CDmeTypedLogLayer< T >::Filter2( DmeTime_t sampleRadius )
  2574. {
  2575. Decompress();
  2576. // Doesn't mess with curvetypes!!!
  2577. const CUtlVector< T > &values = m_values.Get();
  2578. CUtlVector< T > filteredValues;
  2579. int nValues = values.Count();
  2580. filteredValues.EnsureCapacity( nValues );
  2581. DmeTime_t earliest = DMETIME_ZERO;
  2582. if ( nValues > 0 )
  2583. {
  2584. earliest = m_times[ 0 ];
  2585. }
  2586. for ( int i = 0; i < nValues; ++i )
  2587. {
  2588. T vals[ 3 ];
  2589. DmeTime_t t = GetKeyTime( i );
  2590. DmeTime_t t0 = t - sampleRadius;
  2591. DmeTime_t t1 = t + sampleRadius;
  2592. if ( t0 >= earliest )
  2593. {
  2594. vals[ 0 ] = GetValue( t0 );
  2595. }
  2596. else
  2597. {
  2598. vals[ 0 ] = m_values[ 0 ];
  2599. }
  2600. vals[ 1 ] = GetValue( t );
  2601. vals[ 2 ] = GetValue( t1 );
  2602. if ( i == 0 || i == nValues - 1 )
  2603. {
  2604. filteredValues.AddToTail( values[ i ] );
  2605. }
  2606. else
  2607. {
  2608. filteredValues.AddToTail( Average( vals, 3 ) );
  2609. }
  2610. }
  2611. m_values.SwapArray( filteredValues );
  2612. }
  2613. template< class T >
  2614. const T& CDmeTypedLogLayer< T >::GetValueSkippingKey( int nKeyToSkip ) const
  2615. {
  2616. // Curve Interpolation only for 1-D float data right now!!!
  2617. if ( IsUsingCurveTypes() && CanInterpolateType( GetDataType() ) )
  2618. {
  2619. static T out;
  2620. GetValueUsingCurveInfoSkippingKey( nKeyToSkip, out );
  2621. return out;
  2622. }
  2623. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  2624. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  2625. DmeTime_t time = GetKeyTime( nKeyToSkip );
  2626. int prevKey = nKeyToSkip - 1;
  2627. int nextKey = nKeyToSkip + 1;
  2628. DmeTime_t prevTime;
  2629. T prevValue;
  2630. int prevCurveType;
  2631. DmeTime_t nextTime;
  2632. T nextValue;
  2633. int nextCurveType;
  2634. GetBoundedSample( prevKey, prevTime, prevValue, prevCurveType );
  2635. GetBoundedSample( nextKey, nextTime, nextValue, nextCurveType );
  2636. // Figure out the lerp factor
  2637. float t = GetFractionOfTimeBetween( time, prevTime, nextTime );
  2638. static T s_value;
  2639. if( (GetSegmentInterpolationSetting(prevKey) == SEGMENT_NOINTERPOLATE) ||
  2640. (GetSegmentInterpolationSetting(nKeyToSkip) == SEGMENT_NOINTERPOLATE) )
  2641. {
  2642. s_value = prevValue;
  2643. }
  2644. else
  2645. {
  2646. s_value = Interpolate( t, prevValue, nextValue );
  2647. }
  2648. return s_value;
  2649. }
  2650. template< class T >
  2651. void CDmeTypedLog<T>::RemoveRedundantKeys( float threshold, bool bKeepEnds )
  2652. {
  2653. int bestLayer = GetTopmostLayer();
  2654. if ( bestLayer < 0 )
  2655. return;
  2656. GetLayer( bestLayer )->RemoveRedundantKeys( threshold, bKeepEnds );
  2657. }
  2658. template< class T >
  2659. void CDmeTypedLogLayer<T>::RemoveRedundantKeys( float threshold, bool bKeepEnds )
  2660. {
  2661. Decompress();
  2662. Assert( GetTypedOwnerLog() );
  2663. if ( !GetTypedOwnerLog() )
  2664. return;
  2665. float saveThreshold = CDmeTypedLog< T >::GetValueThreshold();
  2666. CDmeTypedLog< T >::SetValueThreshold( threshold );
  2667. RemoveRedundantKeys( bKeepEnds );
  2668. CDmeTypedLog< T >::SetValueThreshold( saveThreshold );
  2669. }
  2670. // Implementation of Douglas-Peucker curve simplification routine (hacked to only care about error against original curve (sort of 1D)
  2671. template< class T >
  2672. void CDmeTypedLogLayer< T >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< T > *output )
  2673. {
  2674. if ( endPoint <= startPoint + 1 )
  2675. {
  2676. return;
  2677. }
  2678. int maxPoint = startPoint;
  2679. float maxDistanceSqr = 0.0f;
  2680. bool bAnyNonInterp = false;
  2681. for ( int i = startPoint + 1 ; i < endPoint; ++i )
  2682. {
  2683. DmeTime_t keyTime = GetKeyTime( i );
  2684. T check = GetKeyValue( i );
  2685. T check2 = output->GetValue( keyTime );
  2686. T dist = Subtract( check, check2 );
  2687. float distSqr = LengthOf( dist ) * LengthOf( dist );
  2688. bAnyNonInterp |= (GetSegmentInterpolationSetting( i ) == SEGMENT_NOINTERPOLATE);
  2689. if ( distSqr < maxDistanceSqr )
  2690. continue;
  2691. maxPoint = i;
  2692. maxDistanceSqr = distSqr;
  2693. }
  2694. if ( maxDistanceSqr > thresholdSqr )
  2695. {
  2696. output->InsertKey( GetKeyTime( maxPoint ), GetKeyValue( maxPoint ), bAnyNonInterp ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE);
  2697. CurveSimplify_R( thresholdSqr, startPoint, maxPoint, output );
  2698. CurveSimplify_R( thresholdSqr, maxPoint, endPoint, output );
  2699. }
  2700. }
  2701. template<> void CDmeTypedLogLayer< bool >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< bool > *output ) {};
  2702. template<> void CDmeTypedLogLayer< int >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< int > *output ) {};
  2703. template<> void CDmeTypedLogLayer< Color >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< Color > *output ) {};
  2704. template<> void CDmeTypedLogLayer< Quaternion >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< Quaternion > *output ) {};
  2705. template<> void CDmeTypedLogLayer< VMatrix >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< VMatrix > *output ) {};
  2706. // We can't just walk the keys linearly since it'll accumulate too much error and give us a bad curve after simplification. We do a recursive subdivide which has a worst case of O(n^2) but
  2707. // probably is better than that in most cases.
  2708. template< class T >
  2709. void CDmeTypedLogLayer<T>::RemoveRedundantKeys( bool bKeepEnds )
  2710. {
  2711. CDmeTypedLog< T > *pOwner = GetTypedOwnerLog();
  2712. if ( !pOwner )
  2713. return;
  2714. int nKeys = GetKeyCount();
  2715. if ( nKeys <= 2 )
  2716. return;
  2717. float thresh = pOwner->GetValueThreshold();
  2718. if ( thresh < 0.0f )
  2719. return;
  2720. Decompress();
  2721. CDmeTypedLogLayer< T > *save = 0;
  2722. {
  2723. CDisableUndoScopeGuard guard;
  2724. save = CastElement< CDmeTypedLogLayer< T > >( CreateLayer< T >( pOwner ) );
  2725. Assert( save );
  2726. bool bHasNonInterpSegments = (m_NonInterpolatedSegments.Count() > 0);
  2727. save->m_bLeftInfinite = m_bLeftInfinite;
  2728. save->m_bRightInfinite = m_bRightInfinite;
  2729. save->m_times.EnsureCapacity( nKeys );
  2730. save->m_values.EnsureCapacity( nKeys );
  2731. if( bHasNonInterpSegments )
  2732. {
  2733. save->m_NonInterpolatedSegments.EnsureCapacity( nKeys );
  2734. }
  2735. // Insert start and end points as first "guess" at simplified curve. Skip
  2736. // preceding and ending keys that have the same value, unless the bKeepFirstLast
  2737. // flag is true, in which case the first and last key are always added.
  2738. int nFirstKey = 0;
  2739. int nLastKey = nKeys - 1;
  2740. if ( !bKeepEnds )
  2741. {
  2742. for ( nFirstKey = 1; nFirstKey < nKeys; ++nFirstKey )
  2743. {
  2744. // FIXME: Should we use a tolerance check here?
  2745. if ( GetKeyValue( nFirstKey ) != GetKeyValue( nFirstKey - 1 ) )
  2746. break;
  2747. }
  2748. --nFirstKey;
  2749. for ( nLastKey = nKeys; --nLastKey >= 1; )
  2750. {
  2751. // FIXME: Should we use a tolerance check here?
  2752. if ( GetKeyValue( nLastKey ) != GetKeyValue( nLastKey - 1 ) )
  2753. break;
  2754. if( GetSegmentInterpolationSetting( nLastKey ) != GetSegmentInterpolationSetting( nLastKey - 1 ) )
  2755. break;
  2756. }
  2757. }
  2758. if ( nLastKey <= nFirstKey )
  2759. {
  2760. save->InsertKey( GetKeyTime( 0 ), GetKeyValue( 0 ), GetSegmentInterpolationSetting( 0 ) );
  2761. }
  2762. else
  2763. {
  2764. if ( GetDataType() == AT_FLOAT )
  2765. {
  2766. save->InsertKey( GetKeyTime( nFirstKey ), GetKeyValue( nFirstKey ), GetSegmentInterpolationSetting( nFirstKey ) );
  2767. save->InsertKey( GetKeyTime( nLastKey ), GetKeyValue( nLastKey ), GetSegmentInterpolationSetting( nLastKey ) );
  2768. // Recursively finds the point with the largest error from the "simplified curve" and subdivides the problem on both sides until the largest delta from the simplified
  2769. // curve is less than the tolerance (squared)
  2770. CurveSimplify_R( thresh * thresh, nFirstKey, nLastKey, save );
  2771. }
  2772. else
  2773. {
  2774. save->InsertKey( GetKeyTime( nFirstKey ), GetKeyValue( nFirstKey ), GetSegmentInterpolationSetting( nFirstKey ) );
  2775. // copy over keys that differ from their prior or next keys - this keeps the first and last key of a run of same-valued keys
  2776. for ( int i = nFirstKey + 1; i < nLastKey; ++i )
  2777. {
  2778. // prev is from the saved log to allow deleting runs of same-valued keys
  2779. const T &prev = save->GetKeyValue( save->GetKeyCount() - 1 );
  2780. const T &curr = GetKeyValue( i );
  2781. const T &next = GetKeyValue( i + 1 );
  2782. if ( pOwner->ValuesDiffer( prev, curr ) || pOwner->ValuesDiffer( curr, next ) )
  2783. {
  2784. save->InsertKey( GetKeyTime( i ), curr, GetSegmentInterpolationSetting( i ) );
  2785. }
  2786. }
  2787. save->InsertKey( GetKeyTime( nLastKey ), GetKeyValue( nLastKey ), GetSegmentInterpolationSetting( nLastKey ) );
  2788. }
  2789. }
  2790. }
  2791. // This operation is undoable
  2792. CopyLayer( save );
  2793. {
  2794. CDisableUndoScopeGuard guard;
  2795. g_pDataModel->DestroyElement( save->GetHandle() );
  2796. }
  2797. }
  2798. // curve info helpers
  2799. template< class T >
  2800. const CDmeTypedCurveInfo< T > *CDmeTypedLogLayer<T>::GetTypedCurveInfo() const
  2801. {
  2802. Assert( GetTypedOwnerLog() );
  2803. return GetTypedOwnerLog()->GetTypedCurveInfo();
  2804. }
  2805. template< class T >
  2806. CDmeTypedCurveInfo< T > *CDmeTypedLogLayer<T>::GetTypedCurveInfo()
  2807. {
  2808. Assert( GetTypedOwnerLog() );
  2809. return GetTypedOwnerLog()->GetTypedCurveInfo();
  2810. }
  2811. template< class T >
  2812. bool CDmeTypedLogLayer< T >::IsUsingEdgeInfo() const
  2813. {
  2814. return GetTypedOwnerLog()->IsUsingEdgeInfo();
  2815. }
  2816. template< class T >
  2817. const T& CDmeTypedLogLayer< T >::GetDefaultEdgeZeroValue() const
  2818. {
  2819. return GetTypedOwnerLog()->GetDefaultEdgeZeroValue();
  2820. }
  2821. template< class T >
  2822. DmeTime_t CDmeTypedLogLayer< T >::GetRightEdgeTime() const
  2823. {
  2824. return GetTypedOwnerLog()->GetRightEdgeTime();
  2825. }
  2826. template< class T >
  2827. void CDmeTypedLogLayer< T >::GetEdgeInfo( int edge, bool& active, T& val, int& curveType ) const
  2828. {
  2829. GetTypedOwnerLog()->GetEdgeInfo( edge, active, val, curveType );
  2830. }
  2831. template< class T >
  2832. int CDmeTypedLogLayer< T >::GetEdgeCurveType( int edge ) const
  2833. {
  2834. return GetTypedOwnerLog()->GetEdgeCurveType( edge );
  2835. }
  2836. template< class T >
  2837. void CDmeTypedLogLayer< T >::GetZeroValue( int side, T& val ) const
  2838. {
  2839. return GetTypedOwnerLog()->GetZeroValue( side, val );
  2840. }
  2841. template< class T >
  2842. void CDmeTypedLogLayer< T >::GetBoundedSample( int keyindex, DmeTime_t& time, T& val, int& curveType ) const
  2843. {
  2844. Assert( GetOwnerLog() );
  2845. if ( !GetOwnerLog() )
  2846. {
  2847. time = DmeTime_t( 0 );
  2848. CDmAttributeInfo< T >::SetDefaultValue( val );
  2849. curveType = CURVE_DEFAULT;
  2850. return;
  2851. }
  2852. if ( keyindex < 0 )
  2853. {
  2854. time = DmeTime_t( 0 );
  2855. GetZeroValue( 0, val );
  2856. curveType = GetEdgeCurveType( 0 );
  2857. return;
  2858. }
  2859. else if ( keyindex >= m_times.Count() )
  2860. {
  2861. time = GetTypedOwnerLog()->GetRightEdgeTime();
  2862. if ( time == DmeTime_t( 0 ) && m_times.Count() > 0 )
  2863. {
  2864. // Push it one tms past the final end time
  2865. time = m_times[ m_times.Count() - 1 ] + DMETIME_MINDELTA;
  2866. }
  2867. GetTypedOwnerLog()->GetZeroValue( 1, val );
  2868. curveType = GetTypedOwnerLog()->GetEdgeCurveType( 1 );
  2869. return;
  2870. }
  2871. time = m_times[ keyindex ];
  2872. val = GetKeyValue( keyindex );
  2873. if ( IsUsingCurveTypes() )
  2874. {
  2875. Assert( m_CurveTypes.Count() == m_times.Count() );
  2876. if ( keyindex >= m_CurveTypes.Count() )
  2877. {
  2878. curveType = GetTypedOwnerLog()->GetDefaultCurveType();
  2879. }
  2880. else
  2881. {
  2882. curveType = m_CurveTypes[ keyindex ];
  2883. if ( curveType == CURVE_DEFAULT )
  2884. {
  2885. curveType = GetTypedOwnerLog()->GetDefaultCurveType();
  2886. }
  2887. }
  2888. }
  2889. }
  2890. template<>
  2891. void CDmeTypedLogLayer< float >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, float& out ) const
  2892. {
  2893. Assert( GetOwnerLog() );
  2894. if ( !GetOwnerLog() )
  2895. {
  2896. out = 0.0f;
  2897. return;
  2898. }
  2899. Assert( CanInterpolateType( GetDataType() ) );
  2900. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  2901. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  2902. Assert( IsInterpolableType( GetDataType() ) );
  2903. float v[ 4 ];
  2904. DmeTime_t t[ 4 ];
  2905. int curvetypes[ 4 ];
  2906. int ti = nKeyToSkip;
  2907. DmeTime_t time = GetKeyTime( nKeyToSkip );
  2908. if ( !IsUsingCurveTypes() )
  2909. {
  2910. if ( ti < 0 )
  2911. {
  2912. CDmAttributeInfo< float >::SetDefaultValue( out ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  2913. return;
  2914. }
  2915. else if ( ti >= m_times.Count() - 1 )
  2916. {
  2917. out = GetKeyValue( ti + 1 );
  2918. return;
  2919. }
  2920. }
  2921. DmeTime_t finalTime = GetTypedOwnerLog()->GetRightEdgeTime();
  2922. if ( finalTime != DmeTime_t( 0 ) )
  2923. {
  2924. if ( time > finalTime )
  2925. {
  2926. GetZeroValue( 1, out );
  2927. return;
  2928. }
  2929. }
  2930. else
  2931. {
  2932. if ( ti >= m_times.Count() - 1 )
  2933. {
  2934. out = GetKeyValue( ti + 1 );
  2935. return;
  2936. }
  2937. }
  2938. GetBoundedSample( ti - 2, t[ 0 ], v[ 0 ], curvetypes[ 0 ] );
  2939. GetBoundedSample( ti - 1, t[ 1 ], v[ 1 ], curvetypes[ 1 ] );
  2940. GetBoundedSample( ti + 1, t[ 2 ], v[ 2 ], curvetypes[ 2 ] );
  2941. GetBoundedSample( ti + 2, t[ 3 ], v[ 3 ], curvetypes[ 3 ] );
  2942. float frac = 0.0f;
  2943. if ( t[2] > t[ 1 ] )
  2944. {
  2945. frac = (time.GetSeconds() - t[1].GetSeconds()) / (float) ( t[2].GetSeconds() - t[ 1 ].GetSeconds() );
  2946. }
  2947. // Compute the lerp between ti and ti+1
  2948. out = Curve_Interpolate( frac, t, v, curvetypes, GetOwnerLog()->GetMinValue(), GetOwnerLog()->GetMaxValue() );
  2949. }
  2950. template<>
  2951. void CDmeTypedLogLayer< Vector >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, Vector& out ) const
  2952. {
  2953. Assert( GetOwnerLog() );
  2954. if ( !GetOwnerLog() )
  2955. {
  2956. CDmAttributeInfo< Vector >::SetDefaultValue( out );
  2957. return;
  2958. }
  2959. Assert( CanInterpolateType( GetDataType() ) );
  2960. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  2961. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  2962. Assert( IsInterpolableType( GetDataType() ) );
  2963. Vector v[ 4 ];
  2964. DmeTime_t t[ 4 ];
  2965. int curvetypes[ 4 ];
  2966. int ti = nKeyToSkip;
  2967. DmeTime_t time = GetKeyTime( nKeyToSkip );
  2968. if ( !IsUsingCurveTypes() )
  2969. {
  2970. if ( ti < 0 )
  2971. {
  2972. CDmAttributeInfo< Vector >::SetDefaultValue( out ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  2973. return;
  2974. }
  2975. else if ( ti >= m_times.Count() - 1 )
  2976. {
  2977. out = GetKeyValue( ti + 1 );
  2978. return;
  2979. }
  2980. }
  2981. DmeTime_t finalTime = GetTypedOwnerLog()->GetRightEdgeTime();
  2982. if ( finalTime != DmeTime_t( 0 ) )
  2983. {
  2984. if ( time > finalTime )
  2985. {
  2986. CDmAttributeInfo< Vector >::SetDefaultValue( out );
  2987. return;
  2988. }
  2989. }
  2990. else
  2991. {
  2992. if ( ti >= m_times.Count() - 1 )
  2993. {
  2994. out = GetKeyValue( ti + 1 );
  2995. return;
  2996. }
  2997. }
  2998. GetBoundedSample( ti - 2, t[ 0 ], v[ 0 ], curvetypes[ 0 ] );
  2999. GetBoundedSample( ti - 1, t[ 1 ], v[ 1 ], curvetypes[ 1 ] );
  3000. GetBoundedSample( ti + 1, t[ 2 ], v[ 2 ], curvetypes[ 2 ] );
  3001. GetBoundedSample( ti + 2, t[ 3 ], v[ 3 ], curvetypes[ 3 ] );
  3002. float frac = 0.0f;
  3003. if ( t[2] > t[ 1 ] )
  3004. {
  3005. frac = (time.GetSeconds() - t[1].GetSeconds()) / (float) ( t[2].GetSeconds() - t[ 1 ].GetSeconds() );
  3006. }
  3007. // Compute the lerp between ti and ti+1
  3008. out = Curve_Interpolate( frac, t, v, curvetypes, GetOwnerLog()->GetMinValue(), GetOwnerLog()->GetMaxValue() );
  3009. }
  3010. template<>
  3011. void CDmeTypedLogLayer< Quaternion >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, Quaternion& out ) const
  3012. {
  3013. Assert( GetOwnerLog() );
  3014. if ( !GetOwnerLog() )
  3015. {
  3016. CDmAttributeInfo< Quaternion >::SetDefaultValue( out );
  3017. return;
  3018. }
  3019. Assert( CanInterpolateType( GetDataType() ) );
  3020. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  3021. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  3022. Assert( IsInterpolableType( GetDataType() ) );
  3023. Quaternion v[ 4 ];
  3024. DmeTime_t t[ 4 ];
  3025. int curvetypes[ 4 ];
  3026. int ti = nKeyToSkip;
  3027. DmeTime_t time = GetKeyTime( nKeyToSkip );
  3028. if ( !IsUsingCurveTypes() )
  3029. {
  3030. if ( ti < 0 )
  3031. {
  3032. CDmAttributeInfo< Quaternion >::SetDefaultValue( out ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  3033. return;
  3034. }
  3035. else if ( ti >= m_times.Count() - 1 )
  3036. {
  3037. out = GetKeyValue( ti + 1 );
  3038. return;
  3039. }
  3040. }
  3041. DmeTime_t finalTime = GetTypedOwnerLog()->GetRightEdgeTime();
  3042. if ( finalTime != DmeTime_t( 0 ) )
  3043. {
  3044. if ( time > finalTime )
  3045. {
  3046. CDmAttributeInfo< Quaternion >::SetDefaultValue( out );
  3047. return;
  3048. }
  3049. }
  3050. else
  3051. {
  3052. if ( ti >= m_times.Count() - 1 )
  3053. {
  3054. out = GetKeyValue( ti + 1 );
  3055. return;
  3056. }
  3057. }
  3058. GetBoundedSample( ti - 2, t[ 0 ], v[ 0 ], curvetypes[ 0 ] );
  3059. GetBoundedSample( ti - 1, t[ 1 ], v[ 1 ], curvetypes[ 1 ] );
  3060. GetBoundedSample( ti + 1, t[ 2 ], v[ 2 ], curvetypes[ 2 ] );
  3061. GetBoundedSample( ti + 2, t[ 3 ], v[ 3 ], curvetypes[ 3 ] );
  3062. float frac = 0.0f;
  3063. if ( t[2] > t[ 1 ] )
  3064. {
  3065. frac = (time.GetSeconds() - t[1].GetSeconds()) / (float) ( t[2].GetSeconds() - t[ 1 ].GetSeconds() );
  3066. }
  3067. // Compute the lerp between ti and ti+1
  3068. out = Curve_Interpolate( frac, t, v, curvetypes, GetOwnerLog()->GetMinValue(), GetOwnerLog()->GetMaxValue() );
  3069. }
  3070. template<>
  3071. void CDmeTypedLogLayer< float >::GetValueUsingCurveInfo( DmeTime_t time, float& out ) const
  3072. {
  3073. Assert( GetOwnerLog() );
  3074. if ( !GetOwnerLog() )
  3075. {
  3076. out = 0.0f;
  3077. return;
  3078. }
  3079. Assert( CanInterpolateType( GetDataType() ) );
  3080. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  3081. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  3082. Assert( IsInterpolableType( GetDataType() ) );
  3083. float v[ 4 ];
  3084. DmeTime_t t[ 4 ];
  3085. int curvetypes[ 4 ];
  3086. int ti = FindKey( time );
  3087. if ( !IsUsingCurveTypes() )
  3088. {
  3089. if ( ti < 0 )
  3090. {
  3091. CDmAttributeInfo< float >::SetDefaultValue( out ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  3092. return;
  3093. }
  3094. else if ( ti >= m_times.Count() - 1 )
  3095. {
  3096. out = GetKeyValue( ti );
  3097. return;
  3098. }
  3099. }
  3100. DmeTime_t finalTime = GetTypedOwnerLog()->GetRightEdgeTime();
  3101. if ( finalTime != DmeTime_t( 0 ) )
  3102. {
  3103. if ( time > finalTime )
  3104. {
  3105. GetZeroValue( 1, out );
  3106. return;
  3107. }
  3108. }
  3109. else
  3110. {
  3111. if ( ti >= m_times.Count() - 1 )
  3112. {
  3113. out = GetKeyValue( ti );
  3114. return;
  3115. }
  3116. }
  3117. GetBoundedSample( ti - 1, t[ 0 ], v[ 0 ], curvetypes[ 0 ] );
  3118. GetBoundedSample( ti + 0, t[ 1 ], v[ 1 ], curvetypes[ 1 ] );
  3119. GetBoundedSample( ti + 1, t[ 2 ], v[ 2 ], curvetypes[ 2 ] );
  3120. GetBoundedSample( ti + 2, t[ 3 ], v[ 3 ], curvetypes[ 3 ] );
  3121. float frac = 0.0f;
  3122. if ( t[2] > t[ 1 ] )
  3123. {
  3124. frac = (time.GetSeconds() - t[1].GetSeconds()) / (float) ( t[2].GetSeconds() - t[ 1 ].GetSeconds() );
  3125. }
  3126. // Compute the lerp between ti and ti+1
  3127. out = Curve_Interpolate( frac, t, v, curvetypes, GetOwnerLog()->GetMinValue(), GetOwnerLog()->GetMaxValue() );
  3128. }
  3129. template<>
  3130. void CDmeTypedLogLayer< Vector >::GetValueUsingCurveInfo( DmeTime_t time, Vector& out ) const
  3131. {
  3132. Assert( GetOwnerLog() );
  3133. if ( !GetOwnerLog() )
  3134. {
  3135. CDmAttributeInfo< Vector >::SetDefaultValue( out );
  3136. return;
  3137. }
  3138. Assert( CanInterpolateType( GetDataType() ) );
  3139. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  3140. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  3141. Assert( IsInterpolableType( GetDataType() ) );
  3142. Vector v[ 4 ];
  3143. DmeTime_t t[ 4 ];
  3144. int curvetypes[ 4 ];
  3145. int ti = FindKey( time );
  3146. if ( !IsUsingCurveTypes() )
  3147. {
  3148. if ( ti < 0 )
  3149. {
  3150. CDmAttributeInfo< Vector >::SetDefaultValue( out ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  3151. return;
  3152. }
  3153. else if ( ti >= m_times.Count() - 1 )
  3154. {
  3155. out = GetKeyValue( ti );
  3156. return;
  3157. }
  3158. }
  3159. DmeTime_t finalTime = GetTypedOwnerLog()->GetRightEdgeTime();
  3160. if ( finalTime != DmeTime_t( 0 ) )
  3161. {
  3162. if ( time > finalTime )
  3163. {
  3164. CDmAttributeInfo< Vector >::SetDefaultValue( out );
  3165. return;
  3166. }
  3167. }
  3168. else
  3169. {
  3170. if ( ti >= m_times.Count() - 1 )
  3171. {
  3172. out = GetKeyValue( ti );
  3173. return;
  3174. }
  3175. }
  3176. GetBoundedSample( ti - 1, t[ 0 ], v[ 0 ], curvetypes[ 0 ] );
  3177. GetBoundedSample( ti + 0, t[ 1 ], v[ 1 ], curvetypes[ 1 ] );
  3178. GetBoundedSample( ti + 1, t[ 2 ], v[ 2 ], curvetypes[ 2 ] );
  3179. GetBoundedSample( ti + 2, t[ 3 ], v[ 3 ], curvetypes[ 3 ] );
  3180. float frac = 0.0f;
  3181. if ( t[2] > t[ 1 ] )
  3182. {
  3183. frac = (time.GetSeconds() - t[1].GetSeconds()) / (float) ( t[2].GetSeconds() - t[ 1 ].GetSeconds() );
  3184. }
  3185. // Compute the lerp between ti and ti+1
  3186. out = Curve_Interpolate( frac, t, v, curvetypes, GetOwnerLog()->GetMinValue(), GetOwnerLog()->GetMaxValue() );
  3187. }
  3188. template<>
  3189. void CDmeTypedLogLayer< Quaternion >::GetValueUsingCurveInfo( DmeTime_t time, Quaternion& out ) const
  3190. {
  3191. Assert( GetOwnerLog() );
  3192. if ( !GetOwnerLog() )
  3193. {
  3194. CDmAttributeInfo< Quaternion >::SetDefaultValue( out );
  3195. return;
  3196. }
  3197. Assert( CanInterpolateType( GetDataType() ) );
  3198. Assert( IsCompressed() || m_values.Count() == m_times.Count() );
  3199. Assert( !IsUsingCurveTypes() || ( m_CurveTypes.Count() == m_times.Count() ) );
  3200. Assert( IsInterpolableType( GetDataType() ) );
  3201. Quaternion v[ 4 ];
  3202. DmeTime_t t[ 4 ];
  3203. int curvetypes[ 4 ];
  3204. int ti = FindKey( time );
  3205. if ( !IsUsingCurveTypes() )
  3206. {
  3207. if ( ti < 0 )
  3208. {
  3209. CDmAttributeInfo< Quaternion >::SetDefaultValue( out ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  3210. return;
  3211. }
  3212. else if ( ti >= m_times.Count() - 1 )
  3213. {
  3214. out = GetKeyValue( ti );
  3215. return;
  3216. }
  3217. }
  3218. DmeTime_t finalTime = GetTypedOwnerLog()->GetRightEdgeTime();
  3219. if ( finalTime != DmeTime_t( 0 ) )
  3220. {
  3221. if ( time > finalTime )
  3222. {
  3223. CDmAttributeInfo< Quaternion >::SetDefaultValue( out );
  3224. return;
  3225. }
  3226. }
  3227. else
  3228. {
  3229. if ( ti >= m_times.Count() - 1 )
  3230. {
  3231. out = GetKeyValue( ti );
  3232. return;
  3233. }
  3234. }
  3235. GetBoundedSample( ti - 1, t[ 0 ], v[ 0 ], curvetypes[ 0 ] );
  3236. GetBoundedSample( ti + 0, t[ 1 ], v[ 1 ], curvetypes[ 1 ] );
  3237. GetBoundedSample( ti + 1, t[ 2 ], v[ 2 ], curvetypes[ 2 ] );
  3238. GetBoundedSample( ti + 2, t[ 3 ], v[ 3 ], curvetypes[ 3 ] );
  3239. float frac = 0.0f;
  3240. if ( t[2] > t[ 1 ] )
  3241. {
  3242. frac = (time.GetSeconds() - t[1].GetSeconds()) / (float) ( t[2].GetSeconds() - t[ 1 ].GetSeconds() );
  3243. }
  3244. // Compute the lerp between ti and ti+1
  3245. out = Curve_Interpolate( frac, t, v, curvetypes, GetOwnerLog()->GetMinValue(), GetOwnerLog()->GetMaxValue() );
  3246. }
  3247. template< class T >
  3248. void CDmeTypedLogLayer< T >::CopyLayer( const CDmeLogLayer *src )
  3249. {
  3250. const CDmeTypedLogLayer< T > *pSrc = static_cast< const CDmeTypedLogLayer< T > * >( src );
  3251. m_times = pSrc->m_times;
  3252. m_lastKey = pSrc->m_lastKey;
  3253. m_bLeftInfinite = pSrc->m_bLeftInfinite;
  3254. m_bRightInfinite = pSrc->m_bRightInfinite;
  3255. m_values = pSrc->m_values;
  3256. m_CurveTypes = pSrc->m_CurveTypes;
  3257. m_Compressed = pSrc->m_Compressed;
  3258. m_NonInterpolatedSegments = pSrc->m_NonInterpolatedSegments;
  3259. }
  3260. template< class T >
  3261. void CDmeTypedLogLayer< T >::InsertKeyFromLayer( DmeTime_t keyTime, const CDmeLogLayer *src, DmeTime_t srcKeyTime )
  3262. {
  3263. Decompress();
  3264. const CDmeTypedLogLayer< T > *pSrc = static_cast< const CDmeTypedLogLayer< T > * >( src );
  3265. Assert( pSrc );
  3266. // NOTE: This copy is necessary if src == this
  3267. T value = pSrc->GetValue( srcKeyTime );
  3268. InsertKey( keyTime, value, pSrc->GetSegmentInterpolationSetting(keyTime) );
  3269. }
  3270. template< class T >
  3271. void CDmeTypedLogLayer< T >::ExplodeLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps, DmeTime_t tResampleInterval )
  3272. {
  3273. Decompress();
  3274. const CDmeTypedLogLayer< T > *pSrc = static_cast< const CDmeTypedLogLayer< T > * >( src );
  3275. Assert( pSrc );
  3276. DmeTime_t tTimeOffset = DMETIME_ZERO;
  3277. if ( bRebaseTimestamps )
  3278. {
  3279. tTimeOffset = -startTime;
  3280. }
  3281. m_times.RemoveAll();
  3282. m_values.RemoveAll();
  3283. m_CurveTypes.RemoveAll();
  3284. bool usecurvetypes = pSrc->IsUsingCurveTypes();
  3285. // Now copy the data for the layer
  3286. for ( DmeTime_t t = startTime ; t + tResampleInterval < endTime; t += tResampleInterval )
  3287. {
  3288. DmeTime_t keyTime = DmeTime_t( t );
  3289. if ( keyTime > endTime )
  3290. {
  3291. keyTime = endTime;
  3292. }
  3293. T val = pSrc->GetValue( keyTime );
  3294. DmeTime_t nextTime = keyTime + tResampleInterval;
  3295. nextTime = MIN( nextTime, endTime );
  3296. SegmentInterpolation_t interpSetting = pSrc->GetSegmentInterpolationSetting( keyTime, nextTime, true );
  3297. keyTime += tTimeOffset;
  3298. InsertKey( keyTime, val, interpSetting, usecurvetypes ? GetDefaultCurveType() : CURVE_DEFAULT );
  3299. }
  3300. m_lastKey = m_times.Count() - 1;
  3301. }
  3302. template< class T >
  3303. void CDmeTypedLogLayer< T >::CopyPartialLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps )
  3304. {
  3305. Decompress();
  3306. const CDmeTypedLogLayer< T > *pSrc = static_cast< const CDmeTypedLogLayer< T > * >( src );
  3307. Assert( pSrc );
  3308. DmeTime_t nTimeOffset = DMETIME_ZERO;
  3309. if ( bRebaseTimestamps )
  3310. {
  3311. nTimeOffset = -startTime;
  3312. }
  3313. m_times.RemoveAll();
  3314. m_values.RemoveAll();
  3315. m_CurveTypes.RemoveAll();
  3316. m_NonInterpolatedSegments.RemoveAll();
  3317. bool usecurvetypes = pSrc->IsUsingCurveTypes();
  3318. bool bHasNonInterpolatedSegments = (pSrc->m_NonInterpolatedSegments.Count() > 0);
  3319. // Now copy the data for the later
  3320. int c = pSrc->m_times.Count();
  3321. for ( int i = 0; i < c; ++i )
  3322. {
  3323. DmeTime_t keyTime = pSrc->m_times[ i ];
  3324. if ( keyTime < startTime || keyTime > endTime )
  3325. continue;
  3326. m_times.AddToTail( pSrc->m_times[ i ] + nTimeOffset );
  3327. m_values.AddToTail( pSrc->GetKeyValue( i ) );
  3328. if ( usecurvetypes )
  3329. {
  3330. m_CurveTypes.AddToTail( pSrc->m_CurveTypes[ i ] );
  3331. }
  3332. if( bHasNonInterpolatedSegments )
  3333. {
  3334. m_NonInterpolatedSegments.AddToTail( pSrc->m_NonInterpolatedSegments[i] );
  3335. }
  3336. }
  3337. m_lastKey = m_times.Count() - 1;
  3338. }
  3339. //-----------------------------------------------------------------------------
  3340. // Purpose: Mask the specified value with the provided component flags, if a
  3341. // component is masked out then the original value of that component at the
  3342. // specified time will be used.
  3343. //-----------------------------------------------------------------------------
  3344. template<>
  3345. Vector CDmeTypedLogLayer< Vector >::MaskValue( DmeTime_t time, const Vector& value, LogComponents_t componentFlags ) const
  3346. {
  3347. Vector writeValue = value;
  3348. if ( ( componentFlags & LOG_COMPONENTS_ALL ) != LOG_COMPONENTS_ALL )
  3349. {
  3350. Vector curVal = GetValue( time );
  3351. writeValue = ::MaskValue( value, curVal, componentFlags );
  3352. }
  3353. return writeValue;
  3354. }
  3355. template<>
  3356. Quaternion CDmeTypedLogLayer< Quaternion >::MaskValue( DmeTime_t time, const Quaternion& value, LogComponents_t componentFlags ) const
  3357. {
  3358. Quaternion writeValue = value;
  3359. if ( ( componentFlags & LOG_COMPONENTS_ALL ) != LOG_COMPONENTS_ALL )
  3360. {
  3361. Quaternion curQuat = GetValue( time );
  3362. writeValue = ::MaskValue( value, curQuat, componentFlags );
  3363. }
  3364. return writeValue;
  3365. }
  3366. template< class T >
  3367. T CDmeTypedLogLayer< T >::MaskValue( DmeTime_t time, const T& value, LogComponents_t componentFlags ) const
  3368. {
  3369. return value;
  3370. }
  3371. template< class T >
  3372. // Masks all keys within the time range, returns true if keys were modified
  3373. bool CDmeTypedLogLayer< T >::MaskKeyRange( DmeTime_t tStartTime, DmeTime_t tEndTime, LogComponents_t nComponentFlags, bool bInfiniteLeft /*= false*/, bool bInfiniteRight /*= false*/ )
  3374. {
  3375. bool bRet = false;
  3376. T startVal = GetValue( tStartTime );
  3377. T endVal = GetValue( tEndTime );
  3378. if ( bInfiniteRight )
  3379. {
  3380. // we'll want to "hold" the masked start value through the region
  3381. endVal = ::MaskValue( startVal, endVal, nComponentFlags );
  3382. }
  3383. else if ( bInfiniteLeft )
  3384. {
  3385. // we'll want to hold the "end" value backwards throug
  3386. startVal = ::MaskValue( endVal, startVal, nComponentFlags );
  3387. }
  3388. DmeTime_t dt = tEndTime - tStartTime;
  3389. if ( dt <= DMETIME_ZERO )
  3390. return bRet;
  3391. int nKeyCount = GetKeyCount();
  3392. for ( int nKey = 0; nKey < nKeyCount; ++nKey )
  3393. {
  3394. DmeTime_t tKeyTime = GetKeyTime( nKey );
  3395. if ( tKeyTime < tStartTime )
  3396. continue;
  3397. if ( tKeyTime > tEndTime )
  3398. break;
  3399. bRet = true;
  3400. T value = GetKeyValue( nKey );
  3401. float frac = ( tKeyTime - tStartTime ) / ( dt );
  3402. T maskedValue = Interpolate< T >( frac, startVal, endVal );
  3403. T newVal = ::MaskValue( maskedValue, value, nComponentFlags );
  3404. SetKeyValue( nKey, newVal );
  3405. }
  3406. return bRet;
  3407. }
  3408. template< class T >
  3409. void CDmeTypedLogLayer< T >::MakeRoomForSamplesMaskedSubcomponents( CDmeLogLayer *pBaseLayer, DmeTime_t tStart, DmeTime_t tEnd, DmeTime_t tLeftShift, DmeTime_t tRightShift, LogComponents_t nComponents )
  3410. {
  3411. CDmeTypedLogLayer< T > *pBase = ( CDmeTypedLogLayer< T > * )pBaseLayer;
  3412. T startVal = pBase->GetValue( tStart );
  3413. T endVal = pBase->GetValue( tEnd );
  3414. DmeTime_t tNewStart = tStart + tLeftShift;
  3415. DmeTime_t tNewEnd = tEnd + tRightShift;
  3416. //I can't quite follow exactly how these shifts end up. Taking the safe route of propogating non-interpolated segements to the new layer
  3417. SegmentInterpolation_t interpSetting = pBase->GetSegmentInterpolationSetting( MIN( tStart, tNewStart ), MAX( tEnd, tNewEnd ), false );
  3418. bool bInterpEndpoints = pBase->GetSegmentInterpolationSetting( tStart, tEnd, false ) == SEGMENT_INTERPOLATE;
  3419. int keyCount = pBase->GetKeyCount();
  3420. for ( int key = 0; key < keyCount; ++key )
  3421. {
  3422. DmeTime_t keyTime = pBase->GetKeyTime( key );
  3423. DmeTime_t newKeyTime = keyTime;
  3424. T origValue = pBase->GetKeyValue( key );
  3425. if ( keyTime <= tStart )
  3426. {
  3427. newKeyTime += tLeftShift;
  3428. }
  3429. else if ( keyTime >= tEnd )
  3430. {
  3431. newKeyTime += tRightShift;
  3432. }
  3433. else
  3434. {
  3435. if ( keyTime <= tNewStart || keyTime >= tNewEnd )
  3436. {
  3437. DmeTime_t oppositeKeyTime = ( keyTime <= tNewStart ) ?
  3438. tStart + ( keyTime - tNewStart ) :
  3439. tEnd + ( keyTime - tNewEnd );
  3440. T xyVal = pBase->GetValue( oppositeKeyTime );
  3441. T unshiftedValue = ::MaskValue( xyVal, origValue, nComponents );
  3442. InsertKey( keyTime, unshiftedValue, interpSetting );
  3443. }
  3444. else
  3445. {
  3446. float frac = GetFractionOfTimeBetween( keyTime, tNewStart, tNewEnd );
  3447. T clearedValue = bInterpEndpoints ? Interpolate( frac, startVal, endVal ) : startVal;
  3448. T val = ::MaskValue( clearedValue, origValue, nComponents );
  3449. InsertKey( keyTime, val, interpSetting );
  3450. }
  3451. continue;
  3452. }
  3453. if ( newKeyTime != keyTime )
  3454. {
  3455. // xy comes from unshifted position
  3456. T newValue = pBase->GetValue( newKeyTime );
  3457. // z preserved from new key time
  3458. T shiftedValue = ::MaskValue( origValue, newValue, nComponents );
  3459. InsertKey( newKeyTime, shiftedValue, interpSetting );
  3460. if ( keyTime <= ( tNewStart ) ||
  3461. keyTime >= ( tNewEnd ) )
  3462. {
  3463. DmeTime_t dt = newKeyTime - keyTime;
  3464. DmeTime_t oppositeKeyTime = keyTime - dt;
  3465. T xyVal = pBase->GetValue( oppositeKeyTime );
  3466. T unshiftedValue = ::MaskValue( xyVal, origValue, nComponents );
  3467. InsertKey( keyTime, unshiftedValue, interpSetting );
  3468. }
  3469. else
  3470. {
  3471. float frac = GetFractionOfTimeBetween( newKeyTime, tStart - tLeftShift, tEnd + tRightShift );
  3472. T clearedValue = bInterpEndpoints ? Interpolate( frac, startVal, endVal ) : startVal;
  3473. T val = ::MaskValue( clearedValue, origValue, nComponents );
  3474. InsertKey( keyTime, val, interpSetting );
  3475. }
  3476. }
  3477. else
  3478. {
  3479. InsertKey( keyTime, origValue, interpSetting );
  3480. }
  3481. }
  3482. }
  3483. //-----------------------------------------------------------------------------
  3484. // Creates a log of a specific type
  3485. //-----------------------------------------------------------------------------
  3486. template< class T >
  3487. CDmeLogLayer *CreateLayer< T >( CDmeTypedLog< T > *pOwnerLog )
  3488. {
  3489. DmFileId_t fileid = pOwnerLog ? pOwnerLog->GetFileId() : DMFILEID_INVALID;
  3490. CDmeLogLayer *layer = NULL;
  3491. switch ( CDmAttributeInfo<T>::AttributeType() )
  3492. {
  3493. case AT_INT:
  3494. case AT_INT_ARRAY:
  3495. layer = CreateElement< CDmeIntLogLayer >( "int log", fileid );
  3496. break;
  3497. case AT_FLOAT:
  3498. case AT_FLOAT_ARRAY:
  3499. layer = CreateElement< CDmeFloatLogLayer >( "float log", fileid );
  3500. break;
  3501. case AT_BOOL:
  3502. case AT_BOOL_ARRAY:
  3503. layer = CreateElement< CDmeBoolLogLayer >( "bool log", fileid );
  3504. break;
  3505. case AT_COLOR:
  3506. case AT_COLOR_ARRAY:
  3507. layer = CreateElement< CDmeColorLogLayer >( "color log", fileid );
  3508. break;
  3509. case AT_VECTOR2:
  3510. case AT_VECTOR2_ARRAY:
  3511. layer = CreateElement< CDmeVector2LogLayer >( "vector2 log", fileid );
  3512. break;
  3513. case AT_VECTOR3:
  3514. case AT_VECTOR3_ARRAY:
  3515. layer = CreateElement< CDmeVector3LogLayer >( "vector3 log", fileid );
  3516. break;
  3517. case AT_VECTOR4:
  3518. case AT_VECTOR4_ARRAY:
  3519. layer = CreateElement< CDmeVector4LogLayer >( "vector4 log", fileid );
  3520. break;
  3521. case AT_QANGLE:
  3522. case AT_QANGLE_ARRAY:
  3523. layer = CreateElement< CDmeQAngleLogLayer >( "qangle log", fileid );
  3524. break;
  3525. case AT_QUATERNION:
  3526. case AT_QUATERNION_ARRAY:
  3527. layer = CreateElement< CDmeQuaternionLogLayer >( "quaternion log", fileid );
  3528. break;
  3529. case AT_VMATRIX:
  3530. case AT_VMATRIX_ARRAY:
  3531. layer = CreateElement< CDmeVMatrixLogLayer >( "vmatrix log", fileid );
  3532. break;
  3533. case AT_STRING:
  3534. case AT_STRING_ARRAY:
  3535. layer = CreateElement< CDmeStringLogLayer >( "string log", fileid );
  3536. break;
  3537. case AT_TIME:
  3538. case AT_TIME_ARRAY:
  3539. layer = CreateElement< CDmeTimeLogLayer >( "time log", fileid );
  3540. break;
  3541. }
  3542. if ( layer )
  3543. {
  3544. layer->SetOwnerLog( pOwnerLog );
  3545. }
  3546. return layer;
  3547. }
  3548. //-----------------------------------------------------------------------------
  3549. //
  3550. // CDmeCurveInfo - abstract base class
  3551. //
  3552. //-----------------------------------------------------------------------------
  3553. void CDmeCurveInfo::OnConstruction()
  3554. {
  3555. m_DefaultCurveType.Init( this, "defaultCurveType" );
  3556. m_MinValue.InitAndSet( this, "minvalue", 0.0f );
  3557. m_MaxValue.InitAndSet( this, "maxvalue", 1.0f );
  3558. }
  3559. void CDmeCurveInfo::OnDestruction()
  3560. {
  3561. }
  3562. // Global override for all keys unless overriden by specific key
  3563. void CDmeCurveInfo::SetDefaultCurveType( int curveType )
  3564. {
  3565. m_DefaultCurveType = curveType;
  3566. }
  3567. int CDmeCurveInfo::GetDefaultCurveType() const
  3568. {
  3569. return m_DefaultCurveType.Get();
  3570. }
  3571. void CDmeCurveInfo::SetMinValue( float val )
  3572. {
  3573. m_MinValue = val;
  3574. }
  3575. float CDmeCurveInfo::GetMinValue() const
  3576. {
  3577. return m_MinValue;
  3578. }
  3579. void CDmeCurveInfo::SetMaxValue( float val )
  3580. {
  3581. m_MaxValue = val;
  3582. }
  3583. float CDmeCurveInfo::GetMaxValue() const
  3584. {
  3585. return m_MaxValue;
  3586. }
  3587. //-----------------------------------------------------------------------------
  3588. //
  3589. // CDmeTypedCurveInfo - implementation class for all logs
  3590. //
  3591. //-----------------------------------------------------------------------------
  3592. template< class T >
  3593. void CDmeTypedCurveInfo< T >::OnConstruction()
  3594. {
  3595. m_bUseEdgeInfo.Init( this, "useEdgeInfo" );
  3596. m_DefaultEdgeValue.Init( this, "defaultEdgeZeroValue" );
  3597. m_RightEdgeTime.Init( this, "rightEdgeTime" );
  3598. for ( int i = 0; i < 2; ++i )
  3599. {
  3600. char edgename[ 32 ];
  3601. Q_snprintf( edgename, sizeof( edgename ), "%s", i == 0 ? "left" : "right" );
  3602. char name[ 32 ];
  3603. Q_snprintf( name, sizeof( name ), "%sEdgeActive", edgename );
  3604. m_bEdgeActive[ i ].Init( this, name );
  3605. Q_snprintf( name, sizeof( name ), "%sEdgeValue", edgename );
  3606. m_EdgeValue[ i ].Init( this, name );
  3607. Q_snprintf( name, sizeof( name ), "%sEdgeCurveType", edgename );
  3608. m_EdgeCurveType[ i ].Init( this, name );
  3609. }
  3610. }
  3611. template< class T >
  3612. void CDmeTypedCurveInfo< T >::OnDestruction()
  3613. {
  3614. }
  3615. template< class T >
  3616. void CDmeTypedCurveInfo< T >::SetUseEdgeInfo( bool state )
  3617. {
  3618. m_bUseEdgeInfo = state;
  3619. }
  3620. template< class T >
  3621. bool CDmeTypedCurveInfo< T >::IsUsingEdgeInfo() const
  3622. {
  3623. return m_bUseEdgeInfo;
  3624. }
  3625. template< class T >
  3626. void CDmeTypedCurveInfo< T >::SetEdgeInfo( int edge, bool active, const T& val, int curveType )
  3627. {
  3628. SetUseEdgeInfo( true );
  3629. Assert( edge == 0 || edge == 1 );
  3630. m_bEdgeActive[ edge ] = active;
  3631. m_EdgeValue[ edge ] = val;
  3632. m_EdgeCurveType[ edge ] = curveType;
  3633. }
  3634. template< class T >
  3635. void CDmeTypedCurveInfo< T >::SetDefaultEdgeZeroValue( const T& val )
  3636. {
  3637. m_DefaultEdgeValue = val;
  3638. }
  3639. template< class T >
  3640. const T& CDmeTypedCurveInfo< T >::GetDefaultEdgeZeroValue() const
  3641. {
  3642. return m_DefaultEdgeValue;
  3643. }
  3644. template< class T >
  3645. void CDmeTypedCurveInfo< T >::SetRightEdgeTime( DmeTime_t time )
  3646. {
  3647. m_RightEdgeTime = time;
  3648. }
  3649. template< class T >
  3650. DmeTime_t CDmeTypedCurveInfo< T >::GetRightEdgeTime() const
  3651. {
  3652. return m_RightEdgeTime;
  3653. }
  3654. template< class T >
  3655. void CDmeTypedCurveInfo< T >::GetEdgeInfo( int edge, bool& active, T& val, int& curveType ) const
  3656. {
  3657. Assert( IsUsingEdgeInfo() );
  3658. Assert( edge == 0 || edge == 1 );
  3659. active = m_bEdgeActive[ edge ];
  3660. val = m_EdgeValue[ edge ];
  3661. curveType = m_EdgeCurveType[ edge ];
  3662. }
  3663. template< class T >
  3664. int CDmeTypedCurveInfo< T >::GetEdgeCurveType( int edge ) const
  3665. {
  3666. Assert( edge == 0 || edge == 1 );
  3667. if ( !m_bEdgeActive[ edge ] )
  3668. {
  3669. return m_DefaultCurveType;
  3670. }
  3671. if ( m_EdgeCurveType[ edge ] == CURVE_DEFAULT )
  3672. {
  3673. return m_DefaultCurveType;
  3674. }
  3675. return m_EdgeCurveType[ edge ];
  3676. }
  3677. template<>
  3678. void CDmeTypedCurveInfo<float>::GetZeroValue( int side, float& val ) const
  3679. {
  3680. if ( !m_bUseEdgeInfo )
  3681. {
  3682. val = 0.0f;
  3683. return;
  3684. }
  3685. if ( m_bEdgeActive[ side ] )
  3686. {
  3687. val = m_EdgeValue[ side ];
  3688. return;
  3689. }
  3690. val = m_DefaultEdgeValue;
  3691. }
  3692. template<>
  3693. bool CDmeTypedCurveInfo<float>::IsEdgeActive( int edge ) const
  3694. {
  3695. return m_bEdgeActive[ edge ];
  3696. }
  3697. template<>
  3698. void CDmeTypedCurveInfo<float>::GetEdgeValue( int edge, float& value ) const
  3699. {
  3700. value = m_EdgeValue[ edge ];
  3701. }
  3702. template<>
  3703. void CDmeTypedCurveInfo<Vector>::GetZeroValue( int side, Vector& val ) const
  3704. {
  3705. if ( !m_bUseEdgeInfo )
  3706. {
  3707. val = vec3_origin;
  3708. return;
  3709. }
  3710. if ( m_bEdgeActive[ side ] )
  3711. {
  3712. val = m_EdgeValue[ side ];
  3713. return;
  3714. }
  3715. val = m_DefaultEdgeValue;
  3716. }
  3717. template<>
  3718. void CDmeTypedCurveInfo<Quaternion>::GetZeroValue( int side, Quaternion& val ) const
  3719. {
  3720. if ( !m_bUseEdgeInfo )
  3721. {
  3722. val.Init();
  3723. return;
  3724. }
  3725. if ( m_bEdgeActive[ side ] )
  3726. {
  3727. val = m_EdgeValue[ side ];
  3728. return;
  3729. }
  3730. val = m_DefaultEdgeValue;
  3731. }
  3732. //-----------------------------------------------------------------------------
  3733. //
  3734. // CDmeLog - abstract base class
  3735. //
  3736. //-----------------------------------------------------------------------------
  3737. void CDmeLog::OnConstruction()
  3738. {
  3739. m_Layers.Init( this, "layers", FATTRIB_MUSTCOPY | FATTRIB_HAS_CALLBACK );
  3740. m_CurveInfo.Init( this, "curveinfo", FATTRIB_MUSTCOPY | FATTRIB_HAS_CALLBACK );
  3741. }
  3742. void CDmeLog::OnDestruction()
  3743. {
  3744. }
  3745. int CDmeLog::GetTopmostLayer() const
  3746. {
  3747. return m_Layers.Count() - 1;
  3748. }
  3749. int CDmeLog::GetNumLayers() const
  3750. {
  3751. return m_Layers.Count();
  3752. }
  3753. CDmeLogLayer *CDmeLog::GetLayer( int index )
  3754. {
  3755. return m_Layers.IsValidIndex( index ) ? m_Layers[ index ] : NULL;
  3756. }
  3757. const CDmeLogLayer *CDmeLog::GetLayer( int index ) const
  3758. {
  3759. return m_Layers.IsValidIndex( index ) ? m_Layers[ index ] : NULL;
  3760. }
  3761. bool CDmeLog::IsEmpty() const
  3762. {
  3763. int c = m_Layers.Count();
  3764. for ( int i = 0; i < c; ++i )
  3765. {
  3766. CDmeLogLayer* layer = m_Layers[ i ];
  3767. if ( layer->GetKeyCount() > 0 )
  3768. return false;
  3769. }
  3770. return true;
  3771. }
  3772. void CDmeLog::ScaleSampleTimes( float scale )
  3773. {
  3774. int nLayers = m_Layers.Count();
  3775. for ( int i = 0; i < nLayers; ++i )
  3776. {
  3777. CDmeLogLayer* layer = m_Layers[ i ];
  3778. if ( !layer )
  3779. continue;
  3780. layer->ScaleSampleTimes( scale );
  3781. }
  3782. }
  3783. void CDmeLog::FindLayersForTime( DmeTime_t time, CUtlVector< int >& list ) const
  3784. {
  3785. list.RemoveAll();
  3786. int c = m_Layers.Count();
  3787. // The base layer is always available!!!
  3788. if ( c > 0 )
  3789. {
  3790. list.AddToTail( 0 );
  3791. }
  3792. for ( int i = 1; i < c; ++i )
  3793. {
  3794. CDmeLogLayer* layer = m_Layers[ i ];
  3795. DmeTime_t layerStart = layer->GetBeginTime( true );
  3796. if ( layerStart == DmeTime_t::InvalidTime() )
  3797. continue;
  3798. DmeTime_t layerEnd = layer->GetEndTime( true );
  3799. if ( layerEnd == DmeTime_t::InvalidTime() )
  3800. continue;
  3801. if ( time >= layerStart && time <= layerEnd )
  3802. {
  3803. list.AddToTail( i );
  3804. }
  3805. }
  3806. }
  3807. //-----------------------------------------------------------------------------
  3808. // Find the top most layer for the specified time below the provided top layer
  3809. //-----------------------------------------------------------------------------
  3810. int CDmeLog::FindLayerForTimeBelowLayer( DmeTime_t time, int topLayerIndex ) const
  3811. {
  3812. int c = topLayerIndex;
  3813. for ( int i = c - 1; i >= 0; --i )
  3814. {
  3815. CDmeLogLayer* layer = m_Layers[ i ];
  3816. DmeTime_t layerStart = layer->GetBeginTime( true );
  3817. if ( layerStart == DmeTime_t::InvalidTime() )
  3818. continue;
  3819. DmeTime_t layerEnd = layer->GetEndTime( true );
  3820. if ( layerEnd == DmeTime_t::InvalidTime() )
  3821. continue;
  3822. if ( time >= layerStart && time <= layerEnd )
  3823. return i;
  3824. }
  3825. return ( c > 0 ) ? 0 : -1;
  3826. }
  3827. int CDmeLog::FindLayerForTimeSkippingTopmost( DmeTime_t time ) const
  3828. {
  3829. // This makes it never consider the topmost layer!!!
  3830. return FindLayerForTimeBelowLayer( time, m_Layers.Count() - 1 );
  3831. }
  3832. int CDmeLog::FindLayerForTime( DmeTime_t time ) const
  3833. {
  3834. int c = m_Layers.Count();
  3835. for ( int i = c - 1; i >= 0; --i )
  3836. {
  3837. CDmeLogLayer* layer = m_Layers[ i ];
  3838. DmeTime_t layerStart = layer->GetBeginTime( true );
  3839. if ( layerStart == DmeTime_t::InvalidTime() )
  3840. continue;
  3841. DmeTime_t layerEnd = layer->GetEndTime( true );
  3842. if ( layerEnd == DmeTime_t::InvalidTime() )
  3843. continue;
  3844. if ( time >= layerStart && time <= layerEnd )
  3845. return i;
  3846. }
  3847. return ( c > 0 ) ? 0 : -1;
  3848. }
  3849. DmeTime_t CDmeLog::GetBeginTime() const
  3850. {
  3851. int c = m_Layers.Count();
  3852. if ( c == 0 )
  3853. return DmeTime_t::MinTime();
  3854. DmeTime_t bestMin = DmeTime_t::MinTime();
  3855. for ( int i = 0; i < c; ++i )
  3856. {
  3857. CDmeLogLayer* layer = m_Layers[ i ];
  3858. DmeTime_t layerStart = layer->GetBeginTime( false );
  3859. if ( layerStart == DmeTime_t::InvalidTime() )
  3860. continue;
  3861. if ( bestMin == DmeTime_t::MinTime() )
  3862. {
  3863. bestMin = layerStart;
  3864. }
  3865. else if ( layerStart < bestMin )
  3866. {
  3867. bestMin = layerStart;
  3868. }
  3869. }
  3870. return bestMin;
  3871. }
  3872. DmeTime_t CDmeLog::GetEndTime() const
  3873. {
  3874. int c = m_Layers.Count();
  3875. if ( c == 0 )
  3876. return DmeTime_t::MaxTime();
  3877. DmeTime_t bestMax = DmeTime_t::MaxTime();
  3878. for ( int i = 0; i < c; ++i )
  3879. {
  3880. CDmeLogLayer *layer = m_Layers[ i ];
  3881. DmeTime_t layerEnd = layer->GetEndTime( false );
  3882. if ( layerEnd == DmeTime_t::InvalidTime() )
  3883. continue;
  3884. if ( bestMax == DmeTime_t::MaxTime() )
  3885. {
  3886. bestMax = layerEnd;
  3887. }
  3888. else if ( layerEnd > bestMax )
  3889. {
  3890. bestMax = layerEnd;
  3891. }
  3892. }
  3893. return bestMax;
  3894. }
  3895. //-----------------------------------------------------------------------------
  3896. // Returns the number of keys
  3897. //-----------------------------------------------------------------------------
  3898. int CDmeLog::GetKeyCount() const
  3899. {
  3900. int bestLayer = GetTopmostLayer();
  3901. if ( bestLayer < 0 )
  3902. return 0;
  3903. return GetLayer( bestLayer )->GetKeyCount();
  3904. }
  3905. //-----------------------------------------------------------------------------
  3906. // Scale + bias key times
  3907. //-----------------------------------------------------------------------------
  3908. void CDmeLog::ScaleBiasKeyTimes( double flScale, DmeTime_t nBias )
  3909. {
  3910. // Don't waste time on the identity transform
  3911. if ( ( nBias == DMETIME_ZERO ) && ( fabs( flScale - 1.0 ) < 1e-5 ) )
  3912. return;
  3913. int nCount = GetNumLayers();
  3914. for ( int i = 0; i < nCount; ++i )
  3915. {
  3916. CDmeLogLayer *pLayer = GetLayer( i );
  3917. pLayer->ScaleBiasKeyTimes( flScale, nBias );
  3918. }
  3919. }
  3920. //-----------------------------------------------------------------------------
  3921. // Resolve - keeps non-attribute data in sync with attribute data
  3922. //-----------------------------------------------------------------------------
  3923. void CDmeLog::Resolve()
  3924. {
  3925. int c = m_Layers.Count();
  3926. for ( int i = 0; i < c; ++i )
  3927. {
  3928. CDmeLogLayer* layer = m_Layers[ i ];
  3929. layer->SetOwnerLog( this );
  3930. }
  3931. }
  3932. void CDmeLog::OnAttributeChanged( CDmAttribute *pAttribute )
  3933. {
  3934. if ( pAttribute == m_CurveInfo.GetAttribute() )
  3935. {
  3936. OnUsingCurveTypesChanged();
  3937. }
  3938. }
  3939. void CDmeLog::OnUsingCurveTypesChanged()
  3940. {
  3941. int c = m_Layers.Count();
  3942. for ( int i = 0; i < c; ++i )
  3943. {
  3944. GetLayer( i )->OnUsingCurveTypesChanged();
  3945. }
  3946. }
  3947. // curve info helpers
  3948. bool CDmeLog::IsUsingCurveTypes() const
  3949. {
  3950. return m_CurveInfo.GetElement() != NULL;
  3951. }
  3952. const CDmeCurveInfo *CDmeLog::GetCurveInfo() const
  3953. {
  3954. return m_CurveInfo.GetElement();
  3955. }
  3956. CDmeCurveInfo *CDmeLog::GetCurveInfo()
  3957. {
  3958. return m_CurveInfo.GetElement();
  3959. }
  3960. // accessors for CurveInfo data
  3961. int CDmeLog::GetDefaultCurveType() const
  3962. {
  3963. Assert( IsUsingCurveTypes() );
  3964. return m_CurveInfo->GetDefaultCurveType();
  3965. }
  3966. // min/max accessors
  3967. float CDmeLog::GetMinValue() const
  3968. {
  3969. Assert( IsUsingCurveTypes() );
  3970. return m_CurveInfo->GetMinValue();
  3971. }
  3972. void CDmeLog::SetMinValue( float val )
  3973. {
  3974. Assert( IsUsingCurveTypes() );
  3975. m_CurveInfo->SetMinValue( val );
  3976. }
  3977. float CDmeLog::GetMaxValue() const
  3978. {
  3979. Assert( IsUsingCurveTypes() );
  3980. return m_CurveInfo->GetMaxValue();
  3981. }
  3982. void CDmeLog::SetMaxValue( float val )
  3983. {
  3984. Assert( IsUsingCurveTypes() );
  3985. m_CurveInfo->SetMaxValue( val );
  3986. }
  3987. void CDmeLog::SetKeyCurveType( int nKeyIndex, int curveType )
  3988. {
  3989. int bestLayer = GetTopmostLayer();
  3990. if ( bestLayer < 0 )
  3991. return;
  3992. GetLayer( bestLayer )->SetKeyCurveType( nKeyIndex, curveType );
  3993. }
  3994. int CDmeLog::GetKeyCurveType( int nKeyIndex ) const
  3995. {
  3996. int bestLayer = GetTopmostLayer();
  3997. if ( bestLayer < 0 )
  3998. return CURVE_DEFAULT;
  3999. return GetLayer( bestLayer )->GetKeyCurveType( nKeyIndex );
  4000. }
  4001. //-----------------------------------------------------------------------------
  4002. // Removes all keys in a certain time interval
  4003. //-----------------------------------------------------------------------------
  4004. bool CDmeLog::RemoveKeys( DmeTime_t tStartTime, DmeTime_t tEndTime )
  4005. {
  4006. CDmeLogLayer *pLayer = GetLayer( GetTopmostLayer() );
  4007. int nKeyCount = pLayer->GetKeyCount();
  4008. int nFirstRemove = -1;
  4009. int nLastRemove = -1;
  4010. for ( int nKey = 0; nKey < nKeyCount; ++nKey )
  4011. {
  4012. DmeTime_t tKeyTime = pLayer->GetKeyTime( nKey );
  4013. if ( tKeyTime < tStartTime )
  4014. continue;
  4015. if ( tKeyTime > tEndTime )
  4016. break;
  4017. if ( nFirstRemove == -1 )
  4018. {
  4019. nFirstRemove = nKey;
  4020. }
  4021. nLastRemove = nKey;
  4022. }
  4023. if ( nFirstRemove != -1 )
  4024. {
  4025. int nRemoveCount = nLastRemove - nFirstRemove + 1;
  4026. pLayer->RemoveKey( nFirstRemove, nRemoveCount );
  4027. return true;
  4028. }
  4029. return false;
  4030. }
  4031. //-----------------------------------------------------------------------------
  4032. // Add keys at tStartTime and tEndTime, and remove all keys outside the range
  4033. //-----------------------------------------------------------------------------
  4034. void CDmeLog::TrimKeys( DmeTime_t tStartTime, DmeTime_t tEndTime )
  4035. {
  4036. CDmeLogLayer *pLayer = GetLayer( GetTopmostLayer() );
  4037. if ( !pLayer )
  4038. return;
  4039. pLayer->TrimKeys( tStartTime, tEndTime );
  4040. }
  4041. //-----------------------------------------------------------------------------
  4042. // Get the number of bookmark times associated with the specified component of
  4043. // the log.
  4044. //-----------------------------------------------------------------------------
  4045. int CDmeLog::GetNumBookmarks( int nComponentIndex ) const
  4046. {
  4047. if ( nComponentIndex < GetNumBookmarkComponents() )
  4048. {
  4049. return m_BookmarkTimes[ nComponentIndex ].Count();
  4050. }
  4051. Assert( nComponentIndex < GetNumBookmarkComponents() );
  4052. return -1;
  4053. }
  4054. //-----------------------------------------------------------------------------
  4055. // Get the time of the specified bookmark
  4056. //-----------------------------------------------------------------------------
  4057. DmeTime_t CDmeLog::GetBookmarkTime( int nBookmarkIndex, int nComponentIndex ) const
  4058. {
  4059. if ( nComponentIndex < GetNumBookmarkComponents() )
  4060. {
  4061. if ( nBookmarkIndex < m_BookmarkTimes[ nComponentIndex ].Count() )
  4062. {
  4063. return m_BookmarkTimes[ nComponentIndex ][ nBookmarkIndex ];
  4064. }
  4065. Assert( nBookmarkIndex < m_BookmarkTimes[ nComponentIndex ].Count() );
  4066. }
  4067. Assert( nComponentIndex < GetNumBookmarkComponents() );
  4068. return DmeTime_t( 0 );
  4069. }
  4070. //-----------------------------------------------------------------------------
  4071. // Add a bookmark time for the specified component. Bookmarks times are stored
  4072. // in order, so the time will be inserted at the appropriate location in the
  4073. // list.
  4074. //-----------------------------------------------------------------------------
  4075. void CDmeLog::AddBookmark( DmeTime_t time, int nComponentIndex )
  4076. {
  4077. if ( nComponentIndex >= GetNumBookmarkComponents() )
  4078. return;
  4079. // Search the existing bookmarks to see if there is already one at the specified time.
  4080. CDmaArray< DmeTime_t > &times = m_BookmarkTimes[ nComponentIndex ];
  4081. int nBookmarks = times.Count();
  4082. for ( int i = 0; i < nBookmarks; ++i )
  4083. {
  4084. if ( times[ i ] == time )
  4085. {
  4086. return;
  4087. }
  4088. else if ( times[ i ] > time )
  4089. {
  4090. times.InsertBefore( i, time );
  4091. return;
  4092. }
  4093. }
  4094. times.AddToTail( time );
  4095. }
  4096. //-----------------------------------------------------------------------------
  4097. // Remove the bookmark at the specified time.
  4098. //-----------------------------------------------------------------------------
  4099. bool CDmeLog::RemoveBookmark( DmeTime_t time, int nComponentIndex )
  4100. {
  4101. if ( nComponentIndex >= GetNumBookmarkComponents() )
  4102. return false;
  4103. CDmaArray< DmeTime_t > &times = m_BookmarkTimes[ nComponentIndex ];
  4104. int nBookmarks = times.Count();
  4105. for ( int i = 0; i < nBookmarks; ++i )
  4106. {
  4107. if ( times[ i ] >= time )
  4108. {
  4109. // Remove the time entry if it matches the specified time,
  4110. // fast remove cannot be used because the times are sorted.
  4111. if ( times[ i ] == time )
  4112. {
  4113. times.Remove( i );
  4114. return true;
  4115. }
  4116. else
  4117. {
  4118. return false;
  4119. }
  4120. }
  4121. }
  4122. return false;
  4123. }
  4124. //-----------------------------------------------------------------------------
  4125. // Remove all bookmarks from the log
  4126. //-----------------------------------------------------------------------------
  4127. void CDmeLog::RemoveAllBookmarks( int nComponentIndex )
  4128. {
  4129. if ( nComponentIndex < GetNumBookmarkComponents() )
  4130. {
  4131. m_BookmarkTimes[ nComponentIndex ].RemoveAll();
  4132. }
  4133. }
  4134. //-----------------------------------------------------------------------------
  4135. // Set all of the bookmark times for the log, clearing out any previous values
  4136. //-----------------------------------------------------------------------------
  4137. void CDmeLog::SetAllBookmarks( int nComponentIndex, const CUtlVector< DmeTime_t > &times )
  4138. {
  4139. if ( nComponentIndex < GetNumBookmarkComponents() )
  4140. {
  4141. m_BookmarkTimes[ nComponentIndex ] = times;
  4142. }
  4143. }
  4144. //-----------------------------------------------------------------------------
  4145. // CDmeTypedLog - implementation class for all logs
  4146. //-----------------------------------------------------------------------------
  4147. template< class T >
  4148. void CDmeTypedLog< T >::OnConstruction()
  4149. {
  4150. if ( !g_pDataModel->IsUnserializing() )
  4151. {
  4152. // Add the default layer!!!
  4153. AddNewLayer();
  4154. Assert( m_Layers.Count() == 1 );
  4155. }
  4156. m_UseDefaultValue.InitAndSet( this, "usedefaultvalue", false );
  4157. m_DefaultValue.Init( this, "defaultvalue" );
  4158. InitalizeBookmarkArrays();
  4159. }
  4160. template< class T >
  4161. void CDmeTypedLog< T >::OnDestruction()
  4162. {
  4163. }
  4164. template< class T >
  4165. void CDmeTypedLog< T >::ClearAndAddSampleAtTime( DmeTime_t time )
  4166. {
  4167. const T &value = GetValue( time );
  4168. SegmentInterpolation_t interpSetting = GetSegmentInterpolationSetting( time );
  4169. ClearKeys();
  4170. SetKey( time, value, interpSetting );
  4171. }
  4172. template< class T >
  4173. void CDmeTypedLog< T >::SetDefaultValue( const T& value )
  4174. {
  4175. m_UseDefaultValue = true;
  4176. m_DefaultValue.Set( value );
  4177. }
  4178. template< class T >
  4179. const T& CDmeTypedLog< T >::GetDefaultValue() const
  4180. {
  4181. Assert( (bool)m_UseDefaultValue );
  4182. return m_DefaultValue;
  4183. }
  4184. template< class T >
  4185. bool CDmeTypedLog< T >::HasDefaultValue() const
  4186. {
  4187. return m_UseDefaultValue;
  4188. }
  4189. template< class T >
  4190. void CDmeTypedLog< T >::ClearDefaultValue()
  4191. {
  4192. m_UseDefaultValue = false;
  4193. T out;
  4194. CDmAttributeInfo< T >::SetDefaultValue( out );
  4195. m_DefaultValue.Set( out );
  4196. }
  4197. template< class T >
  4198. void CDmeTypedLog< T >::InitalizeBookmarkArrays()
  4199. {
  4200. m_BookmarkTimes[ 0 ].Init( this, "bookmarks" );
  4201. }
  4202. template<>
  4203. void CDmeTypedLog< Vector >::InitalizeBookmarkArrays()
  4204. {
  4205. m_BookmarkTimes[ 0 ].Init( this, "bookmarksX" );
  4206. m_BookmarkTimes[ 1 ].Init( this, "bookmarksY" );
  4207. m_BookmarkTimes[ 2 ].Init( this, "bookmarksZ" );
  4208. }
  4209. template<>
  4210. void CDmeTypedLog< Vector2D >::InitalizeBookmarkArrays()
  4211. {
  4212. m_BookmarkTimes[ 0 ].Init( this, "bookmarksX" );
  4213. m_BookmarkTimes[ 1 ].Init( this, "bookmarksY" );
  4214. }
  4215. template<>
  4216. void CDmeTypedLog< Vector4D >::InitalizeBookmarkArrays()
  4217. {
  4218. m_BookmarkTimes[ 0 ].Init( this, "bookmarksX" );
  4219. m_BookmarkTimes[ 1 ].Init( this, "bookmarksY" );
  4220. m_BookmarkTimes[ 2 ].Init( this, "bookmarksZ" );
  4221. m_BookmarkTimes[ 3 ].Init( this, "bookmarksW" );
  4222. }
  4223. template<>
  4224. void CDmeTypedLog< Quaternion >::InitalizeBookmarkArrays()
  4225. {
  4226. m_BookmarkTimes[ 0 ].Init( this, "bookmarksX" );
  4227. m_BookmarkTimes[ 1 ].Init( this, "bookmarksY" );
  4228. m_BookmarkTimes[ 2 ].Init( this, "bookmarksZ" );
  4229. }
  4230. template< class T >
  4231. int CDmeTypedLog< T >::GetNumBookmarkComponents() const
  4232. {
  4233. return 1;
  4234. }
  4235. template<>
  4236. int CDmeTypedLog< Vector >::GetNumBookmarkComponents() const
  4237. {
  4238. return 3;
  4239. }
  4240. template<>
  4241. int CDmeTypedLog< Vector2D >::GetNumBookmarkComponents() const
  4242. {
  4243. return 2;
  4244. }
  4245. template<>
  4246. int CDmeTypedLog< Vector4D >::GetNumBookmarkComponents() const
  4247. {
  4248. return 4;
  4249. }
  4250. template<>
  4251. int CDmeTypedLog< Quaternion >::GetNumBookmarkComponents() const
  4252. {
  4253. return 3;
  4254. }
  4255. // Only used by undo system!!!
  4256. template< class T >
  4257. void CDmeTypedLog< T >::AddLayerToTail( CDmeLogLayer *layer )
  4258. {
  4259. Assert( layer );
  4260. Assert( (static_cast< CDmeTypedLogLayer< T > * >( layer ))->GetTypedOwnerLog() == this );
  4261. m_Layers.AddToTail( layer );
  4262. }
  4263. template< class T >
  4264. CDmeLogLayer *CDmeTypedLog< T >::RemoveLayerFromTail()
  4265. {
  4266. Assert( m_Layers.Count() >= 1 );
  4267. CDmeLogLayer *layer = m_Layers[ m_Layers.Count() -1 ];
  4268. m_Layers.Remove( m_Layers.Count() - 1 );
  4269. return layer;
  4270. }
  4271. template< class T >
  4272. CDmeLogLayer *CDmeTypedLog< T >::RemoveLayer( int iLayer )
  4273. {
  4274. Assert( m_Layers.IsValidIndex( iLayer ) );
  4275. CDmeLogLayer *layer = m_Layers[ iLayer ];
  4276. m_Layers.Remove( iLayer );
  4277. return layer;
  4278. }
  4279. template< class T >
  4280. CDmeLogLayer *CDmeTypedLog< T >::AddNewLayer()
  4281. {
  4282. if ( g_pDataModel->UndoEnabledForElement( this ) )
  4283. {
  4284. CUndoLayerAdded<T> *pUndo = new CUndoLayerAdded<T>( "AddNewLayer", this );
  4285. g_pDataModel->AddUndoElement( pUndo );
  4286. }
  4287. CDisableUndoScopeGuard guard;
  4288. // Now add the layer to the stack!!!
  4289. CDmeTypedLogLayer< T > *layer = static_cast< CDmeTypedLogLayer< T > * >( CreateLayer<T>( this ) );
  4290. if ( layer )
  4291. {
  4292. layer->SetOwnerLog( this );
  4293. m_Layers.AddToTail( layer );
  4294. }
  4295. return layer;
  4296. }
  4297. // curve info helpers
  4298. template< class T >
  4299. const CDmeTypedCurveInfo< T > *CDmeTypedLog<T>::GetTypedCurveInfo() const
  4300. {
  4301. Assert( !m_CurveInfo.GetElement() || dynamic_cast< const CDmeTypedCurveInfo< T > * >( m_CurveInfo.GetElement() ) );
  4302. return static_cast< const CDmeTypedCurveInfo< T > * >( m_CurveInfo.GetElement() );
  4303. }
  4304. template< class T >
  4305. CDmeTypedCurveInfo< T > *CDmeTypedLog<T>::GetTypedCurveInfo()
  4306. {
  4307. Assert( !m_CurveInfo.GetElement() || dynamic_cast< CDmeTypedCurveInfo< T > * >( m_CurveInfo.GetElement() ) );
  4308. return static_cast< CDmeTypedCurveInfo< T > * >( m_CurveInfo.GetElement() );
  4309. }
  4310. template< class T >
  4311. void CDmeTypedLog<T>::SetCurveInfo( CDmeCurveInfo *pCurveInfo )
  4312. {
  4313. Assert( !pCurveInfo || dynamic_cast< CDmeTypedCurveInfo< T > * >( pCurveInfo ) );
  4314. m_CurveInfo = pCurveInfo;
  4315. OnUsingCurveTypesChanged(); // FIXME: Is this really necessary? OnAttributeChanged should have already called this!
  4316. }
  4317. template< class T >
  4318. CDmeCurveInfo *CDmeTypedLog<T>::GetOrCreateCurveInfo()
  4319. {
  4320. CDmeCurveInfo *pCurveInfo = m_CurveInfo.GetElement();
  4321. if ( pCurveInfo )
  4322. return pCurveInfo;
  4323. SetCurveInfo( CreateElement< CDmeTypedCurveInfo< T > >( "curveinfo", GetFileId() ) );
  4324. return m_CurveInfo.GetElement();
  4325. }
  4326. template < class T >
  4327. struct ActiveLayer_t
  4328. {
  4329. ActiveLayer_t() :
  4330. priority( 0 ),
  4331. firstTime( 0 ),
  4332. lastTime( 0 ),
  4333. layer( NULL )
  4334. {
  4335. }
  4336. static bool PriorityLessFunc( ActiveLayer_t< T > * const & lhs, ActiveLayer_t< T > * const & rhs )
  4337. {
  4338. return lhs->priority < rhs->priority;
  4339. }
  4340. int priority; // higher wins
  4341. DmeTime_t firstTime;
  4342. DmeTime_t lastTime;
  4343. CDmeTypedLogLayer< T > *layer;
  4344. };
  4345. template < class T >
  4346. struct LayerEvent_t
  4347. {
  4348. enum EventType_t
  4349. {
  4350. LE_START = 0,
  4351. LE_END
  4352. };
  4353. LayerEvent_t() : m_pList( NULL ), m_Type( LE_START ), m_nLayer( 0 ), m_Time( 0 )
  4354. {
  4355. }
  4356. static bool LessFunc( const LayerEvent_t& lhs, const LayerEvent_t& rhs )
  4357. {
  4358. return lhs.m_Time < rhs.m_Time;
  4359. }
  4360. CUtlVector< ActiveLayer_t< T > > *m_pList;
  4361. EventType_t m_Type;
  4362. int m_nLayer;
  4363. DmeTime_t m_Time;
  4364. T m_NeighborValue;
  4365. };
  4366. template< class T >
  4367. static const T& GetActiveLayerValue( CUtlVector< ActiveLayer_t< T > > &layerlist, DmeTime_t t, int nTopmostLayer )
  4368. {
  4369. int nCount = layerlist.Count();
  4370. #ifdef _DEBUG
  4371. Assert( nCount >= nTopmostLayer );
  4372. #endif
  4373. for ( int i = nTopmostLayer; i >= 0; --i )
  4374. {
  4375. ActiveLayer_t< T > &layer = layerlist[i];
  4376. if ( layer.firstTime > t || layer.lastTime < t )
  4377. continue;
  4378. return layer.layer->GetValue( t );
  4379. }
  4380. if ( nCount != 0 )
  4381. {
  4382. const CDmeTypedLog< T > *pOwner = layerlist[0].layer->GetTypedOwnerLog();
  4383. if ( pOwner->HasDefaultValue() )
  4384. return pOwner->GetDefaultValue();
  4385. }
  4386. static T defaultVal;
  4387. CDmAttributeInfo<T>::SetDefaultValue( defaultVal );
  4388. return defaultVal;
  4389. }
  4390. template< class T >
  4391. static void SpewEvents( CUtlRBTree< LayerEvent_t< T > > &events )
  4392. {
  4393. for ( unsigned short idx = events.FirstInorder(); idx != events.InvalidIndex(); idx = events.NextInorder( idx ) )
  4394. {
  4395. LayerEvent_t< T > *pEvent = &events[ idx ];
  4396. Msg( "Event %u layer %i at time %i type %s\n",
  4397. (unsigned)idx, pEvent->m_nLayer, pEvent->m_Time.GetTenthsOfMS(), pEvent->m_Type == LayerEvent_t< T >::LE_START ? "start" : "end" );
  4398. }
  4399. }
  4400. template< class T >
  4401. static void SpewKey( const T& )
  4402. {
  4403. // Used for all non-specialized types below.
  4404. Msg( "GenericType" );
  4405. }
  4406. template<>
  4407. static void SpewKey<float>( const float& val )
  4408. {
  4409. Msg( "%f", val );
  4410. }
  4411. template<>
  4412. static void SpewKey<int>( const int& val )
  4413. {
  4414. Msg( "%d", val );
  4415. }
  4416. template<>
  4417. static void SpewKey<Vector2D>( const Vector2D& val )
  4418. {
  4419. Msg( "%f,%f", val.x, val.y );
  4420. }
  4421. template<>
  4422. static void SpewKey<Vector4D>( const Vector4D& val )
  4423. {
  4424. Msg( "%f,%f,%f,%f", val.x, val.y, val.z, val.w );
  4425. }
  4426. template<>
  4427. static void SpewKey<DmeTime_t>( const DmeTime_t& val )
  4428. {
  4429. Msg( "%d", val.GetTenthsOfMS() );
  4430. }
  4431. template<>
  4432. static void SpewKey<bool>( const bool& val )
  4433. {
  4434. Msg( "%s", val ? "true" : "false" );
  4435. }
  4436. template<>
  4437. static void SpewKey<Color>( const Color& val )
  4438. {
  4439. Msg( "%08x", val.GetRawColor() );
  4440. }
  4441. template< >
  4442. static void SpewKey( const Vector& val )
  4443. {
  4444. Msg( "[%f %f %f]", val.x, val.y, val.z );
  4445. }
  4446. template< >
  4447. static void SpewKey( const Quaternion& val )
  4448. {
  4449. Msg( "[%f %f %f %f]", val.x, val.y, val.z, val.w );
  4450. }
  4451. template< >
  4452. static void SpewKey( const QAngle& val )
  4453. {
  4454. Msg( "[%f %f %f]", val.x, val.y, val.z );
  4455. }
  4456. template< class T >
  4457. static void SpewFlattenedKey( CDmeTypedLogLayer< T > *pLogLayer, ActiveLayer_t< T > *pActiveLayer, DmeTime_t t, const T& val )
  4458. {
  4459. Msg( "Layer %d: adding key at time %d [%d -> %d], value ",
  4460. pActiveLayer->priority, t.GetTenthsOfMS(), pActiveLayer->firstTime.GetTenthsOfMS(), pActiveLayer->lastTime.GetTenthsOfMS() );
  4461. SpewKey( val );
  4462. Msg( "\n" );
  4463. }
  4464. template< class T >
  4465. static void ComputeLayerEvents( CDmeTypedLog< T >* pLog, CUtlVector< ActiveLayer_t< T > > &layerlist,
  4466. CUtlRBTree< LayerEvent_t< T > > &events, int baseLayer )
  4467. {
  4468. // Build a list of all known layers and a sorted list of layer "transitions"
  4469. int numLayers = pLog->GetNumLayers();
  4470. for ( int i = baseLayer; i < numLayers; ++i )
  4471. {
  4472. ActiveLayer_t< T > layer;
  4473. layer.priority = i;
  4474. layer.layer = static_cast< CDmeTypedLogLayer< T > * >( pLog->GetLayer( i ) );
  4475. layer.firstTime = layer.layer->GetBeginTime( true );
  4476. layer.lastTime = layer.layer->GetEndTime( true );
  4477. // Skip invalid layers, base layer is always valid
  4478. if ( ( layer.firstTime == DMETIME_INVALID || layer.lastTime == DMETIME_INVALID ) && ( i != baseLayer ) )
  4479. continue;
  4480. // Layer zero can capture everything from above...
  4481. if ( i == baseLayer )
  4482. {
  4483. layer.firstTime = DmeTime_t::MinTime();
  4484. layer.lastTime = DmeTime_t::MaxTime();
  4485. }
  4486. // Add layer to global list
  4487. int nIndex = layerlist.AddToTail( layer );
  4488. // Add layer start/end events
  4489. DmeTime_t tNeighbor = ( layer.firstTime != DMETIME_MINTIME ) ? ( layer.firstTime - DMETIME_MINDELTA ) : DMETIME_MINTIME;
  4490. LayerEvent_t< T > start;
  4491. start.m_pList = &layerlist;
  4492. start.m_nLayer = nIndex;
  4493. start.m_Type = LayerEvent_t< T >::LE_START;
  4494. start.m_Time = layer.firstTime;
  4495. start.m_NeighborValue = GetActiveLayerValue( layerlist, tNeighbor, nIndex - 1 );
  4496. events.Insert( start );
  4497. tNeighbor = ( layer.lastTime != DMETIME_MAXTIME ) ? ( layer.lastTime + DMETIME_MINDELTA ) : DMETIME_MAXTIME;
  4498. LayerEvent_t< T > end;
  4499. end.m_pList = &layerlist;
  4500. end.m_nLayer = nIndex;
  4501. end.m_Type = LayerEvent_t< T >::LE_END;
  4502. end.m_Time = layer.lastTime;
  4503. end.m_NeighborValue = GetActiveLayerValue( layerlist, tNeighbor, nIndex - 1 );
  4504. events.Insert( end );
  4505. }
  4506. }
  4507. template< class T >
  4508. static void AddDiscontinitySample( CDmeTypedLogLayer< T > *pTargetLayer, CDmeTypedLog< T > *pLog, DmeTime_t tKeyTime, const T& val, const char *pSpewLabel )
  4509. {
  4510. // Finally, add a helper key.
  4511. // NOTE: The SetKey function is called with removeReduntant false because the discontinuity sample
  4512. // is at the very end of the range of the layer, and may in fact be overwritten by the following
  4513. // layer, meaning that if the proceeding value is removed when the discontinuity sample is overwritten
  4514. // the results will no longer be correct because the last sample of the layer will have been lost.
  4515. const bool bRemoveRedundant = false;
  4516. if ( pLog->IsUsingCurveTypes() )
  4517. {
  4518. if ( pSpewLabel )
  4519. {
  4520. Msg( "Adding %s helper key at %d value ", pSpewLabel, tKeyTime.GetTenthsOfMS() );
  4521. SpewKey( val );
  4522. Msg( " [curvetype %s]\n", Interpolator_NameForCurveType( pLog->GetDefaultCurveType(), false ) );
  4523. }
  4524. pTargetLayer->SetKey( tKeyTime, val, pTargetLayer->GetSegmentInterpolationSetting( tKeyTime, DMETIME_INVALID, false ), pLog->GetDefaultCurveType(), bRemoveRedundant );
  4525. }
  4526. else
  4527. {
  4528. if ( pSpewLabel )
  4529. {
  4530. Msg( "Adding %s helper key at %d value ", pSpewLabel, tKeyTime.GetTenthsOfMS() );
  4531. SpewKey( val );
  4532. Msg( "\n" );
  4533. }
  4534. pTargetLayer->SetKey( tKeyTime, val, pTargetLayer->GetSegmentInterpolationSetting( tKeyTime, DMETIME_INVALID, false ), CURVE_DEFAULT, bRemoveRedundant );
  4535. }
  4536. }
  4537. template< class T >
  4538. static DmeTime_t ProcessStartLayerStartEvent(
  4539. bool bSpew,
  4540. bool bFixupDiscontinuities,
  4541. CDmeTypedLog< T > *pLog,
  4542. LayerEvent_t< T > *pEvent,
  4543. CUtlVector< ActiveLayer_t< T > > &layerlist,
  4544. CUtlRBTree< ActiveLayer_t< T > * > &active,
  4545. CDmeTypedLogLayer< T > *flattenedlayer )
  4546. {
  4547. Assert( pEvent->m_Type == LayerEvent_t< T >::LE_START );
  4548. // Push it onto the active stack if it's not already on the stack
  4549. if ( active.Find( &layerlist[ pEvent->m_nLayer ] ) != active.InvalidIndex() )
  4550. return pEvent->m_Time;
  4551. if ( bSpew )
  4552. {
  4553. Msg( "adding layer %d to stack\n", layerlist[ pEvent->m_nLayer ].priority );
  4554. }
  4555. active.Insert( &layerlist[ pEvent->m_nLayer ] );
  4556. if ( !bFixupDiscontinuities || ( pEvent->m_Time == DMETIME_MINTIME ) )
  4557. return pEvent->m_Time;
  4558. // We'll need to add 2 new "discontinuity" fixup samples.
  4559. // 1) A sample from the base layer @ start time - .1 msec
  4560. // 2) A sample from the new layer @ start time
  4561. int nActiveCount = active.Count();
  4562. if ( nActiveCount >= 2 )
  4563. {
  4564. DmeTime_t tKeyTime = pEvent->m_Time - DmeTime_t( 1 );
  4565. AddDiscontinitySample( flattenedlayer, pLog, tKeyTime, pEvent->m_NeighborValue, bSpew ? "start" : NULL );
  4566. }
  4567. AddDiscontinitySample( flattenedlayer, pLog, pEvent->m_Time, GetActiveLayerValue( layerlist, pEvent->m_Time, pEvent->m_nLayer ), bSpew ? "start" : NULL );
  4568. return pEvent->m_Time;
  4569. }
  4570. template< class T >
  4571. static DmeTime_t ProcessStartLayerEndEvent(
  4572. bool bSpew,
  4573. bool bFixupDiscontinuities,
  4574. CDmeTypedLog< T > *pLog,
  4575. LayerEvent_t< T > *pEvent,
  4576. CUtlVector< ActiveLayer_t< T > > &layerlist,
  4577. CUtlRBTree< ActiveLayer_t< T > * > &active,
  4578. CDmeTypedLogLayer< T > *pBaseLayer )
  4579. {
  4580. Assert( pEvent->m_Type == LayerEvent_t< T >::LE_END );
  4581. // Push it onto the active stack if it's not already on the stack
  4582. if ( bSpew )
  4583. {
  4584. Msg( "removing layer %d from stack\n", layerlist[ pEvent->m_nLayer ].priority );
  4585. }
  4586. // We'll need to add a "discontinuity" fixup sample from the
  4587. // 1) A sample from the ending layer @ start time
  4588. // 2) A sample from the new layer @ start time + .1 msec
  4589. // NOTE: This will cause problems if there are non-default value keys at max time
  4590. Assert( active.Count() >= 1 );
  4591. if ( bFixupDiscontinuities && ( pEvent->m_Time != DMETIME_MAXTIME ) )
  4592. {
  4593. AddDiscontinitySample( pBaseLayer, pLog, pEvent->m_Time, GetActiveLayerValue( layerlist, pEvent->m_Time, pEvent->m_nLayer ), bSpew ? "end" : NULL );
  4594. if ( active.Count() >= 2 )
  4595. {
  4596. DmeTime_t keyTime = pEvent->m_Time + DmeTime_t( 1 );
  4597. AddDiscontinitySample( pBaseLayer, pLog, keyTime, pEvent->m_NeighborValue, bSpew ? "end" : NULL );
  4598. }
  4599. }
  4600. active.Remove( &layerlist[ pEvent->m_nLayer ] );
  4601. return ( active.Count() >= 2 ) ? pEvent->m_Time + DmeTime_t( 1 ) : pEvent->m_Time;
  4602. }
  4603. template< class T >
  4604. void CDmeTypedLog< T >::FlattenLayers( float threshold, int flags, int baseLayer /*=0*/ )
  4605. {
  4606. // Already flattened
  4607. int nLayersToFlatten = m_Layers.Count() - 1 - baseLayer;
  4608. if ( nLayersToFlatten <= 0 )
  4609. return;
  4610. CDmeTypedLogLayer< T > *pBaseLayer = GetLayer( baseLayer );
  4611. if ( pBaseLayer == NULL )
  4612. return;
  4613. if ( g_pDataModel->UndoEnabledForElement( this ) )
  4614. {
  4615. CUndoFlattenLayers<T> *pUndo = new CUndoFlattenLayers<T>( "FlattenLayers", this, threshold, flags, baseLayer );
  4616. g_pDataModel->AddUndoElement( pUndo );
  4617. }
  4618. bool bSpew = ( flags & FLATTEN_SPEW ) != 0;
  4619. bool bFixupDiscontinuities = ( flags & FLATTEN_NODISCONTINUITY_FIXUP ) == 0;
  4620. // NOTE: UNDO IS DISABLED FOR THE REST OF THIS OPERATION (the above function does what we need to preserve the layers)
  4621. CDisableUndoScopeGuard guard;
  4622. CDmeTypedLogLayer< T > *pFlattenedlayer = static_cast< CDmeTypedLogLayer< T > * >( CreateLayer< T >( this ) );
  4623. pFlattenedlayer->SetOwnerLog( this );
  4624. pFlattenedlayer->SetInfinite( pBaseLayer->IsLeftInfinite(), pBaseLayer->IsRightInfinite() );
  4625. // Global list of layers
  4626. CUtlVector< ActiveLayer_t< T > > layerlist;
  4627. // List of all start/end layer events, sorted by the time at which the event occurs ( we walk this list in order )
  4628. CUtlRBTree< LayerEvent_t< T > > events( 0, 0, LayerEvent_t< T >::LessFunc );
  4629. // Stack of active events, sorted by event "priority", which means last item is the one writing data into the new base layer
  4630. CUtlRBTree< ActiveLayer_t< T > * > active( 0, 0, ActiveLayer_t< T >::PriorityLessFunc );
  4631. // Build layer list and list of start/end events and times
  4632. ComputeLayerEvents( this, layerlist, events, baseLayer );
  4633. // Debuggins
  4634. if ( bSpew )
  4635. {
  4636. SpewEvents( events );
  4637. }
  4638. // Set the value equality threshold that will be used by SetKey to match the specified threshold
  4639. float saveThreshold = CDmeTypedLog< T >::GetValueThreshold();
  4640. CDmeTypedLog< T >::SetValueThreshold( 0.0f ); // don't remove redundant keys one-by-one in SetKey, wait until the explicit call to RemoveRedundantKeys()
  4641. // Now walk from the earliest time in any layer until the latest time, going key by key and checking if the active layer should change as we go
  4642. DmeTime_t iCurrentKeyTime = DmeTime_t::MinTime();
  4643. unsigned short idx = events.FirstInorder();
  4644. while ( 1 )
  4645. {
  4646. if ( idx == events.InvalidIndex() )
  4647. break;
  4648. LayerEvent_t< T > *pEvent = &events[ idx ];
  4649. switch ( pEvent->m_Type )
  4650. {
  4651. default:
  4652. iCurrentKeyTime = pEvent->m_Time;
  4653. Assert( 0 );
  4654. break;
  4655. case LayerEvent_t< T >::LE_START:
  4656. iCurrentKeyTime = ProcessStartLayerStartEvent( bSpew, bFixupDiscontinuities, this, pEvent, layerlist, active, pFlattenedlayer );
  4657. break;
  4658. case LayerEvent_t< T >::LE_END:
  4659. iCurrentKeyTime = ProcessStartLayerEndEvent( bSpew, bFixupDiscontinuities, this, pEvent, layerlist, active, pFlattenedlayer );
  4660. break;
  4661. }
  4662. int nNextIndex = events.NextInorder( idx );
  4663. // We popped the last item off the stack
  4664. if ( nNextIndex == events.InvalidIndex() )
  4665. {
  4666. Assert( active.Count() == 0 );
  4667. break;
  4668. }
  4669. // Walk from current time up to the time of the next relevant event
  4670. LayerEvent_t< T > *nextevent = &events[ nNextIndex ];
  4671. DmeTime_t layerFinishTime = nextevent->m_Time;
  4672. // The topmost layer is the active layer
  4673. int layernum = active.LastInorder();
  4674. if ( layernum == active.InvalidIndex() )
  4675. break;
  4676. ActiveLayer_t< T > *activeLayer = active[ layernum ];
  4677. CDmeTypedLogLayer< T > *loglayer = activeLayer->layer;
  4678. // Splat all keys between the current head position and the next event time (layerFinishTime) into the flattened layer
  4679. int keyCount = loglayer->GetKeyCount();
  4680. for ( int j = 0; j < keyCount; ++j )
  4681. {
  4682. DmeTime_t keyTime = loglayer->GetKeyTime( j );
  4683. // Key is too early, skip
  4684. if ( keyTime < iCurrentKeyTime )
  4685. continue;
  4686. // Done with this layer, set time exactly equal to end time so next layer can take over
  4687. // at the correct spot
  4688. if ( keyTime >= layerFinishTime )
  4689. {
  4690. iCurrentKeyTime = layerFinishTime;
  4691. break;
  4692. }
  4693. // Advance the head position
  4694. iCurrentKeyTime = keyTime;
  4695. // Because it's a key, the interpolated value should == the actual value (not true for certain 4 point curve types, but we shouldn't support them
  4696. // for this type of operation anyway)
  4697. const T& val = loglayer->GetKeyValue( j );
  4698. // Debugging spew
  4699. if ( bSpew )
  4700. {
  4701. SpewFlattenedKey( loglayer, activeLayer, iCurrentKeyTime, val );
  4702. }
  4703. // Now set the key into the flattened layer
  4704. pFlattenedlayer->SetKey( iCurrentKeyTime, val, loglayer->GetSegmentInterpolationSetting(j), loglayer->IsUsingCurveTypes() ? loglayer->GetKeyCurveType( j ) : CURVE_DEFAULT );
  4705. }
  4706. bool bLeftInfinite = ( pFlattenedlayer->IsLeftInfinite() || loglayer->IsLeftInfinite() );
  4707. bool bRightInfinite = ( pFlattenedlayer->IsRightInfinite() || loglayer->IsRightInfinite() );
  4708. pFlattenedlayer->SetInfinite( bLeftInfinite, bRightInfinite );
  4709. idx = nNextIndex;
  4710. }
  4711. // Restore the threshold value
  4712. CDmeTypedLog< T >::SetValueThreshold( saveThreshold );
  4713. // Blow away all of the existing layers except the original base layer
  4714. while ( GetNumLayers() > ( baseLayer + 1 ) )
  4715. {
  4716. CDmeTypedLogLayer< T > *layer = static_cast< CDmeTypedLogLayer< T > * >( RemoveLayerFromTail() );
  4717. g_pDataModel->DestroyElement( layer->GetHandle() );
  4718. }
  4719. // Compress the flattened layer
  4720. pFlattenedlayer->RemoveRedundantKeys( threshold, true );
  4721. // Copy the flattened layer over the existing base layer
  4722. pBaseLayer->CopyLayer( pFlattenedlayer );
  4723. g_pDataModel->DestroyElement( pFlattenedlayer->GetHandle() );
  4724. }
  4725. template< class T >
  4726. void CDmeTypedLog< T >::StampKeyAtHead( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t& params, const DmeLogTransformParams_t &transformParams, const CDmAttribute *pAttr, uint arrayIndex /*= 0*/, bool bTimeFilter /*= true*/, int layerIndex /* = -1 */ )
  4727. {
  4728. DmAttributeType_t type = pAttr->GetType();
  4729. if ( IsValueType( type ) )
  4730. {
  4731. Assert( pAttr->GetType() == GetDataType() );
  4732. StampKeyAtHead( tHeadPosition, tPreviousHeadPosition, params, transformParams, pAttr->GetValue< T >(), bTimeFilter, layerIndex );
  4733. }
  4734. else if ( IsArrayType( type ) )
  4735. {
  4736. Assert( ArrayTypeToValueType( type ) == GetDataType() );
  4737. CDmrArrayConst<T> array( pAttr );
  4738. StampKeyAtHead( tHeadPosition, tPreviousHeadPosition, params, transformParams, array[ arrayIndex ], bTimeFilter, layerIndex );
  4739. }
  4740. else
  4741. {
  4742. Assert( 0 );
  4743. }
  4744. }
  4745. template< class T >
  4746. void CDmeTypedLog< T >::FinishTimeSelection( DmeTime_t tHeadPosition, DmeLog_TimeSelection_t& params )
  4747. {
  4748. bool bWasAdvancing = params.IsTimeAdvancing();
  4749. params.ResetTimeAdvancing();
  4750. if ( !params.m_bAttachedMode )
  4751. return;
  4752. if ( !bWasAdvancing )
  4753. return;
  4754. // Should be in "layer recording" mode!!!
  4755. Assert( GetNumLayers() >= 2 );
  4756. int nBestLayer = GetTopmostLayer(); // Topmost should be at least layer # 1 (0 is the base layer)
  4757. if ( nBestLayer < 1 )
  4758. return;
  4759. CDmeTypedLogLayer< T > *pWriteLayer = GetLayer( nBestLayer );
  4760. Assert( pWriteLayer );
  4761. if ( !pWriteLayer )
  4762. return;
  4763. int nKeyCount = pWriteLayer->GetKeyCount();
  4764. if ( nKeyCount <= 0 )
  4765. return;
  4766. // The head is considered to be at the "last" value
  4767. T headValue = pWriteLayer->GetKeyValue( nKeyCount - 1 );
  4768. DmeLogTransformParams_t defaultParams;
  4769. _StampKeyAtHeadResample( tHeadPosition, params, defaultParams, headValue, true, false );
  4770. }
  4771. template< >
  4772. float CDmeTypedLog< float >::ClampValue( const float& value )
  4773. {
  4774. float retval;
  4775. if ( !IsUsingCurveTypes() )
  4776. {
  4777. retval = clamp( value, 0.0f, 1.0f );
  4778. }
  4779. else
  4780. {
  4781. retval = clamp( value, GetMinValue(), GetMaxValue() );
  4782. }
  4783. return retval;
  4784. }
  4785. template < class T >
  4786. T CDmeTypedLog< T >::MaskValue( DmeTime_t time, const T& value, LogComponents_t componentFlags ) const
  4787. {
  4788. T writeValue = value;
  4789. int nLayerForTime = FindLayerForTime( time );
  4790. if ( nLayerForTime != -1 )
  4791. {
  4792. GetLayer( nLayerForTime )->MaskValue( time, value, componentFlags );
  4793. }
  4794. return writeValue;
  4795. }
  4796. template< class T >
  4797. void CDmeTypedLog< T >::StampKeyAtHead( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t& params, const DmeLogTransformParams_t &transformParams, const T& value, bool bFilterByTimeSelection, int layerIndex /*= -1*/ )
  4798. {
  4799. //T useValue = ClampValue( value );
  4800. // This gets set if time ever starts moving (even if the user pauses time while still holding a slider)
  4801. if ( params.IsTimeAdvancing() )
  4802. {
  4803. // If bFilterByTimeSelection is true, this uses the time selection as a "filter" to decide whether to stamp a new
  4804. // key at the current position, otherwise will stamp a new key at the current time regardless of the time selection.
  4805. _StampKeyAtHead( tHeadPosition, tPreviousHeadPosition, params, value, bFilterByTimeSelection, layerIndex );
  4806. }
  4807. else
  4808. {
  4809. _StampKeyAtHeadResample( tHeadPosition, params, transformParams, value, false, true, layerIndex );
  4810. }
  4811. }
  4812. /*
  4813. template<>
  4814. void CDmeTypedLog< float >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const float& value );
  4815. template<>
  4816. void CDmeTypedLog< bool >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const bool& value );
  4817. template<>
  4818. void CDmeTypedLog< Color >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const Color& value );
  4819. template<>
  4820. void CDmeTypedLog< Vector4D >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const Vector4D& value );
  4821. template<>
  4822. void CDmeTypedLog< Vector2D >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const Vector2D& value );
  4823. template<>
  4824. void CDmeTypedLog< VMatrix >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const VMatrix& value );
  4825. template<>
  4826. void CDmeTypedLog< Quaternion >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const Quaternion& value );
  4827. template<>
  4828. void CDmeTypedLog< QAngle >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const QAngle& value );
  4829. */
  4830. // Masks all keys within the time range, returns true if keys were modified
  4831. template< class T >
  4832. bool CDmeTypedLog< T >::MaskKeyRange( DmeTime_t tStartTime, DmeTime_t tEndTime, LogComponents_t nComponentFlags, bool bInfiniteLeft /*= false*/, bool bInfiniteRight /*= false*/ )
  4833. {
  4834. CDmeTypedLogLayer<T> *pLayer = GetLayer( GetTopmostLayer() );
  4835. return pLayer->MaskKeyRange( tStartTime, tEndTime, nComponentFlags, bInfiniteLeft, bInfiniteRight );
  4836. }
  4837. //-----------------------------------------------------------------------------
  4838. // Helper class used to compute falloff blend factors
  4839. //-----------------------------------------------------------------------------
  4840. enum TSRegion_t
  4841. {
  4842. TS_REGION_IN = -1,
  4843. TS_REGION_HOLD = 0,
  4844. TS_REGION_OUT = 1,
  4845. };
  4846. template< class T >
  4847. struct LogClampHelper_t
  4848. {
  4849. public:
  4850. LogClampHelper_t() : m_tLastTime( DMETIME_MINTIME ) {}
  4851. DmeTime_t m_tLastTime;
  4852. T m_LastUnclampedValue;
  4853. };
  4854. template < class T >
  4855. void ComputeTransform( const T &position, const Quaternion &rotation, matrix3x4_t &transformMatrix )
  4856. {
  4857. SetIdentityMatrix( transformMatrix );
  4858. }
  4859. template <>
  4860. void ComputeTransform( const Vector &position, const Quaternion &rotation, matrix3x4_t &transformMatrix )
  4861. {
  4862. AngleMatrix( RadianEuler( rotation ), position, transformMatrix );
  4863. }
  4864. template< class T >
  4865. class CLogFalloffBlend
  4866. {
  4867. public:
  4868. void Init( CDmeTypedLog<T> *pLog, DmeTime_t tHead, const T& delta, bool bUsePresetRules, TSRegion_t nFalloffRegion, const DmeLog_TimeSelection_t &tsParams, const DmeLogTransformParams_t &transformParams );
  4869. float ComputeBlendFactor( DmeTime_t tTime ) const;
  4870. const T& GetDelta() const;
  4871. void StampKey( CDmeTypedLogLayer<T>* pWriteLayer, DmeTime_t t, const CDmeTypedLogLayer<T>* pReadLayer, float flIntensity, LogClampHelper_t<T> &helper, bool bSpew, const T* pInterpTarget, const CDmeTypedLogLayer< Quaternion >* pRotationLayer, const DmeLog_TimeSelection_t &tsParams, const DmeLogTransformParams_t &transformParams ) const;
  4872. void UpdateClampHelper( DmeTime_t t, const CDmeTypedLogLayer<T>* pReadLayer, float flIntensity, LogClampHelper_t<T> &helper, const T* pInterpTarget );
  4873. private:
  4874. void ComputeDelta( CDmeTypedLog<T> *pLog, const T& delta, const T& holdValue );
  4875. void InsertClampTransitionPoints( CDmeTypedLogLayer<T>* pWriteLayer, DmeTime_t t, LogClampHelper_t<T> &clampHelper, const T& val, bool bSpew ) const;
  4876. void ComputeBounds( CDmeTypedLog<T> *pLog );
  4877. bool m_bUsePresetRules;
  4878. T m_HeadValue;
  4879. T m_BaseValue;
  4880. T m_Delta;
  4881. T m_MinValue;
  4882. T m_MaxValue;
  4883. Quaternion m_HeadRotation;
  4884. Quaternion m_BaseRotation;
  4885. matrix3x4_t m_HeadTransform;
  4886. matrix3x4_t m_InvHeadTransform;
  4887. DmeTime_t m_tHeadTime;
  4888. DmeTime_t m_tBaseTime;
  4889. DmeTime_t m_tHoldTime;
  4890. TSRegion_t m_nTSRegion;
  4891. int m_nInterpolatorType;
  4892. int m_nCurveType;
  4893. float m_flOOTime;
  4894. };
  4895. template< class T >
  4896. void CLogFalloffBlend< T >::Init( CDmeTypedLog<T> *pLog, DmeTime_t tHead, const T& delta, bool bUsePresetRules, TSRegion_t nTSRegion, const DmeLog_TimeSelection_t &params, const DmeLogTransformParams_t &transformParams )
  4897. {
  4898. m_bUsePresetRules = bUsePresetRules;
  4899. m_nTSRegion = nTSRegion;
  4900. m_tHeadTime = tHead;
  4901. m_HeadValue = pLog->GetValueSkippingTopmostLayer( m_tHeadTime );
  4902. ComputeBounds( pLog );
  4903. if ( m_nTSRegion == TS_REGION_HOLD )
  4904. {
  4905. m_tBaseTime = m_tHoldTime = DMETIME_INVALID;
  4906. m_flOOTime = 0.0f;
  4907. m_BaseValue = m_HeadValue;
  4908. m_Delta = delta;
  4909. m_nInterpolatorType = INTERPOLATE_DEFAULT;
  4910. }
  4911. else
  4912. {
  4913. int nFalloffRegion = ( m_nTSRegion == TS_REGION_IN ) ? 0 : 1;
  4914. m_tBaseTime = params.m_nTimes[ TS_FALLOFF( nFalloffRegion ) ];
  4915. m_tHoldTime = params.m_nTimes[ TS_HOLD ( nFalloffRegion ) ];
  4916. float flDuration = m_tHoldTime.GetSeconds() - m_tBaseTime.GetSeconds();
  4917. m_flOOTime = ( flDuration != 0.0f ) ? 1.0f / flDuration : 0.0f;
  4918. m_BaseValue = pLog->GetValueSkippingTopmostLayer( m_tBaseTime );
  4919. T holdValue = pLog->GetValueSkippingTopmostLayer( m_tHoldTime );
  4920. ComputeDelta( pLog, delta, holdValue );
  4921. m_nInterpolatorType = params.m_nFalloffInterpolatorTypes[ nFalloffRegion ];
  4922. }
  4923. m_nCurveType = pLog->IsUsingCurveTypes() ? pLog->GetDefaultCurveType() : CURVE_DEFAULT;
  4924. // Read the rotation at the base time and head time if the rotation layer is specified.
  4925. m_HeadRotation = quat_identity;
  4926. m_BaseRotation = quat_identity;
  4927. if ( transformParams.m_pRotationLog != NULL )
  4928. {
  4929. m_HeadRotation = transformParams.m_pRotationLog->GetValueSkippingTopmostLayer( m_tHeadTime );
  4930. m_BaseRotation = transformParams.m_pRotationLog->GetValueSkippingTopmostLayer( m_tBaseTime );
  4931. }
  4932. ComputeTransform( m_HeadValue, m_HeadRotation, m_HeadTransform );
  4933. MatrixInvert( m_HeadTransform, m_InvHeadTransform );
  4934. }
  4935. template< class T >
  4936. void CLogFalloffBlend< T >::ComputeBounds( CDmeTypedLog<T> *pLog )
  4937. {
  4938. }
  4939. template<>
  4940. void CLogFalloffBlend< float >::ComputeBounds( CDmeTypedLog<float> *pLog )
  4941. {
  4942. m_MinValue = pLog->IsUsingCurveTypes() ? pLog->GetMinValue() : 0.0f;
  4943. m_MaxValue = pLog->IsUsingCurveTypes() ? pLog->GetMaxValue() : 1.0f;
  4944. }
  4945. template< class T >
  4946. void CLogFalloffBlend< T >::ComputeDelta( CDmeTypedLog<T> *pLog, const T& delta, const T& holdValue )
  4947. {
  4948. // By default, no clamping
  4949. m_Delta = delta;
  4950. }
  4951. template<>
  4952. void CLogFalloffBlend< float >::ComputeDelta( CDmeTypedLog<float> *pLog, const float& delta, const float& holdValue )
  4953. {
  4954. if ( delta > 0.0f )
  4955. {
  4956. m_Delta = MIN( delta, m_MaxValue - holdValue ); // Max amount we can move up...
  4957. }
  4958. else
  4959. {
  4960. m_Delta = MAX( delta, m_MinValue - holdValue ); // Amount we can move down...
  4961. }
  4962. }
  4963. template< class T >
  4964. float CLogFalloffBlend< T >::ComputeBlendFactor( DmeTime_t tTime ) const
  4965. {
  4966. if ( m_nTSRegion == TS_REGION_HOLD )
  4967. return 1.0f;
  4968. // Clamp inside region; hold time beats base time (for zero width regions)
  4969. if ( ( tTime - m_tHoldTime ) * -m_nTSRegion >= DMETIME_ZERO )
  4970. return 1.0f;
  4971. if ( ( tTime - m_tBaseTime ) * -m_nTSRegion <= DMETIME_ZERO )
  4972. return 0.0f;
  4973. float flFactor = ( tTime.GetSeconds() - m_tBaseTime.GetSeconds() ) * m_flOOTime;
  4974. return ComputeInterpolationFactor( flFactor, m_nInterpolatorType );
  4975. }
  4976. template< class T >
  4977. const T& CLogFalloffBlend< T >::GetDelta( ) const
  4978. {
  4979. return m_Delta;
  4980. }
  4981. //-----------------------------------------------------------------------------
  4982. // Insert points where clamping begins or ends
  4983. //-----------------------------------------------------------------------------
  4984. template< class T >
  4985. void CLogFalloffBlend< T >::InsertClampTransitionPoints( CDmeTypedLogLayer<T>* pWriteLayer,
  4986. DmeTime_t t, LogClampHelper_t<T> &clampHelper, const T& val, bool bSpew ) const
  4987. {
  4988. // NOTE: By default, nothing clamps, so no transition points are needed
  4989. }
  4990. template<>
  4991. void CLogFalloffBlend< float >::InsertClampTransitionPoints( CDmeTypedLogLayer<float>* pWriteLayer,
  4992. DmeTime_t t, LogClampHelper_t<float> &clampHelper, const float& val, bool bSpew ) const
  4993. {
  4994. bool bLastLess, bLastGreater, bCurrLess, bCurrGreater;
  4995. DmeTime_t tCrossing, tDuration;
  4996. double flOODv;
  4997. // First time through? cache last values.
  4998. if ( clampHelper.m_tLastTime == DMETIME_MINTIME )
  4999. goto cacheLastValues;
  5000. bLastLess = clampHelper.m_LastUnclampedValue < m_MinValue;
  5001. bLastGreater = clampHelper.m_LastUnclampedValue > m_MaxValue;
  5002. bCurrLess = val < m_MinValue;
  5003. bCurrGreater = val > m_MaxValue;
  5004. if ( bLastLess == bCurrLess && bLastGreater == bCurrGreater )
  5005. goto cacheLastValues;
  5006. // NOTE: The check above means val != m_LastUnclampedValue
  5007. flOODv = 1.0 / ( val - clampHelper.m_LastUnclampedValue );
  5008. tDuration = t - clampHelper.m_tLastTime;
  5009. // NOTE: Clamp semantics here favor keeping the non-clamped value
  5010. // That's why when we start outside + end inside, we never overwrite the dest
  5011. // and why when we start inside + end outside, we never overwrite the start
  5012. // These two checks deal with starting outside + heading inside
  5013. if ( bLastLess && !bCurrLess )
  5014. {
  5015. // Insert at min crossing
  5016. double flFactor = ( m_MinValue - clampHelper.m_LastUnclampedValue ) * flOODv;
  5017. tCrossing = clampHelper.m_tLastTime + tDuration * flFactor;
  5018. tCrossing.Clamp( clampHelper.m_tLastTime, t - DMETIME_MINDELTA );
  5019. pWriteLayer->InsertKey( tCrossing, m_MinValue, SEGMENT_INTERPOLATE, m_nCurveType );
  5020. if ( bSpew )
  5021. {
  5022. Msg(" Clamp Crossing Key: %d %f\n", tCrossing.GetTenthsOfMS(), m_MinValue );
  5023. }
  5024. }
  5025. else if ( bLastGreater && !bCurrGreater )
  5026. {
  5027. // Insert at max crossing
  5028. double flFactor = ( m_MaxValue - clampHelper.m_LastUnclampedValue ) * flOODv;
  5029. tCrossing = clampHelper.m_tLastTime + tDuration * flFactor;
  5030. tCrossing.Clamp( clampHelper.m_tLastTime, t - DMETIME_MINDELTA );
  5031. pWriteLayer->InsertKey( tCrossing, m_MaxValue, SEGMENT_INTERPOLATE, m_nCurveType );
  5032. if ( bSpew )
  5033. {
  5034. Msg(" Clamp Crossing Key: %d %f\n", tCrossing.GetTenthsOfMS(), m_MaxValue );
  5035. }
  5036. }
  5037. // These two checks deal with starting inside + heading outside
  5038. if ( !bLastLess && bCurrLess )
  5039. {
  5040. // Insert at min crossing
  5041. // NOTE: Clamp semantics here favor keeping the non-clamped value
  5042. double flFactor = ( m_MinValue - clampHelper.m_LastUnclampedValue ) * flOODv;
  5043. tCrossing = clampHelper.m_tLastTime + tDuration * flFactor;
  5044. tCrossing.Clamp( clampHelper.m_tLastTime + DMETIME_MINDELTA, t );
  5045. pWriteLayer->InsertKey( tCrossing, m_MinValue, SEGMENT_INTERPOLATE, m_nCurveType );
  5046. if ( bSpew )
  5047. {
  5048. Msg(" Clamp Crossing Key: %d %f\n", tCrossing.GetTenthsOfMS(), m_MinValue );
  5049. }
  5050. }
  5051. else if ( !bLastGreater && bCurrGreater )
  5052. {
  5053. // Insert at max crossing
  5054. double flFactor = ( m_MaxValue - clampHelper.m_LastUnclampedValue ) * flOODv;
  5055. tCrossing = clampHelper.m_tLastTime + tDuration * flFactor;
  5056. tCrossing.Clamp( clampHelper.m_tLastTime + DMETIME_MINDELTA, t );
  5057. pWriteLayer->InsertKey( tCrossing, m_MaxValue, SEGMENT_INTERPOLATE, m_nCurveType );
  5058. if ( bSpew )
  5059. {
  5060. Msg(" Clamp Crossing Key: %d %f\n", tCrossing.GetTenthsOfMS(), m_MaxValue );
  5061. }
  5062. }
  5063. // Cache off the last values
  5064. cacheLastValues:
  5065. clampHelper.m_tLastTime = t;
  5066. clampHelper.m_LastUnclampedValue = val;
  5067. }
  5068. //-----------------------------------------------------------------------------
  5069. // Stamp the key at the specified time
  5070. //-----------------------------------------------------------------------------
  5071. template< class T >
  5072. void CLogFalloffBlend< T >::StampKey( CDmeTypedLogLayer<T>* pWriteLayer, DmeTime_t t,
  5073. const CDmeTypedLogLayer<T>* pReadLayer, float flIntensity, LogClampHelper_t<T> &clampHelper, bool bSpew,
  5074. const T* pInterpTarget, const CDmeTypedLogLayer< Quaternion >* pRotationLayer,
  5075. const DmeLog_TimeSelection_t &timeSelectionParams, const DmeLogTransformParams_t &transformParams ) const
  5076. {
  5077. bool bIsVector = ( CDmAttributeInfo<T>::ATTRIBUTE_TYPE == AT_VECTOR3 );
  5078. // Stamp the key at the current time
  5079. T oldVal = pReadLayer->GetValue( t );
  5080. T newVal = oldVal;
  5081. if ( !timeSelectionParams.m_bManipulateInFalloff || m_bUsePresetRules ) // bUsePresetRules || translating || typing values into attribute slider || interpolate falloff mode
  5082. {
  5083. // If the transform mode is overwrite and stamping a key in the falloff region, instead of interpolating from the
  5084. // value at the current time interpolate from the base value, which is the value at the edge of the falloff.
  5085. if ( ( m_nTSRegion != TS_REGION_HOLD ) && !m_bUsePresetRules && timeSelectionParams.m_TransformWriteMode == TRANSFORM_WRITE_MODE_OVERWRITE )
  5086. {
  5087. oldVal = m_BaseValue;
  5088. }
  5089. // In the falloff area the blend factor will be between 0 and 1 based on the interpolation type
  5090. float flFactor = ComputeBlendFactor( t );
  5091. flFactor *= flIntensity;
  5092. T targetValue;
  5093. if ( pInterpTarget ) // params.m_TransformWriteMode == TRANSFORM_WRITE_MODE_OVERWRITE || bUsePresetRules (ie head/in/out/default/zero/half/one/random/user-defined)
  5094. {
  5095. targetValue = *pInterpTarget;
  5096. }
  5097. else if ( bIsVector && timeSelectionParams.m_TransformWriteMode == TRANSFORM_WRITE_MODE_TRANSFORM )
  5098. {
  5099. targetValue = TransformAbsolute( transformParams.m_Transform, oldVal );
  5100. }
  5101. else // params.m_TransformWriteMode == TRANSFORM_WRITE_MODE_OFFSET || ( params.m_TransformWriteMode == TRANSFORM_WRITE_MODE_TRANSFORM && T != Vector )
  5102. {
  5103. targetValue = Add( oldVal, m_Delta );
  5104. }
  5105. newVal = Interpolate( flFactor, oldVal, targetValue );
  5106. }
  5107. else
  5108. {
  5109. // If the falloff mode is manipulation, the amount of the input manipulation is
  5110. // interpolated and then applied instead of interpolating the result of the manipulation.
  5111. float flFactor = ComputeBlendFactor( t );
  5112. // Retrieve the rotation value before the transform, this value will be used as
  5113. // the rotation in constructing the local space in which the rotation will occur.
  5114. Quaternion oldRotation = quat_identity;
  5115. if ( pRotationLayer )
  5116. {
  5117. oldRotation = pRotationLayer->GetValue( t );
  5118. }
  5119. // In overwrite mode the result of the falloff with a factor of 1.0 must match the new value at the head, but
  5120. // the result of the falloff with a factor of 0.0f must still match the value at edge of the time selection.
  5121. if ( timeSelectionParams.m_TransformWriteMode == TRANSFORM_WRITE_MODE_OVERWRITE ) // !bUsePresetRules && manipulate falloff mode && rotating && params.m_TransformWriteMode == TRANSFORM_WRITE_MODE_OVERWRITE
  5122. {
  5123. Quaternion scaledRotation; // flFactor * rotationLocal
  5124. ScaleRotationQuaternion( transformParams.m_RotationLocal, flFactor, scaledRotation );
  5125. // Get the rotation at the head time and the base time (edge of falloff), and then
  5126. // calculate the difference in the rotation from the base time to the head time.
  5127. Quaternion inv;
  5128. Quaternion deltaRotation; // headRotation - baseRotation
  5129. QuaternionInvert( m_BaseRotation, inv );
  5130. QuaternionMult( inv, m_HeadRotation, deltaRotation );
  5131. // Scale the rotation from the base to the head and then combine it with
  5132. // the scaled rotation in order to get the total rotation to apply.
  5133. Quaternion headScaledRotation;
  5134. Quaternion totalRotation; // ( flFactor * deltaRotation ) + ( flFactor * rotationLocal )
  5135. QuaternionScale( deltaRotation, flFactor, headScaledRotation );
  5136. QuaternionMult( headScaledRotation, scaledRotation, totalRotation );
  5137. if ( bIsVector )
  5138. {
  5139. // Calculate the inverse of the rotation from the base to the head and rotate the position
  5140. // by this amount to get the position at the head without the effect of the rotation. Then
  5141. // interpolate from the base position to the position at the head without rotation and the
  5142. // apply the total rotation to the resulting position.
  5143. Quaternion invDeltaRotation;
  5144. QuaternionInvert( deltaRotation, invDeltaRotation );
  5145. T targetPosition = Rotate( invDeltaRotation, transformParams.m_Pivot, m_HeadValue, m_HeadRotation );
  5146. oldVal = Interpolate( flFactor, m_BaseValue, targetPosition );
  5147. newVal = Rotate( totalRotation, transformParams.m_Pivot, oldVal, m_BaseRotation );
  5148. }
  5149. else if ( m_nTSRegion == TS_REGION_HOLD ) // in hold region
  5150. {
  5151. newVal = Rotate( scaledRotation, transformParams.m_Pivot, m_HeadValue, oldRotation );
  5152. }
  5153. else // in falloff region
  5154. {
  5155. newVal = Rotate( totalRotation, transformParams.m_Pivot, m_BaseValue, oldRotation );
  5156. }
  5157. }
  5158. else // !bUsePresetRules && rotating && manipulate in falloff mode
  5159. {
  5160. if ( bIsVector && timeSelectionParams.m_TransformWriteMode == TRANSFORM_WRITE_MODE_TRANSFORM )
  5161. {
  5162. Quaternion scaledRotation;
  5163. ScaleRotationQuaternion( transformParams.m_RotationLocal, flFactor, scaledRotation );
  5164. // Compute the scaled rotation matrix using the transform pivot
  5165. matrix3x4_t xform;
  5166. AngleMatrix( RadianEuler( scaledRotation ), xform );
  5167. matrix3x4_t m1, m2;
  5168. AngleMatrix( vec3_angle, transformParams.m_Pivot, m1 );
  5169. AngleMatrix( vec3_angle, -transformParams.m_Pivot, m2 );
  5170. matrix3x4_t temp;
  5171. ConcatTransforms( m1, xform, temp );
  5172. ConcatTransforms( temp, m2, xform );
  5173. ConcatTransforms( m_HeadTransform, xform, xform );
  5174. matrix3x4_t scaledTransformMatrix;
  5175. ConcatTransforms( xform, m_InvHeadTransform, scaledTransformMatrix );
  5176. // Apply the transform using the active reference frame, if any.
  5177. newVal = TransformAbsolute( scaledTransformMatrix, oldVal );
  5178. }
  5179. else
  5180. {
  5181. Quaternion scaledRotation;
  5182. ScaleRotationQuaternion( transformParams.m_RotationParent, flFactor, scaledRotation );
  5183. newVal = Rotate( scaledRotation, transformParams.m_Pivot, oldVal, oldRotation, false );
  5184. }
  5185. }
  5186. }
  5187. InsertClampTransitionPoints( pWriteLayer, t, clampHelper, newVal, bSpew );
  5188. T clampedVal = pWriteLayer->GetTypedOwnerLog()->ClampValue( newVal );
  5189. T maskedVal = pWriteLayer->GetTypedOwnerLog()->MaskValue( t, clampedVal, timeSelectionParams.m_nComponentFlags );
  5190. // Add a key to the new "layer" at this time with this value
  5191. pWriteLayer->InsertKey( t, maskedVal, pReadLayer->GetSegmentInterpolationSetting(t), m_nCurveType, false );
  5192. if ( bSpew )
  5193. {
  5194. Msg(" Key: %d ", t.GetTenthsOfMS() );
  5195. SpewKey( clampedVal );
  5196. Msg(" [" );
  5197. SpewKey( newVal );
  5198. Msg( "]\n" );
  5199. }
  5200. }
  5201. //-----------------------------------------------------------------------------
  5202. // Stamp the key at the specified time
  5203. //-----------------------------------------------------------------------------
  5204. template< class T >
  5205. void CLogFalloffBlend< T >::UpdateClampHelper( DmeTime_t t, const CDmeTypedLogLayer<T>* pReadLayer,
  5206. float flIntensity, LogClampHelper_t<T> &clampHelper, const T* pInterpTarget )
  5207. {
  5208. // Stamp the key at the current time
  5209. T oldVal = pReadLayer->GetValue( t );
  5210. // In the falloff area
  5211. float flFactor = ComputeBlendFactor( t );
  5212. flFactor *= flIntensity;
  5213. T val;
  5214. if ( !pInterpTarget )
  5215. {
  5216. val = ScaleValue( m_Delta, flFactor );
  5217. val = Add( oldVal, val );
  5218. }
  5219. else
  5220. {
  5221. val = Interpolate( flFactor, oldVal, *pInterpTarget );
  5222. }
  5223. clampHelper.m_tLastTime = t;
  5224. clampHelper.m_LastUnclampedValue = val;
  5225. }
  5226. //-----------------------------------------------------------------------------
  5227. // This is used to modify the entire portion of the curve under the time selection
  5228. //-----------------------------------------------------------------------------
  5229. static inline DmeTime_t ComputeResampleStartTime( const DmeLog_TimeSelection_t &params, int nSide )
  5230. {
  5231. // NOTE: This logic will place the resampled points centered in the falloff regions
  5232. TimeSelectionTimes_t start = ( nSide == 0 ) ? TS_LEFT_FALLOFF : TS_RIGHT_HOLD;
  5233. TimeSelectionTimes_t end = ( nSide == 0 ) ? TS_LEFT_HOLD : TS_RIGHT_FALLOFF;
  5234. // The falloff region must be re-sampled if not a linear interpolation or if the the transform write mode
  5235. // is a rotation mode, since in that case the samples are not linear even if the falloff type is linear.
  5236. if ( ( params.m_nFalloffInterpolatorTypes[nSide] != INTERPOLATE_LINEAR_INTERP ) || params.m_bManipulateInFalloff )
  5237. {
  5238. DmeTime_t tDuration = params.m_nTimes[end] - params.m_nTimes[start];
  5239. if ( tDuration > params.m_nResampleInterval )
  5240. {
  5241. int nFactor = tDuration.GetTenthsOfMS() / params.m_nResampleInterval.GetTenthsOfMS();
  5242. tDuration -= params.m_nResampleInterval * nFactor;
  5243. tDuration /= 2;
  5244. return params.m_nTimes[start] + tDuration;
  5245. }
  5246. }
  5247. return DMETIME_MAXTIME;
  5248. }
  5249. //-----------------------------------------------------------------------------
  5250. // This is used to modify the entire portion of the curve under the time selection
  5251. //-----------------------------------------------------------------------------
  5252. template< class T >
  5253. void CDmeTypedLog< T >::_StampKeyAtHeadResample( DmeTime_t tHeadPosition, const DmeLog_TimeSelection_t& params, const DmeLogTransformParams_t &transformParams, const T& value, bool bSkipToHead, bool bClearPreviousKeys, int layerIndex /*= -1*/ )
  5254. {
  5255. Assert( params.m_nResampleInterval > DmeTime_t( 0 ) );
  5256. if ( params.m_nResampleInterval < DmeTime_t( 0 ) )
  5257. return;
  5258. // If a valid layer is specified, write to that layer, otherwise write to the topmost layer.
  5259. if ( ( layerIndex <= 0 ) || ( layerIndex >= m_Layers.Count() ) )
  5260. {
  5261. layerIndex = GetTopmostLayer();
  5262. }
  5263. // Should be in "layer recording" mode!!!
  5264. Assert( GetNumLayers() >= 2 );
  5265. int nBestLayer = layerIndex; // Topmost should be at least layer # 1 (0 is the base layer)
  5266. if ( nBestLayer < 1 )
  5267. return;
  5268. CDmeTypedLogLayer< T > *pWriteLayer = GetLayer( nBestLayer );
  5269. Assert( pWriteLayer );
  5270. if ( !pWriteLayer )
  5271. return;
  5272. if ( bClearPreviousKeys )
  5273. {
  5274. pWriteLayer->ClearKeys();
  5275. }
  5276. bool bSpew = false;
  5277. // NOTE: The headDelta is only used when not blending toward a preset
  5278. // When not blending toward a preset, just add the head delta onto everything.
  5279. // When blending toward a preset, lerp towards the preset.
  5280. T oldHeadValue;
  5281. if ( params.m_pOldHeadValue )
  5282. {
  5283. if ( params.m_OldHeadValueIndex >= 0 )
  5284. {
  5285. CDmrArrayConst<T> headValueArray( params.m_pOldHeadValue );
  5286. oldHeadValue = headValueArray[ params.m_OldHeadValueIndex ];
  5287. }
  5288. else
  5289. {
  5290. oldHeadValue = params.m_pOldHeadValue->GetValue< T >();
  5291. }
  5292. }
  5293. else
  5294. {
  5295. oldHeadValue = GetValueSkippingTopmostLayer( tHeadPosition );
  5296. }
  5297. T headDelta = Difference( value, oldHeadValue );
  5298. // When dragging preset fader, everything get's blended in by the amount of the preset being applied
  5299. bool bUsePresetRules = ( RECORD_PRESET == params.GetRecordingMode() );
  5300. bool bPerformInterpolation = bUsePresetRules;
  5301. // If not using a preset, determine if the existing values should be interpolated toward the
  5302. // new value or added to the new value based on the transform write mode for the appropriate operation.
  5303. if ( !bUsePresetRules )
  5304. {
  5305. if ( params.m_TransformWriteMode == TRANSFORM_WRITE_MODE_OVERWRITE )
  5306. {
  5307. bPerformInterpolation = true;
  5308. }
  5309. // Use the original head position from when the operation took place
  5310. if ( params.m_bManipulateInFalloff )
  5311. {
  5312. tHeadPosition = params.m_tHeadPosition;
  5313. }
  5314. }
  5315. bool bUsePresetValue = bUsePresetRules && params.m_pPresetValue && params.m_pPresetValue->GetType() == CDmAttributeInfo<T>::ATTRIBUTE_TYPE;
  5316. Assert( !params.m_pPresetValue || !IsArrayType( params.m_pPresetValue->GetType() ) );
  5317. if ( bUsePresetRules && !bUsePresetValue )
  5318. return;
  5319. const T& interpTarget = bUsePresetValue ? params.m_pPresetValue->GetValue<T>() : value;
  5320. // Compute falloff region blend factors
  5321. CLogFalloffBlend< T > blend[ 3 ];
  5322. blend[0].Init( this, tHeadPosition, headDelta, bUsePresetRules, TS_REGION_IN, params, transformParams );
  5323. blend[1].Init( this, tHeadPosition, headDelta, bUsePresetRules, TS_REGION_HOLD, params, transformParams );
  5324. blend[2].Init( this, tHeadPosition, headDelta, bUsePresetRules, TS_REGION_OUT, params, transformParams );
  5325. // The algorithm we're going to use is to add samples in the following places:
  5326. // 1) At each time selection transition point (start, end of falloff regions)
  5327. // NOTE: If a falloff region has 0 size, we'll add points right outside the transition
  5328. // 2) At the resample point (we're going to base this so the resamples always occur at the same spots)
  5329. // 3) At any existing sample position
  5330. // 4) Any time we switch from clamped to not clamped
  5331. // By doing this, we will guarantee no bogus slope changes
  5332. // First, compute times for transition regions
  5333. DmeTime_t tTransitionTimes[TS_TIME_COUNT];
  5334. memcpy( &tTransitionTimes, &params.m_nTimes, sizeof(params.m_nTimes) );
  5335. if ( tTransitionTimes[TS_LEFT_FALLOFF] == tTransitionTimes[TS_LEFT_HOLD] )
  5336. {
  5337. tTransitionTimes[TS_LEFT_FALLOFF] -= DMETIME_MINDELTA;
  5338. }
  5339. if ( tTransitionTimes[TS_RIGHT_FALLOFF] == tTransitionTimes[TS_RIGHT_HOLD] )
  5340. {
  5341. tTransitionTimes[TS_RIGHT_FALLOFF] += DMETIME_MINDELTA;
  5342. }
  5343. DmeTime_t tStartTime = params.m_nTimes[ TS_LEFT_FALLOFF ];
  5344. // Next, compute the first resample time for each region
  5345. DmeTime_t tResampleStartTime[TS_TIME_COUNT];
  5346. tResampleStartTime[TS_LEFT_FALLOFF] = DMETIME_MAXTIME;
  5347. tResampleStartTime[TS_LEFT_HOLD] = ComputeResampleStartTime( params, 0 );
  5348. tResampleStartTime[TS_RIGHT_HOLD] = DMETIME_MAXTIME;
  5349. tResampleStartTime[TS_RIGHT_FALLOFF] = ComputeResampleStartTime( params, 1 );
  5350. // Finally, figure out which layer we're reading from,
  5351. // where the next key is, and when we must stop reading from it
  5352. int nReadLayer = FindLayerForTimeSkippingTopmost( tStartTime );
  5353. CDmeTypedLogLayer< T > *pReadLayer = GetLayer( nReadLayer );
  5354. int nLayerSampleIndex = pReadLayer->FindKey( tStartTime ) + 1;
  5355. DmeTime_t tLayerEndTime = pReadLayer->GetEndTime( true );
  5356. // Get the log layer for the rotation if the rotation layer was specified
  5357. CDmeTypedLogLayer< Quaternion > *pRotationLayer = NULL;
  5358. if ( transformParams.m_pRotationLog )
  5359. {
  5360. if ( nReadLayer < transformParams.m_pRotationLog->GetNumLayers() )
  5361. {
  5362. pRotationLayer = transformParams.m_pRotationLog->GetLayer( nReadLayer );
  5363. }
  5364. }
  5365. // NOTE: This can happen after reading off the end of layer 0
  5366. if ( tLayerEndTime <= tStartTime )
  5367. {
  5368. tLayerEndTime = DMETIME_MAXTIME;
  5369. }
  5370. DmeTime_t tNextSampleTime = nLayerSampleIndex >= pReadLayer->GetKeyCount() ? tLayerEndTime : pReadLayer->GetKeyTime( nLayerSampleIndex );
  5371. if ( tNextSampleTime > tLayerEndTime )
  5372. {
  5373. tNextSampleTime = tLayerEndTime;
  5374. }
  5375. // If the time selection is infinite on either side skip
  5376. // the falloff section on the side that is infinite.
  5377. int nNextTransition = params.m_bInfinite[ 0 ] ? TS_RIGHT_HOLD : TS_LEFT_HOLD;
  5378. int nLastTransition = params.m_bInfinite[ 1 ] ? TS_RIGHT_FALLOFF : TS_TIME_COUNT;
  5379. // Now keep going until we've hit the end point
  5380. // NOTE: We use tTransitionTimes, *not* params.m_nTimes, so that we can get a single
  5381. // sample before zero-width left falloff regions
  5382. DmeTime_t tCurrent = tTransitionTimes[ nNextTransition - 1 ];
  5383. DmeTime_t tResampleTime = tResampleStartTime[nNextTransition];
  5384. const T* pInterpTarget = bPerformInterpolation ? &interpTarget : NULL;
  5385. if ( bSpew )
  5386. {
  5387. Msg( "Stamp key at head resample: %s\n", GetName() );
  5388. }
  5389. LogClampHelper_t<T> clampHelper;
  5390. while( nNextTransition < nLastTransition )
  5391. {
  5392. // Stamp the key at the current time
  5393. if ( !bSkipToHead || ( tCurrent >= tHeadPosition ) )
  5394. {
  5395. blend[nNextTransition-1].StampKey( pWriteLayer, tCurrent, pReadLayer, params.m_flIntensity, clampHelper, bSpew, pInterpTarget, pRotationLayer, params, transformParams );
  5396. }
  5397. // Update the read layer sample
  5398. if ( tCurrent == tNextSampleTime )
  5399. {
  5400. ++nLayerSampleIndex;
  5401. tNextSampleTime = nLayerSampleIndex >= pReadLayer->GetKeyCount() ? tLayerEndTime : pReadLayer->GetKeyTime( nLayerSampleIndex );
  5402. }
  5403. // Update the read layer
  5404. if ( tCurrent == tLayerEndTime )
  5405. {
  5406. nReadLayer = FindLayerForTimeSkippingTopmost( tCurrent + DMETIME_MINDELTA );
  5407. pReadLayer = GetLayer( nReadLayer );
  5408. nLayerSampleIndex = pReadLayer->FindKey( tCurrent ) + 1;
  5409. tLayerEndTime = pReadLayer->GetEndTime( true );
  5410. // NOTE: This can happen after reading off the end of layer 0
  5411. if ( tLayerEndTime <= tCurrent )
  5412. {
  5413. tLayerEndTime = DMETIME_MAXTIME;
  5414. }
  5415. tNextSampleTime = nLayerSampleIndex >= pReadLayer->GetKeyCount() ? tLayerEndTime : pReadLayer->GetKeyTime( nLayerSampleIndex );
  5416. if ( tNextSampleTime > tLayerEndTime )
  5417. {
  5418. tNextSampleTime = tLayerEndTime;
  5419. }
  5420. }
  5421. // Update the transition time
  5422. if ( tCurrent == tTransitionTimes[nNextTransition] )
  5423. {
  5424. // NOTE: This is necessary because each blend region has different 'deltas'
  5425. // to avoid overdriving in the falloff regions. Therefore, the 'previous value'
  5426. // used in the clamping operation will be different
  5427. if ( nNextTransition < TS_RIGHT_FALLOFF )
  5428. {
  5429. blend[nNextTransition].UpdateClampHelper( tCurrent, pReadLayer, params.m_flIntensity, clampHelper, pInterpTarget );
  5430. }
  5431. // Also need to update the 'previous' value stored in the
  5432. ++nNextTransition;
  5433. // Update the first resample time
  5434. tResampleTime = tResampleStartTime[nNextTransition];
  5435. if ( bSpew )
  5436. {
  5437. Msg( " Entering region %d\n", nNextTransition-1 );
  5438. }
  5439. }
  5440. // Update the resample time
  5441. if ( tCurrent == tResampleTime )
  5442. {
  5443. tResampleTime += params.m_nResampleInterval;
  5444. }
  5445. // Now that the key is stamped, update current time.
  5446. tCurrent = tTransitionTimes[nNextTransition];
  5447. if ( tResampleTime < tCurrent )
  5448. {
  5449. tCurrent = tResampleTime;
  5450. }
  5451. if ( tNextSampleTime < tCurrent )
  5452. {
  5453. tCurrent = tNextSampleTime;
  5454. }
  5455. }
  5456. Assert( !params.m_bInfinite[ 1 ] || ( pWriteLayer->GetEndTime( false ) <= params.m_nTimes[ TS_RIGHT_HOLD ] ) );
  5457. // Now apply final mask
  5458. LogComponents_t nComponentFlags = params.m_nComponentFlags;
  5459. if ( nComponentFlags != LOG_COMPONENTS_ALL )
  5460. {
  5461. // Mask output against base layer
  5462. MaskAgainstLayer( pWriteLayer, pReadLayer, nComponentFlags );
  5463. }
  5464. }
  5465. //-----------------------------------------------------------------------------
  5466. // Stamp the key directly into the log layer at the specified time. If
  5467. // specified filter by the time selection, only stamping the key if the time is
  5468. // within the selection.
  5469. //-----------------------------------------------------------------------------
  5470. template< class T >
  5471. void CDmeTypedLog< T >::_StampKeyAtTime( CDmeTypedLogLayer< T > *pWriteLayer, DmeTime_t t, const DmeLog_TimeSelection_t &params, const T& value, bool bFilterByTimeSelection, bool bForce )
  5472. {
  5473. float flFraction = params.m_flIntensity;
  5474. if ( bFilterByTimeSelection )
  5475. {
  5476. float flFraction = params.GetAmountForTime( t ) * params.m_flIntensity;
  5477. if ( flFraction <= 0.0f && !bForce )
  5478. return;
  5479. }
  5480. // When dragging preset fader, everything get's blended in by the amount of the preset being applied
  5481. bool bUsePresetRules = ( RECORD_PRESET == params.GetRecordingMode() );
  5482. if ( bUsePresetRules && !params.m_pPresetValue )
  5483. return;
  5484. Assert( !IsArrayType( params.m_pPresetValue->GetType() ) );
  5485. // FIXME: Preset value should never be NULL. We need to grab it from the attribute
  5486. const T& interpTarget = ( bUsePresetRules && params.m_pPresetValue ) ? params.m_pPresetValue->GetValue<T>() : value;
  5487. T oldVal = GetValueSkippingTopmostLayer( t );
  5488. T newVal = Interpolate( flFraction, oldVal, interpTarget, params.m_nComponentFlags );
  5489. T writeVal = ClampValue( newVal );
  5490. pWriteLayer->InsertKey( t, writeVal, GetSegmentInterpolationSetting_SkippingTopmostLayer(t), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  5491. }
  5492. //-----------------------------------------------------------------------------
  5493. // In this case, we actually stamp a key right at the head position unlike the above method
  5494. //-----------------------------------------------------------------------------
  5495. template< class T >
  5496. void CDmeTypedLog< T >::_StampKeyAtHead( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t &params, const T& value, bool bFilterByTimeSelection, int layerIndex /*= -1*/ )
  5497. {
  5498. // If a valid layer is specified, write to that layer, otherwise write to the topmost layer.
  5499. if ( ( layerIndex <= 0 ) || ( layerIndex >= m_Layers.Count() ) )
  5500. {
  5501. layerIndex = GetTopmostLayer();
  5502. }
  5503. // Should be in "layer recording" mode!!!
  5504. Assert( GetNumLayers() >= 2 );
  5505. int nBestLayer = layerIndex; // Topmost should be at least layer # 1 (0 is the base layer)
  5506. if ( nBestLayer < 1 )
  5507. return;
  5508. CDmeTypedLogLayer< T > *pWriteLayer = GetLayer( nBestLayer );
  5509. Assert( pWriteLayer );
  5510. if ( !pWriteLayer )
  5511. return;
  5512. // NOTE: This little trickery is necessary to generate samples right outside the
  5513. // transition region in the case of zero length falloff regions
  5514. DmeLog_TimeSelection_t tempParams = params;
  5515. if ( tempParams.m_nTimes[TS_LEFT_FALLOFF] == tempParams.m_nTimes[TS_LEFT_HOLD] )
  5516. {
  5517. tempParams.m_nTimes[TS_LEFT_FALLOFF] -= DMETIME_MINDELTA;
  5518. }
  5519. if ( tempParams.m_nTimes[TS_RIGHT_FALLOFF] == tempParams.m_nTimes[TS_RIGHT_HOLD] )
  5520. {
  5521. tempParams.m_nTimes[TS_RIGHT_FALLOFF] += DMETIME_MINDELTA;
  5522. }
  5523. int nPrevRegion = tempParams.ComputeRegionForTime( tPreviousHeadPosition );
  5524. int nCurrRegion = tempParams.ComputeRegionForTime( tHeadPosition );
  5525. // Test for backward performance!
  5526. if ( nCurrRegion < nPrevRegion )
  5527. {
  5528. V_swap( nCurrRegion, nPrevRegion );
  5529. }
  5530. // Insert samples at each transition point we skipped over
  5531. if ( bFilterByTimeSelection )
  5532. {
  5533. for ( int i = nPrevRegion; i < nCurrRegion; ++i )
  5534. {
  5535. _StampKeyAtTime( pWriteLayer, tempParams.m_nTimes[ i ], params, value, true, true );
  5536. }
  5537. }
  5538. _StampKeyAtTime( pWriteLayer, tHeadPosition, params, value, bFilterByTimeSelection );
  5539. }
  5540. template< class T >
  5541. void CDmeTypedLog< T >::RemoveKeys( DmeTime_t starttime )
  5542. {
  5543. int bestLayer = GetTopmostLayer();
  5544. if ( bestLayer < 0 )
  5545. return;
  5546. GetLayer( bestLayer )->RemoveKeys( starttime );
  5547. }
  5548. template< class T >
  5549. void CDmeTypedLog< T >::RemoveKey( int nKeyIndex, int nNumKeysToRemove /*= 1*/ )
  5550. {
  5551. int bestLayer = GetTopmostLayer();
  5552. if ( bestLayer < 0 )
  5553. return;
  5554. GetLayer( bestLayer )->RemoveKey( nKeyIndex, nNumKeysToRemove );
  5555. }
  5556. template< class T >
  5557. void CDmeTypedLog< T >::ClearKeys()
  5558. {
  5559. int bestLayer = GetTopmostLayer();
  5560. if ( bestLayer < 0 )
  5561. return;
  5562. GetLayer( bestLayer )->ClearKeys();
  5563. }
  5564. //-----------------------------------------------------------------------------
  5565. // Returns a specific key's value
  5566. //-----------------------------------------------------------------------------
  5567. template< class T >
  5568. DmeTime_t CDmeTypedLog< T >::GetKeyTime( int nKeyIndex ) const
  5569. {
  5570. int bestLayer = GetTopmostLayer();
  5571. if ( bestLayer < 0 )
  5572. return DmeTime_t::MinTime();
  5573. return GetLayer( bestLayer )->GetKeyTime( nKeyIndex );
  5574. }
  5575. template< class T >
  5576. void CDmeTypedLog< T >::SetKeyTime( int nKeyIndex, DmeTime_t keyTime )
  5577. {
  5578. int bestLayer = GetTopmostLayer();
  5579. if ( bestLayer < 0 )
  5580. return;
  5581. return GetLayer( bestLayer )->SetKeyTime( nKeyIndex, keyTime );
  5582. }
  5583. //-----------------------------------------------------------------------------
  5584. // Returns the index of a particular key
  5585. //-----------------------------------------------------------------------------
  5586. template< class T >
  5587. int CDmeTypedLog< T >::FindKeyWithinTolerance( DmeTime_t nTime, DmeTime_t nTolerance )
  5588. {
  5589. int bestLayer = GetTopmostLayer();
  5590. if ( bestLayer < 0 )
  5591. return -1;
  5592. return GetLayer( bestLayer )->FindKeyWithinTolerance( nTime, nTolerance );
  5593. }
  5594. //-----------------------------------------------------------------------------
  5595. // tests whether two values differ by more than the threshold
  5596. //-----------------------------------------------------------------------------
  5597. template<>
  5598. bool CDmeTypedLog< Vector >::ValuesDiffer( const Vector& a, const Vector& b ) const
  5599. {
  5600. return a.DistToSqr( b ) > s_threshold * s_threshold;
  5601. }
  5602. template<>
  5603. bool CDmeTypedLog< QAngle >::ValuesDiffer( const QAngle& a, const QAngle& b ) const
  5604. {
  5605. return ( a - b ).LengthSqr() > s_threshold * s_threshold;
  5606. }
  5607. template<>
  5608. bool CDmeTypedLog< Quaternion >::ValuesDiffer( const Quaternion& a, const Quaternion& b ) const
  5609. {
  5610. return QuaternionAngleDiff( a, b ) > s_threshold;
  5611. }
  5612. template<>
  5613. bool CDmeTypedLog< float >::ValuesDiffer( const float& a, const float& b ) const
  5614. {
  5615. return fabs( a - b ) > s_threshold;
  5616. }
  5617. template< class T >
  5618. bool CDmeTypedLog< T >::ValuesDiffer( const T& a, const T& b ) const
  5619. {
  5620. return a != b;
  5621. }
  5622. //-----------------------------------------------------------------------------
  5623. // Sets a key, removes all keys after this time
  5624. //-----------------------------------------------------------------------------
  5625. template< class T >
  5626. void CDmeTypedLog< T >::SetKey( DmeTime_t time, const T& value, SegmentInterpolation_t interpSetting /*= SEGMENT_INTERPOLATE*/, int curveType /*=CURVE_DEFAULT*/)
  5627. {
  5628. int bestLayer = GetTopmostLayer();
  5629. if ( bestLayer < 0 )
  5630. return;
  5631. GetLayer( bestLayer )->SetKey( time, value, interpSetting, curveType );
  5632. }
  5633. template< class T >
  5634. CDmeTypedLogLayer< T > *CDmeTypedLog< T >::GetLayer( int index )
  5635. {
  5636. if ( index < 0 )
  5637. return NULL;
  5638. return static_cast< CDmeTypedLogLayer< T > * >( m_Layers[ index ] );
  5639. }
  5640. template< class T >
  5641. const CDmeTypedLogLayer< T > *CDmeTypedLog< T >::GetLayer( int index ) const
  5642. {
  5643. if ( index < 0 )
  5644. return NULL;
  5645. return static_cast< CDmeTypedLogLayer< T > * >( m_Layers[ index ] );
  5646. }
  5647. //-----------------------------------------------------------------------------
  5648. // Finds a key within tolerance, or adds one
  5649. //-----------------------------------------------------------------------------
  5650. template< class T >
  5651. int CDmeTypedLog< T >::FindOrAddKey( DmeTime_t nTime, DmeTime_t nTolerance, const T& value, SegmentInterpolation_t interpSetting /*= SEGMENT_INTERPOLATE*/, int curveType /*=CURVE_DEFAULT*/ )
  5652. {
  5653. int bestLayer = GetTopmostLayer();
  5654. if ( bestLayer == -1 )
  5655. return -1;
  5656. return GetLayer( bestLayer )->FindOrAddKey( nTime, nTolerance, value, interpSetting, curveType );
  5657. }
  5658. //-----------------------------------------------------------------------------
  5659. // This inserts a key. Unlike SetKey, this will *not* delete keys after the specified time
  5660. //-----------------------------------------------------------------------------
  5661. template < class T >
  5662. int CDmeTypedLog< T >::InsertKey( DmeTime_t nTime, const T& value, SegmentInterpolation_t interpSetting /*= SEGMENT_INTERPOLATE*/, int curveType /*=CURVE_DEFAULT*/, bool bIgnoreTolerance /*= false*/ )
  5663. {
  5664. int bestLayer = GetTopmostLayer();
  5665. if ( bestLayer == -1 )
  5666. return -1;
  5667. return GetLayer( bestLayer )->InsertKey( nTime, value, interpSetting, curveType, bIgnoreTolerance );
  5668. }
  5669. template < class T >
  5670. int CDmeTypedLog< T >::InsertKeyAtTime( DmeTime_t nTime, int curveType /*=CURVE_DEFAULT*/ )
  5671. {
  5672. int bestLayer = GetTopmostLayer();
  5673. if ( bestLayer == -1 )
  5674. return -1;
  5675. return GetLayer( bestLayer )->InsertKeyAtTime( nTime, curveType );
  5676. }
  5677. template< class T >
  5678. const T& CDmeTypedLog< T >::GetValue( DmeTime_t time ) const
  5679. {
  5680. int bestLayer = FindLayerForTime( time );
  5681. if ( bestLayer < 0 )
  5682. {
  5683. static T s_value;
  5684. CDmAttributeInfo< T >::SetDefaultValue( s_value ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  5685. return s_value;
  5686. }
  5687. return GetLayer( bestLayer )->GetValue( time );
  5688. }
  5689. template< class T >
  5690. SegmentInterpolation_t CDmeTypedLog< T >::GetSegmentInterpolationSetting( DmeTime_t time ) const
  5691. {
  5692. int bestLayer = FindLayerForTime( time );
  5693. if ( bestLayer < 0 )
  5694. {
  5695. return SEGMENT_INTERPOLATE;
  5696. }
  5697. return GetLayer( bestLayer )->GetSegmentInterpolationSetting( time );
  5698. }
  5699. template< class T >
  5700. const T& CDmeTypedLog< T >::GetValueSkippingTopmostLayer( DmeTime_t time ) const
  5701. {
  5702. int nLayer = FindLayerForTimeSkippingTopmost( time );
  5703. if ( nLayer < 0 )
  5704. return GetValue( time );
  5705. return GetLayer( nLayer )->GetValue( time );
  5706. }
  5707. template< class T >
  5708. SegmentInterpolation_t CDmeTypedLog< T >::GetSegmentInterpolationSetting_SkippingTopmostLayer( DmeTime_t time ) const
  5709. {
  5710. int nLayer = FindLayerForTimeSkippingTopmost( time );
  5711. if ( nLayer < 0 )
  5712. return GetSegmentInterpolationSetting( time );
  5713. return GetLayer( nLayer )->GetSegmentInterpolationSetting( time );
  5714. }
  5715. template< class T >
  5716. const T& CDmeTypedLog< T >::GetValueBelowLayer( DmeTime_t time, int nTopLayerIndex ) const
  5717. {
  5718. int nLayer = FindLayerForTimeBelowLayer( time, nTopLayerIndex );
  5719. if ( nLayer < 0 )
  5720. return GetValue( time );
  5721. return GetLayer( nLayer )->GetValue( time );
  5722. }
  5723. template< class T >
  5724. void CDmeTypedLog< T >::SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index, SegmentInterpolation_t interpSetting /*= SEGMENT_INTERPOLATE*/, int curveType /*= CURVE_DEFAULT*/ )
  5725. {
  5726. int bestLayer = GetTopmostLayer();
  5727. if ( bestLayer == -1 )
  5728. return;
  5729. GetLayer( bestLayer )->SetKey( time, pAttr, index, interpSetting, curveType );
  5730. }
  5731. template< class T >
  5732. bool CDmeTypedLog< T >::SetDuplicateKeyAtTime( DmeTime_t time )
  5733. {
  5734. int bestLayer = GetTopmostLayer();
  5735. if ( bestLayer == -1 )
  5736. return false;
  5737. return GetLayer( bestLayer )->SetDuplicateKeyAtTime( time );
  5738. }
  5739. //-----------------------------------------------------------------------------
  5740. // Returns a specific key's value
  5741. //-----------------------------------------------------------------------------
  5742. template< class T >
  5743. const T& CDmeTypedLog< T >::GetKeyValue( int nKeyIndex ) const
  5744. {
  5745. int bestLayer = GetTopmostLayer();
  5746. if ( bestLayer == -1 )
  5747. {
  5748. static T s_value;
  5749. CDmAttributeInfo< T >::SetDefaultValue( s_value ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  5750. return s_value;
  5751. }
  5752. return GetLayer( bestLayer )->GetKeyValue( nKeyIndex );
  5753. }
  5754. template< class T >
  5755. void CDmeTypedLog< T >::GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index ) const
  5756. {
  5757. int bestLayer = FindLayerForTime( time );
  5758. if ( bestLayer < 0 )
  5759. {
  5760. T value;
  5761. CDmAttributeInfo< T >::SetDefaultValue( value ); // TODO - create GetDefaultValue that returns a default T, to avoid rebuilding every time
  5762. pAttr->SetValue( CDmAttributeInfo< T >::AttributeType(), &value );
  5763. return;
  5764. }
  5765. GetLayer( bestLayer )->GetValue( time, pAttr, index );
  5766. }
  5767. template< class T >
  5768. void CDmeTypedLog< T >::GetValueSkippingTopmostLayer( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const
  5769. {
  5770. CUtlVector< int > layers;
  5771. FindLayersForTime( time, layers );
  5772. int layerCount = layers.Count();
  5773. if ( layerCount <= 1 )
  5774. {
  5775. GetValue( time, pAttr, index );
  5776. return;
  5777. }
  5778. int topMostLayer = GetTopmostLayer();
  5779. int useLayer = layers[ layerCount - 1 ];
  5780. if ( topMostLayer == useLayer )
  5781. {
  5782. useLayer = layers[ layerCount - 2 ];
  5783. }
  5784. Assert( useLayer >= 0 );
  5785. GetLayer( useLayer )->GetValue( time, pAttr, index );
  5786. }
  5787. template< class T >
  5788. float CDmeTypedLog< T >::GetComponent( DmeTime_t time, int componentIndex ) const
  5789. {
  5790. return ::GetComponent( GetValue( time ), componentIndex );
  5791. }
  5792. //-----------------------------------------------------------------------------
  5793. // resampling and filtering
  5794. //-----------------------------------------------------------------------------
  5795. template< class T >
  5796. void CDmeTypedLog< T >::Resample( DmeFramerate_t samplerate )
  5797. {
  5798. int c = m_Layers.Count();
  5799. for ( int i = 0; i < c; ++i )
  5800. {
  5801. GetLayer( i )->Resample( samplerate );
  5802. }
  5803. }
  5804. template< class T >
  5805. void CDmeTypedLog< T >::Filter( int nSampleRadius )
  5806. {
  5807. int c = m_Layers.Count();
  5808. for ( int i = 0; i < c; ++i )
  5809. {
  5810. GetLayer( i )->Filter( nSampleRadius );
  5811. }
  5812. }
  5813. template< class T >
  5814. void CDmeTypedLog< T >::Filter2( DmeTime_t sampleRadius )
  5815. {
  5816. int c = m_Layers.Count();
  5817. for ( int i = 0; i < c; ++i )
  5818. {
  5819. GetLayer( i )->Filter2( sampleRadius );
  5820. }
  5821. }
  5822. template< class T >
  5823. void CDmeTypedLog< T >::OnAttributeArrayElementAdded( CDmAttribute *pAttribute, int nFirstElem, int nLastElem )
  5824. {
  5825. BaseClass::OnAttributeArrayElementAdded( pAttribute, nFirstElem, nLastElem );
  5826. if ( pAttribute == m_Layers.GetAttribute() )
  5827. {
  5828. for ( int i = nFirstElem; i <= nLastElem; ++i )
  5829. {
  5830. CDmeLogLayer *pLayer = m_Layers[i];
  5831. if ( !pLayer )
  5832. continue;
  5833. pLayer->SetOwnerLog( this );
  5834. }
  5835. return;
  5836. }
  5837. }
  5838. template< class T >
  5839. void CDmeTypedLog< T >::SetUseEdgeInfo( bool state )
  5840. {
  5841. Assert( IsUsingCurveTypes() );
  5842. GetTypedCurveInfo()->SetUseEdgeInfo( state );
  5843. }
  5844. template< class T >
  5845. bool CDmeTypedLog< T >::IsUsingEdgeInfo() const
  5846. {
  5847. Assert( IsUsingCurveTypes() );
  5848. return GetTypedCurveInfo()->IsUsingEdgeInfo();
  5849. }
  5850. template< class T >
  5851. void CDmeTypedLog< T >::SetEdgeInfo( int edge, bool active, const T& val, int curveType )
  5852. {
  5853. Assert( IsUsingCurveTypes() );
  5854. GetTypedCurveInfo()->SetEdgeInfo( edge, active, val, curveType );
  5855. }
  5856. template< class T >
  5857. void CDmeTypedLog< T >::SetDefaultEdgeZeroValue( const T& val )
  5858. {
  5859. Assert( IsUsingCurveTypes() );
  5860. GetTypedCurveInfo()->SetDefaultEdgeZeroValue( val );
  5861. }
  5862. template< class T >
  5863. const T& CDmeTypedLog< T >::GetDefaultEdgeZeroValue() const
  5864. {
  5865. Assert( IsUsingCurveTypes() );
  5866. return GetTypedCurveInfo()->GetDefaultEdgeZeroValue();
  5867. }
  5868. template< class T >
  5869. void CDmeTypedLog< T >::SetRightEdgeTime( DmeTime_t time )
  5870. {
  5871. Assert( IsUsingCurveTypes() );
  5872. GetTypedCurveInfo()->SetRightEdgeTime( time );
  5873. }
  5874. template< class T >
  5875. DmeTime_t CDmeTypedLog< T >::GetRightEdgeTime() const
  5876. {
  5877. Assert( IsUsingCurveTypes() );
  5878. return GetTypedCurveInfo()->GetRightEdgeTime();
  5879. }
  5880. template< class T >
  5881. void CDmeTypedLog< T >::GetEdgeInfo( int edge, bool& active, T& val, int& curveType ) const
  5882. {
  5883. Assert( IsUsingCurveTypes() );
  5884. GetTypedCurveInfo()->GetEdgeInfo( edge, active, val, curveType );
  5885. }
  5886. template< class T >
  5887. int CDmeTypedLog< T >::GetEdgeCurveType( int edge ) const
  5888. {
  5889. Assert( IsUsingCurveTypes() );
  5890. return GetTypedCurveInfo()->GetEdgeCurveType( edge );
  5891. }
  5892. template< class T >
  5893. void CDmeTypedLog< T >::GetZeroValue( int side, T& val ) const
  5894. {
  5895. Assert( IsUsingCurveTypes() );
  5896. GetTypedCurveInfo()->GetZeroValue( side, val );
  5897. }
  5898. template< class T >
  5899. bool CDmeTypedLog< T >::IsEdgeActive( int edge ) const
  5900. {
  5901. Assert( IsUsingCurveTypes() );
  5902. return GetTypedCurveInfo()->IsEdgeActive( edge );
  5903. }
  5904. template< class T >
  5905. void CDmeTypedLog< T >::GetEdgeValue( int edge, T& val ) const
  5906. {
  5907. Assert( IsUsingCurveTypes() );
  5908. GetTypedCurveInfo()->GetEdgeValue( edge, val );
  5909. }
  5910. template< class T >
  5911. void CDmeTypedLog< T >::BlendTimesUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t &params, DmeTime_t tStartOffset, bool bFeatherBlendInFalloff )
  5912. {
  5913. // Top layer has the moved key times (not including tStartOffset)
  5914. const CDmeTypedLogLayer< T > *topLayer = static_cast< const CDmeTypedLogLayer< T > * >( secondLayer );
  5915. if ( !topLayer )
  5916. return;
  5917. // Base layer has the original key times (not including tStartOffset)
  5918. const CDmeTypedLogLayer< T > *baseLayer = static_cast< const CDmeTypedLogLayer< T > * >( firstLayer );
  5919. if ( !baseLayer )
  5920. return;
  5921. // Output layer which has tStartOffset factored in
  5922. CDmeTypedLogLayer< T > *newLayer = static_cast< CDmeTypedLogLayer< T > * >( outputLayer );
  5923. if ( !newLayer )
  5924. return;
  5925. Assert( topLayer->GetKeyCount() == baseLayer->GetKeyCount() );
  5926. newLayer->ClearKeys();
  5927. LogComponents_t nComponentFlags = params.m_nComponentFlags;
  5928. int kc = baseLayer->GetKeyCount();
  5929. for ( int i = 0; i < kc; ++i )
  5930. {
  5931. DmeTime_t baseKeyTime = baseLayer->GetKeyTime( i );
  5932. DmeTime_t checkTime = baseKeyTime + tStartOffset;
  5933. if ( checkTime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  5934. continue;
  5935. if ( checkTime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  5936. break;
  5937. float flInterp = bFeatherBlendInFalloff ? params.m_flIntensity * params.GetAmountForTime( checkTime ) : params.m_flIntensity;
  5938. DmeTime_t targetKeyTime = topLayer->GetKeyTime( i );
  5939. DmeTime_t blendedKeyTime = Lerp( flInterp, baseKeyTime, targetKeyTime );
  5940. // Apply mask if needed
  5941. T val = baseLayer->MaskValue( blendedKeyTime, baseLayer->GetKeyValue( i ), nComponentFlags );
  5942. newLayer->InsertKey( blendedKeyTime + tStartOffset, val, baseLayer->GetSegmentInterpolationSetting( baseKeyTime, blendedKeyTime, false ) );
  5943. }
  5944. // If masking parts of logs, then stamp old key times, too,
  5945. // so that we can preserver the specific peaks from the old data set
  5946. if ( nComponentFlags != LOG_COMPONENTS_ALL )
  5947. {
  5948. for ( int i = 0; i < kc; ++i )
  5949. {
  5950. DmeTime_t baseKeyTime = baseLayer->GetKeyTime( i );
  5951. DmeTime_t checkTime = baseKeyTime + tStartOffset;
  5952. if ( checkTime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  5953. continue;
  5954. if ( checkTime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  5955. break;
  5956. T val = baseLayer->GetKeyValue( i );
  5957. T newLayerValue = newLayer->GetValue( checkTime );
  5958. T masked = ::MaskValue( newLayerValue, val, nComponentFlags );
  5959. int iNextKey = ((i+1) < kc) ? i+1 : i;
  5960. SegmentInterpolation_t interpSetting = (baseLayer->GetSegmentInterpolationSetting( i, iNextKey ) == SEGMENT_NOINTERPOLATE) ||
  5961. (newLayer->GetSegmentInterpolationSetting( checkTime, baseLayer->GetKeyTime( iNextKey ) + tStartOffset, ((i+1) < kc) ) == SEGMENT_NOINTERPOLATE) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  5962. newLayer->InsertKey( checkTime, masked, interpSetting );
  5963. }
  5964. }
  5965. }
  5966. //-----------------------------------------------------------------------------
  5967. // Purpose: Blend the first and second layer together using the intensity
  5968. // parameter of the time selection and then blend the result with the base
  5969. // layer using the time falloff.
  5970. //-----------------------------------------------------------------------------
  5971. template< class T >
  5972. void CDmeTypedLog< T >::BlendLayersUsingTimeSelection( const CDmeLogLayer *baseLayer, const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t &params, bool bUseBaseLayerSamples, DmeTime_t tStartOffset )
  5973. {
  5974. const CDmeTypedLogLayer< T > *pBaseLayer = static_cast< const CDmeTypedLogLayer< T > * >( baseLayer );
  5975. if ( !pBaseLayer )
  5976. return;
  5977. const CDmeTypedLogLayer< T > *pLayerA = static_cast< const CDmeTypedLogLayer< T > * >( firstLayer );
  5978. if ( !pLayerA )
  5979. return;
  5980. const CDmeTypedLogLayer< T > *pLayerB = static_cast< const CDmeTypedLogLayer< T > * >( secondLayer );
  5981. if ( !pLayerB )
  5982. return;
  5983. CDmeTypedLogLayer< T > *pOutputLayer = static_cast< CDmeTypedLogLayer< T > * >( outputLayer );
  5984. if ( !pOutputLayer )
  5985. return;
  5986. LogComponents_t nComponents = params.m_nComponentFlags;
  5987. int i;
  5988. // Resample everything in the base layer first
  5989. int kc = pBaseLayer->GetKeyCount();
  5990. if ( bUseBaseLayerSamples )
  5991. {
  5992. for ( i = 0; i < kc; ++i )
  5993. {
  5994. DmeTime_t keyTime = pBaseLayer->GetKeyTime( i );
  5995. if ( keyTime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  5996. continue;
  5997. if ( keyTime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  5998. break;
  5999. float falloff = params.GetAmountForTime( keyTime );
  6000. T baseVal = pBaseLayer->GetKeyValue( i );
  6001. T valA = pLayerA->GetValue( keyTime );
  6002. T valB = pLayerB->GetValue( keyTime );
  6003. T blended = Interpolate( params.m_flIntensity, valA, valB );
  6004. T newVal = Interpolate( falloff, baseVal, blended, nComponents );
  6005. DmeTime_t nextTime = ((i+1) < kc) ? pBaseLayer->GetKeyTime(i+1) : DMETIME_INVALID;
  6006. SegmentInterpolation_t interpSetting = (pBaseLayer->GetSegmentInterpolationSetting( i ) == SEGMENT_NOINTERPOLATE) ||
  6007. (pLayerA->GetSegmentInterpolationSetting( keyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ||
  6008. (pLayerB->GetSegmentInterpolationSetting( keyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  6009. pOutputLayer->SetKey( keyTime + tStartOffset, newVal, interpSetting, CURVE_DEFAULT, false );
  6010. }
  6011. }
  6012. kc = pLayerA->GetKeyCount();
  6013. for ( i = 0; i < kc; ++i )
  6014. {
  6015. DmeTime_t keyTime = pLayerA->GetKeyTime( i );
  6016. DmeTime_t finalKeyTime = keyTime + tStartOffset;
  6017. if ( finalKeyTime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6018. continue;
  6019. if ( finalKeyTime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6020. break;
  6021. float falloff = params.GetAmountForTime( finalKeyTime );
  6022. T baseVal = pBaseLayer->GetValue( keyTime );
  6023. T valA = pLayerA->GetKeyValue( i );
  6024. T valB = pLayerB->GetValue( keyTime );
  6025. T blended = Interpolate( params.m_flIntensity, valA, valB );
  6026. T newVal = Interpolate( falloff, baseVal, blended, nComponents );
  6027. DmeTime_t nextTime = ((i+1) < kc) ? pLayerA->GetKeyTime(i+1) : DMETIME_INVALID;
  6028. SegmentInterpolation_t interpSetting = (pBaseLayer->GetSegmentInterpolationSetting( keyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ||
  6029. (pLayerA->GetSegmentInterpolationSetting( i ) == SEGMENT_NOINTERPOLATE) ||
  6030. (pLayerB->GetSegmentInterpolationSetting( keyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  6031. pOutputLayer->InsertKey( finalKeyTime, newVal, interpSetting );
  6032. }
  6033. kc = pLayerB->GetKeyCount();
  6034. for ( i = 0; i < kc; ++i )
  6035. {
  6036. DmeTime_t keyTime = pLayerB->GetKeyTime( i );
  6037. DmeTime_t finalKeyTime = keyTime + tStartOffset;
  6038. if ( finalKeyTime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6039. continue;
  6040. if ( finalKeyTime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6041. break;
  6042. float falloff = params.GetAmountForTime( finalKeyTime );
  6043. T baseVal = pBaseLayer->GetValue( keyTime );
  6044. T valA = pLayerA->GetValue( keyTime );
  6045. T valB = pLayerB->GetKeyValue( i );
  6046. T blended = Interpolate( params.m_flIntensity, valA, valB );
  6047. T newVal = Interpolate( falloff, baseVal, blended, nComponents );
  6048. DmeTime_t nextTime = ((i+1) < kc) ? pLayerB->GetKeyTime(i+1) : DMETIME_INVALID;
  6049. SegmentInterpolation_t interpSetting = (pBaseLayer->GetSegmentInterpolationSetting( keyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ||
  6050. (pLayerA->GetSegmentInterpolationSetting( keyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ||
  6051. (pLayerB->GetSegmentInterpolationSetting( i ) == SEGMENT_NOINTERPOLATE) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  6052. pOutputLayer->InsertKey( finalKeyTime, newVal, interpSetting );
  6053. }
  6054. if ( nComponents != LOG_COMPONENTS_ALL )
  6055. {
  6056. // Mask output against true base layer
  6057. MaskAgainstLayer( pOutputLayer, GetLayer( 0 ), nComponents );
  6058. }
  6059. if ( g_pDmElementFramework->GetPhase() == PH_EDIT )
  6060. {
  6061. pOutputLayer->RemoveRedundantKeys( params.m_flThreshold, false );
  6062. }
  6063. }
  6064. template< class T >
  6065. void CDmeTypedLog< T >::MaskAgainstLayer( CDmeTypedLogLayer< T > *pFinalLayer, const CDmeTypedLogLayer< T > *pReferenceLayer, LogComponents_t nComponentFlags )
  6066. {
  6067. // Nothing to do
  6068. if ( nComponentFlags == LOG_COMPONENTS_ALL )
  6069. return;
  6070. int kc = pFinalLayer->GetKeyCount();
  6071. for ( int i = 0; i < kc; ++i )
  6072. {
  6073. DmeTime_t t = pFinalLayer->GetKeyTime( i );
  6074. T val = pFinalLayer->GetKeyValue( i );
  6075. T maskedVal = pReferenceLayer->MaskValue( t, val, nComponentFlags );
  6076. pFinalLayer->SetKeyValue( i, maskedVal );
  6077. }
  6078. }
  6079. template< class T >
  6080. void CDmeTypedLog< T >::BlendLayersUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t &params, bool bUseBaseLayerSamples, bool bUseFalloff, bool bSelectionSamples, DmeTime_t tStartOffset )
  6081. {
  6082. const CDmeTypedLogLayer< T > *topLayer = static_cast< const CDmeTypedLogLayer< T > * >( secondLayer );
  6083. if ( !topLayer )
  6084. return;
  6085. const CDmeTypedLogLayer< T > *baseLayer = static_cast< const CDmeTypedLogLayer< T > * >( firstLayer );
  6086. if ( !baseLayer )
  6087. return;
  6088. CDmeTypedLogLayer< T > *newLayer = static_cast< CDmeTypedLogLayer< T > * >( outputLayer );
  6089. if ( !newLayer )
  6090. return;
  6091. LogComponents_t nComponents = params.m_nComponentFlags;
  6092. int i;
  6093. // Resample everything in the base layer first
  6094. int kc = baseLayer->GetKeyCount();
  6095. if ( bUseBaseLayerSamples )
  6096. {
  6097. for ( i = 0; i < kc; ++i )
  6098. {
  6099. DmeTime_t keyTime = baseLayer->GetKeyTime( i );
  6100. if ( keyTime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6101. continue;
  6102. if ( keyTime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6103. break;
  6104. float frac = bUseFalloff ? params.GetAmountForTime( keyTime ) : 1.0f;
  6105. float frac2 = params.m_flIntensity;
  6106. T baseVal = baseLayer->GetKeyValue( i );
  6107. T newVal = topLayer->GetValue( keyTime );
  6108. T blended = Interpolate( frac2 * frac, baseVal, newVal, nComponents );
  6109. DmeTime_t nextTime = ((i+1) < kc) ? baseLayer->GetKeyTime(i+1) : DMETIME_INVALID;
  6110. SegmentInterpolation_t interpSetting = (baseLayer->GetSegmentInterpolationSetting( i ) == SEGMENT_NOINTERPOLATE) ||
  6111. (topLayer->GetSegmentInterpolationSetting( keyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  6112. newLayer->SetKey( keyTime + tStartOffset, blended, interpSetting, CURVE_DEFAULT, false );
  6113. }
  6114. }
  6115. kc = topLayer->GetKeyCount();
  6116. for ( i = 0; i < kc; ++i )
  6117. {
  6118. DmeTime_t keyTime = topLayer->GetKeyTime( i );
  6119. DmeTime_t finalKeyTime = keyTime + tStartOffset;
  6120. if ( finalKeyTime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6121. continue;
  6122. if ( finalKeyTime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6123. break;
  6124. float frac = bUseFalloff ? params.GetAmountForTime( finalKeyTime ) : 1.0f;
  6125. float frac2 = params.m_flIntensity;
  6126. T baseVal = baseLayer->GetValue( keyTime );
  6127. T newVal = topLayer->GetKeyValue( i );
  6128. T blended = Interpolate( frac2 * frac, baseVal, newVal, nComponents );
  6129. DmeTime_t nextTime = ((i+1) < kc) ? topLayer->GetKeyTime(i+1) : DMETIME_INVALID;
  6130. SegmentInterpolation_t interpSetting = (baseLayer->GetSegmentInterpolationSetting( keyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ||
  6131. (topLayer->GetSegmentInterpolationSetting( i ) == SEGMENT_NOINTERPOLATE) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  6132. newLayer->InsertKey( finalKeyTime, blended, interpSetting );
  6133. }
  6134. if ( g_pDmElementFramework->GetPhase() == PH_EDIT )
  6135. {
  6136. newLayer->RemoveRedundantKeys( params.m_flThreshold, false );
  6137. }
  6138. // If the selection samples flag is set, insert keys at each of the time points of the time selection.
  6139. // This is used to ensure that there is a key with the appropriate value at the edge of the time selection.
  6140. // Note, this is done after the removal of redundant keys so that these keys will never be removed.
  6141. if ( bSelectionSamples )
  6142. {
  6143. for ( int i = 0; i < TS_TIME_COUNT; ++i )
  6144. {
  6145. DmeTime_t time = params.m_nTimes[ i ];
  6146. float falloff = bUseFalloff ? params.GetAmountForTime( time ) : 1.0f;
  6147. T baseVal = baseLayer->GetValue( time - tStartOffset );
  6148. T newVal = topLayer->GetValue( time - tStartOffset );
  6149. T blended = Interpolate( params.m_flIntensity * falloff, baseVal, newVal, nComponents );
  6150. DmeTime_t nextTime = ((i+1) < TS_TIME_COUNT) ? params.m_nTimes[i+1] - tStartOffset : DMETIME_INVALID;
  6151. SegmentInterpolation_t interpSetting = (baseLayer->GetSegmentInterpolationSetting( time - tStartOffset, nextTime, true ) == SEGMENT_NOINTERPOLATE) ||
  6152. (topLayer->GetSegmentInterpolationSetting( time - tStartOffset, nextTime, true ) == SEGMENT_NOINTERPOLATE) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  6153. newLayer->InsertKey( time, blended, interpSetting );
  6154. }
  6155. }
  6156. if ( nComponents != LOG_COMPONENTS_ALL )
  6157. {
  6158. // Mask output against true base layer
  6159. MaskAgainstLayer( newLayer, GetLayer( 0 ), nComponents );
  6160. }
  6161. }
  6162. template< class T >
  6163. void CDmeTypedLog< T >::BlendLayersUsingTimeSelection( const DmeLog_TimeSelection_t &params, int baseLayerIndex )
  6164. {
  6165. Assert( GetNumLayers() >= 2 );
  6166. int bestLayer = GetTopmostLayer(); // Topmost should be at least layer # 1 (0 is the base layer)
  6167. if ( bestLayer <= 0 )
  6168. return;
  6169. Assert( baseLayerIndex < bestLayer );
  6170. if ( baseLayerIndex >= bestLayer )
  6171. return;
  6172. Assert( params.m_nResampleInterval > DmeTime_t( 0 ) );
  6173. if ( params.m_nResampleInterval < DmeTime_t( 0 ) )
  6174. return;
  6175. CDmeTypedLogLayer< T > *topLayer = GetLayer( bestLayer );
  6176. Assert( topLayer );
  6177. if ( !topLayer )
  6178. return;
  6179. CDmeTypedLogLayer< T > *baseLayer = GetLayer( baseLayerIndex );
  6180. if ( !baseLayer )
  6181. return;
  6182. CDmeTypedLogLayer< T > *newLayer = static_cast< CDmeTypedLogLayer< T > * >( CreateLayer< T >( this ) );
  6183. Assert( newLayer );
  6184. if ( !newLayer )
  6185. return;
  6186. BlendLayersUsingTimeSelection( baseLayer, topLayer, newLayer, params, true, true, true, DMETIME_ZERO );
  6187. // Store it back into the new topmost layer
  6188. topLayer->CopyLayer( newLayer );
  6189. g_pDataModel->DestroyElement( newLayer->GetHandle() );
  6190. }
  6191. void InterleaveSampleTimes( CUtlVector< DmeTime_t > &times, int nFirstTime, DmeTime_t startTime, DmeTime_t endTime, DmeTime_t resampleInterval )
  6192. {
  6193. Assert( ( nFirstTime >= times.Count() ) || times[ nFirstTime ] > startTime );
  6194. DmeTime_t sampleTime = startTime + resampleInterval;
  6195. int nNumSampleTimes = ( ( endTime - sampleTime ).GetTenthsOfMS() / resampleInterval.GetTenthsOfMS() );
  6196. CUtlVector< DmeTime_t > combineTimes( 0, times.Count() + nNumSampleTimes + 2 );
  6197. combineTimes.AddMultipleToTail( nFirstTime, times.Base() );
  6198. int nBlendTimeIndex = nFirstTime;
  6199. int nNumBlendTimes = times.Count();
  6200. DmeTime_t blendTime = ( nBlendTimeIndex < nNumBlendTimes ) ? times[ nBlendTimeIndex ] : DMETIME_MAXTIME;
  6201. while ( ( sampleTime < endTime ) || ( blendTime < endTime ) )
  6202. {
  6203. while ( ( sampleTime <= blendTime ) && ( sampleTime < endTime ) )
  6204. {
  6205. combineTimes.AddToTail( sampleTime );
  6206. sampleTime = sampleTime + resampleInterval;
  6207. }
  6208. while ( ( blendTime <= sampleTime ) && ( blendTime < endTime ) )
  6209. {
  6210. times.AddToTail( blendTime );
  6211. ++nBlendTimeIndex;
  6212. blendTime = ( nBlendTimeIndex < nNumBlendTimes ) ? times[ nBlendTimeIndex ] : DMETIME_MAXTIME;
  6213. }
  6214. }
  6215. if ( nBlendTimeIndex < nNumBlendTimes )
  6216. {
  6217. Assert( ( combineTimes.Count() == 0 ) || ( times[ nBlendTimeIndex ] > combineTimes.Tail() ) );
  6218. int nNumRemainingTimes = ( nNumBlendTimes - nBlendTimeIndex );
  6219. combineTimes.AddMultipleToTail( nNumRemainingTimes, times.Base() + nBlendTimeIndex );
  6220. }
  6221. times = combineTimes;
  6222. }
  6223. template< class T >
  6224. void CDmeTypedLog< T >::BlendLayersUsingTimeSelection( const DmeLog_TimeSelection_t &params, const CDmeTypedLogLayer< T > *pBaseLayer, const CDmeTypedLogLayer< T > *pTargetLayer, CDmeTypedLogLayer< T > *pOutputLayer )
  6225. {
  6226. VPROF_BUDGET( "CDmeTypedLog< T >::BlendLayersUsingTimeSelection", VPROF_BUDGETGROUP_TOOLS );
  6227. if ( ( pBaseLayer == NULL ) || ( pTargetLayer == NULL ) || ( pOutputLayer == NULL ) )
  6228. return;
  6229. DmeTime_t timeSelection[ TS_TIME_COUNT ];
  6230. timeSelection[ TS_LEFT_FALLOFF ] = MIN( params.m_nTimes[ TS_LEFT_FALLOFF ], params.m_nTimes[ TS_LEFT_HOLD ] - DMETIME_MINDELTA );
  6231. timeSelection[ TS_LEFT_HOLD ] = params.m_nTimes[ TS_LEFT_HOLD ];
  6232. timeSelection[ TS_RIGHT_HOLD ] = params.m_nTimes[ TS_RIGHT_HOLD ];
  6233. timeSelection[ TS_RIGHT_FALLOFF ] = MAX( params.m_nTimes[ TS_RIGHT_FALLOFF ], params.m_nTimes[ TS_RIGHT_HOLD ] + DMETIME_MINDELTA );
  6234. const DmeTime_t tsStartTime = timeSelection[ TS_LEFT_FALLOFF ];
  6235. const DmeTime_t tsEndTime = timeSelection[ TS_RIGHT_FALLOFF ];
  6236. int nBaseKeyCount = pBaseLayer->GetKeyCount();
  6237. int nTargetKeyCount = pTargetLayer->GetKeyCount();
  6238. int nMaxSamples = nBaseKeyCount + nTargetKeyCount;
  6239. CUtlVector< DmeTime_t > times( 0, nMaxSamples );
  6240. CUtlVector< T > values( 0, nMaxSamples );
  6241. int nBaseKeyIndex = 0;
  6242. DmeTime_t currentTime = DMETIME_MINTIME;
  6243. // Copy all the keys from the base layer proceeding the time selection
  6244. while ( nBaseKeyIndex < nBaseKeyCount )
  6245. {
  6246. currentTime = pBaseLayer->GetKeyTime( nBaseKeyIndex );
  6247. if ( currentTime > tsStartTime )
  6248. break;
  6249. T keyValue = pBaseLayer->GetKeyValue( nBaseKeyIndex );
  6250. ++nBaseKeyIndex;
  6251. times.AddToTail( currentTime );
  6252. values.AddToTail( keyValue );
  6253. }
  6254. int nNumProceedingTimes = times.Count();
  6255. // Add the times at which the layers will need to be blended
  6256. int nTargetKeyIndex = pTargetLayer->FindKey( tsStartTime ) + 1;
  6257. DmeTime_t baseKeyTime = ( nBaseKeyIndex < nBaseKeyCount ) ? pBaseLayer->GetKeyTime( nBaseKeyIndex ) : DMETIME_MAXTIME;
  6258. DmeTime_t targetKeyTime = ( nTargetKeyIndex < nTargetKeyCount ) ? pTargetLayer->GetKeyTime( nTargetKeyIndex ) : DMETIME_MAXTIME;
  6259. while ( ( baseKeyTime < tsEndTime ) || ( targetKeyTime < tsEndTime ) )
  6260. {
  6261. while ( ( baseKeyTime <= targetKeyTime ) && ( baseKeyTime < tsEndTime ) )
  6262. {
  6263. times.AddToTail( baseKeyTime );
  6264. ++nBaseKeyIndex;
  6265. baseKeyTime = ( nBaseKeyIndex < nBaseKeyCount ) ? pBaseLayer->GetKeyTime( nBaseKeyIndex ) : DMETIME_MAXTIME;
  6266. }
  6267. while ( ( targetKeyTime <= baseKeyTime ) && ( targetKeyTime < tsEndTime ) )
  6268. {
  6269. times.AddToTail( targetKeyTime );
  6270. ++nTargetKeyIndex;
  6271. targetKeyTime = ( nTargetKeyIndex < nTargetKeyCount ) ? pTargetLayer->GetKeyTime( nTargetKeyIndex ) : DMETIME_MAXTIME;
  6272. }
  6273. }
  6274. // Add sample times in the falloff regions if the falloff type is not linear so that the falloff type will
  6275. // be properly represented even if neither the base or the target layer have samples in the falloff region.
  6276. if ( params.m_nFalloffInterpolatorTypes[ 0 ] != INTERPOLATE_LINEAR_INTERP )
  6277. {
  6278. InterleaveSampleTimes( times, nNumProceedingTimes, timeSelection[ TS_LEFT_FALLOFF ], timeSelection[ TS_LEFT_HOLD ], params.m_nResampleInterval );
  6279. }
  6280. if ( params.m_nFalloffInterpolatorTypes[ 1 ] != INTERPOLATE_LINEAR_INTERP )
  6281. {
  6282. // Find the index of the time which is the first time after the right edge of the hold region of the time selection.
  6283. int nIndex = times.Count();
  6284. while ( nIndex > 0 )
  6285. {
  6286. if ( times[ nIndex - 1 ] <= timeSelection[ TS_RIGHT_HOLD ] )
  6287. break;
  6288. --nIndex;
  6289. }
  6290. if ( nIndex < times.Count() )
  6291. {
  6292. DmeTime_t testTime = times[ nIndex ];
  6293. Assert( testTime > timeSelection[ TS_RIGHT_HOLD ] );
  6294. }
  6295. InterleaveSampleTimes( times, nIndex, timeSelection[ TS_RIGHT_HOLD ], timeSelection[ TS_RIGHT_FALLOFF ], params.m_nResampleInterval );
  6296. }
  6297. // Blend between the keys from both layers within the time selection
  6298. int nNumTimes = times.Count();
  6299. for ( int iTime = values.Count(); iTime < nNumTimes; ++iTime )
  6300. {
  6301. currentTime = times[ iTime ];
  6302. float frac = params.GetAmountForTime( currentTime ) * params.m_flIntensity;
  6303. T targetValue = pTargetLayer->GetValue( currentTime );
  6304. T baseValue = pBaseLayer->GetValue( currentTime );
  6305. T newValue;
  6306. if ( frac < 1.0f )
  6307. {
  6308. newValue = Interpolate( frac, baseValue, targetValue, params.m_nComponentFlags );
  6309. }
  6310. else
  6311. {
  6312. newValue = ::MaskValue( targetValue, baseValue, params.m_nComponentFlags );
  6313. }
  6314. values.AddToTail( newValue );
  6315. }
  6316. Assert( values.Count() == times.Count() );
  6317. // Copy all the keys from the destination layer following the time selection
  6318. while ( nBaseKeyIndex < nBaseKeyCount )
  6319. {
  6320. currentTime = pBaseLayer->GetKeyTime( nBaseKeyIndex );
  6321. if ( currentTime > tsEndTime )
  6322. break;
  6323. T keyValue = pBaseLayer->GetKeyValue( nBaseKeyIndex );
  6324. ++nBaseKeyIndex;
  6325. times.AddToTail( currentTime );
  6326. values.AddToTail( keyValue );
  6327. }
  6328. // Update the destination layer
  6329. pOutputLayer->SetAllKeys( times, values );
  6330. // Remove redundant keys
  6331. if ( g_pDmElementFramework->GetPhase() == PH_EDIT )
  6332. {
  6333. pOutputLayer->RemoveRedundantKeys( params.m_flThreshold, false );
  6334. }
  6335. // Add samples a the time selection times
  6336. for ( int i = 0; i < TS_TIME_COUNT; ++i )
  6337. {
  6338. currentTime = timeSelection[ i ];
  6339. float frac = params.GetAmountForTime( currentTime ) * params.m_flIntensity;
  6340. T targetValue = pTargetLayer->GetValue( currentTime );
  6341. T baseValue = pBaseLayer->GetValue( currentTime );
  6342. T newValue = Interpolate( frac, baseValue, targetValue, params.m_nComponentFlags );
  6343. DmeTime_t nextTime = ((i+1) < TS_TIME_COUNT) ? timeSelection[i+1] : DMETIME_INVALID;
  6344. SegmentInterpolation_t interpSetting = (pBaseLayer->GetSegmentInterpolationSetting( currentTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ||
  6345. (pTargetLayer->GetSegmentInterpolationSetting( currentTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  6346. pOutputLayer->InsertKey( currentTime, newValue, interpSetting );
  6347. }
  6348. }
  6349. template< class T >
  6350. void CDmeTypedLog< T >::RevealUsingTimeSelection( const DmeLog_TimeSelection_t &params, const CDmeLogLayer *savedLayer )
  6351. {
  6352. const CDmeTypedLogLayer< T > *pTargetLayer = static_cast< const CDmeTypedLogLayer< T > * >( savedLayer );
  6353. if ( !pTargetLayer )
  6354. return;
  6355. Assert( GetNumLayers() >= 2 );
  6356. int nTopLayerIndex = GetTopmostLayer(); // Topmost should be at least layer # 1 (0 is the base layer)
  6357. if ( nTopLayerIndex <= 0 )
  6358. return;
  6359. CDmeTypedLogLayer< T > *pWriteLayer = static_cast< CDmeTypedLogLayer< T > * >( GetLayer( nTopLayerIndex ) );
  6360. Assert( pWriteLayer );
  6361. if ( !pWriteLayer )
  6362. return;
  6363. const CDmeTypedLogLayer< T > *pBaseLayer = static_cast< CDmeTypedLogLayer< T > * >( GetLayer( 0 ) );
  6364. Assert( pBaseLayer );
  6365. if ( !pBaseLayer )
  6366. return;
  6367. BlendLayersUsingTimeSelection( params, pBaseLayer, pTargetLayer, pWriteLayer );
  6368. }
  6369. template< class T >
  6370. void CDmeTypedLog< T >::RecaleAndRevealUsingTimeSelection( const DmeLog_TimeSelection_t &params, TimeSelection_t &sourceTimeSelection, const CDmeLogLayer *pTargetLayer )
  6371. {
  6372. CDisableUndoScopeGuard disableUndoSg;
  6373. CDmeTypedLogLayer< T > *pNewLayer = static_cast< CDmeTypedLogLayer< T > * >( CreateLayer< T >( this ) );
  6374. if ( !pNewLayer )
  6375. return;
  6376. pNewLayer->CopyLayer( pTargetLayer );
  6377. pNewLayer->RescaleSamplesInTimeSelection( sourceTimeSelection, params.m_nTimes );
  6378. {
  6379. //CEnableUndoScopeGuard enableUndoSg;
  6380. RevealUsingTimeSelection( params, pNewLayer );
  6381. }
  6382. g_pDataModel->DestroyElement( pNewLayer->GetHandle() );
  6383. }
  6384. template< class T >
  6385. void RandomValue( IUniformRandomStream &random, const T& average, const T& oldValue, T& newValue )
  6386. {
  6387. newValue = oldValue;
  6388. }
  6389. template<> void RandomValue( IUniformRandomStream &random, const Vector& average, const Vector& oldValue, Vector& newValue )
  6390. {
  6391. newValue = oldValue;
  6392. for ( int i = 0; i < 3; ++i )
  6393. {
  6394. newValue[ i ] += random.RandomFloat( -fabs( average[ i ] ), fabs( average[ i ] ) );
  6395. }
  6396. }
  6397. template<> void RandomValue( IUniformRandomStream &random, const Quaternion& average, const Quaternion& oldValue, Quaternion& newValue )
  6398. {
  6399. QAngle newAngle;
  6400. QuaternionAngles( oldValue, newAngle );
  6401. QAngle avgA;
  6402. QuaternionAngles( average, avgA );
  6403. for ( int i = 0; i < 3; ++i )
  6404. {
  6405. newAngle[ i ] += random.RandomFloat( -fabs( avgA[ i ] ), fabs( avgA[ i ] ) );
  6406. }
  6407. AngleQuaternion( newAngle, newValue );
  6408. }
  6409. template<> void RandomValue( IUniformRandomStream &random, const Vector4D& average, const Vector4D& oldValue, Vector4D& newValue )
  6410. {
  6411. newValue = oldValue;
  6412. for ( int i = 0; i < 4; ++i )
  6413. {
  6414. newValue[ i ] += random.RandomFloat( -fabs( average[ i ] ), fabs( average[ i ] ) );
  6415. }
  6416. }
  6417. template<> void RandomValue( IUniformRandomStream &random, const Vector2D& average, const Vector2D& oldValue, Vector2D& newValue )
  6418. {
  6419. newValue = oldValue;
  6420. for ( int i = 0; i < 2; ++i )
  6421. {
  6422. newValue[ i ] += random.RandomFloat( -fabs( average[ i ] ), fabs( average[ i ] ) );
  6423. }
  6424. }
  6425. template<> void RandomValue( IUniformRandomStream &random, const float& average, const float& oldValue, float& newValue )
  6426. {
  6427. newValue = oldValue + random.RandomFloat( -average, average );
  6428. }
  6429. template<> void RandomValue( IUniformRandomStream &random, const int& average, const int& oldValue, int& newValue )
  6430. {
  6431. newValue = oldValue + random.RandomInt( -average, average );
  6432. }
  6433. template<> void RandomValue( IUniformRandomStream &random, const DmeTime_t& average, const DmeTime_t& oldValue, DmeTime_t& newValue )
  6434. {
  6435. int n = average.GetTenthsOfMS();
  6436. newValue = oldValue + DmeTime_t( random.RandomInt( -n, n ) );
  6437. }
  6438. // Builds a layer with samples matching the times in reference layer, from the data in pDataLayer, putting the resulting keys into pOutputLayer
  6439. template< class T >
  6440. void CDmeTypedLog< T >::BuildCorrespondingLayer( const CDmeLogLayer *pReferenceLayer, const CDmeLogLayer *pDataLayer, CDmeLogLayer *pOutputLayer )
  6441. {
  6442. const CDmeTypedLogLayer< T > *ref = static_cast< const CDmeTypedLogLayer< T > * >( pReferenceLayer );
  6443. const CDmeTypedLogLayer< T > *data = static_cast< const CDmeTypedLogLayer< T > * >( pDataLayer );
  6444. CDmeTypedLogLayer< T > *out = static_cast< CDmeTypedLogLayer< T > * >( pOutputLayer );
  6445. if ( !ref || !data || !out )
  6446. {
  6447. Assert( 0 );
  6448. return;
  6449. }
  6450. bool usecurvetypes = ref->IsUsingCurveTypes();
  6451. out->ClearKeys();
  6452. int kc = ref->GetKeyCount();
  6453. for ( int i = 0; i < kc; ++i )
  6454. {
  6455. DmeTime_t keyTime = ref->GetKeyTime( i );
  6456. T value = data->GetValue( keyTime );
  6457. DmeTime_t nextTime = ((i+1) < kc) ? ref->GetKeyTime(i+1) : DMETIME_INVALID;
  6458. out->InsertKey( keyTime, value, data->GetSegmentInterpolationSetting( keyTime, nextTime, true ), usecurvetypes ? GetDefaultCurveType() : CURVE_DEFAULT );
  6459. }
  6460. }
  6461. template< class T >
  6462. void CDmeTypedLog< T >::StaggerUsingTimeSelection( const DmeLog_TimeSelection_t& params, DmeTime_t tStaggerAmount, const CDmeLogLayer *pBaseLayer, CDmeLogLayer *pWriteLayer )
  6463. {
  6464. CDmeTypedLogLayer< T > *writeLayer = static_cast< CDmeTypedLogLayer< T > * >( pWriteLayer );
  6465. Assert( writeLayer );
  6466. if ( !writeLayer )
  6467. return;
  6468. const CDmeTypedLogLayer< T > *baseLayer = static_cast< const CDmeTypedLogLayer< T > * >( pBaseLayer );
  6469. if ( !baseLayer )
  6470. return;
  6471. writeLayer->ClearKeys();
  6472. DmeLog_TimeSelection_t newParams;
  6473. newParams = params;
  6474. // Move the hold area by the stagger amount
  6475. float flScaleFactor[ 2 ] = { 1.0f, 1.0f };
  6476. newParams.m_nTimes[ TS_LEFT_HOLD ] += tStaggerAmount;
  6477. newParams.m_nTimes[ TS_RIGHT_HOLD ] += tStaggerAmount;
  6478. for ( int i = 0; i < 2 ; ++i )
  6479. {
  6480. DmeTime_t dt = params.m_nTimes[ 2 * i + 1 ] - params.m_nTimes[ 2 * i ];
  6481. if ( dt > DMETIME_ZERO )
  6482. {
  6483. DmeTime_t newDt = newParams.m_nTimes[ 2 * i + 1 ] - newParams.m_nTimes[ 2 * i ];
  6484. flScaleFactor[ i ] = newDt / dt;
  6485. }
  6486. }
  6487. int kc = baseLayer->GetKeyCount();
  6488. for ( int i = 0; i < kc; ++i )
  6489. {
  6490. DmeTime_t curtime = baseLayer->GetKeyTime( i );
  6491. T oldValue = baseLayer->GetKeyValue( i );
  6492. // Classify time
  6493. if ( curtime <= params.m_nTimes[ TS_LEFT_HOLD ] )
  6494. {
  6495. curtime = curtime * flScaleFactor[ 0 ];
  6496. }
  6497. else if ( curtime >= params.m_nTimes[ TS_RIGHT_HOLD ] )
  6498. {
  6499. curtime = params.m_nTimes[ TS_RIGHT_FALLOFF ] - ( params.m_nTimes[ TS_RIGHT_FALLOFF ] - curtime ) * flScaleFactor[ 1 ];
  6500. }
  6501. else
  6502. {
  6503. curtime += tStaggerAmount;
  6504. }
  6505. writeLayer->InsertKey( curtime, oldValue, baseLayer->GetSegmentInterpolationSetting(i), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6506. }
  6507. }
  6508. // returns -1 if no elements in vector are less than value
  6509. template< class T >
  6510. int FindLessInSortedVector( const T &value, const CUtlVector< T > &vector )
  6511. {
  6512. int n = vector.Count();
  6513. for ( int i = 0; i < n; ++i )
  6514. {
  6515. if ( vector[ i ] >= value )
  6516. return i - 1;
  6517. }
  6518. return n - 1;
  6519. }
  6520. template< class T >
  6521. void CDmeTypedLog< T >::GenerateSplineUsingTimeSelection( const DmeLog_TimeSelection_t& params, const CUtlVector< DmeTime_t > &sortedSplineKeyTimes, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer )
  6522. {
  6523. Assert( params.m_nResampleInterval > DmeTime_t( 0 ) );
  6524. if ( params.m_nResampleInterval <= DmeTime_t( 0 ) )
  6525. return;
  6526. const CDmeTypedLogLayer< T > *pBaseLayer = static_cast< const CDmeTypedLogLayer< T > * >( baseLayer );
  6527. Assert( pBaseLayer );
  6528. if ( !pBaseLayer )
  6529. return;
  6530. CDmeTypedLogLayer< T > *pWriteLayer = static_cast< CDmeTypedLogLayer< T > * >( writeLayer );
  6531. Assert( pWriteLayer );
  6532. if ( !pWriteLayer )
  6533. return;
  6534. int nSplineKeys = sortedSplineKeyTimes.Count();
  6535. if ( nSplineKeys == 0 )
  6536. return;
  6537. pWriteLayer->ClearKeys();
  6538. int nKeys = pBaseLayer->GetKeyCount();
  6539. for ( int i = 0; i < nKeys; ++i )
  6540. {
  6541. DmeTime_t t = pBaseLayer->GetKeyTime( i );
  6542. int si = FindLessInSortedVector( t, sortedSplineKeyTimes );
  6543. if ( si < 0 || si > nSplineKeys - 2 )
  6544. {
  6545. T val = pBaseLayer->GetValue( t );
  6546. pWriteLayer->InsertKey( t, val, pBaseLayer->GetSegmentInterpolationSetting(i), CURVE_DEFAULT );
  6547. continue;
  6548. }
  6549. DmeTime_t times[ 4 ];
  6550. times[ 1 ] = sortedSplineKeyTimes[ si ];
  6551. times[ 2 ] = sortedSplineKeyTimes[ si + 1 ];
  6552. times[ 0 ] = si < 1 ? times[ 1 ] - DMETIME_MINTIME : sortedSplineKeyTimes[ si - 1 ];
  6553. times[ 3 ] = si > nSplineKeys - 3 ? times[ 2 ] + DMETIME_MINTIME : sortedSplineKeyTimes[ si + 2 ];
  6554. SegmentInterpolation_t interpSetting = pBaseLayer->GetSegmentInterpolationSetting( times[0], times[3], true );
  6555. if( interpSetting == SEGMENT_INTERPOLATE )
  6556. {
  6557. T values[ 4 ];
  6558. values[ 0 ] = pBaseLayer->GetValue( times[ 0 ] );
  6559. values[ 1 ] = pBaseLayer->GetValue( times[ 1 ] );
  6560. values[ 2 ] = pBaseLayer->GetValue( times[ 2 ] );
  6561. values[ 3 ] = pBaseLayer->GetValue( times[ 3 ] );
  6562. int curveTypes[ 4 ] = { CURVE_CATMULL_ROM_TO_CATMULL_ROM, CURVE_CATMULL_ROM_TO_CATMULL_ROM, CURVE_CATMULL_ROM_TO_CATMULL_ROM, CURVE_CATMULL_ROM_TO_CATMULL_ROM };
  6563. Assert( t >= times[ 1 ] && t <= times[ 2 ] );
  6564. float frac = GetFractionOfTimeBetween( t, times[ 1 ], times[ 2 ] );
  6565. T val = Curve_Interpolate( frac, times, values, curveTypes, -FLT_MAX, FLT_MAX );
  6566. pWriteLayer->InsertKey( t, val, interpSetting, CURVE_DEFAULT );
  6567. }
  6568. else
  6569. {
  6570. //we pass through a non-interpolated segment for this range of the spline, easy solution is to continue our noninterpolation. Probably needs rethinking
  6571. T val = pBaseLayer->GetValue( t );
  6572. pWriteLayer->InsertKey( t, val, interpSetting, CURVE_DEFAULT );
  6573. }
  6574. }
  6575. }
  6576. template< class T >
  6577. void CDmeTypedLog< T >::CopySamplesFromPreset( const DmeLog_TimeSelection_t& params, const CDmAttribute *pPresetValue, const CDmAttribute *pPresetTimes, DmeTime_t tLogTimeOffset, const CDmeChannelsClip *pChannelsClip, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer )
  6578. {
  6579. Assert( params.m_nResampleInterval > DmeTime_t( 0 ) );
  6580. if ( params.m_nResampleInterval <= DmeTime_t( 0 ) )
  6581. return;
  6582. const CDmeTypedLogLayer< T > *pBaseLayer = static_cast< const CDmeTypedLogLayer< T > * >( baseLayer );
  6583. Assert( pBaseLayer );
  6584. if ( !pBaseLayer )
  6585. return;
  6586. CDmeTypedLogLayer< T > *pWriteLayer = static_cast< CDmeTypedLogLayer< T > * >( writeLayer );
  6587. Assert( pWriteLayer );
  6588. if ( !pWriteLayer )
  6589. return;
  6590. CDmrArrayConst< T > presetValues( pPresetValue );
  6591. CDmrArrayConst< DmeTime_t > presetTimes ( pPresetTimes );
  6592. int nPresetKeys = presetTimes.Count();
  6593. Assert( nPresetKeys != 0 && nPresetKeys == presetValues.Count() );
  6594. if ( nPresetKeys == 0 || nPresetKeys != presetValues.Count() )
  6595. return;
  6596. pWriteLayer->ClearKeys();
  6597. int nKeys = pBaseLayer->GetKeyCount();
  6598. for ( int i = 0; i < nKeys; ++i )
  6599. {
  6600. DmeTime_t tLog = pBaseLayer->GetKeyTime( i );
  6601. DmeTime_t tShot = pChannelsClip->FromChildMediaDuration( tLog - tLogTimeOffset ); // presetTimes are relative to the head, and in shot time
  6602. int ti = FindLessInSortedVector( tShot, presetTimes.Get() );
  6603. if ( ti < 0 )
  6604. {
  6605. pWriteLayer->InsertKey( tLog, presetValues[ 0 ], pBaseLayer->GetSegmentInterpolationSetting(i), CURVE_DEFAULT );
  6606. continue;
  6607. }
  6608. if ( ti >= nPresetKeys - 1 )
  6609. {
  6610. pWriteLayer->InsertKey( tLog, presetValues[ nPresetKeys - 1 ], pBaseLayer->GetSegmentInterpolationSetting(i), CURVE_DEFAULT );
  6611. continue;
  6612. }
  6613. float frac = GetFractionOfTimeBetween( tShot, presetTimes[ ti ], presetTimes[ ti + 1 ] );
  6614. T value = Interpolate( frac, presetValues[ ti ], presetValues[ ti + 1 ] );
  6615. pWriteLayer->InsertKey( tLog, value, pBaseLayer->GetSegmentInterpolationSetting(i), CURVE_DEFAULT );
  6616. }
  6617. }
  6618. template< class T >
  6619. void DumpLayers( const CDmeTypedLogLayer< T > *baseLayer, CDmeTypedLogLayer< T > *writeLayer )
  6620. {
  6621. }
  6622. template<>
  6623. void DumpLayers< Vector >( const CDmeTypedLogLayer< Vector > *baseLayer, CDmeTypedLogLayer< Vector > *writeLayer )
  6624. {
  6625. int kc = baseLayer->GetKeyCount();
  6626. if ( kc != writeLayer->GetKeyCount() )
  6627. {
  6628. return;
  6629. }
  6630. for ( int i = 0; i < kc; ++i )
  6631. {
  6632. Vector v1 = baseLayer->GetKeyValue( i );
  6633. Vector v2 = writeLayer->GetKeyValue( i );
  6634. DmeTime_t t1 = baseLayer->GetKeyTime( i );
  6635. DmeTime_t t2 = writeLayer->GetKeyTime( i );
  6636. float spd1 = 0.0f;
  6637. float spd2 = 0.0f;
  6638. if ( i > 0 )
  6639. {
  6640. DmeTime_t dt1 = t1 - baseLayer->GetKeyTime( i - 1 );
  6641. DmeTime_t dt2 = t2 - writeLayer->GetKeyTime( i - 1 );
  6642. Vector d1 = v1 - baseLayer->GetKeyValue( i - 1 );
  6643. Vector d2 = v2 - writeLayer->GetKeyValue( i - 1 );
  6644. if ( dt1 > DMETIME_ZERO )
  6645. {
  6646. spd1 = d1.Length() / dt1.GetSeconds();
  6647. }
  6648. if ( dt2 > DMETIME_ZERO )
  6649. {
  6650. spd2 = d2.Length() / dt2.GetSeconds();
  6651. }
  6652. }
  6653. Msg( "%i: %d %d v1 %.3f v2 %.3f = (%f %f %f) (%f %f %f)\n",
  6654. i, t1.GetTenthsOfMS(), t2.GetTenthsOfMS(),
  6655. spd1, spd2, VectorExpand( v1 ), VectorExpand( v2 ) );
  6656. }
  6657. }
  6658. template< class T >
  6659. void CDmeTypedLog< T >::HoldOrReleaseUsingTimeSelection( const DmeLog_TimeSelection_t& params, bool bHold, const CDmeLogLayer *pBaseLayer, CDmeLogLayer *pWriteLayer )
  6660. {
  6661. CDmeTypedLogLayer< T > *writeLayer = static_cast< CDmeTypedLogLayer< T > * >( pWriteLayer );
  6662. Assert( writeLayer );
  6663. if ( !writeLayer )
  6664. return;
  6665. const CDmeTypedLogLayer< T > *baseLayer = static_cast< const CDmeTypedLogLayer< T > * >( pBaseLayer );
  6666. if ( !baseLayer )
  6667. return;
  6668. writeLayer->ClearKeys();
  6669. int kc = baseLayer->GetKeyCount();
  6670. for ( int i = 0; i < kc; ++i )
  6671. {
  6672. DmeTime_t curtime = baseLayer->GetKeyTime( i );
  6673. DmeTime_t targetTime = curtime;
  6674. DmeTime_t baseTime = curtime;
  6675. if ( curtime < params.m_nTimes[ TS_LEFT_HOLD ] && curtime > params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6676. {
  6677. targetTime = params.m_nTimes[ TS_LEFT_HOLD ];
  6678. baseTime = params.m_nTimes[ TS_LEFT_FALLOFF ];
  6679. }
  6680. else if ( curtime > params.m_nTimes[ TS_RIGHT_HOLD ] && curtime < params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6681. {
  6682. targetTime = params.m_nTimes[ TS_RIGHT_HOLD ];
  6683. baseTime = params.m_nTimes[ TS_RIGHT_FALLOFF ];
  6684. }
  6685. float scale = params.GetAmountForTime( curtime );
  6686. if ( bHold )
  6687. {
  6688. scale = scale * scale;
  6689. }
  6690. else
  6691. {
  6692. scale = sqrt( scale );
  6693. }
  6694. DmeTime_t keyTime = Lerp( scale, baseTime, targetTime );
  6695. if ( i > 0 && keyTime <= writeLayer->GetKeyTime( i - 1 ) )
  6696. {
  6697. keyTime = writeLayer->GetKeyTime( i - 1 ) + DMETIME_MINTIME; // unlikely, but just in case, since otherwise the blend fails if the writeLayer has a missing key
  6698. }
  6699. writeLayer->InsertKey( keyTime, baseLayer->GetKeyValue( i ), baseLayer->GetSegmentInterpolationSetting( i ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6700. }
  6701. Assert( writeLayer->GetKeyCount() == kc );
  6702. }
  6703. #ifdef MSVC
  6704. #pragma warning( push )
  6705. // Potential division by zero... because flTotalDist is initialized to 0 and then used later as the divisor but
  6706. // compiled just looks at static values. The loop after flTotalDist is initialized will make it non-zero before
  6707. // it's used as a divisor, so ignore the warning. Warning disable has to be here because warnings in the range
  6708. // [4700, 4799] cannot be changed in the scope of a function
  6709. #pragma warning( disable : 4723 )
  6710. #endif // ifdef MSVC
  6711. template< class T >
  6712. void CDmeTypedLog< T >::SteadyUsingTimeSelection( const DmeLog_TimeSelection_t& params, const CDmeLogLayer *pBaseLayer, CDmeLogLayer *pWriteLayer )
  6713. {
  6714. CDmeTypedLogLayer< T > *writeLayer = static_cast< CDmeTypedLogLayer< T > * >( pWriteLayer );
  6715. Assert( writeLayer );
  6716. if ( !writeLayer )
  6717. return;
  6718. const CDmeTypedLogLayer< T > *baseLayer = static_cast< const CDmeTypedLogLayer< T > * >( pBaseLayer );
  6719. if ( !baseLayer )
  6720. return;
  6721. writeLayer->ClearKeys();
  6722. // Try to smooth out the spatial "velocity" over the time selection
  6723. int keyCount = baseLayer->GetKeyCount();
  6724. float flTotalDist = 0.0f;
  6725. for ( int i = 1; i < keyCount; ++i )
  6726. {
  6727. const T &v0 = baseLayer->GetKeyValue( i - 1 );
  6728. const T &v1 = baseLayer->GetKeyValue( i );
  6729. float flDistance = LengthOf( Subtract( v0, v1 ) );
  6730. flTotalDist += flDistance;
  6731. }
  6732. if ( keyCount <= 2 || flTotalDist == 0.0f )
  6733. {
  6734. for ( int i = 0; i < keyCount ; ++i )
  6735. {
  6736. writeLayer->InsertKey( baseLayer->GetKeyTime( i ), baseLayer->GetKeyValue( i ), baseLayer->GetSegmentInterpolationSetting( i ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6737. }
  6738. return;
  6739. }
  6740. DmeTime_t t0 = baseLayer->GetKeyTime( 0 );
  6741. DmeTime_t tn = baseLayer->GetKeyTime( keyCount - 1 );
  6742. DmeTime_t tTotalTime = tn - t0;
  6743. int nCurveType = IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT;
  6744. writeLayer->InsertKey( t0, baseLayer->GetKeyValue( 0 ), baseLayer->GetSegmentInterpolationSetting( 0 ), nCurveType, true );
  6745. float flRunningDist = 0.0f;
  6746. for ( int i = 1; i < keyCount - 1; ++i )
  6747. {
  6748. const T &v0 = baseLayer->GetKeyValue( i - 1 );
  6749. const T &v1 = baseLayer->GetKeyValue( i );
  6750. float flDistance = LengthOf( Subtract( v0, v1 ) );
  6751. flRunningDist += flDistance;
  6752. DmeTime_t t = t0 + tTotalTime * ( flRunningDist / flTotalDist );
  6753. writeLayer->InsertKey( t, v1, baseLayer->GetSegmentInterpolationSetting( i - 1, i ), nCurveType, true );
  6754. }
  6755. writeLayer->InsertKey( tn, baseLayer->GetKeyValue( keyCount - 1 ), baseLayer->GetSegmentInterpolationSetting( keyCount - 1 ), nCurveType, true );
  6756. Assert( writeLayer->GetKeyCount() == keyCount );
  6757. }
  6758. #ifdef MSVC
  6759. #pragma warning( pop )
  6760. #endif // ifdef MSVC
  6761. template< class T >
  6762. void CDmeTypedLog< T >::FilterUsingTimeSelection( IUniformRandomStream &random, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff )
  6763. {
  6764. Assert( GetNumLayers() >= 2 );
  6765. int bestLayer = GetTopmostLayer(); // Topmost should be at least layer # 1 (0 is the base layer)
  6766. if ( bestLayer <= 0 )
  6767. return;
  6768. CDmeTypedLogLayer< T > *writeLayer = GetLayer( bestLayer );
  6769. Assert( writeLayer );
  6770. if ( !writeLayer )
  6771. return;
  6772. CDmeTypedLogLayer< T > *baseLayer = GetLayer( 0 );
  6773. if ( !baseLayer )
  6774. return;
  6775. FilterUsingTimeSelection( random, 1.0f, params, filterType, bResample, bApplyFalloff, baseLayer, writeLayer );
  6776. }
  6777. template< class T >
  6778. void CDmeTypedLog< T >::FilterUsingTimeSelection( IUniformRandomStream &random, float flScale, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff, const CDmeLogLayer *pBaseLayer, CDmeLogLayer *pWriteLayer )
  6779. {
  6780. Assert( params.m_nResampleInterval > DmeTime_t( 0 ) );
  6781. if ( params.m_nResampleInterval <= DmeTime_t( 0 ) )
  6782. return;
  6783. CDmeTypedLogLayer< T > *writeLayer = static_cast< CDmeTypedLogLayer< T > * >( pWriteLayer );
  6784. Assert( writeLayer );
  6785. if ( !writeLayer )
  6786. return;
  6787. const CDmeTypedLogLayer< T > *baseLayer = static_cast< const CDmeTypedLogLayer< T > * >( pBaseLayer );
  6788. if ( !baseLayer )
  6789. return;
  6790. writeLayer->ClearKeys();
  6791. DmeTime_t resample = 0.5f * params.m_nResampleInterval;
  6792. switch ( filterType )
  6793. {
  6794. default:
  6795. case FILTER_SMOOTH:
  6796. {
  6797. int t;
  6798. if ( bResample )
  6799. {
  6800. for ( t = params.m_nTimes[ TS_LEFT_FALLOFF ].GetTenthsOfMS(); t < params.m_nTimes[ TS_RIGHT_FALLOFF ].GetTenthsOfMS() + resample.GetTenthsOfMS(); t += resample.GetTenthsOfMS() )
  6801. {
  6802. DmeTime_t curtime = DmeTime_t( t );
  6803. if ( curtime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6804. curtime = params.m_nTimes[ TS_RIGHT_FALLOFF ];
  6805. T curValue = baseLayer->GetValue( curtime );
  6806. writeLayer->SetKey( curtime, curValue, baseLayer->GetSegmentInterpolationSetting( curtime, curtime + resample, true ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6807. }
  6808. }
  6809. else
  6810. {
  6811. // Do a second pass where we bias the keys in the falloff area back toward the original value
  6812. int kc = baseLayer->GetKeyCount();
  6813. for ( int i = 0; i < kc; ++i )
  6814. {
  6815. DmeTime_t curtime = baseLayer->GetKeyTime( i );
  6816. if ( curtime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6817. continue;
  6818. if ( curtime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6819. continue;
  6820. T oldValue = baseLayer->GetKeyValue( i );
  6821. writeLayer->InsertKey( curtime, oldValue, baseLayer->GetSegmentInterpolationSetting( curtime ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6822. }
  6823. }
  6824. writeLayer->Filter2( params.m_nResampleInterval * 0.95f * flScale );
  6825. if ( bApplyFalloff )
  6826. {
  6827. if ( bResample )
  6828. {
  6829. // Do a second pass where we bias the keys in the falloff area back toward the original value
  6830. for ( t = params.m_nTimes[ TS_LEFT_FALLOFF ].GetTenthsOfMS(); t < params.m_nTimes[ TS_RIGHT_FALLOFF ].GetTenthsOfMS() + resample.GetTenthsOfMS(); t += resample.GetTenthsOfMS() )
  6831. {
  6832. DmeTime_t curtime = DmeTime_t( t );
  6833. if ( curtime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6834. curtime = params.m_nTimes[ TS_RIGHT_FALLOFF ];
  6835. T oldValue = baseLayer->GetValue( curtime );
  6836. if ( curtime >= params.m_nTimes[ TS_LEFT_HOLD ] && curtime <= params.m_nTimes[ TS_RIGHT_HOLD ] )
  6837. continue;
  6838. // Modulate these keys back down toward the original value
  6839. T newValue = writeLayer->GetValue( curtime );
  6840. float frac = bApplyFalloff ? params.GetAmountForTime( curtime ) : 1.0f;
  6841. newValue = Interpolate( frac, oldValue, newValue );
  6842. // Overwrite key
  6843. writeLayer->InsertKey( curtime, newValue, baseLayer->GetSegmentInterpolationSetting( curtime, curtime + resample, true ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6844. }
  6845. }
  6846. else
  6847. {
  6848. // Do a second pass where we bias the keys in the falloff area back toward the original value
  6849. int kc = writeLayer->GetKeyCount();
  6850. for ( int i = 0; i < kc; ++i )
  6851. {
  6852. DmeTime_t curtime = writeLayer->GetKeyTime( i );
  6853. if ( curtime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6854. continue;
  6855. if ( curtime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6856. continue;
  6857. if ( curtime >= params.m_nTimes[ TS_LEFT_HOLD ] && curtime <= params.m_nTimes[ TS_RIGHT_HOLD ] )
  6858. continue;
  6859. T oldValue = baseLayer->GetValue( curtime );
  6860. // Modulate these keys back down toward the original value
  6861. T newValue = writeLayer->GetValue( curtime );
  6862. float frac = bApplyFalloff ? params.GetAmountForTime( curtime ) : 1.0f;
  6863. newValue = Interpolate( frac, oldValue, newValue );
  6864. DmeTime_t nextTime = ((i + 1) < kc) ? writeLayer->GetKeyTime(i + 1) : DMETIME_INVALID;
  6865. //don't interpolate if either of the two layers think they shouldn't
  6866. SegmentInterpolation_t interpSetting = ((baseLayer->GetSegmentInterpolationSetting( curtime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ||
  6867. (writeLayer->GetSegmentInterpolationSetting( i ) == SEGMENT_NOINTERPOLATE)) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  6868. // Overwrite key
  6869. writeLayer->InsertKey( curtime, newValue, interpSetting, IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6870. }
  6871. }
  6872. }
  6873. if ( bResample )
  6874. {
  6875. writeLayer->RemoveRedundantKeys( params.m_flThreshold, false );
  6876. }
  6877. }
  6878. break;
  6879. case FILTER_INOUT:
  6880. {
  6881. // Compute average value in entire log
  6882. DmeTime_t tIn = params.m_nTimes[ TS_LEFT_HOLD ];
  6883. DmeTime_t tOut = params.m_nTimes[ TS_RIGHT_HOLD ];
  6884. if ( tIn != tOut )
  6885. {
  6886. T inValue = baseLayer->GetValue( tIn );
  6887. T outValue = baseLayer->GetValue( tOut );
  6888. if ( bResample )
  6889. {
  6890. // Do a second pass where we bias the keys in the falloff area back toward the original value
  6891. for ( int t = params.m_nTimes[ TS_LEFT_FALLOFF ].GetTenthsOfMS(); t < params.m_nTimes[ TS_RIGHT_FALLOFF ].GetTenthsOfMS() + resample.GetTenthsOfMS(); t += resample.GetTenthsOfMS() )
  6892. {
  6893. DmeTime_t curtime = DmeTime_t( t );
  6894. if ( curtime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6895. curtime = params.m_nTimes[ TS_RIGHT_FALLOFF ];
  6896. if ( curtime < tIn || curtime > tOut )
  6897. {
  6898. T oldValue = baseLayer->GetValue( curtime );
  6899. writeLayer->InsertKey( curtime, oldValue, baseLayer->GetSegmentInterpolationSetting( curtime, curtime + resample, true ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6900. }
  6901. else
  6902. {
  6903. float frac = GetFractionOfTimeBetween( curtime, tIn, tOut, true );
  6904. T newValue = Interpolate( frac, inValue, outValue );
  6905. writeLayer->InsertKey( curtime, newValue, baseLayer->GetSegmentInterpolationSetting( curtime, curtime + resample, true ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6906. }
  6907. }
  6908. }
  6909. else
  6910. {
  6911. int kc = baseLayer->GetKeyCount();
  6912. for ( int i = 0; i < kc; ++i )
  6913. {
  6914. DmeTime_t curtime = baseLayer->GetKeyTime( i );
  6915. if ( curtime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6916. continue;
  6917. if ( curtime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6918. continue;
  6919. if ( curtime < tIn || curtime > tOut )
  6920. {
  6921. T oldValue = baseLayer->GetValue( curtime );
  6922. writeLayer->InsertKey( curtime, oldValue, baseLayer->GetSegmentInterpolationSetting( i ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6923. }
  6924. else
  6925. {
  6926. float frac = GetFractionOfTimeBetween( curtime, tIn, tOut, true );
  6927. T newValue = Interpolate( frac, inValue, outValue );
  6928. writeLayer->InsertKey( curtime, newValue, baseLayer->GetSegmentInterpolationSetting( i ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6929. }
  6930. }
  6931. }
  6932. }
  6933. }
  6934. break;
  6935. case FILTER_JITTER:
  6936. {
  6937. // Compute average value in entire log
  6938. Assert( !baseLayer->IsCompressed() );
  6939. T average = Average( baseLayer->m_values.Base(), baseLayer->m_values.Count() );
  6940. average = ScaleValue( average, 0.05f * flScale );
  6941. if ( bResample )
  6942. {
  6943. int t;
  6944. for ( t = params.m_nTimes[ TS_LEFT_FALLOFF ].GetTenthsOfMS(); t < params.m_nTimes[ TS_RIGHT_FALLOFF ].GetTenthsOfMS() + resample.GetTenthsOfMS(); t += resample.GetTenthsOfMS() )
  6945. {
  6946. DmeTime_t curtime = DmeTime_t( t );
  6947. if ( curtime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6948. curtime = params.m_nTimes[ TS_RIGHT_FALLOFF ];
  6949. float frac = bApplyFalloff ? params.GetAmountForTime( curtime ) : 1.0f;
  6950. T oldValue = baseLayer->GetValue( curtime );
  6951. T newValue;
  6952. RandomValue( random, average, oldValue, newValue );
  6953. if ( frac != 1.0f )
  6954. {
  6955. newValue = Interpolate( frac, oldValue, newValue );
  6956. }
  6957. writeLayer->SetKey( curtime, newValue, baseLayer->GetSegmentInterpolationSetting( curtime, curtime + resample, true ), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6958. }
  6959. }
  6960. else
  6961. {
  6962. int kc = baseLayer->GetKeyCount();
  6963. for ( int i = 0; i < kc; ++i )
  6964. {
  6965. DmeTime_t curtime = baseLayer->GetKeyTime( i );
  6966. if ( curtime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6967. continue;
  6968. if ( curtime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6969. continue;
  6970. float frac = bApplyFalloff ? params.GetAmountForTime( curtime ) : 1.0f;
  6971. T oldValue = baseLayer->GetValue( curtime );
  6972. T newValue;
  6973. RandomValue( random, average, oldValue, newValue );
  6974. if ( frac != 1.0f )
  6975. {
  6976. newValue = Interpolate( frac, oldValue, newValue );
  6977. }
  6978. writeLayer->InsertKey( curtime, newValue, baseLayer->GetSegmentInterpolationSetting(i), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  6979. }
  6980. }
  6981. }
  6982. break;
  6983. case FILTER_SHARPEN:
  6984. case FILTER_SOFTEN:
  6985. {
  6986. writeLayer->ClearKeys();
  6987. bool bSharpen = filterType == FILTER_SHARPEN;
  6988. int kc = baseLayer->GetKeyCount();
  6989. for ( int i = 0; i < kc; ++i )
  6990. {
  6991. DmeTime_t curtime = baseLayer->GetKeyTime( i );
  6992. if ( curtime < params.m_nTimes[ TS_LEFT_FALLOFF ] )
  6993. continue;
  6994. if ( curtime > params.m_nTimes[ TS_RIGHT_FALLOFF ] )
  6995. continue;
  6996. float frac = bApplyFalloff ? params.GetAmountForTime( curtime ) : 1.0f;
  6997. T oldValue = baseLayer->GetValue( curtime );
  6998. T newValue = oldValue;
  6999. if ( frac != 1.0f )
  7000. {
  7001. T crossingValue[ 2 ] = { oldValue, oldValue };
  7002. if ( curtime <= params.m_nTimes[ TS_LEFT_HOLD ] )
  7003. {
  7004. // Get the value at the crossing point (either green edge for sharpen, or left edge for soften...)
  7005. crossingValue[ 0 ] = baseLayer->GetValue( params.m_nTimes[ TS_LEFT_FALLOFF ] );
  7006. crossingValue[ 1 ] = baseLayer->GetValue( params.m_nTimes[ TS_LEFT_HOLD ] );
  7007. }
  7008. else if ( curtime >= params.m_nTimes[ TS_RIGHT_HOLD ] )
  7009. {
  7010. crossingValue[ 0 ] = baseLayer->GetValue( params.m_nTimes[ TS_RIGHT_FALLOFF ] );
  7011. crossingValue[ 1 ] = baseLayer->GetValue( params.m_nTimes[ TS_RIGHT_HOLD ] );
  7012. }
  7013. else
  7014. {
  7015. Assert( 0 );
  7016. }
  7017. T dynamicRange = Subtract( crossingValue[ 1 ], crossingValue[ 0 ] );
  7018. int iType = bSharpen ? INTERPOLATE_EASE_IN : INTERPOLATE_EASE_OUT;
  7019. float flOut = ComputeInterpolationFactor( frac, iType );
  7020. float flBias = clamp( flOut, 0.0f, 1.0f );
  7021. float dFrac = flScale * ( frac - flBias );
  7022. newValue = Add( oldValue, ScaleValue( dynamicRange, dFrac ) );
  7023. }
  7024. writeLayer->InsertKey( curtime, newValue, baseLayer->GetSegmentInterpolationSetting(i), IsUsingCurveTypes() ? GetDefaultCurveType() : CURVE_DEFAULT );
  7025. }
  7026. }
  7027. break;
  7028. }
  7029. }
  7030. template< class T >
  7031. void CDmeTypedLog< T >::PasteAndRescaleSamples(
  7032. const CDmeLogLayer *pBase,
  7033. const CDmeLogLayer *pDataLayer,
  7034. CDmeLogLayer *pOutputLayer,
  7035. const DmeLog_TimeSelection_t& srcParams,
  7036. const DmeLog_TimeSelection_t& destParams,
  7037. bool bBlendAreaInFalloffRegion,
  7038. bool bReverse )
  7039. {
  7040. Assert( GetNumLayers() >= 2 );
  7041. if ( GetNumLayers() < 2 )
  7042. return;
  7043. CDmeTypedLogLayer< T > *pClipboard = CastElement< CDmeTypedLogLayer< T > >( const_cast< CDmeLogLayer * >( pDataLayer ) );
  7044. // Could have passed in layer with wrong attribute type?!
  7045. Assert( pClipboard );
  7046. if ( !pClipboard )
  7047. return;
  7048. CDmeTypedLogLayer< T > *pBaseLayer = CastElement< CDmeTypedLogLayer< T > >( const_cast< CDmeLogLayer * >( pBase ) );
  7049. CDmeTypedLogLayer< T > *pWriteLayer = CastElement< CDmeTypedLogLayer< T > >( pOutputLayer );
  7050. Assert( pBaseLayer );
  7051. Assert( pWriteLayer );
  7052. TimeSelection_t tSrcTimes;
  7053. tSrcTimes[ TS_LEFT_FALLOFF ] = DmeTime_t( 0 );
  7054. tSrcTimes[ TS_LEFT_HOLD ] = srcParams.m_nTimes[ 1 ] - srcParams.m_nTimes[ 0 ];
  7055. tSrcTimes[ TS_RIGHT_HOLD ] = srcParams.m_nTimes[ 2 ] - srcParams.m_nTimes[ 0 ];
  7056. tSrcTimes[ TS_RIGHT_FALLOFF ] = srcParams.m_nTimes[ 3 ] - srcParams.m_nTimes[ 0 ];
  7057. const TimeSelection_t &tDstTimes = destParams.m_nTimes;
  7058. DmeTime_t tFirstKey = tDstTimes[ 0 ] != tDstTimes[ 1 ] ? tDstTimes[ 0 ] : tDstTimes[ 0 ] - DMETIME_MINDELTA;
  7059. pWriteLayer->InsertKey( tFirstKey, pBaseLayer->GetValue( tFirstKey ), pBaseLayer->GetSegmentInterpolationSetting( tFirstKey ) );
  7060. DmeTime_t tLastKey = tDstTimes[ 3 ] != tDstTimes[ 2 ] ? tDstTimes[ 3 ] : tDstTimes[ 3 ] + DMETIME_MINDELTA;
  7061. pWriteLayer->InsertKey( tLastKey, pBaseLayer->GetValue( tLastKey ), pBaseLayer->GetSegmentInterpolationSetting( tLastKey ) );
  7062. DmeTime_t tLastWrittenTime = tFirstKey;
  7063. LogComponents_t nComponentFlags = destParams.m_nComponentFlags;
  7064. CLogTimeIterator< T > it( pClipboard, bReverse );
  7065. it.AddLayer();
  7066. // Remap the base layer keys into src layer timespace, so that we'll preserve the base layer samples after remapping them back out
  7067. for ( int i = 0; i < pBaseLayer->GetKeyCount(); ++i )
  7068. {
  7069. DmeTime_t tBaseKeyTime = pBaseLayer->GetKeyTime( i );
  7070. // Remap FROM dest TO src time!!!
  7071. DmeTime_t tSrcKeyTime = RemapTime( tBaseKeyTime, tDstTimes, tSrcTimes );
  7072. // Can't possibly matter?
  7073. if ( tSrcKeyTime < tSrcTimes[ TS_LEFT_FALLOFF ] ||
  7074. tSrcKeyTime > tSrcTimes[ TS_RIGHT_FALLOFF ] )
  7075. continue;
  7076. it.AddKeyTime( tSrcKeyTime );
  7077. }
  7078. for( int i = it.First() ; i != it.InvalidIndex(); i = it.Next( i ) )
  7079. {
  7080. DmeTime_t tKeyTime = it.GetKeyTime( i );
  7081. T val;
  7082. it.GetValue( i, val );
  7083. int nSrcTSI = 1;
  7084. if ( tKeyTime < tSrcTimes[ TS_LEFT_HOLD ] )
  7085. {
  7086. if ( tKeyTime <= tSrcTimes[ TS_LEFT_FALLOFF ] )
  7087. continue;
  7088. nSrcTSI = 0;
  7089. }
  7090. else if ( tKeyTime > tSrcTimes[ TS_RIGHT_HOLD ] )
  7091. {
  7092. if ( tKeyTime >= tSrcTimes[ TS_RIGHT_FALLOFF ] )
  7093. continue;
  7094. nSrcTSI = 2;
  7095. }
  7096. int nDstTSI = ( bReverse ? ( 2 - nSrcTSI ) : nSrcTSI );
  7097. bool bHold = nSrcTSI == 1;
  7098. DmeTime_t tSrcDuration = tSrcTimes[ nSrcTSI + 1 ] - tSrcTimes[ nSrcTSI ];
  7099. DmeTime_t tDstDuration = tDstTimes[ nDstTSI + 1 ] - tDstTimes[ nDstTSI ];
  7100. if ( !bHold && tDstDuration == DMETIME_ZERO )
  7101. continue;
  7102. DmeTime_t tDstTime;
  7103. if ( tKeyTime == tSrcTimes[ TS_LEFT_HOLD ] )
  7104. {
  7105. tDstTime = bReverse ? tDstTimes[ TS_RIGHT_HOLD ] : tDstTimes[ TS_LEFT_HOLD ];
  7106. }
  7107. else if ( tKeyTime == tSrcTimes[ TS_RIGHT_HOLD ] )
  7108. {
  7109. tDstTime = bReverse ? tDstTimes[ TS_LEFT_HOLD ] : tDstTimes[ TS_RIGHT_HOLD ];
  7110. }
  7111. else
  7112. {
  7113. float flRatio = MIN( 1.0f, ( tKeyTime - tSrcTimes[ nSrcTSI ] ).GetSeconds() / tSrcDuration.GetSeconds() );
  7114. flRatio = bReverse ? ( 1.0f - flRatio ) : flRatio;
  7115. tDstTime = tDstTimes[ nDstTSI ] + flRatio * tDstDuration;
  7116. if ( tDstTime < tLastWrittenTime + DMETIME_MINDELTA )
  7117. {
  7118. tDstTime = tLastWrittenTime + DMETIME_MINDELTA;
  7119. }
  7120. if ( tDstTime > tDstTimes[ nDstTSI + 1 ] - DMETIME_MINDELTA )
  7121. {
  7122. tDstTime = tDstTimes[ nDstTSI + 1 ] - DMETIME_MINDELTA;
  7123. }
  7124. if ( bBlendAreaInFalloffRegion && !bHold )
  7125. {
  7126. flRatio = destParams.AdjustFactorForInterpolatorType( flRatio, nDstTSI != 0 ? 1 : 0 );
  7127. T baseValue = pBaseLayer->GetValue( tDstTime );
  7128. val = Interpolate( nDstTSI == 0 ? flRatio : 1.0f - flRatio, baseValue, val );
  7129. }
  7130. }
  7131. // Have the layer itself do the masking!!!
  7132. T maskedVal = pBaseLayer->MaskValue( tDstTime, val, nComponentFlags );
  7133. int iNext = it.Next( i );
  7134. iNext = (iNext != it.InvalidIndex()) ? iNext : i;
  7135. pWriteLayer->InsertKey( tDstTime, maskedVal, pClipboard->GetSegmentInterpolationSetting( i, iNext ) );
  7136. tLastWrittenTime = tDstTime;
  7137. }
  7138. // Now walk the dest space and remap original samples into it
  7139. if ( nComponentFlags != LOG_COMPONENTS_ALL )
  7140. {
  7141. for ( int i = 0; i < pBaseLayer->GetKeyCount(); ++i )
  7142. {
  7143. DmeTime_t tBaseKeyTime = pBaseLayer->GetKeyTime( i );
  7144. DmeTime_t tSrcKeyTime = RemapTime( tBaseKeyTime, tDstTimes, tSrcTimes );
  7145. T val;
  7146. if ( tSrcKeyTime <= tSrcTimes[ TS_LEFT_FALLOFF ] ||
  7147. tSrcKeyTime >= tSrcTimes[ TS_RIGHT_FALLOFF ] )
  7148. {
  7149. val = pBaseLayer->GetValue( tBaseKeyTime );
  7150. }
  7151. else
  7152. {
  7153. val = pWriteLayer->GetValue( tBaseKeyTime );
  7154. }
  7155. DmeTime_t nextTime = ((i+1) < pBaseLayer->GetKeyCount()) ? pBaseLayer->GetKeyTime(i+1) : DMETIME_INVALID;
  7156. SegmentInterpolation_t interpSetting = ((pBaseLayer->GetSegmentInterpolationSetting( tBaseKeyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE) ||
  7157. (pWriteLayer->GetSegmentInterpolationSetting( tBaseKeyTime, nextTime, true ) == SEGMENT_NOINTERPOLATE)) ? SEGMENT_NOINTERPOLATE : SEGMENT_INTERPOLATE;
  7158. // Have the layer itself do the masking!!!
  7159. T maskedVal = pBaseLayer->MaskValue( tBaseKeyTime, val, nComponentFlags );
  7160. pWriteLayer->InsertKey( tBaseKeyTime, maskedVal, interpSetting );
  7161. }
  7162. }
  7163. // Update the bookmark times on the log to reflect the time changes as well
  7164. int nNumComponents = GetNumBookmarkComponents();
  7165. for ( int iComp = 0; iComp < nNumComponents; ++iComp )
  7166. {
  7167. CDmaArray< DmeTime_t > &bookmarkTimes = m_BookmarkTimes[ iComp ];
  7168. int nNumBookmarks = bookmarkTimes.Count();
  7169. if ( nNumBookmarks > 0 )
  7170. {
  7171. CEnableUndoScopeGuard sg;
  7172. for ( int iBookmark = 0; iBookmark < nNumBookmarks; ++iBookmark )
  7173. {
  7174. DmeTime_t originalTime = bookmarkTimes[ iBookmark ];
  7175. DmeTime_t newTime = RemapTime( originalTime, srcParams.m_nTimes, tDstTimes );
  7176. bookmarkTimes.Set( iBookmark, newTime );
  7177. }
  7178. }
  7179. }
  7180. }
  7181. template< class T >
  7182. void CDmeTypedLog< T >::PasteAndRescaleSamples(
  7183. const CDmeLogLayer *src, // clipboard data
  7184. const DmeLog_TimeSelection_t& srcParams, // clipboard time selection
  7185. const DmeLog_TimeSelection_t& destParams, // current time selection
  7186. bool bBlendAreaInFalloffRegion, // blending behavior in falloff area of current time selection
  7187. bool bReverse ) // reverse the samples when pasting
  7188. {
  7189. CDmeLogLayer *pBaseLayer = GetLayer( 0 );
  7190. CDmeLogLayer *pWriteLayer = GetLayer( GetTopmostLayer() );
  7191. PasteAndRescaleSamples( pBaseLayer, src, pWriteLayer, srcParams, destParams, bBlendAreaInFalloffRegion, bReverse );
  7192. }
  7193. //-----------------------------------------------------------------------------
  7194. // Purpose: Enforce a specified minimum range between the two values,
  7195. // repositioning the values equidistant from the average at a distance of half
  7196. // the minimum range if the values are the the specified distance apart
  7197. //-----------------------------------------------------------------------------
  7198. void EnsureSeparation( Vector &minVal, Vector &maxVal, float separation )
  7199. {
  7200. Vector vecOffset( separation * 0.5f, separation * 0.5f, separation * 0.5f );
  7201. Vector vecAvg = ( minVal + maxVal ) * 0.5f;
  7202. Vector vecForceMin = vecAvg - vecOffset;
  7203. Vector vecForceMax = vecAvg + vecOffset;
  7204. VectorMin( minVal, vecForceMin, minVal );
  7205. VectorMax( maxVal, vecForceMax, maxVal );
  7206. }
  7207. void EnsureSeparation( float &minVal, float &maxVal, float separation )
  7208. {
  7209. float flAvg = ( minVal + maxVal ) * 0.5f;
  7210. float flForceMin = flAvg - ( separation * 0.5f );
  7211. float flForceMax = flAvg + ( separation * 0.5f );
  7212. minVal = MIN( minVal, flForceMin );
  7213. maxVal = MAX( maxVal, flForceMax );
  7214. }
  7215. template<>
  7216. void CDmeTypedLog< Vector >::BuildNormalizedLayer( int nChannels, CDmeTypedLogLayer< float > **pChannels, int nLayer )
  7217. {
  7218. Assert( GetDataType() != AT_FLOAT );
  7219. Assert( nChannels == 3 );
  7220. if ( nChannels != 3 )
  7221. return;
  7222. // HACK HACK: This is using layer 0 to compute the bounds, rather than the requested layer
  7223. CDmeTypedLogLayer< Vector > *boundsLayer = static_cast< CDmeTypedLogLayer< Vector > * >( GetLayer( 0 ) );
  7224. if ( !boundsLayer )
  7225. return;
  7226. CDmeTypedLogLayer< Vector > *baseLayer = static_cast< CDmeTypedLogLayer< Vector > * >( GetLayer( nLayer ) );
  7227. if ( !baseLayer )
  7228. return;
  7229. Vector vecMins( FLT_MAX, FLT_MAX, FLT_MAX );
  7230. Vector vecMaxs( -FLT_MAX, -FLT_MAX, -FLT_MAX );
  7231. // Compute bounds
  7232. int kc = boundsLayer->GetKeyCount();
  7233. for ( int i = 0; i < kc; ++i )
  7234. {
  7235. Vector keyValue = boundsLayer->GetKeyValue( i );
  7236. for ( int j = 0; j < 3; ++j )
  7237. {
  7238. float val = keyValue[ j ];
  7239. if ( val < vecMins[ j ] )
  7240. {
  7241. vecMins[ j ] = val;
  7242. }
  7243. if ( val > vecMaxs[ j ] )
  7244. {
  7245. vecMaxs[ j ] = val;
  7246. }
  7247. }
  7248. }
  7249. // Forces the normalization to represent at least the specified minimum range.
  7250. EnsureSeparation( vecMins, vecMaxs, s_threshold * 10.0f );
  7251. // Now add values, etc.
  7252. kc = baseLayer->GetKeyCount();
  7253. for ( int i = 0; i < kc; ++i )
  7254. {
  7255. DmeTime_t keyTime = baseLayer->GetKeyTime( i );
  7256. Vector keyValue = baseLayer->GetKeyValue( i );
  7257. SegmentInterpolation_t interpSetting = baseLayer->GetSegmentInterpolationSetting( i );
  7258. for ( int j = 0; j < 3; ++j )
  7259. {
  7260. pChannels[ j ]->InsertKey( keyTime, keyValue[ j ], interpSetting );
  7261. }
  7262. }
  7263. for ( int j = 0; j < 3; ++j )
  7264. {
  7265. for ( int i = 0; i < kc; ++i )
  7266. {
  7267. float keyValue = pChannels[ j ]->GetKeyValue( i );
  7268. float normalized = RemapVal( keyValue, vecMins[ j ], vecMaxs[ j ], 0.0f, 1.0f );
  7269. pChannels[ j ]->SetKeyValue( i, normalized );
  7270. }
  7271. if ( HasDefaultValue() )
  7272. {
  7273. pChannels[ j ]->GetTypedOwnerLog()->SetDefaultValue( RemapVal( GetDefaultValue().Length(), vecMins[ j ], vecMaxs[ j ], 0.0f, 1.0f ) );
  7274. }
  7275. }
  7276. }
  7277. template<>
  7278. void CDmeTypedLog< Vector2D >::BuildNormalizedLayer( int nChannels, CDmeTypedLogLayer< float > **pChannels, int nLayer )
  7279. {
  7280. Assert( GetDataType() != AT_FLOAT );
  7281. CDmeTypedLogLayer< Vector2D > *baseLayer = static_cast< CDmeTypedLogLayer< Vector2D > * >( GetLayer( nLayer ) );
  7282. if ( !baseLayer )
  7283. return;
  7284. float flMin = FLT_MAX;
  7285. float flMax = FLT_MIN;
  7286. int kc = baseLayer->GetKeyCount();
  7287. for ( int i = 0; i < kc; ++i )
  7288. {
  7289. DmeTime_t keyTime = baseLayer->GetKeyTime( i );
  7290. Vector2D keyValue = baseLayer->GetKeyValue( i );
  7291. SegmentInterpolation_t interpSetting = baseLayer->GetSegmentInterpolationSetting( i );
  7292. float len = keyValue.Length();
  7293. if ( len < flMin )
  7294. {
  7295. flMin = len;
  7296. }
  7297. if ( len > flMax )
  7298. {
  7299. flMax = len;
  7300. }
  7301. pChannels[ 0 ]->InsertKey( keyTime, len, interpSetting );
  7302. }
  7303. for ( int i = 0; i < kc; ++i )
  7304. {
  7305. float keyValue = pChannels[ 0 ]->GetKeyValue( i );
  7306. float normalized = RemapVal( keyValue, flMin, flMax, 0.0f, 1.0f );
  7307. pChannels[ 0 ]->SetKeyValue( i, normalized );
  7308. }
  7309. if ( HasDefaultValue() )
  7310. {
  7311. pChannels[ 0 ]->GetTypedOwnerLog()->SetDefaultValue( RemapVal( GetDefaultValue().Length(), flMin, flMax, 0.0f, 1.0f ) );
  7312. }
  7313. }
  7314. template<>
  7315. void CDmeTypedLog< Vector4D >::BuildNormalizedLayer( int nChannels, CDmeTypedLogLayer< float > **pChannels, int nLayer )
  7316. {
  7317. Assert( GetDataType() != AT_FLOAT );
  7318. CDmeTypedLogLayer< Vector4D > *baseLayer = static_cast< CDmeTypedLogLayer< Vector4D > * >( GetLayer( nLayer ) );
  7319. if ( !baseLayer )
  7320. return;
  7321. float flMin = FLT_MAX;
  7322. float flMax = FLT_MIN;
  7323. int kc = baseLayer->GetKeyCount();
  7324. for ( int i = 0; i < kc; ++i )
  7325. {
  7326. DmeTime_t keyTime = baseLayer->GetKeyTime( i );
  7327. Vector4D keyValue = baseLayer->GetKeyValue( i );
  7328. SegmentInterpolation_t interpSetting = baseLayer->GetSegmentInterpolationSetting( i );
  7329. float len = keyValue.Length();
  7330. if ( len < flMin )
  7331. {
  7332. flMin = len;
  7333. }
  7334. if ( len > flMax )
  7335. {
  7336. flMax = len;
  7337. }
  7338. pChannels[ 0 ]->InsertKey( keyTime, len, interpSetting );
  7339. }
  7340. for ( int i = 0; i < kc; ++i )
  7341. {
  7342. float keyValue = pChannels[ 0 ]->GetKeyValue( i );
  7343. float normalized = RemapVal( keyValue, flMin, flMax, 0.0f, 1.0f );
  7344. pChannels[ 0 ]->SetKeyValue( i, normalized );
  7345. }
  7346. if ( HasDefaultValue() )
  7347. {
  7348. pChannels[ 0 ]->GetTypedOwnerLog()->SetDefaultValue( RemapVal( GetDefaultValue().Length(), flMin, flMax, 0.0f, 1.0f ) );
  7349. }
  7350. }
  7351. template<>
  7352. void CDmeTypedLog< int >::BuildNormalizedLayer( int nChannels, CDmeTypedLogLayer< float > **pChannels, int nLayer )
  7353. {
  7354. Assert( GetDataType() != AT_FLOAT );
  7355. CDmeTypedLogLayer< int > *baseLayer = static_cast< CDmeTypedLogLayer< int > * >( GetLayer( nLayer ) );
  7356. if ( !baseLayer )
  7357. return;
  7358. float flMin = FLT_MAX;
  7359. float flMax = FLT_MIN;
  7360. int kc = baseLayer->GetKeyCount();
  7361. for ( int i = 0; i < kc; ++i )
  7362. {
  7363. DmeTime_t keyTime = baseLayer->GetKeyTime( i );
  7364. int keyValue = baseLayer->GetKeyValue( i );
  7365. SegmentInterpolation_t interpSetting = baseLayer->GetSegmentInterpolationSetting( i );
  7366. float len = (float)keyValue;
  7367. if ( len < flMin )
  7368. {
  7369. flMin = len;
  7370. }
  7371. if ( len > flMax )
  7372. {
  7373. flMax = len;
  7374. }
  7375. pChannels[ 0 ]->InsertKey( keyTime, len, interpSetting );
  7376. }
  7377. for ( int i = 0; i < kc; ++i )
  7378. {
  7379. float keyValue = pChannels[ 0 ]->GetKeyValue( i );
  7380. float normalized = RemapVal( keyValue, flMin, flMax, 0.0f, 1.0f );
  7381. pChannels[ 0 ]->SetKeyValue( i, normalized );
  7382. }
  7383. if ( HasDefaultValue() )
  7384. {
  7385. pChannels[ 0 ]->GetTypedOwnerLog()->SetDefaultValue( RemapVal( GetDefaultValue(), flMin, flMax, 0.0f, 1.0f ) );
  7386. }
  7387. }
  7388. template<>
  7389. void CDmeTypedLog< float >::BuildNormalizedLayer( int nChannels, CDmeTypedLogLayer< float > **pChannels, int nLayer )
  7390. {
  7391. Assert( GetDataType() != AT_FLOAT );
  7392. CDmeTypedLogLayer< float > *baseLayer = static_cast< CDmeTypedLogLayer< float > * >( GetLayer( nLayer ) );
  7393. if ( !baseLayer )
  7394. return;
  7395. float flMin = FLT_MAX;
  7396. float flMax = FLT_MIN;
  7397. int kc = baseLayer->GetKeyCount();
  7398. for ( int i = 0; i < kc; ++i )
  7399. {
  7400. DmeTime_t keyTime = baseLayer->GetKeyTime( i );
  7401. float len = baseLayer->GetKeyValue( i );
  7402. SegmentInterpolation_t interpSetting = baseLayer->GetSegmentInterpolationSetting( i );
  7403. if ( len < flMin )
  7404. {
  7405. flMin = len;
  7406. }
  7407. if ( len > flMax )
  7408. {
  7409. flMax = len;
  7410. }
  7411. pChannels[ 0 ]->InsertKey( keyTime, len, interpSetting );
  7412. }
  7413. for ( int i = 0; i < kc; ++i )
  7414. {
  7415. float keyValue = pChannels[ 0 ]->GetKeyValue( i );
  7416. float normalized = RemapVal( keyValue, flMin, flMax, 0.0f, 1.0f );
  7417. pChannels[ 0 ]->SetKeyValue( i, normalized );
  7418. }
  7419. if ( HasDefaultValue() )
  7420. {
  7421. pChannels[ 0 ]->GetTypedOwnerLog()->SetDefaultValue( RemapVal( GetDefaultValue(), flMin, flMax, 0.0f, 1.0f ) );
  7422. }
  7423. }
  7424. template<>
  7425. void CDmeTypedLog< DmeTime_t >::BuildNormalizedLayer( int nChannels, CDmeTypedLogLayer< float > **pChannels, int nLayer )
  7426. {
  7427. Assert( GetDataType() != AT_FLOAT );
  7428. CDmeTypedLogLayer< DmeTime_t > *baseLayer = static_cast< CDmeTypedLogLayer< DmeTime_t > * >( GetLayer( nLayer ) );
  7429. if ( !baseLayer )
  7430. return;
  7431. float flMin = FLT_MAX;
  7432. float flMax = FLT_MIN;
  7433. int kc = baseLayer->GetKeyCount();
  7434. for ( int i = 0; i < kc; ++i )
  7435. {
  7436. DmeTime_t keyTime = baseLayer->GetKeyTime( i );
  7437. DmeTime_t keyValue = baseLayer->GetKeyValue( i );
  7438. SegmentInterpolation_t interpSetting = baseLayer->GetSegmentInterpolationSetting( i );
  7439. float len = keyValue.GetSeconds();
  7440. if ( len < flMin )
  7441. {
  7442. flMin = len;
  7443. }
  7444. if ( len > flMax )
  7445. {
  7446. flMax = len;
  7447. }
  7448. pChannels[ 0 ]->InsertKey( keyTime, len, interpSetting );
  7449. }
  7450. for ( int i = 0; i < kc; ++i )
  7451. {
  7452. float keyValue = pChannels[ 0 ]->GetKeyValue( i );
  7453. float normalized = RemapVal( keyValue, flMin, flMax, 0.0f, 1.0f );
  7454. pChannels[ 0 ]->SetKeyValue( i, normalized );
  7455. }
  7456. if ( HasDefaultValue() )
  7457. {
  7458. pChannels[ 0 ]->GetTypedOwnerLog()->SetDefaultValue( RemapVal( GetDefaultValue().GetSeconds(), flMin, flMax, 0.0f, 1.0f ) );
  7459. }
  7460. }
  7461. template<>
  7462. void CDmeTypedLog< Quaternion >::BuildNormalizedLayer( int nChannels, CDmeTypedLogLayer< float > **pChannels, int nLayer )
  7463. {
  7464. Assert( GetDataType() != AT_FLOAT );
  7465. Assert( nChannels == 3 || nChannels == 1 );
  7466. if ( nChannels != 3 && nChannels != 1 )
  7467. return;
  7468. CDmeTypedLogLayer< Quaternion > *baseLayer = static_cast< CDmeTypedLogLayer< Quaternion > * >( GetLayer( nLayer ) );
  7469. if ( !baseLayer )
  7470. return;
  7471. if ( nChannels == 1 )
  7472. {
  7473. int kc = baseLayer->GetKeyCount();
  7474. for ( int i = 0; i < kc; ++i )
  7475. {
  7476. DmeTime_t tKeyTime = baseLayer->GetKeyTime( i );
  7477. Quaternion keyValue = baseLayer->GetKeyValue( i );
  7478. SegmentInterpolation_t interpSetting = baseLayer->GetSegmentInterpolationSetting( i );
  7479. float flNormalized = Normalize( keyValue );
  7480. pChannels[ 0 ]->InsertKey( tKeyTime, flNormalized, interpSetting );
  7481. }
  7482. if ( HasDefaultValue() )
  7483. {
  7484. pChannels[ 0 ]->GetTypedOwnerLog()->SetDefaultValue( Normalize( GetDefaultValue() ) );
  7485. }
  7486. return;
  7487. }
  7488. // HACK HACK: This is using layer 0 to compute the bounds, rather than the requested layer
  7489. CDmeTypedLogLayer< Quaternion > *boundsLayer = static_cast< CDmeTypedLogLayer< Quaternion > * >( GetLayer( 0 ) );
  7490. if ( !boundsLayer )
  7491. return;
  7492. QAngle angMins( FLT_MAX, FLT_MAX, FLT_MAX );
  7493. QAngle angMaxs( -FLT_MAX, -FLT_MAX, -FLT_MAX );
  7494. // Compute bounds
  7495. int kc = boundsLayer->GetKeyCount();
  7496. for ( int i = 0; i < kc; ++i )
  7497. {
  7498. Quaternion keyValue = boundsLayer->GetKeyValue( i );
  7499. QAngle ang;
  7500. QuaternionAngles( keyValue, ang );
  7501. for ( int j = 0; j < 3; ++j )
  7502. {
  7503. float val = ang[ j ];
  7504. if ( val < angMins[ j ] )
  7505. {
  7506. angMins[ j ] = val;
  7507. }
  7508. if ( val > angMaxs[ j ] )
  7509. {
  7510. angMaxs[ j ] = val;
  7511. }
  7512. }
  7513. }
  7514. // Forces the normalization to represent at least the specified minimum range.
  7515. //EnsureSeparation( angMins, angMaxs, s_threshold * 10.0f );
  7516. // Now add values, etc.
  7517. kc = baseLayer->GetKeyCount();
  7518. for ( int i = 0; i < kc; ++i )
  7519. {
  7520. DmeTime_t keyTime = baseLayer->GetKeyTime( i );
  7521. Quaternion keyValue = baseLayer->GetKeyValue( i );
  7522. SegmentInterpolation_t interpSetting = baseLayer->GetSegmentInterpolationSetting( i );
  7523. QAngle ang;
  7524. QuaternionAngles( keyValue, ang );
  7525. for ( int j = 0; j < 3; ++j )
  7526. {
  7527. pChannels[ j ]->InsertKey( keyTime, ang[ j ], interpSetting );
  7528. }
  7529. }
  7530. for ( int j = 0; j < 3; ++j )
  7531. {
  7532. for ( int i = 0; i < kc; ++i )
  7533. {
  7534. float keyValue = pChannels[ j ]->GetKeyValue( i );
  7535. float normalized = RemapVal( keyValue, angMins[ j ], angMaxs[ j ], 0.0f, 1.0f );
  7536. pChannels[ j ]->SetKeyValue( i, normalized );
  7537. }
  7538. }
  7539. }
  7540. //-----------------------------------------------------------------------------
  7541. // Creates a log of a specific type
  7542. //-----------------------------------------------------------------------------
  7543. CDmeLog *CDmeLog::CreateLog( DmAttributeType_t type, DmFileId_t fileid )
  7544. {
  7545. switch ( type )
  7546. {
  7547. case AT_INT:
  7548. case AT_INT_ARRAY:
  7549. return CreateElement< CDmeIntLog >( "int log", fileid );
  7550. case AT_FLOAT:
  7551. case AT_FLOAT_ARRAY:
  7552. return CreateElement< CDmeFloatLog >( "float log", fileid );
  7553. case AT_BOOL:
  7554. case AT_BOOL_ARRAY:
  7555. return CreateElement< CDmeBoolLog >( "bool log", fileid );
  7556. case AT_COLOR:
  7557. case AT_COLOR_ARRAY:
  7558. return CreateElement< CDmeColorLog >( "color log", fileid );
  7559. case AT_VECTOR2:
  7560. case AT_VECTOR2_ARRAY:
  7561. return CreateElement< CDmeVector2Log >( "vector2 log", fileid );
  7562. case AT_VECTOR3:
  7563. case AT_VECTOR3_ARRAY:
  7564. return CreateElement< CDmeVector3Log >( "vector3 log", fileid );
  7565. case AT_VECTOR4:
  7566. case AT_VECTOR4_ARRAY:
  7567. return CreateElement< CDmeVector4Log >( "vector4 log", fileid );
  7568. case AT_QANGLE:
  7569. case AT_QANGLE_ARRAY:
  7570. return CreateElement< CDmeQAngleLog >( "qangle log", fileid );
  7571. case AT_QUATERNION:
  7572. case AT_QUATERNION_ARRAY:
  7573. return CreateElement< CDmeQuaternionLog >( "quaternion log", fileid );
  7574. case AT_VMATRIX:
  7575. case AT_VMATRIX_ARRAY:
  7576. return CreateElement< CDmeVMatrixLog >( "vmatrix log", fileid );
  7577. case AT_STRING:
  7578. case AT_STRING_ARRAY:
  7579. return CreateElement< CDmeStringLog >( "string log", fileid );
  7580. case AT_TIME:
  7581. case AT_TIME_ARRAY:
  7582. return CreateElement< CDmeTimeLog >( "time log", fileid );
  7583. }
  7584. return NULL;
  7585. }
  7586. // Disallowed methods for types
  7587. //template<> void CDmeTypedLog< bool >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const bool& value ) { Assert( 0 ); }
  7588. //template<> void CDmeTypedLog< bool >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const bool& value ) { Assert( 0 ); }
  7589. //template<> void CDmeTypedLog< bool >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index /*= 0*/ ) { Assert( 0 ); }
  7590. //template<> void CDmeTypedLog< bool >::FinishTimeSelection( DmeLog_TimeSelection_t& params ) { Assert( 0 ); }
  7591. //
  7592. //template<> void CDmeTypedLog< Color >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const Color& value ) { Assert( 0 ); }
  7593. //template<> void CDmeTypedLog< Color >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const Color& value ) { Assert( 0 ); }
  7594. //template<> void CDmeTypedLog< Color >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index /*= 0*/ ) { Assert( 0 ); }
  7595. //template<> void CDmeTypedLog< Color >::FinishTimeSelection( DmeLog_TimeSelection_t& params ) { Assert( 0 ); }
  7596. //
  7597. //template<> void CDmeTypedLog< Vector4D >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const Vector4D& value ) { Assert( 0 ); }
  7598. //template<> void CDmeTypedLog< Vector4D >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const Vector4D& value ) { Assert( 0 ); }
  7599. //template<> void CDmeTypedLog< Vector4D >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index /*= 0*/ ) { Assert( 0 ); }
  7600. //template<> void CDmeTypedLog< Vector4D >::FinishTimeSelection( DmeLog_TimeSelection_t& params ) { Assert( 0 ); }
  7601. //
  7602. //template<> void CDmeTypedLog< Vector2D >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const Vector2D& value ) { Assert( 0 ); }
  7603. //template<> void CDmeTypedLog< Vector2D >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const Vector2D& value ) { Assert( 0 ); }
  7604. //template<> void CDmeTypedLog< Vector2D >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index /*= 0*/ ) { Assert( 0 ); }
  7605. //template<> void CDmeTypedLog< Vector2D >::FinishTimeSelection( DmeLog_TimeSelection_t& params ) { Assert( 0 ); }
  7606. //template<> void CDmeTypedLog< Vector >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const Vector& value ) { Assert( 0 ); }
  7607. //template<> void CDmeTypedLog< Vector >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const Vector& value ) { Assert( 0 ); }
  7608. //template<> void CDmeTypedLog< Vector >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index /*= 0*/ ) { Assert( 0 ); }
  7609. //template<> void CDmeTypedLog< Vector >::FinishTimeSelection( DmeLog_TimeSelection_t& params ) { Assert( 0 ); }
  7610. //template<> void CDmeTypedLog< VMatrix >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const VMatrix& value ) { Assert( 0 ); }
  7611. //template<> void CDmeTypedLog< VMatrix >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const VMatrix& value ) { Assert( 0 ); }
  7612. //template<> void CDmeTypedLog< VMatrix >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index /*= 0*/ ) { Assert( 0 ); }
  7613. //template<> void CDmeTypedLog< VMatrix >::FinishTimeSelection( DmeLog_TimeSelection_t& params ) { Assert( 0 ); }
  7614. //
  7615. //template<> void CDmeTypedLog< Quaternion >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const Quaternion& value ) { Assert( 0 ); }
  7616. //template<> void CDmeTypedLog< Quaternion >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const Quaternion& value ) { Assert( 0 ); }
  7617. //template<> void CDmeTypedLog< Quaternion >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index /*= 0*/ ) { Assert( 0 ); }
  7618. //template<> void CDmeTypedLog< Quaternion >::FinishTimeSelection( DmeLog_TimeSelection_t& params ) { Assert( 0 ); }
  7619. //
  7620. //template<> void CDmeTypedLog< QAngle >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const QAngle& value ) { Assert( 0 ); }
  7621. //template<> void CDmeTypedLog< QAngle >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const QAngle& value ) { Assert( 0 ); }
  7622. //template<> void CDmeTypedLog< QAngle >::StampKeyAtHead( const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index /*= 0*/ ) { Assert( 0 ); }
  7623. //template<> void CDmeTypedLog< QAngle >::FinishTimeSelection( DmeLog_TimeSelection_t& params ) { Assert( 0 ); }
  7624. //-----------------------------------------------------------------------------
  7625. // Helpers for particular types of log layers
  7626. //-----------------------------------------------------------------------------
  7627. void GenerateRotationLog( CDmeQuaternionLogLayer *pLayer, const Vector &vecAxis, DmeTime_t pTime[4], float pRevolutionsPerSec[4] )
  7628. {
  7629. for ( int i = 1; i < 4; ++i )
  7630. {
  7631. if ( pTime[i] < pTime[i-1] )
  7632. {
  7633. Warning( "Bogus times passed into GenerateRotationLog\n" );
  7634. return;
  7635. }
  7636. }
  7637. // Gets the initial value
  7638. matrix3x4_t initial;
  7639. Quaternion q = pLayer->GetValue( pTime[0] );
  7640. QuaternionMatrix( q, initial );
  7641. // Find the max rps, and compute the total rotation in degrees
  7642. // by the time we reach the transition points. The total rotation =
  7643. // integral from 0 to t of 360 * ( rate[i] - rate[i-1] ) t / tl + rate[i-1] )
  7644. // == 360 * ( ( rate[i] - rate[i-1] ) t^2 / 2 + rate[i-1] t )
  7645. float pTotalRotation[4];
  7646. float flMaxRPS = pRevolutionsPerSec[0];
  7647. pTotalRotation[0] = 0.0f;
  7648. for ( int i = 1; i < 4; ++i )
  7649. {
  7650. if ( pRevolutionsPerSec[i] > flMaxRPS )
  7651. {
  7652. flMaxRPS = pRevolutionsPerSec[i];
  7653. }
  7654. float dt = pTime[i].GetSeconds() - pTime[i-1].GetSeconds();
  7655. float dRot = pRevolutionsPerSec[i] - pRevolutionsPerSec[i-1];
  7656. pTotalRotation[i] = 360.0f * ( dRot * dt * 0.5 + pRevolutionsPerSec[i-1] * dt ) + pTotalRotation[i-1];
  7657. }
  7658. // We need to compute how long a single rotation takes, then create samples
  7659. // at 1/4 the frequency of that amount of time
  7660. VMatrix rot;
  7661. matrix3x4_t total;
  7662. QAngle angles;
  7663. float flMaxRotationTime = (flMaxRPS != 0.0f) ? ( 0.125f / flMaxRPS ) : ( pTime[3].GetSeconds() - pTime[0].GetSeconds() );
  7664. DmeTime_t dt( flMaxRotationTime );
  7665. for ( DmeTime_t t = pTime[0]; t <= pTime[3]; t += dt )
  7666. {
  7667. int i = ( t < pTime[1] ) ? 1 : ( ( t < pTime[2] ) ? 2 : 3 );
  7668. float flInterval = t.GetSeconds() - pTime[i-1].GetSeconds();
  7669. float flOOSegmentDur = pTime[i].GetSeconds() - pTime[i-1].GetSeconds();
  7670. if ( flOOSegmentDur == 0.0f )
  7671. {
  7672. Assert( flInterval == 0.0f );
  7673. flOOSegmentDur = 1.0f;
  7674. }
  7675. else
  7676. {
  7677. flOOSegmentDur = 1.0f / flOOSegmentDur;
  7678. }
  7679. float dRot = pRevolutionsPerSec[i] - pRevolutionsPerSec[i-1];
  7680. float flRotation = 360.0f * ( dRot * flInterval * flInterval * 0.5f * flOOSegmentDur + pRevolutionsPerSec[i-1] * flInterval ) + pTotalRotation[i-1];
  7681. MatrixBuildRotationAboutAxis( rot, vecAxis, flRotation );
  7682. ConcatTransforms( initial, rot.As3x4(), total );
  7683. MatrixToAngles( VMatrix( total ), angles );
  7684. AngleQuaternion( angles, q );
  7685. pLayer->SetKey( t, q );
  7686. }
  7687. }
  7688. //-----------------------------------------------------------------------------
  7689. // Transforms a position log
  7690. //-----------------------------------------------------------------------------
  7691. void RotatePositionLog( CDmeVector3LogLayer *pPositionLog, const matrix3x4_t& matrix )
  7692. {
  7693. Assert( fabs( matrix[0][3] ) < 1e-3 && fabs( matrix[1][3] ) < 1e-3 && fabs( matrix[2][3] ) < 1e-3 );
  7694. Vector position;
  7695. int nCount = pPositionLog->GetKeyCount();
  7696. for ( int i = 0; i < nCount; ++i )
  7697. {
  7698. const Vector &srcPosition = pPositionLog->GetKeyValue( i );
  7699. VectorTransform( srcPosition, matrix, position );
  7700. pPositionLog->SetKeyValue( i, position );
  7701. }
  7702. }
  7703. //-----------------------------------------------------------------------------
  7704. // Transforms a orientation log
  7705. //-----------------------------------------------------------------------------
  7706. void RotateOrientationLog( CDmeQuaternionLogLayer *pOrientationLog, const matrix3x4_t& matrix, bool bPreMultiply = false )
  7707. {
  7708. Assert( fabs( matrix[0][3] ) < 1e-3 && fabs( matrix[1][3] ) < 1e-3 && fabs( matrix[2][3] ) < 1e-3 );
  7709. matrix3x4_t orientation, newOrientation;
  7710. Quaternion q;
  7711. int nCount = pOrientationLog->GetKeyCount();
  7712. for ( int i = 0; i < nCount; ++i )
  7713. {
  7714. const Quaternion &srcQuat = pOrientationLog->GetKeyValue( i );
  7715. QuaternionMatrix( srcQuat, orientation );
  7716. if ( bPreMultiply )
  7717. {
  7718. ConcatTransforms( matrix, orientation, newOrientation );
  7719. }
  7720. else
  7721. {
  7722. ConcatTransforms( orientation, matrix, newOrientation );
  7723. }
  7724. MatrixQuaternion( newOrientation, q );
  7725. pOrientationLog->SetKeyValue( i, q );
  7726. }
  7727. }
  7728. float ComputeInterpolationFactor( float flFactor, int nInterpolatorType )
  7729. {
  7730. static Vector s_pInterolationPoints[ 4 ] =
  7731. {
  7732. Vector( 0.0f, 0.0f, 0.0f ),
  7733. Vector( 0.0f, 0.0f, 0.0f ),
  7734. Vector( 1.0f, 1.0f, 0.0f ),
  7735. Vector( 1.0f, 1.0f, 0.0f )
  7736. };
  7737. Vector out;
  7738. Interpolator_CurveInterpolate
  7739. (
  7740. nInterpolatorType,
  7741. s_pInterolationPoints[ 0 ], // unused
  7742. s_pInterolationPoints[ 1 ],
  7743. s_pInterolationPoints[ 2 ],
  7744. s_pInterolationPoints[ 3 ], // unused
  7745. flFactor,
  7746. out
  7747. );
  7748. return out.y; // clamp( out.y, 0.0f, 1.0f );
  7749. }
  7750. float GetAmountForTime( DmeTime_t dmetime, const TimeSelection_t &times, const int nInterpolationTypes[ 2 ] )
  7751. {
  7752. if ( dmetime < times[ 0 ] || dmetime > times[ 3 ] )
  7753. return 0.0f; // outside selection
  7754. int nInterpolationType = INTERPOLATE_LINEAR_INTERP;
  7755. float f = 0.0f;
  7756. if ( dmetime >= times[ 1 ] )
  7757. {
  7758. if ( dmetime <= times[ 2 ] )
  7759. return 1.0f; // hold
  7760. f = ( times[ 3 ] - dmetime ).GetSeconds() / ( times[ 3 ] - times[ 2 ] ).GetSeconds();
  7761. nInterpolationType = nInterpolationTypes[ 1 ];
  7762. }
  7763. else
  7764. {
  7765. f = ( dmetime - times[ 0 ] ).GetSeconds() / ( times[ 1 ] - times[ 0 ] ).GetSeconds();
  7766. nInterpolationType = nInterpolationTypes[ 0 ];
  7767. }
  7768. float flOut = ComputeInterpolationFactor( f, nInterpolationType );
  7769. return clamp( flOut, 0.0f, 1.0f );
  7770. }