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.

3281 lines
107 KiB

  1. //====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "movieobjects/dmechannel.h"
  7. #include "movieobjects/dmelog.h"
  8. #include "movieobjects/dmeclip.h"
  9. #include "movieobjects/dmetimeselection.h"
  10. #include "movieobjects/dmetransformcontrol.h"
  11. #include "datamodel/dmelementfactoryhelper.h"
  12. #include "datamodel/dmehandle.h"
  13. #include "datamodel/dmattribute.h"
  14. #include "tier0/vprof.h"
  15. #include "tier1/KeyValues.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. // Paste data utility function declarations
  19. KeyValues *FindLayerInPasteData( const CUtlVector< KeyValues * > &list, CDmeLog *log );
  20. static int FindSpanningLayerAndSetIntensity( DmeLog_TimeSelection_t &ts, LayerSelectionData_t *data );
  21. void CopyPasteData( CUtlVector< KeyValues * > &dstList, const CUtlVector< KeyValues * > &srcList );
  22. void DestroyPasteData( CUtlVector< KeyValues * > &list );
  23. //-----------------------------------------------------------------------------
  24. //
  25. // CRecordingLayer
  26. //
  27. //-----------------------------------------------------------------------------
  28. //-----------------------------------------------------------------------------
  29. // Default constructor
  30. //-----------------------------------------------------------------------------
  31. CRecordingLayer::CRecordingLayer()
  32. : m_pPresetValuesDict( 0 )
  33. , m_tHeadShotTime( DMETIME_INVALID )
  34. , m_ProceduralType( 0 )
  35. , m_OperationFlags( 0 )
  36. , m_RandomSeed( 0 )
  37. , m_flThreshold( 0 )
  38. , m_flIntensity( 0 )
  39. , m_RecordingMode( RECORD_PRESET )
  40. , m_pUndoOperation( NULL )
  41. , m_pfnAddChannelCallback( NULL )
  42. , m_pfnFinishChannelCallback( NULL )
  43. {
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Destructor, releases any clipboard data or log layer data that may be held
  47. // by the recording layer.
  48. //-----------------------------------------------------------------------------
  49. CRecordingLayer::~CRecordingLayer()
  50. {
  51. DestroyPasteData( m_ClipboardData );
  52. int nChannels = m_LayerChannels.Count();
  53. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  54. {
  55. LayerChannelInfo_t &info = m_LayerChannels[ iChannel ];
  56. g_pDataModel->DestroyElement( info.m_hRawDataLayer );
  57. }
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Purpose: Determine if the specified channel is in the list of modify
  61. // channels, regardless of component flags.
  62. //-----------------------------------------------------------------------------
  63. bool ModifyChannel::IsChannelInList( const CUtlVector< ModifyChannel > &modifyList, CDmeChannel *pChannel )
  64. {
  65. int nChannels = modifyList.Count();
  66. for ( int i = 0; i < nChannels; ++i )
  67. {
  68. if ( modifyList[ i ].m_pChannel == pChannel )
  69. {
  70. return true;
  71. }
  72. }
  73. return false;
  74. }
  75. //-----------------------------------------------------------------------------
  76. //
  77. // CDmeChannelModificationLayer
  78. //
  79. //-----------------------------------------------------------------------------
  80. //-----------------------------------------------------------------------------
  81. // Default constructor
  82. //-----------------------------------------------------------------------------
  83. CDmeChannelModificationLayer::CDmeChannelModificationLayer()
  84. : m_bVisible( true )
  85. {
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Destructor
  89. //-----------------------------------------------------------------------------
  90. CDmeChannelModificationLayer::~CDmeChannelModificationLayer()
  91. {
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Purpose: Add a channel to the modification layer if it is not already
  95. // present, adding the channel to the modification layer causes a new log layer
  96. // to be added to the channel to which modifications will be made.
  97. // Input : pChannel - Pointer to the channel to be added.
  98. // enableUndo - Flag indicating if undo should be enabled when adding
  99. // the modification layer to the log of the channel.
  100. // Output : Returns the index of the location in the modification layer's array
  101. // of channels where the information for the channel was stored.
  102. //-----------------------------------------------------------------------------
  103. int CDmeChannelModificationLayer::AddChannel( CDmeChannel *pChannel, bool enableUndo )
  104. {
  105. // Make sure the channel is valid and that is has a valid log.
  106. Assert( pChannel );
  107. if ( pChannel == NULL )
  108. return -1;
  109. CDmeLog* pLog = pChannel->GetLog();
  110. if ( pLog == NULL )
  111. return -1;
  112. // Check to see if the channel is already in the modification layer,
  113. // if so just update the reference count of the channel and return.
  114. int nChannels = m_ActiveChannels.Count();
  115. int availableSlot = -1;
  116. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  117. {
  118. if ( m_ActiveChannels[ iChannel ].m_Channel == pChannel->GetHandle() )
  119. {
  120. ++m_ActiveChannels[ iChannel ].m_RefCount;
  121. return iChannel;
  122. }
  123. if ( ( availableSlot < 0 ) && ( m_ActiveChannels[ iChannel ].m_Channel.Get() == NULL ) )
  124. {
  125. Assert( m_ActiveChannels[ iChannel ].m_RefCount == 0 );
  126. availableSlot = iChannel;
  127. }
  128. }
  129. // Add the new channel to the modification layer's list in the
  130. // available slot or at the end if there is not an available slot.
  131. if ( availableSlot < 0 )
  132. {
  133. availableSlot = m_ActiveChannels.AddToTail();
  134. }
  135. m_ActiveChannels[ availableSlot ].m_Channel = pChannel->GetHandle();
  136. m_ActiveChannels[ availableSlot ].m_RefCount = 1;
  137. // Store the index of the current topmost layer, this is the layer which will be copied.
  138. int sourceLayerIndex = pLog->GetTopmostLayer();
  139. // If there is only one layer in the log add a new log layer, this is the layer upon which modifications
  140. // within the modification layer will be applied to until the modification layer is completed.
  141. if ( sourceLayerIndex == 0 )
  142. {
  143. pLog->GetLayer( sourceLayerIndex );
  144. g_pDataModel->SetUndoEnabled( enableUndo );
  145. CDmeLogLayer *pLayer = pLog->AddNewLayer();
  146. g_pDataModel->SetUndoEnabled( false );
  147. if ( ( pLayer ) && ( sourceLayerIndex >= 0 ) )
  148. {
  149. CDmeLogLayer *pSrcLayer = pLog->GetLayer( sourceLayerIndex );
  150. if ( pSrcLayer )
  151. {
  152. pLayer->CopyLayer( pSrcLayer );
  153. }
  154. // The modification layer is always considered infinite so
  155. // as long as it is active it will be used at any time.
  156. pLayer->SetInfinite( true, true );
  157. }
  158. }
  159. // Return the index of the location in the array where the channel was added.
  160. return availableSlot;
  161. }
  162. //-----------------------------------------------------------------------------
  163. // Purpose: Flatten the log layers of all of the active channels onto the base
  164. // layer.
  165. // Input : bSaveChanges - Flag indicating if the changes recorded on the
  166. // modification layer should be applied to the base layer ( true ) or
  167. // completely discarded ( false ).
  168. // Input : bFlattenLayers - Flag indicating if the modification layers of the
  169. // logs should be flattened onto the base layer of the logs. Ignored
  170. // if bSaveChanges is false.
  171. //-----------------------------------------------------------------------------
  172. void CDmeChannelModificationLayer::Finish( bool bSaveChanges, bool bFlattenLayers, bool bRunChannelCallbacks )
  173. {
  174. int nChannels = m_ActiveChannels.Count();
  175. if ( ( bSaveChanges == false ) && ( bFlattenLayers == true ) )
  176. {
  177. // If not saving the changes just remove all by the layers from the log except the base layer.
  178. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  179. {
  180. CDmeChannel *pChannel = m_ActiveChannels[ iChannel ].m_Channel.Get();
  181. if ( pChannel )
  182. {
  183. CDmeLog *pLog = pChannel->GetLog();
  184. if ( pLog )
  185. {
  186. while ( pLog->GetNumLayers() > 1 )
  187. {
  188. pLog->RemoveLayerFromTail();
  189. }
  190. }
  191. }
  192. }
  193. }
  194. else if ( bFlattenLayers )
  195. {
  196. // If requested flatten the logs of the active channels. This flattens the logs completely,
  197. // so if there are any layers above the modification layer they will be flattened too.
  198. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  199. {
  200. CDmeChannel *pChannel = m_ActiveChannels[ iChannel ].m_Channel.Get();
  201. if ( pChannel )
  202. {
  203. CDmeLog *pLog = pChannel->GetLog();
  204. if ( pLog )
  205. {
  206. pLog->FlattenLayers( 0.0f, 0 );
  207. }
  208. }
  209. }
  210. }
  211. if ( bRunChannelCallbacks )
  212. {
  213. int nLayers = m_RecordingLayerStack.Count();
  214. for ( int iLayer = 0; iLayer < nLayers; ++iLayer )
  215. {
  216. CDmeChannelRecordingMgr::RunFinishCallbacksOnRecordingLayer( &m_RecordingLayerStack[ iLayer ] );
  217. }
  218. }
  219. // Remove all recording layers
  220. m_RecordingLayerStack.Purge();
  221. // Remove all channels
  222. m_ActiveChannels.Purge();
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Purpose: Add a recording layer to the modification layer.
  226. // Output : Returns a pointer to the recording layer which was added.
  227. //-----------------------------------------------------------------------------
  228. CRecordingLayer* CDmeChannelModificationLayer::AddRecordingLayer()
  229. {
  230. int index = m_RecordingLayerStack.AddToTail();
  231. return &m_RecordingLayerStack[ index ];
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Purpose: Remove the last recording layer from the modification layer.
  235. //-----------------------------------------------------------------------------
  236. void CDmeChannelModificationLayer::RemoveLastRecordingLayer()
  237. {
  238. // Iterate through the channels in the recording layer and update the reference count of the
  239. // channel in the modification layer. If the channel is no longer referenced by any of the
  240. // recording layers in the modification layer it will be removed from the modification layer.
  241. CRecordingLayer &recLayer = m_RecordingLayerStack.Tail();
  242. int nChannels = recLayer.m_LayerChannels.Count();
  243. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  244. {
  245. int index = recLayer.m_LayerChannels[ iChannel ].m_ModLayerIndex;
  246. Assert( index >= 0 );
  247. Assert( index < m_ActiveChannels.Count() );
  248. if ( index >= 0 && index < m_ActiveChannels.Count() )
  249. {
  250. --m_ActiveChannels[ index ].m_RefCount;
  251. if ( m_ActiveChannels[ index ].m_RefCount < 1 )
  252. {
  253. Assert( m_ActiveChannels[ index ].m_RefCount == 0 );
  254. m_ActiveChannels[ index ].m_Channel = NULL;
  255. }
  256. }
  257. }
  258. m_RecordingLayerStack.RemoveMultipleFromTail( 1 );
  259. }
  260. //-----------------------------------------------------------------------------
  261. // Purpose: Restore the modification log layer of each of the channels in the
  262. // modification layer to their original state before any recording layers were
  263. // applied by copying the base layer.
  264. //-----------------------------------------------------------------------------
  265. void CDmeChannelModificationLayer::WipeChannelModifications()
  266. {
  267. int nChannels = m_ActiveChannels.Count();
  268. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  269. {
  270. CDmeChannel *pChannel = m_ActiveChannels[ iChannel ].m_Channel.Get();
  271. if ( pChannel )
  272. {
  273. // Get the log from the channel
  274. CDmeLog *pLog = pChannel->GetLog();
  275. if ( pLog == NULL )
  276. continue;
  277. // Get the number of layers, it must be at least two,
  278. // the base layer and the modification layer.
  279. int numLayers = pLog->GetNumLayers();
  280. if ( numLayers < 2 )
  281. {
  282. Assert( numLayers >= 2 );
  283. continue;
  284. }
  285. // Get the modification layer and the base layer and then copy the base layer into the
  286. // modification layer, overwriting anything that is currently in the modification layer.
  287. CDmeLogLayer *pModLayer = pLog->GetLayer( numLayers - 1 );
  288. CDmeLogLayer *pBaseLayer = pLog->GetLayer( numLayers - 2 );
  289. pModLayer->CopyLayer( pBaseLayer );
  290. // Modification layer is always infinite, while
  291. // it is active no layers beneath it matter.
  292. pModLayer->SetInfinite( true, true );
  293. }
  294. }
  295. }
  296. //-----------------------------------------------------------------------------
  297. // Purpose: Get the number of recording layers in the modification layer
  298. //-----------------------------------------------------------------------------
  299. int CDmeChannelModificationLayer::NumRecordingLayers() const
  300. {
  301. return m_RecordingLayerStack.Count();
  302. }
  303. //-----------------------------------------------------------------------------
  304. // Purpose: Get a reference to the specified recording layer
  305. //-----------------------------------------------------------------------------
  306. CRecordingLayer &CDmeChannelModificationLayer::GetRecordingLayer( int index )
  307. {
  308. return m_RecordingLayerStack[ index ];
  309. }
  310. //-----------------------------------------------------------------------------
  311. // Purpose: Return if the modification layer visible to the user
  312. //-----------------------------------------------------------------------------
  313. bool CDmeChannelModificationLayer::IsVisible() const
  314. {
  315. return m_bVisible;
  316. }
  317. //-----------------------------------------------------------------------------
  318. // Apply the specified transform write mode all of the active channels in each
  319. // of the recording layers
  320. //-----------------------------------------------------------------------------
  321. void CDmeChannelModificationLayer::UpdateTransformWriteMode( TransformWriteMode_t mode )
  322. {
  323. int nLayers = m_RecordingLayerStack.Count();
  324. for ( int iLayer = 0; iLayer < nLayers; ++iLayer )
  325. {
  326. CRecordingLayer &layer = m_RecordingLayerStack[ iLayer ];
  327. int nChannels = layer.m_LayerChannels.Count();
  328. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  329. {
  330. LayerChannelInfo_t &channelInfo = layer.m_LayerChannels[ iChannel ];
  331. channelInfo.m_TransformWriteMode = mode;
  332. }
  333. }
  334. }
  335. //-----------------------------------------------------------------------------
  336. // CUndoAddRecoringLayer
  337. //
  338. // Undo operation for adding a recording layer to the modification layer,
  339. // removes the last recording layer from the modification layer.
  340. //
  341. //-----------------------------------------------------------------------------
  342. class CUndoAddRecordingLayer : public CUndoElement
  343. {
  344. public:
  345. CUndoAddRecordingLayer( const char *pUndoDesc, CDmeChannelRecordingMgr* pRecordingMgr )
  346. : CUndoElement( pUndoDesc )
  347. , m_pRecordingMgr( pRecordingMgr )
  348. , m_pPresetValuesDict( NULL )
  349. , m_tHeadShotTime( NULL )
  350. , m_ProceduralType( PROCEDURAL_PRESET_NOT )
  351. , m_OperationFlags( 0 )
  352. , m_pfnAddChannelCallback( NULL )
  353. , m_pfnFinishChannelCallback( NULL )
  354. {
  355. Assert( m_pRecordingMgr );
  356. m_TimeSelection = m_pRecordingMgr->GetTimeSelection();
  357. if ( pRecordingMgr )
  358. {
  359. m_bInModificationLayer = pRecordingMgr->IsModificationLayerActive();
  360. }
  361. }
  362. ~CUndoAddRecordingLayer()
  363. {
  364. // Destroy any paste data which was stored.
  365. DestroyPasteData( m_ClipboardData );
  366. // Destroy any log layer data
  367. int nChannels = m_ChannelInfo.Count();
  368. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  369. {
  370. g_pDataModel->DestroyElement( m_ChannelInfo[ iChannel ].m_hRawDataLayer );
  371. }
  372. if ( m_pPresetValuesDict )
  373. {
  374. delete m_pPresetValuesDict;
  375. }
  376. }
  377. void SaveRecordingLayerData( CRecordingLayer *pRecordingLayer )
  378. {
  379. Assert( pRecordingLayer );
  380. // Save the operation type
  381. m_pPresetValuesDict = CopyAttributeDict( pRecordingLayer->m_pPresetValuesDict );
  382. m_tHeadShotTime = pRecordingLayer->m_tHeadShotTime;
  383. m_ProceduralType = pRecordingLayer->m_ProceduralType;
  384. m_OperationFlags = pRecordingLayer->m_OperationFlags;
  385. m_pfnAddChannelCallback = pRecordingLayer->m_pfnAddChannelCallback;
  386. m_pfnFinishChannelCallback = pRecordingLayer->m_pfnFinishChannelCallback;
  387. // Save the operation time parameters
  388. m_TimeSelection.m_flIntensity = pRecordingLayer->m_flIntensity;
  389. m_TimeSelection.m_flThreshold = pRecordingLayer->m_flThreshold;
  390. m_TimeSelection.SetRecordingMode( pRecordingLayer->m_RecordingMode );
  391. // Store the channel information for all of the channels that are modified by the recording layer. This
  392. // information is not required for the undo, which simply destroys the recording layer, but is required
  393. // for the redo operation as it needs to add the channels to the recording layer when it re-creates it.
  394. int nChannels = pRecordingLayer->m_LayerChannels.Count();
  395. m_ChannelInfo.EnsureCount( nChannels );
  396. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  397. {
  398. ChannelInfo_t &dstInfo = m_ChannelInfo[ iChannel ];
  399. LayerChannelInfo_t &srcInfo = pRecordingLayer->m_LayerChannels[ iChannel ];
  400. dstInfo.m_Channel = srcInfo.m_Channel;
  401. dstInfo.m_ComponentFlags = srcInfo.m_ComponentFlags;
  402. dstInfo.m_pPresetValue = srcInfo.m_pPresetValue;
  403. dstInfo.m_pPresetTimes = srcInfo.m_pPresetTimes;
  404. dstInfo.m_pRoot = srcInfo.m_pRoot;
  405. dstInfo.m_pShot = srcInfo.m_pShot;
  406. // Copy the transform info
  407. dstInfo.m_HeadPosition = srcInfo.m_HeadPosition;
  408. dstInfo.m_TransformWriteMode = srcInfo.m_TransformWriteMode;
  409. dstInfo.m_bManipulateInFalloff = srcInfo.m_bManipulateInFalloff;
  410. dstInfo.m_Transform = srcInfo.m_Transform;
  411. dstInfo.m_DeltaRotationLocal = srcInfo.m_DeltaRotationLocal;
  412. dstInfo.m_DeltaRotationParent = srcInfo.m_DeltaRotationParent;
  413. dstInfo.m_PivotPosition = srcInfo.m_PivotPosition;
  414. // Copy the data of the to attribute
  415. if ( srcInfo.m_ToAttrData.Size() > 0 )
  416. {
  417. dstInfo.m_ToAttrData.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
  418. srcInfo.m_ToAttrData.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  419. dstInfo.m_ToAttrData.Put( srcInfo.m_ToAttrData.PeekGet( 0 ), srcInfo.m_ToAttrData.GetBytesRemaining() );
  420. }
  421. // Copy the data of the from attribute
  422. if ( srcInfo.m_FromAttrData.Size() > 0 )
  423. {
  424. dstInfo.m_FromAttrData.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
  425. srcInfo.m_FromAttrData.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  426. dstInfo.m_FromAttrData.Put( srcInfo.m_FromAttrData.PeekGet( 0 ), srcInfo.m_FromAttrData.GetBytesRemaining() );
  427. }
  428. // If the recording layer had a raw data layer for the channel make a copy of it.
  429. if ( srcInfo.m_hRawDataLayer.Get() )
  430. {
  431. CDmeChannel *pChannel = srcInfo.m_Channel.Get();
  432. if ( pChannel )
  433. {
  434. CDmeLog *pLog = pChannel->GetLog();
  435. if ( pLog )
  436. {
  437. dstInfo.m_hRawDataLayer = pLog->AddNewLayer();
  438. dstInfo.m_hRawDataLayer->CopyLayer( srcInfo.m_hRawDataLayer );
  439. pLog->RemoveLayerFromTail();
  440. }
  441. }
  442. }
  443. }
  444. // Copy the paste data from the recording layer if it has stored it.
  445. CopyPasteData( m_ClipboardData, pRecordingLayer->m_ClipboardData );
  446. }
  447. virtual void Undo()
  448. {
  449. CDmeChannelModificationLayer* pModificationLayer = m_pRecordingMgr->GetModificationLayer();
  450. if ( pModificationLayer )
  451. {
  452. pModificationLayer->RemoveLastRecordingLayer();
  453. // If the modification layer is now empty, destroy it completely.
  454. if ( pModificationLayer->NumRecordingLayers() == 0 )
  455. {
  456. m_pRecordingMgr->FinishModificationLayer( false );
  457. }
  458. }
  459. }
  460. virtual void Redo()
  461. {
  462. m_pRecordingMgr->SetInRedo( true );
  463. // Create a new modification layer if needed.
  464. m_pRecordingMgr->StartModificationLayer( &m_TimeSelection, m_bInModificationLayer );
  465. // Add the recording layer to the modification layer.
  466. m_pRecordingMgr->StartLayerRecording( "AddRecordingLayerRedo", m_pPresetValuesDict, m_tHeadShotTime, m_ProceduralType, m_OperationFlags, m_pfnAddChannelCallback, m_pfnFinishChannelCallback );
  467. // Add the channels to the recording layer.
  468. int nChannels = m_ChannelInfo.Count();
  469. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  470. {
  471. ChannelInfo_t &srcInfo = m_ChannelInfo[ iChannel ];
  472. int nChannelIndex = m_pRecordingMgr->AddChannelToRecordingLayer( srcInfo.m_Channel.Get(), srcInfo.m_ComponentFlags, srcInfo.m_pRoot, srcInfo.m_pShot );
  473. if ( nChannelIndex >= 0 )
  474. {
  475. LayerChannelInfo_t &dstInfo = m_pRecordingMgr->m_pActiveRecordingLayer->m_LayerChannels[ nChannelIndex ];
  476. // Copy the transform info
  477. dstInfo.m_HeadPosition = srcInfo.m_HeadPosition;
  478. dstInfo.m_TransformWriteMode = srcInfo.m_TransformWriteMode;
  479. dstInfo.m_bManipulateInFalloff = srcInfo.m_bManipulateInFalloff;
  480. dstInfo.m_Transform = srcInfo.m_Transform;
  481. dstInfo.m_DeltaRotationLocal = srcInfo.m_DeltaRotationLocal;
  482. dstInfo.m_DeltaRotationParent = srcInfo.m_DeltaRotationParent;
  483. dstInfo.m_PivotPosition = srcInfo.m_PivotPosition;
  484. dstInfo.m_ComponentFlags = srcInfo.m_ComponentFlags;
  485. dstInfo.m_pPresetValue = srcInfo.m_pPresetValue;
  486. dstInfo.m_pPresetTimes = srcInfo.m_pPresetTimes;
  487. // Copy the data of the to attribute
  488. if ( srcInfo.m_ToAttrData.Size() > 0 )
  489. {
  490. dstInfo.m_ToAttrData.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
  491. srcInfo.m_ToAttrData.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  492. dstInfo.m_ToAttrData.Put( srcInfo.m_ToAttrData.PeekGet( 0 ), srcInfo.m_ToAttrData.GetBytesRemaining() );
  493. }
  494. // Copy the data of the from attribute
  495. if ( srcInfo.m_FromAttrData.Size() > 0 )
  496. {
  497. dstInfo.m_FromAttrData.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
  498. srcInfo.m_FromAttrData.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  499. dstInfo.m_FromAttrData.Put( srcInfo.m_FromAttrData.PeekGet( 0 ), srcInfo.m_FromAttrData.GetBytesRemaining() );
  500. }
  501. // If there there is a raw data layer make a copy of it.
  502. if ( srcInfo.m_hRawDataLayer.Get() )
  503. {
  504. CDmeChannel *pChannel = srcInfo.m_Channel.Get();
  505. if ( pChannel )
  506. {
  507. CDmeLog *pLog = pChannel->GetLog();
  508. if ( pLog )
  509. {
  510. dstInfo.m_hRawDataLayer = pLog->AddNewLayer();
  511. dstInfo.m_hRawDataLayer->CopyLayer( srcInfo.m_hRawDataLayer );
  512. pLog->RemoveLayerFromTail();
  513. }
  514. }
  515. }
  516. }
  517. }
  518. // Restore the clipboard data in the recording layer
  519. CopyPasteData( m_pRecordingMgr->m_pActiveRecordingLayer->m_ClipboardData, m_ClipboardData );
  520. m_pRecordingMgr->FinishLayerRecording( m_TimeSelection.m_flThreshold, true, false );
  521. m_pRecordingMgr->SetModificationLayerDirty();
  522. m_pRecordingMgr->SetInRedo( false );
  523. }
  524. private:
  525. struct ChannelInfo_t
  526. {
  527. CDmeHandle< CDmeChannel > m_Channel;
  528. CDmeHandle< CDmeLogLayer, HT_UNDO > m_hRawDataLayer;
  529. CUtlBuffer m_ToAttrData;
  530. CUtlBuffer m_FromAttrData;
  531. DmeTime_t m_HeadPosition;
  532. TransformWriteMode_t m_TransformWriteMode;
  533. bool m_bManipulateInFalloff;
  534. matrix3x4_t m_Transform;
  535. Quaternion m_DeltaRotationLocal;
  536. Quaternion m_DeltaRotationParent;
  537. Vector m_PivotPosition;
  538. LogComponents_t m_ComponentFlags;
  539. const CDmAttribute *m_pPresetValue;
  540. const CDmAttribute *m_pPresetTimes;
  541. CDmeClip *m_pRoot;
  542. CDmeClip *m_pShot;
  543. };
  544. CDmeChannelRecordingMgr *m_pRecordingMgr;
  545. DmeLog_TimeSelection_t m_TimeSelection;
  546. AttributeDict_t *m_pPresetValuesDict;
  547. DmeTime_t m_tHeadShotTime;
  548. int m_ProceduralType;
  549. int m_OperationFlags;
  550. bool m_bInModificationLayer;
  551. CUtlVector< ChannelInfo_t > m_ChannelInfo;
  552. CUtlVector< KeyValues * > m_ClipboardData;
  553. FnRecordChannelCallback m_pfnAddChannelCallback;
  554. FnRecordChannelCallback m_pfnFinishChannelCallback;
  555. };
  556. //-----------------------------------------------------------------------------
  557. // CUndoFinishModificationLayer
  558. //
  559. // Undo operation for finishing a modification layer, stores all of the
  560. // information required to reconstruct the modification layer, redo simply
  561. // finishes the modification layer again. Used both for saving and not saving
  562. // the changes in the modification layer when finishing. The implementation is
  563. // simply to use the functionality of the CUndoAddRecordingLayer to store and
  564. // re-create the recording layers of the modification layer.
  565. //
  566. //-----------------------------------------------------------------------------
  567. class CUndoFinishModificationLayer : public CUndoElement
  568. {
  569. public:
  570. CUndoFinishModificationLayer( const char *pUndoDesc, CDmeChannelRecordingMgr* pRecordingMgr, bool saveChanges )
  571. : CUndoElement( pUndoDesc )
  572. , m_pRecordingMgr( pRecordingMgr )
  573. , m_bSaveChanges( saveChanges )
  574. {
  575. Assert( m_pRecordingMgr );
  576. if ( m_pRecordingMgr )
  577. {
  578. CDmeChannelModificationLayer* pModificationLayer = pRecordingMgr->GetModificationLayer();
  579. if ( pModificationLayer )
  580. {
  581. // Save the data required to restore each of the recording layers.
  582. int nLayers = pModificationLayer->NumRecordingLayers();
  583. for ( int iLayer = 0; iLayer < nLayers; ++iLayer )
  584. {
  585. // Add a new undo operation for the recording layer
  586. CUndoAddRecordingLayer *pUndoLayer = new CUndoAddRecordingLayer( "Undo Recoding Layer", m_pRecordingMgr );
  587. m_RecordingLayers.AddToTail( pUndoLayer );
  588. // Save the data from the recording layer in the new undo operation
  589. CRecordingLayer &recordingLayer = pModificationLayer->GetRecordingLayer( iLayer );
  590. pUndoLayer->SaveRecordingLayerData( &recordingLayer );
  591. }
  592. }
  593. }
  594. }
  595. ~CUndoFinishModificationLayer()
  596. {
  597. int nLayers = m_RecordingLayers.Count();
  598. for ( int iLayer = 0; iLayer < nLayers; ++iLayer )
  599. {
  600. delete m_RecordingLayers[ iLayer ];
  601. m_RecordingLayers[ iLayer ] = NULL;
  602. }
  603. }
  604. virtual void Undo()
  605. {
  606. // Undoing a finish operation requires reconstructing each of the recording layers, so to undo
  607. // the modification layer finish operation we actually redo all of the recording layer operations.
  608. int nLayers = m_RecordingLayers.Count();
  609. for ( int iLayer = 0; iLayer < nLayers; ++iLayer )
  610. {
  611. Assert( m_RecordingLayers[ iLayer ] );
  612. if ( m_RecordingLayers[ iLayer ] )
  613. {
  614. m_RecordingLayers[ iLayer ]->Redo();
  615. }
  616. }
  617. }
  618. virtual void Redo()
  619. {
  620. // Redoing the modification layer finish is simply a matter of calling finish again, except
  621. // this time undo will be disabled. Note we never flatten the layers here because flatten
  622. // layers has its own redo and we do not remove layers when not saving changes.
  623. m_pRecordingMgr->SetInRedo( true );
  624. m_pRecordingMgr->FinishModificationLayer( m_bSaveChanges, false );
  625. m_pRecordingMgr->SetInRedo( false );
  626. }
  627. private:
  628. CDmeChannelRecordingMgr *m_pRecordingMgr;
  629. bool m_bSaveChanges;
  630. CUtlVector< CUndoAddRecordingLayer* > m_RecordingLayers;
  631. };
  632. //-----------------------------------------------------------------------------
  633. // CUndoSetTimeSelection
  634. //
  635. // Undo operation for changing setting the time selection. This correctly
  636. // updates both the standard time selection and the base time selection.
  637. //
  638. //-----------------------------------------------------------------------------
  639. class CUndoSetTimeSelection : public CUndoElement
  640. {
  641. public:
  642. CUndoSetTimeSelection( const char *pUndoDesc, CDmeChannelRecordingMgr* pRecordingMgr, const DmeLog_TimeSelection_t &newTS, const CUtlVector< TimeSelection_t > &oldBaseTS, const CUtlVector< TimeSelection_t > &newBaseTS )
  643. : CUndoElement( pUndoDesc )
  644. , m_pRecordingMgr( pRecordingMgr )
  645. , m_newTimeSelection( newTS.m_nTimes )
  646. , m_newLeftFalloffType( newTS.m_nFalloffInterpolatorTypes[ 0 ] )
  647. , m_newRightFalloffType( newTS.m_nFalloffInterpolatorTypes[ 1 ] )
  648. , m_newLeftInfinite( newTS.m_bInfinite[ 0 ] )
  649. , m_newRightInfinite( newTS.m_bInfinite[ 1 ] )
  650. {
  651. if ( m_pRecordingMgr )
  652. {
  653. const DmeLog_TimeSelection_t &orignalTimeSelection = m_pRecordingMgr->GetTimeSelection();
  654. m_originalTimeSelection = orignalTimeSelection.m_nTimes;
  655. m_originalLeftFalloffType = orignalTimeSelection.m_nFalloffInterpolatorTypes[ 0 ];
  656. m_originalRightFalloffType = orignalTimeSelection.m_nFalloffInterpolatorTypes[ 1 ];
  657. m_originalLeftInfinite = orignalTimeSelection.m_bInfinite[ 0 ];
  658. m_originalRightInfinite = orignalTimeSelection.m_bInfinite[ 1 ];
  659. m_newBaseTimeSelectionList = newBaseTS;
  660. m_originalBaseTimeSelectionList = oldBaseTS;
  661. }
  662. }
  663. virtual void Undo()
  664. {
  665. if ( m_pRecordingMgr )
  666. {
  667. m_pRecordingMgr->UpdateTimeSelection( m_originalTimeSelection, m_originalBaseTimeSelectionList, m_originalLeftFalloffType, m_originalRightFalloffType, m_originalLeftInfinite, m_originalRightInfinite );
  668. }
  669. }
  670. virtual void Redo()
  671. {
  672. if ( m_pRecordingMgr )
  673. {
  674. m_pRecordingMgr->UpdateTimeSelection( m_newTimeSelection, m_newBaseTimeSelectionList, m_newLeftFalloffType, m_newRightFalloffType, m_newLeftInfinite, m_newRightInfinite );
  675. }
  676. }
  677. private:
  678. CDmeChannelRecordingMgr *m_pRecordingMgr;
  679. CUtlVector< TimeSelection_t > m_newBaseTimeSelectionList;
  680. TimeSelection_t m_newTimeSelection;
  681. int m_newLeftFalloffType;
  682. int m_newRightFalloffType;
  683. bool m_newLeftInfinite;
  684. bool m_newRightInfinite;
  685. CUtlVector< TimeSelection_t > m_originalBaseTimeSelectionList;
  686. TimeSelection_t m_originalTimeSelection;
  687. int m_originalLeftFalloffType;
  688. int m_originalRightFalloffType;
  689. bool m_originalLeftInfinite;
  690. bool m_originalRightInfinite;
  691. };
  692. //-----------------------------------------------------------------------------
  693. //
  694. // CDmeChannelRecordingMgr
  695. //
  696. //-----------------------------------------------------------------------------
  697. //-----------------------------------------------------------------------------
  698. // Globals
  699. //-----------------------------------------------------------------------------
  700. static CDmeChannelRecordingMgr s_ChannelRecordingMgr;
  701. CDmeChannelRecordingMgr *g_pChannelRecordingMgr = &s_ChannelRecordingMgr;
  702. //-----------------------------------------------------------------------------
  703. // Constructor
  704. //-----------------------------------------------------------------------------
  705. CDmeChannelRecordingMgr::CDmeChannelRecordingMgr()
  706. {
  707. m_bSavedUndoState = false;
  708. m_bUseTimeSelection = false;
  709. m_bModificationLayerDirty = false;
  710. m_bModificationProcessing = false;
  711. m_bWantsToFinish = false;
  712. m_bFinishFlattenLayers = false;
  713. m_bModificationLayerEnabled = true;
  714. m_bInRedo = false;
  715. m_pActiveRecordingLayer = NULL;
  716. m_pModificationLayer = NULL;
  717. m_nProceduralType = PROCEDURAL_PRESET_NOT;
  718. m_pRevealTarget = NULL;
  719. m_RandomSeed = 0;
  720. m_TransformWriteMode = TRANSFORM_WRITE_MODE_TRANSFORM;
  721. }
  722. //-----------------------------------------------------------------------------
  723. // Purpose: Start a new recording layer, may not be done when there is already
  724. // and active recording layer.
  725. // Input : pUndoRedoDesc - String to be used as the description for the undo
  726. // and redo operations of the recording layer.
  727. // Input : operationType - Specification of the general operation which the
  728. // recording layer will perform.
  729. // Input : proceduralType - If the recording operation is a procedural
  730. // operation this may specify the specific type of procedural operation.
  731. //-----------------------------------------------------------------------------
  732. void CDmeChannelRecordingMgr::StartLayerRecording( const char * const pUndoRedoDesc, AttributeDict_t *pPresetValuesDict /*= NULL*/, DmeTime_t tHeadShotTime /*= DMETIME_INVALID*/, int proceduralType /*=PROCEDURAL_PRESET_NOT*/, int nFlags /* = 0 */, FnRecordChannelCallback pfnAddChannel /*= NULL*/, FnRecordChannelCallback pfnFinishChannel /*= NULL*/ )
  733. {
  734. g_pDataModel->StartUndo( pUndoRedoDesc, pUndoRedoDesc );
  735. m_bSavedUndoState = g_pDataModel->IsUndoEnabled();
  736. Assert( m_pActiveRecordingLayer == NULL );
  737. if ( m_pModificationLayer )
  738. {
  739. m_pActiveRecordingLayer = m_pModificationLayer->AddRecordingLayer();
  740. }
  741. else
  742. {
  743. m_pActiveRecordingLayer = new CRecordingLayer;
  744. }
  745. m_pActiveRecordingLayer->m_pPresetValuesDict = CopyAttributeDict( pPresetValuesDict );
  746. m_pActiveRecordingLayer->m_tHeadShotTime = tHeadShotTime;
  747. m_pActiveRecordingLayer->m_ProceduralType = proceduralType;
  748. m_pActiveRecordingLayer->m_OperationFlags = nFlags;
  749. m_pActiveRecordingLayer->m_pfnAddChannelCallback = pfnAddChannel;
  750. m_pActiveRecordingLayer->m_pfnFinishChannelCallback = pfnFinishChannel;
  751. m_pActiveRecordingLayer->m_OriginalTimes = m_TimeSelection.m_nTimes;
  752. m_pActiveRecordingLayer->m_BaseTimes = m_TimeSelection.m_nTimes;
  753. if ( m_bSavedUndoState == true )
  754. {
  755. CUndoAddRecordingLayer *pUndo = new CUndoAddRecordingLayer( "AddRecordingLayer", this );
  756. g_pDataModel->AddUndoElement( pUndo );
  757. m_pActiveRecordingLayer->m_pUndoOperation = pUndo;
  758. }
  759. g_pDataModel->SetUndoEnabled( false );
  760. }
  761. //-----------------------------------------------------------------------------
  762. // Purpose: Complete the current recording layer, there must be an active
  763. // recording layer.
  764. // Input : flThreshold - threshold value used in flattening the log layers from
  765. // the recording layer on to their proceeding log layers.
  766. // Input : bFlattenLayers - Flag indicating if the log layers resulting from
  767. // the record operation should be flattened on to the proceeding layer.
  768. // Input : bAllowFinishModification - Flag indicating if the recording layer is
  769. // allowed to finish the modification layer. Most recording operations
  770. // will not finish the modification layer, but some such as the drop
  771. // operation will finish the modification layer if this flag is true.
  772. //-----------------------------------------------------------------------------
  773. void CDmeChannelRecordingMgr::FinishLayerRecording( float flThreshhold, bool bFlattenLayers /*=true*/, bool bAllowFinishModification /*= true*/ )
  774. {
  775. Assert( m_pActiveRecordingLayer );
  776. bool finishModification = false;
  777. if ( m_pActiveRecordingLayer )
  778. {
  779. m_pActiveRecordingLayer->m_flThreshold = flThreshhold;
  780. m_pActiveRecordingLayer->m_flIntensity = m_TimeSelection.m_flIntensity;
  781. m_pActiveRecordingLayer->m_RecordingMode = m_TimeSelection.GetRecordingMode();
  782. m_pActiveRecordingLayer->m_RandomSeed = m_RandomSeed;
  783. if ( m_pActiveRecordingLayer->m_ProceduralType == PROCEDURAL_PRESET_NOT )
  784. {
  785. m_pActiveRecordingLayer->m_ProceduralType = GetProceduralType();
  786. }
  787. // Set the flag to for the modification layer to be completed if the operation is to drop the layer.
  788. if ( bAllowFinishModification && ( m_pActiveRecordingLayer->m_ProceduralType == PROCEDURAL_PRESET_DROP_LAYER ) )
  789. {
  790. finishModification = true;
  791. }
  792. // If the recording layer is a paste operation that is part of a modification layer it will need store the paste
  793. // data so that the operation can be correctly executed even if the contents of the clipboard have been changed.
  794. bool pasteOperation = ( m_pActiveRecordingLayer->m_ProceduralType == PROCEDURAL_PRESET_PASTE );
  795. if ( pasteOperation && ( m_pModificationLayer != NULL ) )
  796. {
  797. if ( m_pActiveRecordingLayer->m_ClipboardData.Count() == 0)
  798. {
  799. CUtlVector< KeyValues * > clipBoardList;
  800. g_pDataModel->GetClipboardData( clipBoardList );
  801. CopyClipboardDataForRecordingLayer( clipBoardList );
  802. }
  803. }
  804. // If time is advancing add an additional layer which will hold
  805. // the original recorded values not filtered by the time selection.
  806. if ( IsTimeAdvancing() && IsModificationLayerActive() )
  807. {
  808. int c = m_pActiveRecordingLayer->m_LayerChannels.Count();
  809. for ( int i = 0 ; i < c; ++i )
  810. {
  811. LayerChannelInfo_t &channelInfo = m_pActiveRecordingLayer->m_LayerChannels[ i ];
  812. if ( channelInfo.m_hRawDataLayer.Get() == NULL )
  813. {
  814. CDmeChannel *pChannel = channelInfo.m_Channel.Get();
  815. if ( !pChannel )
  816. continue;
  817. CDmeLog *pLog = pChannel->GetLog();
  818. Assert( pLog );
  819. if ( !pLog )
  820. continue;
  821. CDmeLogLayer *pTopLayer = pLog->GetLayer( pLog->GetTopmostLayer() );
  822. channelInfo.m_hRawDataLayer = pLog->AddNewLayer();
  823. channelInfo.m_hRawDataLayer->CopyLayer( pTopLayer );
  824. pLog->RemoveLayerFromTail();
  825. }
  826. }
  827. }
  828. // Save the information from the recording layer that will be required to reconstruct the recording
  829. // layer for the redo operation which was not available when the recording layer was created.
  830. if ( m_pActiveRecordingLayer->m_pUndoOperation )
  831. {
  832. m_pActiveRecordingLayer->m_pUndoOperation->SaveRecordingLayerData( m_pActiveRecordingLayer );
  833. }
  834. // Finalize the recording for all channels in the layer and detach the channels from the
  835. // recording layer. The channels will no longer know where they are within the recording
  836. // layer, but the recording layer will retain the list of channels it operated on.
  837. RemoveAllChannelsFromRecordingLayer( m_pActiveRecordingLayer, false );
  838. g_pDataModel->SetUndoEnabled( m_bSavedUndoState );
  839. if ( bFlattenLayers )
  840. {
  841. FlattenLayers( m_pActiveRecordingLayer );
  842. }
  843. // If there is no modification layer then the recording layer was allocated and should be destroyed.
  844. if ( m_pModificationLayer == NULL )
  845. {
  846. if ( !m_bInRedo )
  847. {
  848. RunFinishCallbacksOnRecordingLayer( m_pActiveRecordingLayer );
  849. }
  850. delete m_pActiveRecordingLayer;
  851. }
  852. if ( finishModification == false )
  853. {
  854. g_pDataModel->FinishUndo();
  855. }
  856. }
  857. m_pActiveRecordingLayer = NULL;
  858. m_nProceduralType = PROCEDURAL_PRESET_NOT;
  859. m_pRevealTarget = NULL;
  860. m_PasteTarget.RemoveAll();
  861. // If the finish modification layer flag was set, finish the modification layer. Some
  862. // recording operations such as the drop preset force the completion of the layer.
  863. if ( finishModification )
  864. {
  865. FinishModificationLayer();
  866. g_pDataModel->FinishUndo();
  867. }
  868. }
  869. //-----------------------------------------------------------------------------
  870. // Purpose: Cancel the current recording layer, losing all of its changes.
  871. //-----------------------------------------------------------------------------
  872. void CDmeChannelRecordingMgr::CancelLayerRecording()
  873. {
  874. if ( m_pActiveRecordingLayer )
  875. {
  876. RunFinishCallbacksOnRecordingLayer( m_pActiveRecordingLayer );
  877. // Detach all of the channels from the recording layer and and delete the associate log layers.
  878. RemoveAllChannelsFromRecordingLayer( m_pActiveRecordingLayer, !m_bSavedUndoState );
  879. if ( m_bSavedUndoState )
  880. {
  881. m_pActiveRecordingLayer = NULL;
  882. g_pDataModel->SetUndoEnabled( m_bSavedUndoState );
  883. g_pDataModel->AbortUndoableOperation();
  884. }
  885. else
  886. {
  887. if ( m_pModificationLayer )
  888. {
  889. m_pActiveRecordingLayer = NULL;
  890. CDisableUndoScopeGuard undosg;
  891. // If the modification layer is now empty, destroy it completely.
  892. if ( m_pModificationLayer->NumRecordingLayers() < 2 )
  893. {
  894. FinishModificationLayer( false );
  895. }
  896. else
  897. {
  898. // Remove the recording layer from the modification layer
  899. m_pModificationLayer->RemoveLastRecordingLayer();
  900. }
  901. }
  902. else
  903. {
  904. delete m_pActiveRecordingLayer;
  905. m_pActiveRecordingLayer = NULL;
  906. }
  907. }
  908. m_nProceduralType = PROCEDURAL_PRESET_NOT;
  909. m_pRevealTarget = NULL;
  910. m_PasteTarget.RemoveAll();
  911. }
  912. }
  913. //-----------------------------------------------------------------------------
  914. // Purpose: Creates a modification layer on which all further editing will
  915. // take place until EndModificationLayer() is called. If there is already an
  916. // active modification layer then the time selection of the active modification
  917. // layer will be updated, but a new modification layer will not be started.
  918. // Input : pTimeSelection - pointer to the active time selection which the
  919. // modification layer is to apply to.
  920. // Input : createLayer - flag indicating if a modification layer should be
  921. // created, if false the function may be used to update the current
  922. // time selection.
  923. //-----------------------------------------------------------------------------
  924. void CDmeChannelRecordingMgr::StartModificationLayer( const DmeLog_TimeSelection_t *pTimeSelection, bool createLayer /*= true*/ )
  925. {
  926. // If the modification layer has already been started just update the time parameters.
  927. if ( m_pModificationLayer != NULL )
  928. {
  929. if ( pTimeSelection )
  930. {
  931. m_TimeSelection = *pTimeSelection;
  932. m_TimeSelection.ResetTimeAdvancing();
  933. }
  934. return;
  935. }
  936. // Create the modification layer unless create flag is false.
  937. if ( createLayer && m_bModificationLayerEnabled )
  938. {
  939. m_pModificationLayer = new CDmeChannelModificationLayer();
  940. }
  941. // Set the time selection to provided time selection or reset the time selection
  942. // to the default values and disable its use if no time selection was provided.
  943. if ( pTimeSelection )
  944. {
  945. m_TimeSelection = *pTimeSelection;
  946. m_bUseTimeSelection = true;
  947. }
  948. else
  949. {
  950. m_TimeSelection = DmeLog_TimeSelection_t();
  951. m_bUseTimeSelection = false;
  952. }
  953. m_TimeSelection.ResetTimeAdvancing();
  954. }
  955. //-----------------------------------------------------------------------------
  956. // Purpose: Complete the current modification layer, applying the modifications
  957. // to the base log layers of the effected channels and destroying all of the
  958. // recording layer data contained within the modification layer.
  959. // Input : bSaveChanges - flag indicating if the changes within the
  960. // modification layer should be applied or discarded.
  961. // Input : bFlattenLayers - flag indicating if the log layers of the
  962. // modification should be flattened onto the base layer.
  963. //-----------------------------------------------------------------------------
  964. void CDmeChannelRecordingMgr::FinishModificationLayer( bool bSaveChanges, bool bFlattenLayers )
  965. {
  966. // Should never call finish modification layer while there is an active
  967. // recording layer. FinishLayerRecording() should be called first.
  968. Assert( m_pActiveRecordingLayer == NULL );
  969. if ( m_pActiveRecordingLayer != NULL )
  970. {
  971. return;
  972. }
  973. // If the modification layer has already been finished
  974. // is is already waiting to finish, ignore the request.
  975. if ( IsModificationLayerActive() == false )
  976. {
  977. m_bUseTimeSelection = false;
  978. m_TimeSelection.ResetTimeAdvancing();
  979. return;
  980. }
  981. // Make sure the modification layer is not dirty. If it is set the flag which specifies the
  982. // modification layer should be finished once the processing is complete. If we are not
  983. // going to save the changes ignore the fact that the layer is dirty and just finish it.
  984. if ( m_bModificationLayerDirty && bSaveChanges )
  985. {
  986. // If this assert is hit finish modification layer has been called twice without the
  987. // modification layer being processed or the flags have not been properly cleared.
  988. Assert( m_bWantsToFinish == false );
  989. m_bWantsToFinish = true;
  990. m_bFinishFlattenLayers = bFlattenLayers;
  991. }
  992. else
  993. {
  994. if ( g_pDataModel->IsUndoEnabled() )
  995. {
  996. g_pDataModel->StartUndo( "Finish Modification Layer", "Finish Modification Layer" );
  997. CUndoFinishModificationLayer *pUndo = new CUndoFinishModificationLayer( "FinishModificationLayer", this, bSaveChanges );
  998. g_pDataModel->AddUndoElement( pUndo );
  999. }
  1000. // Destroy the modification layer and the recording layers it contains.
  1001. if ( m_pModificationLayer )
  1002. {
  1003. // Complete the modification layer and flatten the channel log layers if requested.
  1004. m_pModificationLayer->Finish( bSaveChanges, bFlattenLayers, !m_bInRedo );
  1005. delete m_pModificationLayer;
  1006. m_pModificationLayer = NULL;
  1007. }
  1008. // Complete the undo operation for the modification layer
  1009. if ( g_pDataModel->IsUndoEnabled() )
  1010. {
  1011. g_pDataModel->FinishUndo();
  1012. }
  1013. // Reset the time selection information
  1014. m_bUseTimeSelection = false;
  1015. m_TimeSelection.ResetTimeAdvancing();
  1016. // Clear the finish flags
  1017. m_bWantsToFinish = false;
  1018. m_bFinishFlattenLayers = false;
  1019. m_bModificationLayerDirty = false;
  1020. }
  1021. }
  1022. //-----------------------------------------------------------------------------
  1023. // Purpose: Enable or disable use of the modification layer.
  1024. //-----------------------------------------------------------------------------
  1025. void CDmeChannelRecordingMgr::EnableModificationLayer( bool enable )
  1026. {
  1027. if ( enable )
  1028. {
  1029. m_bModificationLayerEnabled = true;
  1030. }
  1031. else
  1032. {
  1033. // Finish any active modification layer before disabling.
  1034. FinishModificationLayer();
  1035. m_bModificationLayerEnabled = false;
  1036. }
  1037. }
  1038. //-----------------------------------------------------------------------------
  1039. // Purpose: Get the current time selection as a CDmeTimeSelection element
  1040. // Output : timeSelection - reference to the time selection to be returned with
  1041. // the current time selection values.
  1042. //-----------------------------------------------------------------------------
  1043. void CDmeChannelRecordingMgr::GetTimeSelection( CDmeTimeSelection &timeSelection ) const
  1044. {
  1045. timeSelection.SetThreshold( m_TimeSelection.m_flThreshold );
  1046. timeSelection.SetCurrent( m_TimeSelection.m_nTimes );
  1047. timeSelection.SetFalloffInterpolatorType( 0, m_TimeSelection.m_nFalloffInterpolatorTypes[ 0 ] );
  1048. timeSelection.SetFalloffInterpolatorType( 1, m_TimeSelection.m_nFalloffInterpolatorTypes[ 1 ] );
  1049. timeSelection.SetResampleInterval( m_TimeSelection.m_nResampleInterval );
  1050. if ( m_TimeSelection.m_bInfinite[ 0 ] )
  1051. {
  1052. timeSelection.SetInfinite( 0 );
  1053. }
  1054. if ( m_TimeSelection.m_bInfinite[ 1 ] )
  1055. {
  1056. timeSelection.SetInfinite( 1 );
  1057. }
  1058. }
  1059. //-----------------------------------------------------------------------------
  1060. // Purpose: Get the current time selection
  1061. // Output : Returns a reference to the current time selection structure
  1062. //-----------------------------------------------------------------------------
  1063. const DmeLog_TimeSelection_t &CDmeChannelRecordingMgr::GetTimeSelection() const
  1064. {
  1065. return m_TimeSelection;
  1066. }
  1067. //-----------------------------------------------------------------------------
  1068. // Purpose: Set the time selection for the modification layer and re-apply all
  1069. // recording layers that are on the current modification layer with the new
  1070. // time selection. Must be done with active modification layer, but without an
  1071. // active recording layer.
  1072. //-----------------------------------------------------------------------------
  1073. void CDmeChannelRecordingMgr::SetTimeSelection( const DmeLog_TimeSelection_t &newTS, bool bUpdateBaseTimes )
  1074. {
  1075. // Can only set the time selection with the modification layer active but without any active recording layers.
  1076. if ( ( m_pModificationLayer == NULL ) || ( m_pActiveRecordingLayer != NULL ) )
  1077. {
  1078. Assert( m_pModificationLayer != NULL );
  1079. Assert( m_pActiveRecordingLayer == NULL );
  1080. return;
  1081. }
  1082. int nNumRecordingLayers = m_pModificationLayer->NumRecordingLayers();
  1083. CUtlVector< TimeSelection_t > newBaseTimeList;
  1084. CUtlVector< TimeSelection_t > oldBaseTimeList;
  1085. newBaseTimeList.SetCount( nNumRecordingLayers );
  1086. oldBaseTimeList.SetCount( nNumRecordingLayers );
  1087. for ( int iRecordingLayer = 0; iRecordingLayer < nNumRecordingLayers; ++iRecordingLayer )
  1088. {
  1089. CRecordingLayer &recordingLayer = m_pModificationLayer->GetRecordingLayer( iRecordingLayer );
  1090. TimeSelection_t newBaseTimes = recordingLayer.m_BaseTimes;
  1091. Assert( newBaseTimes[ TS_LEFT_HOLD ] >= newBaseTimes[ TS_LEFT_FALLOFF ] );
  1092. Assert( newBaseTimes[ TS_RIGHT_HOLD ] >= newBaseTimes[ TS_LEFT_HOLD ] );
  1093. Assert( newBaseTimes[ TS_RIGHT_FALLOFF ] >= newBaseTimes[ TS_RIGHT_HOLD ] );
  1094. // Update the base times by the same amount the time selection is to be changed.
  1095. if ( bUpdateBaseTimes )
  1096. {
  1097. // As long as the base times are being updated, the ratio of the duration of each section of the base time selection compared to
  1098. // the visible time selection should remain the same. Additionally movements of the hold region should operate such the source sample
  1099. // data appears static. This means for a change applied to the visible hold region, the change applied to the base time selection
  1100. // needs to be multiplied by the hold region ration. Although it would be desirable for the falloff regions to behave this way, if
  1101. // both the falloff time and the hold times are being modified this is not possible, so the hold region takes precedence.
  1102. DmeTime_t baseLeftTime = newBaseTimes[ TS_LEFT_HOLD ] - newBaseTimes[ TS_LEFT_FALLOFF ];
  1103. DmeTime_t baseHoldTime = newBaseTimes[ TS_RIGHT_HOLD ] - newBaseTimes[ TS_LEFT_HOLD ];
  1104. DmeTime_t baseRightTime = newBaseTimes[ TS_RIGHT_FALLOFF ] - newBaseTimes[ TS_RIGHT_HOLD ];
  1105. DmeTime_t leftTime = m_TimeSelection.m_nTimes[ TS_LEFT_HOLD ] - m_TimeSelection.m_nTimes[ TS_LEFT_FALLOFF ];
  1106. DmeTime_t holdTime = m_TimeSelection.m_nTimes[ TS_RIGHT_HOLD ] - m_TimeSelection.m_nTimes[ TS_LEFT_HOLD ];
  1107. DmeTime_t rightTime = m_TimeSelection.m_nTimes[ TS_RIGHT_FALLOFF ] - m_TimeSelection.m_nTimes[ TS_RIGHT_HOLD ];
  1108. float flLeftRatio = ( ( leftTime > DMETIME_ZERO ) && ( baseLeftTime > DMETIME_ZERO ) ) ? ( baseLeftTime / leftTime ) : 1.0f;
  1109. float flHoldRatio = ( ( holdTime > DMETIME_ZERO ) && ( baseHoldTime > DMETIME_ZERO ) ) ? ( baseHoldTime / holdTime ) : 1.0f;
  1110. float flRightRatio = ( ( rightTime > DMETIME_ZERO ) && ( baseRightTime > DMETIME_ZERO ) ) ? ( baseRightTime / rightTime ) : 1.0f;
  1111. // Apply the ratio adjusted delta time to the left and right hold times
  1112. DmeTime_t leftHoldDT = newTS.m_nTimes[ TS_LEFT_HOLD ] - m_TimeSelection.m_nTimes[ TS_LEFT_HOLD ];
  1113. DmeTime_t rightHoldDT = newTS.m_nTimes[ TS_RIGHT_HOLD ] - m_TimeSelection.m_nTimes[ TS_RIGHT_HOLD ];
  1114. newBaseTimes[ TS_LEFT_HOLD ] += ( leftHoldDT * flHoldRatio );
  1115. newBaseTimes[ TS_RIGHT_HOLD ] += ( rightHoldDT * flHoldRatio );
  1116. // Update the falloff times so that the ratios are preserved.
  1117. newBaseTimes[ TS_LEFT_FALLOFF ] = newBaseTimes[ TS_LEFT_HOLD ] - ( ( newTS.m_nTimes[ TS_LEFT_HOLD ] - newTS.m_nTimes[ TS_LEFT_FALLOFF ] ) * flLeftRatio );
  1118. newBaseTimes[ TS_RIGHT_FALLOFF ] = newBaseTimes[ TS_RIGHT_HOLD ] + ( ( newTS.m_nTimes[ TS_RIGHT_FALLOFF ] - newTS.m_nTimes[ TS_RIGHT_HOLD ] ) * flRightRatio );
  1119. // Make sure the time selection times remain in order.
  1120. newBaseTimes[ TS_LEFT_FALLOFF ] = MIN( newBaseTimes[ TS_LEFT_FALLOFF ], newBaseTimes[ TS_LEFT_HOLD ] - DMETIME_MINDELTA );
  1121. newBaseTimes[ TS_RIGHT_HOLD ] = MAX( newBaseTimes[ TS_RIGHT_HOLD ], newBaseTimes[ TS_LEFT_HOLD ] );
  1122. newBaseTimes[ TS_RIGHT_FALLOFF ] = MAX( newBaseTimes[ TS_RIGHT_FALLOFF ], newBaseTimes[ TS_RIGHT_HOLD ] + DMETIME_MINDELTA );
  1123. }
  1124. oldBaseTimeList[ iRecordingLayer ] = recordingLayer.m_BaseTimes;
  1125. newBaseTimeList[ iRecordingLayer ] = newBaseTimes;
  1126. recordingLayer.m_BaseTimes = newBaseTimes;
  1127. }
  1128. if ( g_pDataModel->IsUndoEnabled() )
  1129. {
  1130. CUndoSetTimeSelection *pUndo = new CUndoSetTimeSelection( "SetTimeSelection", this, newTS, oldBaseTimeList, newBaseTimeList );
  1131. g_pDataModel->AddUndoElement( pUndo );
  1132. }
  1133. // Set the new time selection for which the effects of the recording layers are to be applied.
  1134. m_TimeSelection.m_nTimes = newTS.m_nTimes;
  1135. m_TimeSelection.m_nFalloffInterpolatorTypes[ 0 ] = newTS.m_nFalloffInterpolatorTypes[ 0 ];
  1136. m_TimeSelection.m_nFalloffInterpolatorTypes[ 1 ] = newTS.m_nFalloffInterpolatorTypes[ 1 ];
  1137. m_TimeSelection.m_bInfinite[ 0 ] = newTS.m_bInfinite[ 0 ];
  1138. m_TimeSelection.m_bInfinite[ 1 ] = newTS.m_bInfinite[ 1 ];
  1139. m_bUseTimeSelection = true;
  1140. m_bModificationLayerDirty = true;
  1141. }
  1142. //-----------------------------------------------------------------------------
  1143. // Update the time selection state, this is used by undo
  1144. //-----------------------------------------------------------------------------
  1145. void CDmeChannelRecordingMgr::UpdateTimeSelection( const TimeSelection_t &timeSelection, const CUtlVector< TimeSelection_t > &baseTimeSelectionList, int leftFalloff, int rightFalloff, bool bLeftInfinite, bool bRightInfinite )
  1146. {
  1147. m_TimeSelection.m_nTimes = timeSelection;
  1148. m_TimeSelection.m_nFalloffInterpolatorTypes[ 0 ] = leftFalloff;
  1149. m_TimeSelection.m_nFalloffInterpolatorTypes[ 1 ] = rightFalloff;
  1150. m_TimeSelection.m_bInfinite[ 0 ] = bLeftInfinite;
  1151. m_TimeSelection.m_bInfinite[ 1 ] = bRightInfinite;
  1152. m_bUseTimeSelection = true;
  1153. m_bModificationLayerDirty = true;
  1154. int nNumRecordingLayers = m_pModificationLayer->NumRecordingLayers();
  1155. Assert( baseTimeSelectionList.Count() == nNumRecordingLayers );
  1156. if ( baseTimeSelectionList.Count() == nNumRecordingLayers )
  1157. {
  1158. for ( int iRecordingLayer = 0; iRecordingLayer < nNumRecordingLayers; ++iRecordingLayer )
  1159. {
  1160. CRecordingLayer &recordingLayer = m_pModificationLayer->GetRecordingLayer( iRecordingLayer );
  1161. recordingLayer.m_BaseTimes = baseTimeSelectionList[ iRecordingLayer ];
  1162. }
  1163. }
  1164. }
  1165. //-----------------------------------------------------------------------------
  1166. // Purpose: Start or continue processing of the recording layers within the
  1167. // modification layer.
  1168. // In/Out : recordingLayer - Input with the index of the recording layer to
  1169. // process, returns the index of the next recording layer to be
  1170. // processed.
  1171. // Output : proceduralType - returns the specific procedural preset type for
  1172. // procedural recording operations.
  1173. // Output : operationFlags - returns flags providing information about the
  1174. // operation of the recording layer.
  1175. // Output : randomSeed - returns the random seed used by the recording layer
  1176. // for procedural operations which depend on random values.
  1177. // Output : flIntensity - returns the intensity parameter of the recording layer
  1178. // which was processed.
  1179. // Output : Returns true if recording layer index is valid and the recording
  1180. // layer was processed, returns false if the recording layer index was
  1181. // out of range, which occurs when processing of all layers has been
  1182. // completed.
  1183. //-----------------------------------------------------------------------------
  1184. CRecordingLayer *CDmeChannelRecordingMgr::ProcessModificationLayer( int &recordingLayer )
  1185. {
  1186. // Do nothing if the modification layer does not require an update.
  1187. if ( !m_bModificationLayerDirty )
  1188. return NULL;
  1189. // Obviously the modification layer must exist in order to process it.
  1190. if ( m_pModificationLayer == NULL )
  1191. {
  1192. Assert( m_pModificationLayer );
  1193. return NULL;
  1194. }
  1195. // If all of the recording layers have been processed clear the dirty
  1196. // flag and return false to indicate no further processing is required.
  1197. if ( recordingLayer >= m_pModificationLayer->NumRecordingLayers() )
  1198. {
  1199. m_bModificationLayerDirty = false;
  1200. m_bModificationProcessing = false;
  1201. // If the flag specifying that the modification layer should be finished is set, call
  1202. // the finish function to flatten the layers and complete the modification layer.
  1203. if ( m_bWantsToFinish )
  1204. {
  1205. m_bWantsToFinish = false;
  1206. FinishModificationLayer( m_bFinishFlattenLayers );
  1207. }
  1208. return NULL;
  1209. }
  1210. // Perform initialization actions
  1211. if ( recordingLayer == 0 )
  1212. {
  1213. // Set the flag to indicate that the modification layer is currently being processed.
  1214. m_bModificationProcessing = true;
  1215. // Restore the modification log layer of each of the channels in the modification layer to their
  1216. // original state before any recording layers were applied by copying the base layer.
  1217. m_pModificationLayer->WipeChannelModifications();
  1218. }
  1219. // Get the current recording layer and perform the initial update for applying it to the modification layer.
  1220. CRecordingLayer &recLayer = m_pModificationLayer->GetRecordingLayer( recordingLayer++ );
  1221. ApplyRecordingLayer( recLayer );
  1222. return &recLayer;
  1223. }
  1224. //-----------------------------------------------------------------------------
  1225. // Purpose: Complete the modification layer processing of the current recording
  1226. // layer.
  1227. //-----------------------------------------------------------------------------
  1228. void CDmeChannelRecordingMgr::CompleteModificationProcessing()
  1229. {
  1230. Assert( m_pActiveRecordingLayer );
  1231. // Record the channel operations if the operation mode requires it. Paste does not
  1232. // as the values are applied to the channel outside of the record mechanism.
  1233. if ( m_pActiveRecordingLayer->m_ProceduralType != PROCEDURAL_PRESET_PASTE )
  1234. {
  1235. int c = m_pActiveRecordingLayer->m_LayerChannels.Count();
  1236. for ( int i = 0 ; i < c; ++i )
  1237. {
  1238. LayerChannelInfo_t &channelInfo = m_pActiveRecordingLayer->m_LayerChannels[ i ];
  1239. CDmeChannel *pChannel = channelInfo.m_Channel.Get();
  1240. if ( pChannel )
  1241. {
  1242. pChannel->Operate();
  1243. }
  1244. }
  1245. }
  1246. // Finish the record operation by detaching the channels from the record
  1247. // layer, returning them to play mode, and flattening the newly created layer.
  1248. RemoveAllChannelsFromRecordingLayer( m_pActiveRecordingLayer, false );
  1249. FlattenLayers( m_pActiveRecordingLayer );
  1250. // Reset the active recording layer to NULL since the recording
  1251. // layer being applied is not actually being recorded.
  1252. m_pActiveRecordingLayer = NULL;
  1253. m_nProceduralType = PROCEDURAL_PRESET_NOT;
  1254. m_pRevealTarget = NULL;
  1255. m_PasteTarget.RemoveAll();
  1256. }
  1257. //-----------------------------------------------------------------------------
  1258. // Purpose: Apply the effects of the recording layer to its channels with the
  1259. // active time selection.
  1260. // Input : recordingLayer - Reference to the recording layer to apply.
  1261. // Output : Returns the procedural type of the recording layer.
  1262. //-----------------------------------------------------------------------------
  1263. bool CDmeChannelRecordingMgr::ApplyRecordingLayer( CRecordingLayer &recordingLayer )
  1264. {
  1265. // An existing recording layer cannot be applied to the the modification
  1266. // layer while there is currently an active recording layer.
  1267. if ( m_pActiveRecordingLayer != NULL )
  1268. {
  1269. Assert( m_pActiveRecordingLayer == NULL );
  1270. return false;
  1271. }
  1272. // Temporarily set the recording layer being re-applied as the active recording layer, this
  1273. // is done because the channel Operate() function assumes an active recording channel.
  1274. m_pActiveRecordingLayer = &recordingLayer;
  1275. m_nProceduralType = recordingLayer.m_ProceduralType;
  1276. m_RandomSeed = recordingLayer.m_RandomSeed;
  1277. m_TimeSelection.m_flIntensity = recordingLayer.m_flIntensity;
  1278. m_TimeSelection.SetRecordingMode( recordingLayer.m_RecordingMode );
  1279. // Iterate through the channels in the recording layer, add a new layer to
  1280. // the log of each channel and put the channel in recording mode so that
  1281. // the operation of the layer can be recorded into the log.
  1282. int c = recordingLayer.m_LayerChannels.Count();
  1283. for ( int i = 0 ; i < c; ++i )
  1284. {
  1285. LayerChannelInfo_t &channelInfo = recordingLayer.m_LayerChannels[ i ];
  1286. CDmeChannel *pChannel = channelInfo.m_Channel.Get();
  1287. if ( !pChannel )
  1288. continue;
  1289. CDmeLog *pLog = pChannel->GetLog();
  1290. Assert( pLog );
  1291. if ( !pLog )
  1292. continue;
  1293. // Add the new layer to the log and assign the channel
  1294. // its location within the current recoding layer.
  1295. CDmeLogLayer* pNewLayer = pLog->AddNewLayer();
  1296. if ( pNewLayer == NULL )
  1297. continue;
  1298. pNewLayer->SetInfinite( m_TimeSelection.m_bInfinite[ 0 ], m_TimeSelection.m_bInfinite[ 1 ] );
  1299. pChannel->SetRecordLayerIndex( i );
  1300. // If the recording operation was an attribute over time, use the stored recorded
  1301. // log data to re-apply the recording operation for the current time frame.
  1302. if ( channelInfo.m_hRawDataLayer.Get() )
  1303. {
  1304. DmeLog_TimeSelection_t localTimeSelection = m_TimeSelection;
  1305. localTimeSelection.m_flIntensity = 1.0f;
  1306. for ( int i = 0; i < TS_TIME_COUNT; ++i )
  1307. {
  1308. localTimeSelection.m_nTimes[i] = channelInfo.m_ClipStack.ToChildMediaTime( localTimeSelection.m_nTimes[i], false );
  1309. }
  1310. pLog->BlendLayersUsingTimeSelection( pLog->GetLayer( channelInfo.m_BaseLayer ), channelInfo.m_hRawDataLayer, pNewLayer, localTimeSelection, true, true, true, DMETIME_ZERO );
  1311. // Do not put the channel into record mode.
  1312. continue;
  1313. }
  1314. if ( recordingLayer.m_ProceduralType == PROCEDURAL_PRESET_NOT )
  1315. {
  1316. // If the recording layer's operation was not a procedural operation, restore the value of
  1317. // the source attribute to the recording value before re-recording with the new time frame.
  1318. CDmAttribute *pFromAttr = pChannel->GetFromAttribute();
  1319. if ( pFromAttr )
  1320. {
  1321. channelInfo.m_FromAttrData.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  1322. if ( IsArrayType( pFromAttr->GetType() ) )
  1323. {
  1324. pFromAttr->UnserializeElement( pChannel->GetFromArrayIndex(), channelInfo.m_FromAttrData );
  1325. }
  1326. else
  1327. {
  1328. pFromAttr->Unserialize( channelInfo.m_FromAttrData );
  1329. }
  1330. }
  1331. CDmAttribute *pToAttr = pChannel->GetToAttribute();
  1332. if ( pToAttr )
  1333. {
  1334. channelInfo.m_ToAttrData.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  1335. if ( IsArrayType( pToAttr->GetType() ) )
  1336. {
  1337. pToAttr->UnserializeElement( pChannel->GetToArrayIndex(), channelInfo.m_ToAttrData );
  1338. }
  1339. else
  1340. {
  1341. pToAttr->Unserialize( channelInfo.m_ToAttrData );
  1342. }
  1343. }
  1344. // Restore the transform, delta rotation, and pivot values in the control to the values used in the original operation.
  1345. CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( pChannel->GetFromElement() );
  1346. if ( pTransformControl )
  1347. {
  1348. pTransformControl->SetManipulationTransform( channelInfo.m_Transform );
  1349. pTransformControl->SetManipulationRotationLocal( channelInfo.m_DeltaRotationLocal );
  1350. pTransformControl->SetManipulationRotationParent( channelInfo.m_DeltaRotationParent );
  1351. pTransformControl->SetManipulationPivot( channelInfo.m_PivotPosition );
  1352. }
  1353. }
  1354. // Record the operation.
  1355. pChannel->SetMode( CM_RECORD );
  1356. }
  1357. return true;
  1358. }
  1359. //-----------------------------------------------------------------------------
  1360. // Purpose: Store the data of the provided attribute in the channel's recording
  1361. // data.
  1362. // Input : nChannelIndex - Index of the channel within the recording layer's
  1363. // array of active channels.
  1364. // Input : fromAttr - flag indicating if the data of the from attribute is to
  1365. // be stored ( true ) or the data of the to attribute is to be stored
  1366. // ( false ).
  1367. //-----------------------------------------------------------------------------
  1368. void CDmeChannelRecordingMgr::StoreChannelAttributeData( int nChannelIndex, bool fromAttr )
  1369. {
  1370. Assert( m_pActiveRecordingLayer );
  1371. if ( m_pActiveRecordingLayer )
  1372. {
  1373. LayerChannelInfo_t& info = m_pActiveRecordingLayer->m_LayerChannels[ nChannelIndex ];
  1374. CDmeChannel *pChannel = info.m_Channel.Get();
  1375. // The data from the provided attribute may be stored in either the to or from attribute
  1376. // data for the channel, select the appropriate data buffer based on selection flag.
  1377. CUtlBuffer *pBuffer = fromAttr ? &info.m_FromAttrData : &info.m_ToAttrData;
  1378. CDmAttribute *pAttr = fromAttr ? pChannel->GetFromAttribute() : pChannel->GetToAttribute();
  1379. if ( pAttr )
  1380. {
  1381. // Clear the buffer, we only want to store a single value.
  1382. pBuffer->Clear();
  1383. // If storing the to attribute data, make sure it is current and has the
  1384. // actual value of the log, not the control default value if the log is empty.
  1385. if ( !fromAttr )
  1386. {
  1387. pChannel->Play( true );
  1388. }
  1389. if ( IsArrayType( pAttr->GetType() ) )
  1390. {
  1391. int nArrayIndex = fromAttr ? pChannel->GetFromArrayIndex() : pChannel->GetToArrayIndex();
  1392. pAttr->SerializeElement( nArrayIndex, *pBuffer );
  1393. }
  1394. else
  1395. {
  1396. pAttr->Serialize( *pBuffer );
  1397. }
  1398. }
  1399. // If saving the from attribute, save the transform, delta rotation and pivot information.
  1400. if ( fromAttr )
  1401. {
  1402. CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( pChannel->GetFromElement() );
  1403. if ( pTransformControl )
  1404. {
  1405. pTransformControl->GetManipulationTransform( info.m_Transform );
  1406. pTransformControl->GetManipulationRotationLocal( info.m_DeltaRotationLocal );
  1407. pTransformControl->GetManipulationRotationParent( info.m_DeltaRotationParent );
  1408. pTransformControl->GetManipulationPivot( info.m_PivotPosition );
  1409. }
  1410. }
  1411. }
  1412. }
  1413. //-----------------------------------------------------------------------------
  1414. // Purpose: Adds a channel to the recording layer
  1415. // Input : pChannel - pointer to the channel to be added to the recording
  1416. // layer.
  1417. // Input : componentFlags - flags specifying which components of the channel
  1418. // are to be recorded.
  1419. // Input : pRoot - pointer to the current root clip ( movie )
  1420. // Input : pShot - pointer to the current shot
  1421. // Output : Returns - Index of the location in the recording layer's array of
  1422. // channel information to which the new channel was assigned.
  1423. //-----------------------------------------------------------------------------
  1424. int CDmeChannelRecordingMgr::AddChannelToRecordingLayer( CDmeChannel *pChannel, LogComponents_t componentFlags, CDmeClip *pRoot, CDmeClip *pShot )
  1425. {
  1426. Assert( pChannel );
  1427. if ( pChannel == NULL )
  1428. return -1;
  1429. // The channel must not already be in an active recording layer.
  1430. Assert( pChannel->GetRecordLayerIndex() == -1 );
  1431. // There must be an active recording layer before channels may be added.
  1432. Assert( m_pActiveRecordingLayer );
  1433. if ( m_pActiveRecordingLayer == NULL )
  1434. return -1;
  1435. CDmeLog *pLog = pChannel->GetLog();
  1436. if ( !pLog )
  1437. return -1;
  1438. // If specified call the add channel callback before adding the channel to the recording layer.
  1439. if ( !m_bInRedo && ( m_pActiveRecordingLayer->m_pfnAddChannelCallback ) )
  1440. {
  1441. CEnableUndoScopeGuard undosg;
  1442. m_pActiveRecordingLayer->m_pfnAddChannelCallback( pChannel );
  1443. }
  1444. int nRecordLayerIndex = m_pActiveRecordingLayer->m_LayerChannels.AddToTail();
  1445. LayerChannelInfo_t& info = m_pActiveRecordingLayer->m_LayerChannels[nRecordLayerIndex];
  1446. info.m_Channel = pChannel;
  1447. info.m_pRoot = pRoot;
  1448. info.m_pShot = pShot;
  1449. info.m_ComponentFlags = componentFlags;
  1450. info.m_HeadPosition = pChannel->GetCurrentTime();
  1451. info.m_TransformWriteMode = m_TransformWriteMode;
  1452. info.m_bManipulateInFalloff = m_TimeSelection.m_bManipulateInFalloff;
  1453. if ( !m_bInRedo && pLog->IsEmpty() )
  1454. {
  1455. CEnableUndoScopeGuard undosg;
  1456. pLog->SetKey( pChannel->GetCurrentTime(), pChannel->GetFromAttribute(), pChannel->GetFromArrayIndex() );
  1457. }
  1458. // Add the channel to the modification layer, which results in a new layer being
  1459. // added to the log on which subsequent modifications to the log will take place.
  1460. if ( m_pModificationLayer )
  1461. {
  1462. info.m_ModLayerIndex = m_pModificationLayer->AddChannel( pChannel, m_bSavedUndoState );
  1463. }
  1464. // Store the index of the current top most layer, this is the modification layer
  1465. // which was just added. When flatting the recording layer it will be flattened
  1466. // only to the modification layer, not all the way to the base layer of the log.
  1467. info.m_BaseLayer = pLog->GetTopmostLayer();
  1468. if ( pRoot )
  1469. {
  1470. if ( !pChannel->BuildClipStack( &info.m_ClipStack, pRoot, pShot ) )
  1471. {
  1472. m_pActiveRecordingLayer->m_LayerChannels.Remove( nRecordLayerIndex );
  1473. return -1;
  1474. }
  1475. }
  1476. // Store the index of the the channel in the recording layer for obtaining
  1477. // access to the channel info in the recording layer from the channel.
  1478. pChannel->SetRecordLayerIndex( nRecordLayerIndex );
  1479. // Store the value of the To attribute before recording starts
  1480. // to use as a reference value when re-applying the operation.
  1481. StoreChannelAttributeData( nRecordLayerIndex, false );
  1482. bool bWasUndoEnabled = false;
  1483. if ( m_bSavedUndoState )
  1484. {
  1485. bWasUndoEnabled = g_pDataModel->IsUndoEnabled();
  1486. g_pDataModel->SetUndoEnabled( true );
  1487. }
  1488. CDmeLogLayer *pNewLayer = pLog->AddNewLayer();
  1489. if ( pNewLayer )
  1490. {
  1491. pNewLayer->SetInfinite( m_TimeSelection.m_bInfinite[ 0 ], m_TimeSelection.m_bInfinite[ 1 ] );
  1492. }
  1493. if ( m_bSavedUndoState )
  1494. {
  1495. g_pDataModel->SetUndoEnabled( bWasUndoEnabled );
  1496. }
  1497. pChannel->SetMode( CM_RECORD );
  1498. return nRecordLayerIndex;
  1499. }
  1500. //-----------------------------------------------------------------------------
  1501. // Explicitly set the clipboard data for the active recording layer
  1502. //-----------------------------------------------------------------------------
  1503. void CDmeChannelRecordingMgr::CopyClipboardDataForRecordingLayer( const CUtlVector< KeyValues * > &keyValuesList )
  1504. {
  1505. if ( m_pActiveRecordingLayer == NULL )
  1506. return;
  1507. // Destroy any existing clipboard data
  1508. DestroyPasteData( m_pActiveRecordingLayer->m_ClipboardData );
  1509. // Copy the new clipboard data
  1510. CopyPasteData( m_pActiveRecordingLayer->m_ClipboardData, keyValuesList );
  1511. }
  1512. //-----------------------------------------------------------------------------
  1513. // Purpose: Removes all channels from the recording layer
  1514. // Input : pRecordingLayer - Pointer to the recording layer from which all the
  1515. // channel information is to be removed.
  1516. //-----------------------------------------------------------------------------
  1517. void CDmeChannelRecordingMgr::RemoveAllChannelsFromRecordingLayer( CRecordingLayer *pRecordingLayer, bool destroyLogLayers )
  1518. {
  1519. Assert( pRecordingLayer );
  1520. if ( pRecordingLayer == NULL )
  1521. return;
  1522. int c = pRecordingLayer->m_LayerChannels.Count();
  1523. for ( int i = 0 ; i < c; ++i )
  1524. {
  1525. CDmeChannel *pChannel = pRecordingLayer->m_LayerChannels[ i ].m_Channel.Get();
  1526. if ( !pChannel )
  1527. continue;
  1528. CDmeLog *pLog = pChannel->GetLog();
  1529. if ( pLog )
  1530. {
  1531. if ( IsUsingTimeSelection() )
  1532. {
  1533. // Computes local times for the time selection
  1534. DmeLog_TimeSelection_t timeSelection;
  1535. GetLocalTimeSelection( timeSelection, pChannel->GetRecordLayerIndex() );
  1536. pLog->FinishTimeSelection( pChannel->GetCurrentTime(), timeSelection );
  1537. }
  1538. // Release recording layer from the log.
  1539. if ( destroyLogLayers )
  1540. {
  1541. pLog->RemoveLayerFromTail();
  1542. }
  1543. }
  1544. pChannel->SetRecordLayerIndex( -1 );
  1545. pChannel->SetMode( CM_PLAY );
  1546. }
  1547. }
  1548. //-----------------------------------------------------------------------------
  1549. // Flattens recorded layers into the base layer
  1550. //-----------------------------------------------------------------------------
  1551. void CDmeChannelRecordingMgr::FlattenLayers( CRecordingLayer *pRecordingLayer )
  1552. {
  1553. Assert( pRecordingLayer );
  1554. if ( pRecordingLayer == NULL )
  1555. return;
  1556. int nFlags = 0;
  1557. if ( IsUsingDetachedTimeSelection() && IsTimeAdvancing() )
  1558. {
  1559. nFlags |= CDmeLog::FLATTEN_NODISCONTINUITY_FIXUP;
  1560. }
  1561. int c = pRecordingLayer->m_LayerChannels.Count();
  1562. for ( int i = 0 ; i < c; ++i )
  1563. {
  1564. LayerChannelInfo_t &channelInfo = pRecordingLayer->m_LayerChannels[ i ];
  1565. CDmeChannel *pChannel = channelInfo.m_Channel.Get();
  1566. if ( !pChannel )
  1567. continue;
  1568. CDmeLog *pLog = pChannel->GetLog();
  1569. Assert( pLog );
  1570. if ( !pLog )
  1571. continue;
  1572. if ( channelInfo.m_BaseLayer < 0 )
  1573. continue;
  1574. pLog->FlattenLayers( pRecordingLayer->m_flThreshold, nFlags, channelInfo.m_BaseLayer );
  1575. }
  1576. }
  1577. //-----------------------------------------------------------------------------
  1578. // Calls the callback for all channels in the specified recording layer
  1579. //-----------------------------------------------------------------------------
  1580. void CDmeChannelRecordingMgr::RunFinishCallbacksOnRecordingLayer( CRecordingLayer *pRecordingLayer )
  1581. {
  1582. if ( pRecordingLayer == NULL )
  1583. return;
  1584. if ( pRecordingLayer->m_pfnFinishChannelCallback == NULL )
  1585. return;
  1586. int nNumChannels = pRecordingLayer->m_LayerChannels.Count();
  1587. for ( int iChannel = 0; iChannel < nNumChannels; ++iChannel )
  1588. {
  1589. LayerChannelInfo_t &channelInfo = pRecordingLayer->m_LayerChannels[ iChannel ];
  1590. CDmeChannel *pChannel = channelInfo.m_Channel.Get();
  1591. if ( pChannel == NULL )
  1592. continue;
  1593. pRecordingLayer->m_pfnFinishChannelCallback( pChannel );
  1594. }
  1595. }
  1596. //-----------------------------------------------------------------------------
  1597. // Used to iterate over all channels currently being recorded
  1598. //-----------------------------------------------------------------------------
  1599. int CDmeChannelRecordingMgr::GetLayerRecordingChannelCount()
  1600. {
  1601. if ( m_pActiveRecordingLayer )
  1602. {
  1603. return m_pActiveRecordingLayer->m_LayerChannels.Count();
  1604. }
  1605. return 0;
  1606. }
  1607. CDmeChannel* CDmeChannelRecordingMgr::GetLayerRecordingChannel( int nIndex )
  1608. {
  1609. if ( m_pActiveRecordingLayer )
  1610. {
  1611. Assert( nIndex < m_pActiveRecordingLayer->m_LayerChannels.Count() );
  1612. if ( nIndex < m_pActiveRecordingLayer->m_LayerChannels.Count() )
  1613. {
  1614. return m_pActiveRecordingLayer->m_LayerChannels[ nIndex ].m_Channel.Get();
  1615. }
  1616. }
  1617. return NULL;
  1618. }
  1619. //-----------------------------------------------------------------------------
  1620. // Computes time selection info in log time for a particular recorded channel
  1621. //-----------------------------------------------------------------------------
  1622. void CDmeChannelRecordingMgr::GetLocalTimeSelection( DmeLog_TimeSelection_t& selection, int nIndex )
  1623. {
  1624. Assert( m_bUseTimeSelection );
  1625. Assert( m_pActiveRecordingLayer );
  1626. if ( m_pActiveRecordingLayer )
  1627. {
  1628. LayerChannelInfo_t& info = m_pActiveRecordingLayer->m_LayerChannels[nIndex];
  1629. CDmeChannel *pChannel = info.m_Channel.Get();
  1630. Assert( pChannel );
  1631. if ( pChannel == NULL )
  1632. return;
  1633. selection = m_TimeSelection;
  1634. for ( int i = 0; i < TS_TIME_COUNT; ++i )
  1635. {
  1636. selection.m_nTimes[i] = info.m_ClipStack.ToChildMediaTime( selection.m_nTimes[i], false );
  1637. }
  1638. selection.m_pPresetValue = info.m_pPresetValue;
  1639. selection.m_pPresetTimes = info.m_pPresetTimes;
  1640. selection.m_tHeadPosition = info.m_HeadPosition;
  1641. selection.m_TransformWriteMode = info.m_TransformWriteMode;
  1642. selection.m_nComponentFlags = info.m_ComponentFlags;
  1643. selection.m_bManipulateInFalloff = info.m_bManipulateInFalloff;
  1644. // If the time selection is marked as infinite, make sure it extents past the ends of the log
  1645. CDmeLog *pLog = pChannel->GetLog();
  1646. if ( pLog && selection.m_bInfinite[ 0 ] )
  1647. {
  1648. selection.m_nTimes[ TS_LEFT_HOLD ] = MIN( pLog->GetBeginTime() , selection.m_nTimes[ TS_LEFT_HOLD ] );
  1649. selection.m_nTimes[ TS_LEFT_FALLOFF ] = selection.m_nTimes[ TS_LEFT_HOLD ];
  1650. }
  1651. if ( pLog && selection.m_bInfinite[ 1 ] )
  1652. {
  1653. selection.m_nTimes[ TS_RIGHT_HOLD ] = MAX( pLog->GetEndTime(), selection.m_nTimes[ TS_RIGHT_HOLD ] );
  1654. selection.m_nTimes[ TS_RIGHT_FALLOFF ] = selection.m_nTimes[ TS_RIGHT_HOLD ];
  1655. }
  1656. // If the modification layer is currently being processed set the pointer to the channel's to attribute
  1657. // to be used as the old head position, this is required because the value of the head position now may
  1658. // not be what it was when the recording first took place.
  1659. if ( m_bModificationProcessing )
  1660. {
  1661. CDmAttribute *pAttr = pChannel->GetToAttribute();
  1662. if ( pAttr )
  1663. {
  1664. selection.m_pOldHeadValue = pAttr;
  1665. if ( IsArrayType( pAttr->GetType() ) )
  1666. {
  1667. selection.m_OldHeadValueIndex = pChannel->GetToArrayIndex();
  1668. }
  1669. }
  1670. }
  1671. }
  1672. }
  1673. //-----------------------------------------------------------------------------
  1674. // Get the index of the modification base layer for the specified channel
  1675. // within the current recording layer.
  1676. //-----------------------------------------------------------------------------
  1677. int CDmeChannelRecordingMgr::GetModificationBaseLayer( int nIndex )
  1678. {
  1679. Assert( m_pActiveRecordingLayer );
  1680. if ( m_pActiveRecordingLayer )
  1681. {
  1682. LayerChannelInfo_t& info = m_pActiveRecordingLayer->m_LayerChannels[ nIndex ];
  1683. return info.m_BaseLayer;
  1684. }
  1685. return -1;
  1686. }
  1687. //-----------------------------------------------------------------------------
  1688. // Methods which control various aspects of recording
  1689. //-----------------------------------------------------------------------------
  1690. void CDmeChannelRecordingMgr::UpdateTimeAdvancing( bool bPaused, DmeTime_t tCurTime )
  1691. {
  1692. Assert( m_bUseTimeSelection );
  1693. Assert( m_pActiveRecordingLayer );
  1694. if ( !bPaused && !m_TimeSelection.IsTimeAdvancing() && m_pActiveRecordingLayer )
  1695. {
  1696. m_TimeSelection.StartTimeAdvancing();
  1697. // blow away logs after curtime
  1698. int nCount = m_pActiveRecordingLayer->m_LayerChannels.Count();
  1699. for ( int i = 0; i < nCount; ++i )
  1700. {
  1701. LayerChannelInfo_t& info = m_pActiveRecordingLayer->m_LayerChannels[i];
  1702. DmeTime_t t = info.m_ClipStack.ToChildMediaTime( tCurTime, false );
  1703. info.m_Channel->GetLog()->RemoveKeys( t, DMETIME_MAXTIME );
  1704. }
  1705. }
  1706. }
  1707. //-----------------------------------------------------------------------------
  1708. // Update the head positions of all of the channels in the active recording
  1709. // layer. The input time should be a global time which will be converted to the
  1710. // local time for each channel.
  1711. //-----------------------------------------------------------------------------
  1712. void CDmeChannelRecordingMgr::UpdateRecordingChannelHeadPositions( DmeTime_t tCurTime )
  1713. {
  1714. Assert( m_pActiveRecordingLayer );
  1715. if ( m_pActiveRecordingLayer )
  1716. {
  1717. int nChannels = m_pActiveRecordingLayer->m_LayerChannels.Count();
  1718. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  1719. {
  1720. LayerChannelInfo_t &info = m_pActiveRecordingLayer->m_LayerChannels[ iChannel ];
  1721. DmeTime_t channelTime = info.m_ClipStack.ToChildMediaTime( tCurTime, false );
  1722. if ( info.m_HeadPosition != channelTime )
  1723. {
  1724. info.m_HeadPosition = channelTime;
  1725. CDmeChannel *pChannel = info.m_Channel.Get();
  1726. if ( pChannel )
  1727. {
  1728. pChannel->SetCurrentTime( channelTime );
  1729. }
  1730. // Update the stored To attribute value to match the value at the new head position.
  1731. StoreChannelAttributeData( iChannel, false );
  1732. }
  1733. }
  1734. }
  1735. }
  1736. void CDmeChannelRecordingMgr::UpdateRecordingTimeSelectionTimes( const DmeLog_TimeSelection_t& timeSelection )
  1737. {
  1738. Assert( m_pActiveRecordingLayer );
  1739. m_TimeSelection.m_nTimes = timeSelection.m_nTimes;
  1740. for ( int i = 0; i < 2; ++i )
  1741. {
  1742. m_TimeSelection.m_nFalloffInterpolatorTypes[ i ] = timeSelection.m_nFalloffInterpolatorTypes[ i ];
  1743. m_TimeSelection.m_bInfinite[ i ] = timeSelection.m_bInfinite[ i ];
  1744. }
  1745. m_TimeSelection.m_nResampleInterval = timeSelection.m_nResampleInterval;
  1746. }
  1747. void CDmeChannelRecordingMgr::SetIntensityOnAllLayers( float flIntensity )
  1748. {
  1749. m_TimeSelection.m_flIntensity = flIntensity;
  1750. }
  1751. void CDmeChannelRecordingMgr::SetRecordingMode( RecordingMode_t mode )
  1752. {
  1753. m_TimeSelection.SetRecordingMode( mode );
  1754. }
  1755. void CDmeChannelRecordingMgr::SetPresetValue( CDmeChannel* pChannel, const CDmAttribute *pPresetValue, const CDmAttribute *pPresetTimes )
  1756. {
  1757. Assert( m_pActiveRecordingLayer );
  1758. if ( m_pActiveRecordingLayer == NULL )
  1759. return;
  1760. Assert( pChannel->GetRecordLayerIndex() != -1 );
  1761. if ( pChannel->GetRecordLayerIndex() == -1 )
  1762. return;
  1763. LayerChannelInfo_t &info = m_pActiveRecordingLayer->m_LayerChannels[ pChannel->GetRecordLayerIndex() ];
  1764. info.m_pPresetValue = pPresetValue;
  1765. info.m_pPresetTimes = pPresetTimes;
  1766. }
  1767. void CDmeChannelRecordingMgr::SetInRedo( bool bInRedo )
  1768. {
  1769. Assert( bInRedo != m_bInRedo );
  1770. m_bInRedo = bInRedo;
  1771. }
  1772. //-----------------------------------------------------------------------------
  1773. // Methods to query aspects of recording
  1774. //-----------------------------------------------------------------------------
  1775. bool CDmeChannelRecordingMgr::IsUsingDetachedTimeSelection() const
  1776. {
  1777. Assert( m_pActiveRecordingLayer );
  1778. return !m_TimeSelection.m_bAttachedMode;
  1779. }
  1780. bool CDmeChannelRecordingMgr::IsTimeAdvancing() const
  1781. {
  1782. Assert( m_pActiveRecordingLayer );
  1783. return m_TimeSelection.IsTimeAdvancing();
  1784. }
  1785. bool CDmeChannelRecordingMgr::IsUsingTimeSelection() const
  1786. {
  1787. return m_bUseTimeSelection;
  1788. }
  1789. bool CDmeChannelRecordingMgr::IsRecordingLayerActive() const
  1790. {
  1791. return ( m_pActiveRecordingLayer != NULL );
  1792. }
  1793. bool CDmeChannelRecordingMgr::IsModificationLayerActive() const
  1794. {
  1795. return ( ( m_pModificationLayer != NULL ) && ( m_bWantsToFinish == false ) );
  1796. }
  1797. bool CDmeChannelRecordingMgr::IsModificationLayerVisible() const
  1798. {
  1799. if ( !IsModificationLayerActive() )
  1800. return false;
  1801. return m_pModificationLayer->IsVisible();
  1802. }
  1803. bool CDmeChannelRecordingMgr::IsProcessingModifications() const
  1804. {
  1805. return m_bModificationProcessing;
  1806. }
  1807. bool CDmeChannelRecordingMgr::IsModificationLayerEnabled() const
  1808. {
  1809. return m_bModificationLayerEnabled;
  1810. }
  1811. bool CDmeChannelRecordingMgr::ShouldRecordUsingTimeSelection() const
  1812. {
  1813. return m_bUseTimeSelection;
  1814. }
  1815. bool CDmeChannelRecordingMgr::IsInRedo() const
  1816. {
  1817. return m_bInRedo;
  1818. }
  1819. void CDmeChannelRecordingMgr::SetProceduralTarget( int nProceduralMode, const CDmAttribute *pTarget )
  1820. {
  1821. m_nProceduralType = nProceduralMode;
  1822. m_pRevealTarget = pTarget;
  1823. m_PasteTarget.RemoveAll();
  1824. m_RandomSeed = 0;
  1825. }
  1826. void CDmeChannelRecordingMgr::SetProceduralTarget( int nProceduralMode, const CUtlVector< KeyValues * >& list, int randomSeed )
  1827. {
  1828. m_nProceduralType = nProceduralMode;
  1829. m_pRevealTarget = NULL;
  1830. m_PasteTarget.RemoveAll();
  1831. for ( int i = 0; i < list.Count(); ++i )
  1832. {
  1833. m_PasteTarget.AddToTail( list[ i ] );
  1834. }
  1835. m_RandomSeed = randomSeed;
  1836. }
  1837. int CDmeChannelRecordingMgr::GetProceduralType() const
  1838. {
  1839. return m_nProceduralType;
  1840. }
  1841. const CDmAttribute *CDmeChannelRecordingMgr::GetProceduralTarget() const
  1842. {
  1843. Assert( m_pRevealTarget );
  1844. return m_pRevealTarget;
  1845. }
  1846. const CUtlVector< KeyValues * > &CDmeChannelRecordingMgr::GetPasteTarget() const
  1847. {
  1848. return m_PasteTarget;
  1849. }
  1850. void CDmeChannelRecordingMgr::SetModificationLayerDirty()
  1851. {
  1852. if ( m_pModificationLayer )
  1853. {
  1854. m_bModificationLayerDirty = true;
  1855. }
  1856. }
  1857. CDmeChannelModificationLayer *CDmeChannelRecordingMgr::GetModificationLayer()
  1858. {
  1859. return m_pModificationLayer;
  1860. }
  1861. void CDmeChannelRecordingMgr::SetTransformWriteMode( TransformWriteMode_t mode )
  1862. {
  1863. m_TransformWriteMode = mode;
  1864. if ( m_pModificationLayer )
  1865. {
  1866. m_pModificationLayer->UpdateTransformWriteMode( mode );
  1867. SetModificationLayerDirty();
  1868. }
  1869. }
  1870. TransformWriteMode_t CDmeChannelRecordingMgr::GetTransformWriteMode() const
  1871. {
  1872. return m_TransformWriteMode;
  1873. }
  1874. void CDmeChannelRecordingMgr::UpdateActiveLayerManipulateInFalloff( bool bManipulateInFalloff )
  1875. {
  1876. if ( m_pActiveRecordingLayer )
  1877. {
  1878. int nChannels = m_pActiveRecordingLayer->m_LayerChannels.Count();
  1879. for ( int iChannel = 0; iChannel < nChannels; ++iChannel )
  1880. {
  1881. LayerChannelInfo_t &channelInfo = m_pActiveRecordingLayer->m_LayerChannels[ iChannel ];
  1882. channelInfo.m_bManipulateInFalloff = bManipulateInFalloff;
  1883. }
  1884. }
  1885. }
  1886. //-----------------------------------------------------------------------------
  1887. // Copy the clipboard data for the paste operation
  1888. //-----------------------------------------------------------------------------
  1889. void CDmeChannelRecordingMgr::GetPasteClipboardData( CUtlVector< KeyValues * > &list ) const
  1890. {
  1891. if ( m_pActiveRecordingLayer )
  1892. {
  1893. if ( m_pActiveRecordingLayer->m_ClipboardData.Count() > 0 )
  1894. {
  1895. int nKeys = m_pActiveRecordingLayer->m_ClipboardData.Count();
  1896. for ( int iKey = 0; iKey < nKeys; ++iKey )
  1897. {
  1898. list.AddToTail( m_pActiveRecordingLayer->m_ClipboardData[ iKey ] );
  1899. }
  1900. return;
  1901. }
  1902. }
  1903. g_pDataModel->GetClipboardData( list );
  1904. }
  1905. DmeTime_t GetGlobalKeyTime( const DmeClipStack_t &clipStack, CDmeLog *pLog, int idx )
  1906. {
  1907. return pLog && idx < pLog->GetKeyCount() ? clipStack.FromChildMediaTime( pLog->GetKeyTime( idx ), false ) : DMETIME_MAXTIME;
  1908. }
  1909. //-----------------------------------------------------------------------------
  1910. // Expose this class to the scene database
  1911. //-----------------------------------------------------------------------------
  1912. IMPLEMENT_ELEMENT_FACTORY( DmeChannel, CDmeChannel );
  1913. //-----------------------------------------------------------------------------
  1914. // Purpose:
  1915. //-----------------------------------------------------------------------------
  1916. void CDmeChannel::OnConstruction()
  1917. {
  1918. m_nRecordLayerIndex = -1;
  1919. m_nNextCurveType = CURVE_DEFAULT;
  1920. m_fromElement .Init( this, "fromElement", FATTRIB_HAS_CALLBACK | FATTRIB_NEVERCOPY );
  1921. m_fromAttribute .Init( this, "fromAttribute", FATTRIB_TOPOLOGICAL | FATTRIB_HAS_CALLBACK );
  1922. m_fromIndex .Init( this, "fromIndex", FATTRIB_TOPOLOGICAL );
  1923. m_toElement .Init( this, "toElement", FATTRIB_HAS_CALLBACK | FATTRIB_NEVERCOPY );
  1924. m_toAttribute .Init( this, "toAttribute", FATTRIB_TOPOLOGICAL | FATTRIB_HAS_CALLBACK );
  1925. m_toIndex .Init( this, "toIndex", FATTRIB_TOPOLOGICAL );
  1926. m_mode .InitAndSet( this, "mode", (int)CM_PASS );
  1927. m_log .Init( this, "log" );
  1928. m_FromAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  1929. m_ToAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  1930. }
  1931. void CDmeChannel::OnDestruction()
  1932. {
  1933. }
  1934. int CDmeChannel::GetFromArrayIndex() const
  1935. {
  1936. return m_fromIndex;
  1937. }
  1938. int CDmeChannel::GetToArrayIndex() const
  1939. {
  1940. return m_toIndex;
  1941. }
  1942. int CDmeChannel::GetRecordLayerIndex() const
  1943. {
  1944. return m_nRecordLayerIndex;
  1945. }
  1946. void CDmeChannel::SetRecordLayerIndex( int layerIndex )
  1947. {
  1948. // If this assert is hit it most likely means that the
  1949. // channel is a being assigned to two record layers at once.
  1950. Assert( ( layerIndex == -1 ) || ( m_nRecordLayerIndex == -1 ) );
  1951. m_nRecordLayerIndex = layerIndex;
  1952. }
  1953. void CDmeChannel::Play( bool useEmptyLog /*= false*/ )
  1954. {
  1955. CDmAttribute *pToAttr = GetToAttribute();
  1956. if ( pToAttr == NULL )
  1957. return;
  1958. CDmeLog *pLog = GetLog();
  1959. if ( !pLog )
  1960. return;
  1961. DmeTime_t time = GetCurrentTime();
  1962. DmeTime_t t0 = pLog->GetBeginTime();
  1963. DmeTime_t tn = pLog->GetEndTime();
  1964. PlayMode_t pmode = PM_HOLD;
  1965. switch ( pmode )
  1966. {
  1967. case PM_HOLD:
  1968. time = clamp( time, t0, tn );
  1969. break;
  1970. case PM_LOOP:
  1971. if ( tn == t0 )
  1972. {
  1973. time = t0;
  1974. }
  1975. else
  1976. {
  1977. time -= t0;
  1978. time = time % ( tn - t0 );
  1979. time += t0;
  1980. }
  1981. break;
  1982. }
  1983. // We might not want to do it this way, but this makes empty logs not get in the way if there is a valid pFromAttr
  1984. if ( !useEmptyLog )
  1985. {
  1986. if ( pLog->IsEmpty() && !pLog->HasDefaultValue() &&
  1987. GetFromAttribute() != NULL )
  1988. {
  1989. Pass();
  1990. return;
  1991. }
  1992. }
  1993. pLog->GetValue( time, pToAttr, m_toIndex.Get() );
  1994. }
  1995. void CDmeChannel::Pass()
  1996. {
  1997. CDmAttribute *pFromAttr = GetFromAttribute();
  1998. CDmAttribute *pToAttr = GetToAttribute();
  1999. if ( !pFromAttr || !pToAttr )
  2000. return;
  2001. if ( pFromAttr == pToAttr )
  2002. return;
  2003. DmAttributeType_t type = pFromAttr->GetType();
  2004. const void *pValue = NULL;
  2005. if ( IsArrayType( type ) )
  2006. {
  2007. CDmrGenericArray array( pFromAttr );
  2008. pValue = array.GetUntyped( m_fromIndex.Get() );
  2009. type = ArrayTypeToValueType( type );
  2010. }
  2011. else
  2012. {
  2013. pValue = pFromAttr->GetValueUntyped();
  2014. }
  2015. if ( IsArrayType( pToAttr->GetType() ) )
  2016. {
  2017. CDmrGenericArray array( pToAttr );
  2018. array.Set( m_toIndex.Get(), type, pValue );
  2019. }
  2020. else
  2021. {
  2022. pToAttr->SetValue( type, pValue );
  2023. }
  2024. }
  2025. //-----------------------------------------------------------------------------
  2026. // IsDirty - ie needs to operate
  2027. //-----------------------------------------------------------------------------
  2028. bool CDmeChannel::IsDirty()
  2029. {
  2030. if ( BaseClass::IsDirty() )
  2031. return true;
  2032. switch( GetMode() )
  2033. {
  2034. case CM_PLAY:
  2035. return true;
  2036. case CM_RECORD:
  2037. if ( m_nRecordLayerIndex != -1 )
  2038. return true;
  2039. // NOTE: Fall through!
  2040. case CM_PASS:
  2041. {
  2042. CDmAttribute *pFromAttr = GetFromAttribute();
  2043. if ( pFromAttr && pFromAttr->IsFlagSet( FATTRIB_OPERATOR_DIRTY ) )
  2044. return true;
  2045. }
  2046. break;
  2047. default:
  2048. break;
  2049. }
  2050. return false;
  2051. }
  2052. void CDmeChannel::Operate()
  2053. {
  2054. VPROF( "CDmeChannel::Operate" );
  2055. switch ( GetMode() )
  2056. {
  2057. case CM_OFF:
  2058. return;
  2059. case CM_PLAY:
  2060. Play();
  2061. return;
  2062. case CM_RECORD:
  2063. Record();
  2064. return;
  2065. case CM_PASS:
  2066. Pass();
  2067. return;
  2068. }
  2069. }
  2070. void CDmeChannel::GetInputAttributes( CUtlVector< CDmAttribute * > &attrs )
  2071. {
  2072. ChannelMode_t mode = GetMode();
  2073. if ( mode == CM_OFF || mode == CM_PLAY )
  2074. return; // off and play ignore inputs
  2075. CDmAttribute *pAttr = GetFromAttribute();
  2076. if ( pAttr != NULL )
  2077. {
  2078. attrs.AddToTail( pAttr );
  2079. }
  2080. }
  2081. void CDmeChannel::GetOutputAttributes( CUtlVector< CDmAttribute * > &attrs )
  2082. {
  2083. ChannelMode_t mode = GetMode();
  2084. if ( mode == CM_OFF )
  2085. return; // off ignores inputs
  2086. if ( mode == CM_RECORD || mode == CM_PASS )
  2087. {
  2088. if ( GetFromAttribute() == GetToAttribute() )
  2089. return; // record/pass from and to the same attribute doesn't write anything
  2090. }
  2091. CDmAttribute *pAttr = GetToAttribute();
  2092. if ( pAttr != NULL )
  2093. {
  2094. attrs.AddToTail( pAttr );
  2095. }
  2096. }
  2097. //-----------------------------------------------------------------------------
  2098. // accessors
  2099. //-----------------------------------------------------------------------------
  2100. CDmElement *CDmeChannel::GetFromElement() const
  2101. {
  2102. return m_fromElement;
  2103. }
  2104. CDmElement *CDmeChannel::GetToElement() const
  2105. {
  2106. return m_toElement;
  2107. }
  2108. void CDmeChannel::SetLog( CDmeLog *pLog )
  2109. {
  2110. m_log = pLog;
  2111. }
  2112. CDmeLog *CDmeChannel::CreateLog( DmAttributeType_t type )
  2113. {
  2114. CDmeLog *log = CDmeLog::CreateLog( type, GetFileId() );
  2115. m_log.Set( log );
  2116. return log;
  2117. }
  2118. // HACK: This is an evil hack since the element and attribute change sequentially, but they really need to change in lockstep or else you're looking
  2119. // up an attribute from some other element or vice versa.
  2120. void CDmeChannel::SetInput( CDmElement* pElement, const char* pAttribute, int index )
  2121. {
  2122. m_fromElement.Set( pElement );
  2123. m_fromAttribute.Set( pAttribute );
  2124. m_fromIndex.Set( index );
  2125. SetupFromAttribute();
  2126. }
  2127. void CDmeChannel::SetOutput( CDmElement* pElement, const char* pAttribute, int index )
  2128. {
  2129. m_toElement.Set( pElement );
  2130. m_toAttribute.Set( pAttribute );
  2131. m_toIndex.Set( index );
  2132. SetupToAttribute();
  2133. }
  2134. void CDmeChannel::SetInput( CDmAttribute *pAttribute, int index )
  2135. {
  2136. if ( pAttribute )
  2137. {
  2138. SetInput( pAttribute->GetOwner(), pAttribute->GetName(), index );
  2139. }
  2140. else
  2141. {
  2142. SetInput( NULL, "", index );
  2143. }
  2144. }
  2145. void CDmeChannel::SetOutput( CDmAttribute *pAttribute, int index )
  2146. {
  2147. if ( pAttribute )
  2148. {
  2149. SetOutput( pAttribute->GetOwner(), pAttribute->GetName(), index );
  2150. }
  2151. else
  2152. {
  2153. SetOutput( NULL, "", index );
  2154. }
  2155. }
  2156. ChannelMode_t CDmeChannel::GetMode()
  2157. {
  2158. return static_cast< ChannelMode_t >( m_mode.Get() );
  2159. }
  2160. void CDmeChannel::SetMode( ChannelMode_t mode )
  2161. {
  2162. if ( mode != m_mode )
  2163. {
  2164. m_mode.Set( static_cast< int >( mode ) );
  2165. m_TimeState.m_tPreviousTime = DMETIME_INVALID;
  2166. }
  2167. }
  2168. void CDmeChannel::ClearLog()
  2169. {
  2170. GetLog()->ClearKeys();
  2171. }
  2172. CDmeLog *CDmeChannel::GetLog()
  2173. {
  2174. if ( !m_log.GetElement() && ( m_FromAttributeHandle == DMATTRIBUTE_HANDLE_INVALID ) )
  2175. {
  2176. // NOTE: This will generate a new log based on the from attribute
  2177. SetupFromAttribute();
  2178. }
  2179. return m_log.GetElement();
  2180. }
  2181. //-----------------------------------------------------------------------------
  2182. // Used to cache off handles to attributes
  2183. //-----------------------------------------------------------------------------
  2184. CDmAttribute *CDmeChannel::SetupFromAttribute()
  2185. {
  2186. m_FromAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  2187. CDmElement *pObject = m_fromElement.GetElement();
  2188. const char *pName = m_fromAttribute.Get();
  2189. if ( pObject == NULL || pName == NULL || !pName[0] )
  2190. return NULL;
  2191. CDmAttribute *pAttr = pObject->GetAttribute( pName );
  2192. if ( !pAttr )
  2193. return NULL;
  2194. m_FromAttributeHandle = pAttr->GetHandle();
  2195. DmAttributeType_t fromType = pAttr->GetType();
  2196. if ( IsArrayType( fromType ) )
  2197. {
  2198. fromType = ArrayTypeToValueType( fromType );
  2199. }
  2200. CDmeLog *pLog = m_log.GetElement();
  2201. if ( pLog == NULL )
  2202. {
  2203. CreateLog( fromType );
  2204. return pAttr;
  2205. }
  2206. DmAttributeType_t logType = pLog->GetDataType();
  2207. if ( IsArrayType( logType ) )
  2208. {
  2209. logType = ArrayTypeToValueType( logType );
  2210. }
  2211. if ( logType != fromType )
  2212. {
  2213. // NOTE: This will release the current log
  2214. CreateLog( fromType );
  2215. }
  2216. return pAttr;
  2217. }
  2218. CDmAttribute *CDmeChannel::SetupToAttribute()
  2219. {
  2220. m_ToAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  2221. CDmElement *pObject = m_toElement.GetElement();
  2222. const char *pName = m_toAttribute.Get();
  2223. if ( pObject == NULL || pName == NULL || !pName[0] )
  2224. return NULL;
  2225. CDmAttribute *pAttr = pObject->GetAttribute( pName );
  2226. if ( !pAttr )
  2227. return NULL;
  2228. m_ToAttributeHandle = pAttr->GetHandle();
  2229. return pAttr;
  2230. }
  2231. //-----------------------------------------------------------------------------
  2232. // This function gets called whenever an attribute changes
  2233. //-----------------------------------------------------------------------------
  2234. void CDmeChannel::OnAttributeChanged( CDmAttribute *pAttribute )
  2235. {
  2236. if ( ( pAttribute == m_fromElement .GetAttribute() ) ||
  2237. ( pAttribute == m_fromAttribute.GetAttribute() ) )
  2238. {
  2239. // NOTE: This will force a recache of the attribute handle
  2240. m_FromAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  2241. return;
  2242. }
  2243. if ( ( pAttribute == m_toElement .GetAttribute() ) ||
  2244. ( pAttribute == m_toAttribute.GetAttribute() ) )
  2245. {
  2246. m_ToAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  2247. return;
  2248. }
  2249. BaseClass::OnAttributeChanged( pAttribute );
  2250. }
  2251. DmeTime_t CDmeChannel::GetCurrentTime() const
  2252. {
  2253. return m_TimeState.m_tCurrentTime;
  2254. }
  2255. //-----------------------------------------------------------------------------
  2256. // Simple version. Only works if multiple active channels clips
  2257. // do not reference the same channels
  2258. //-----------------------------------------------------------------------------
  2259. void CDmeChannel::SetCurrentTime( DmeTime_t time )
  2260. {
  2261. m_TimeState.m_tPreviousTime = m_TimeState.m_tCurrentTime;
  2262. m_TimeState.m_tCurrentTime = time;
  2263. m_TimeState.m_timeOutsideTimeframe = DMETIME_ZERO;
  2264. }
  2265. const TimeState_t &CDmeChannel::GetTimeState() const
  2266. {
  2267. return m_TimeState;
  2268. }
  2269. void CDmeChannel::SetTimeState( TimeState_t &TimeState )
  2270. {
  2271. m_TimeState = TimeState;
  2272. }
  2273. //-----------------------------------------------------------------------------
  2274. // SetCurrentTime sets the current time on the clip,
  2275. // choosing the time closest to (and after) a timeframe if multiple sets in a frame
  2276. //-----------------------------------------------------------------------------
  2277. void CDmeChannel::SetCurrentTime( DmeTime_t time, DmeTime_t start, DmeTime_t end )
  2278. {
  2279. m_TimeState.m_tPreviousTime = m_TimeState.m_tCurrentTime;
  2280. DmeTime_t dt( 0 );
  2281. if ( time < start )
  2282. {
  2283. dt = time - start;
  2284. time = start;
  2285. }
  2286. else if ( time >= end )
  2287. {
  2288. dt = time - end;
  2289. time = end;
  2290. }
  2291. DmeTime_t totf = m_TimeState.m_timeOutsideTimeframe;
  2292. const DmeTime_t t0( 0 );
  2293. if ( ( dt < t0 && totf < t0 && dt < totf ) || // both prior to clip, old totf closer
  2294. ( dt < t0 && totf >= t0 ) || // new dt prior to clip, old totf in or after
  2295. ( dt >= t0 && totf >= t0 && dt > totf ) ) // both after clip, old totf closer
  2296. return; // if old todt is a better match, don't update channel time
  2297. m_TimeState.m_tCurrentTime = time;
  2298. m_TimeState.m_timeOutsideTimeframe = dt;
  2299. }
  2300. //-----------------------------------------------------------------------------
  2301. // ClearTimeMetric marks m_timeOutsideTimeframe invalid (-inf is the worst possible match)
  2302. //-----------------------------------------------------------------------------
  2303. void CDmeChannel::ClearTimeMetric()
  2304. {
  2305. m_TimeState.m_timeOutsideTimeframe = DmeTime_t::MinTime();
  2306. }
  2307. void CDmeChannel::SetChannelToPlayToSelf( const char *outputAttributeName, float defaultValue, bool force /*= false*/ )
  2308. {
  2309. if ( !HasAttribute( outputAttributeName ) )
  2310. {
  2311. AddAttribute( outputAttributeName, AT_FLOAT );
  2312. }
  2313. CDmeTypedLog< bool > *log = static_cast< CDmeTypedLog< bool >* >( GetLog() );
  2314. // Usually we won't put it into playback if it's empty, we'll just read the default value continously
  2315. if ( force || ( log && !log->IsEmpty() && !log->HasDefaultValue() ) )
  2316. {
  2317. SetMode( CM_PLAY );
  2318. SetOutput( this, outputAttributeName );
  2319. }
  2320. SetValue( outputAttributeName, defaultValue );
  2321. }
  2322. void CDmeChannel::SetNextKeyCurveType( int nCurveType )
  2323. {
  2324. m_nNextCurveType = nCurveType;
  2325. }
  2326. CDmeLogLayer *FindLayerInSnapshot( const CDmrElementArray<CDmElement>& snapshotArray, CDmeLog *origLog )
  2327. {
  2328. if ( !snapshotArray.IsValid() )
  2329. return NULL;
  2330. int c = snapshotArray.Count();
  2331. for ( int i = 0; i < c; ++i )
  2332. {
  2333. CDmeLogLayer *layer = CastElement< CDmeLogLayer >( snapshotArray[ i ] );
  2334. if ( !layer )
  2335. continue;
  2336. CDmeLog *pLog = layer->GetValueElement< CDmeLog >( "origLog" );
  2337. if ( !pLog )
  2338. {
  2339. Assert( 0 );
  2340. continue;
  2341. }
  2342. if ( pLog == origLog )
  2343. return layer;
  2344. }
  2345. return NULL;
  2346. }
  2347. KeyValues *FindLayerInPasteData( const CUtlVector< KeyValues * > &list, CDmeLog *log )
  2348. {
  2349. int c = list.Count();
  2350. for ( int i = 0; i < c; ++i )
  2351. {
  2352. CDisableUndoScopeGuard noundo;
  2353. KeyValues *kv = list[ i ];
  2354. Assert( kv );
  2355. if ( Q_stricmp( kv->GetName(), "ControlLayers" ) )
  2356. continue;
  2357. LayerSelectionData_t *data = reinterpret_cast< LayerSelectionData_t * >( kv->GetPtr( "LayerData" ) );
  2358. if ( !data )
  2359. continue;
  2360. CDmeChannel *ch = data->m_hChannel;
  2361. if ( !ch )
  2362. continue;
  2363. CDmeLog *chLog = ch->GetLog();
  2364. if ( chLog == log )
  2365. return kv;
  2366. }
  2367. return NULL;
  2368. }
  2369. static int FindSpanningLayerAndSetIntensity( DmeLog_TimeSelection_t &ts, LayerSelectionData_t *data )
  2370. {
  2371. Assert( data->m_vecData.Count() >= 2 );
  2372. float frac = ts.m_flIntensity;
  2373. int i = 0;
  2374. for ( ; i < data->m_vecData.Count() - 1; ++i )
  2375. {
  2376. LayerSelectionData_t::DataLayer_t *current = &data->m_vecData[ i ];
  2377. LayerSelectionData_t::DataLayer_t *next = &data->m_vecData[ i + 1 ];
  2378. if ( frac >= current->m_flStartFraction && frac <= next->m_flStartFraction )
  2379. {
  2380. frac = RemapVal( frac, current->m_flStartFraction, next->m_flStartFraction, 0.0f, 1.0f );
  2381. ts.m_flIntensity = frac;
  2382. break;
  2383. }
  2384. }
  2385. return i;
  2386. }
  2387. //-----------------------------------------------------------------------------
  2388. // Purpose: Copy the paste data from the source key values list into the
  2389. // destination key values list. This makes a complete copy of all data so the
  2390. // destination can be safely referenced when the source has been modified or
  2391. // destroyed.
  2392. // Input : srcList - Reference to the source list of key values to be copied
  2393. // Output : dstList - Reference to the list to which the key values of the the
  2394. // source list are to be copied.
  2395. //-----------------------------------------------------------------------------
  2396. void CopyPasteData( CUtlVector< KeyValues * > &dstList, const CUtlVector< KeyValues * > &srcList )
  2397. {
  2398. // Assuming the list is empty, if not we could be improperly accumulating data.
  2399. Assert( dstList.Count() == 0 );
  2400. int nKeys = srcList.Count();
  2401. for ( int iKey = 0; iKey < nKeys; ++iKey )
  2402. {
  2403. KeyValues *pKeyValue = srcList[ iKey ];
  2404. // Skip null key values, but there should not be any.
  2405. if ( pKeyValue == NULL )
  2406. {
  2407. Assert( pKeyValue );
  2408. continue;
  2409. }
  2410. // Skip any unknown key value sets
  2411. if ( V_stricmp( pKeyValue->GetName(), "ControlLayers" ) )
  2412. {
  2413. continue;
  2414. }
  2415. // Get the layer selection data from the key value, if there is no LayerData entry, then skip the key.
  2416. LayerSelectionData_t *pSrcLayerData = reinterpret_cast< LayerSelectionData_t * >( pKeyValue->GetPtr( "LayerData" ) );
  2417. if ( pSrcLayerData == NULL )
  2418. {
  2419. continue;
  2420. }
  2421. // Get the pointer to the log to which the layer data is for.
  2422. CDmeLog *pLog = pSrcLayerData->m_hLog.Get();
  2423. if ( pLog == NULL )
  2424. {
  2425. Assert( pLog );
  2426. continue;
  2427. }
  2428. // Create the new layer selection structure and create a new
  2429. // key value set for it and place it in the destination list.
  2430. LayerSelectionData_t *pDstLayerData = new LayerSelectionData_t;
  2431. KeyValues *pDstKeyValues = new KeyValues( "ControlLayers" );
  2432. dstList.AddToTail( pDstKeyValues );
  2433. // Add the layer data structure pointer to the key value set.
  2434. pDstKeyValues->SetPtr( "LayerData", reinterpret_cast< void * >( pDstLayerData ) );
  2435. // Copy the simple data element of the layer selection data
  2436. pDstLayerData->m_hChannel = pSrcLayerData->m_hChannel;
  2437. pDstLayerData->m_hOwner = pSrcLayerData->m_hOwner;
  2438. pDstLayerData->m_hShot = pSrcLayerData->m_hShot;
  2439. pDstLayerData->m_hLog = pSrcLayerData->m_hLog;
  2440. pDstLayerData->m_DataType = pSrcLayerData->m_DataType;
  2441. pDstLayerData->m_nTimes[ 0 ] = pSrcLayerData->m_nTimes[ 0 ];
  2442. pDstLayerData->m_nTimes[ 1 ] = pSrcLayerData->m_nTimes[ 1 ];
  2443. pDstLayerData->m_nTimes[ 2 ] = pSrcLayerData->m_nTimes[ 2 ];
  2444. pDstLayerData->m_nTimes[ 3 ] = pSrcLayerData->m_nTimes[ 3 ];
  2445. // Copy each of the log layers in the layer selection data.
  2446. int nLayers = pSrcLayerData->m_vecData.Count();
  2447. for ( int iLayer = 0; iLayer < nLayers; ++iLayer )
  2448. {
  2449. float srcFrac = pSrcLayerData->m_vecData[ iLayer ].m_flStartFraction;
  2450. CDmeLogLayer *pSrcLayer = pSrcLayerData->m_vecData[ iLayer ].m_hData.Get();
  2451. if ( pSrcLayer )
  2452. {
  2453. // Create a new layer and copy the source layer
  2454. CDmeLogLayer* pNewLayer = pLog->AddNewLayer();
  2455. pNewLayer->CopyLayer( pSrcLayer );
  2456. // Add the new layer to the layer selection data
  2457. LayerSelectionData_t::DataLayer_t dataLayer( srcFrac, pNewLayer );
  2458. pDstLayerData->m_vecData.AddToTail( dataLayer );
  2459. // Disconnect the new layer from log
  2460. pLog->RemoveLayerFromTail();
  2461. }
  2462. }
  2463. } // For iKey
  2464. }
  2465. //-----------------------------------------------------------------------------
  2466. // Purpose: Destroy the contents of the provided paste data list, freeing all
  2467. // associated resources.
  2468. // Input : list - Paste data key value list to be destroyed.
  2469. //-----------------------------------------------------------------------------
  2470. void DestroyPasteData( CUtlVector< KeyValues * > &list )
  2471. {
  2472. int c = list.Count();
  2473. for ( int i = 0; i < c; ++i )
  2474. {
  2475. KeyValues *kv = list[ i ];
  2476. Assert( kv );
  2477. if ( !kv )
  2478. continue;
  2479. LayerSelectionData_t *data = reinterpret_cast< LayerSelectionData_t * >( kv->GetPtr( "LayerData" ) );
  2480. if ( !data )
  2481. continue;
  2482. data->Release();
  2483. delete data;
  2484. }
  2485. }
  2486. void CDmeChannel::Record()
  2487. {
  2488. VPROF( "CDmeChannel::Record" );
  2489. CDmElement* pElement = GetFromElement();
  2490. CDmAttribute *pFromAttr = GetFromAttribute();
  2491. if ( pFromAttr == NULL )
  2492. return; // or clear out the log?
  2493. CDmeLog *pLog = GetLog();
  2494. DmeTime_t time = GetCurrentTime();
  2495. if ( m_TimeState.m_tPreviousTime == DMETIME_INVALID )
  2496. {
  2497. m_TimeState.m_tPreviousTime = time;
  2498. }
  2499. if ( g_pChannelRecordingMgr->ShouldRecordUsingTimeSelection() )
  2500. {
  2501. Assert( m_nRecordLayerIndex != -1 );
  2502. if ( m_nRecordLayerIndex == -1 )
  2503. return;
  2504. // Computes local times for the time selection
  2505. DmeLog_TimeSelection_t timeSelection;
  2506. g_pChannelRecordingMgr->GetLocalTimeSelection( timeSelection, m_nRecordLayerIndex );
  2507. int nType = g_pChannelRecordingMgr->GetProceduralType();
  2508. enum { PROCEDURAL_PRESET_ANIMATED = NUM_PROCEDURAL_PRESET_TYPES + 1 };
  2509. if ( nType == PROCEDURAL_PRESET_NOT && timeSelection.m_pPresetTimes )
  2510. {
  2511. nType = PROCEDURAL_PRESET_ANIMATED; // this is an animated preset, which is blended in like paste/spline/etc
  2512. }
  2513. switch ( nType )
  2514. {
  2515. default:
  2516. case PROCEDURAL_PRESET_NOT:
  2517. {
  2518. DmeLogTransformParams_t transformParams;
  2519. transformParams.m_nProceduralType = nType;
  2520. // If the element is a transform control, get the additional manipulation parameters from the
  2521. // transform control and store them in the transform parameters so they can be used by the log.
  2522. CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( pElement );
  2523. if ( pTransformControl )
  2524. {
  2525. pTransformControl->GetManipulationTransform( transformParams.m_Transform );
  2526. pTransformControl->GetManipulationRotationLocal( transformParams.m_RotationLocal );
  2527. pTransformControl->GetManipulationRotationParent( transformParams.m_RotationParent );
  2528. pTransformControl->GetManipulationPivot( transformParams.m_Pivot );
  2529. CDmeChannel* pRotChannel = pTransformControl->GetOrientationChannel();
  2530. if ( pRotChannel )
  2531. {
  2532. CDmeLog* pLog = pRotChannel->GetLog();
  2533. if ( pLog && pLog->GetDataType() == AT_QUATERNION )
  2534. {
  2535. transformParams.m_pRotationLog = static_cast< CDmeTypedLog< Quaternion >* >( pLog );
  2536. }
  2537. }
  2538. }
  2539. else
  2540. {
  2541. // Only transform controls can have manipulation in falloff
  2542. timeSelection.m_bManipulateInFalloff = false;
  2543. }
  2544. // Stamp the key at the current head position, re-sampling the current time selection if time is not moving or writing
  2545. // a key at the current time if time is moving. If the modification layer is active and the time is moving forward the
  2546. // key will be recorded without respect to the current time selection as the time selection will be applied later.
  2547. g_pChannelRecordingMgr->StoreChannelAttributeData( m_nRecordLayerIndex, true );
  2548. pLog->StampKeyAtHead( time, m_TimeState.m_tPreviousTime, timeSelection, transformParams, pFromAttr, m_fromIndex.Get(), !g_pChannelRecordingMgr->IsModificationLayerActive() );
  2549. }
  2550. break;
  2551. case PROCEDURAL_PRESET_REVEAL:
  2552. {
  2553. // Find the matching layer in the "target" data array
  2554. const CDmrElementArray<CDmElement> snapshotArray = const_cast< CDmAttribute * >( g_pChannelRecordingMgr->GetProceduralTarget() );
  2555. CDmeLogLayer *snapshotLayer = FindLayerInSnapshot( snapshotArray, pLog );
  2556. if ( snapshotLayer )
  2557. {
  2558. Assert( pLog );
  2559. pLog->RevealUsingTimeSelection( timeSelection, snapshotLayer );
  2560. }
  2561. }
  2562. break;
  2563. case PROCEDURAL_PRESET_DROP_LAYER:
  2564. {
  2565. int nLayers = pLog->GetNumLayers();
  2566. // There must be at least 3 layers in order for the drop to operate:
  2567. // the base layer, the modification layer and the active recording layer.
  2568. if ( nLayers >= 3 )
  2569. {
  2570. CDmeLogLayer* pRecLayer = pLog->GetLayer( nLayers - 1 );
  2571. CDmeLogLayer* pModLayer = pLog->GetLayer( nLayers - 2 );
  2572. CDmeLogLayer* pBaseLayer = pLog->GetLayer( nLayers - 3 );
  2573. pLog->BlendLayersUsingTimeSelection( pBaseLayer, pModLayer, pRecLayer, timeSelection, true, false, false, DMETIME_ZERO );
  2574. }
  2575. }
  2576. break;
  2577. case PROCEDURAL_PRESET_INOUT:
  2578. case PROCEDURAL_PRESET_JITTER:
  2579. case PROCEDURAL_PRESET_SMOOTH:
  2580. case PROCEDURAL_PRESET_SHARPEN:
  2581. case PROCEDURAL_PRESET_SOFTEN:
  2582. case PROCEDURAL_PRESET_STAGGER:
  2583. case PROCEDURAL_PRESET_HOLD:
  2584. case PROCEDURAL_PRESET_RELEASE:
  2585. case PROCEDURAL_PRESET_STEADY:
  2586. case PROCEDURAL_PRESET_PASTE:
  2587. case PROCEDURAL_PRESET_SPLINE:
  2588. case PROCEDURAL_PRESET_ANIMATED:
  2589. {
  2590. const CUtlVector< KeyValues * > &pasteTarget = g_pChannelRecordingMgr->GetPasteTarget();
  2591. KeyValues *layer = FindLayerInPasteData( pasteTarget, pLog );
  2592. if ( layer )
  2593. {
  2594. LayerSelectionData_t *data = reinterpret_cast< LayerSelectionData_t * >( layer->GetPtr( "LayerData" ) );
  2595. Assert( data );
  2596. DmeLog_TimeSelection_t blendTimeSelction = timeSelection;
  2597. int iSourceLayer = FindSpanningLayerAndSetIntensity( blendTimeSelction, data );
  2598. CDmeLogLayer *sourceLayer = data->m_vecData[ iSourceLayer ].m_hData.Get();
  2599. CDmeLogLayer *targetLayer = data->m_vecData[ iSourceLayer + 1 ].m_hData.Get();
  2600. if ( sourceLayer && sourceLayer->GetKeyCount() > 0 &&
  2601. targetLayer && targetLayer->GetKeyCount() > 0 &&
  2602. sourceLayer->GetKeyCount() == targetLayer->GetKeyCount() )
  2603. {
  2604. Assert( pLog->GetNumLayers() >= 2 );
  2605. CDmeLogLayer *outputLayer = pLog->GetLayer( pLog->GetTopmostLayer() );
  2606. if ( IsPresetTimeOperation( nType ) ) // stagger and steady operate on sample times mostly
  2607. {
  2608. bool bFeatherBlendInFalloff = nType == PROCEDURAL_PRESET_STAGGER || nType == PROCEDURAL_PRESET_STEADY;
  2609. pLog->BlendTimesUsingTimeSelection( sourceLayer, targetLayer, outputLayer, blendTimeSelction, data->m_nTimes[ TS_LEFT_FALLOFF ], bFeatherBlendInFalloff );
  2610. }
  2611. else if ( iSourceLayer != 0 )
  2612. {
  2613. CDmeLogLayer *baseLayer = data->m_vecData[ 0 ].m_hData.Get();
  2614. pLog->BlendLayersUsingTimeSelection( baseLayer, sourceLayer, targetLayer, outputLayer, blendTimeSelction, false, data->m_nTimes[ TS_LEFT_FALLOFF ] );
  2615. }
  2616. else
  2617. {
  2618. pLog->BlendLayersUsingTimeSelection( sourceLayer, targetLayer, outputLayer, blendTimeSelction, false, true, true, data->m_nTimes[ TS_LEFT_FALLOFF ] );
  2619. }
  2620. }
  2621. }
  2622. }
  2623. break;
  2624. }
  2625. }
  2626. else
  2627. {
  2628. int bestLayer = pLog->GetTopmostLayer();
  2629. SegmentInterpolation_t interpSetting = (bestLayer == -1) ? SEGMENT_INTERPOLATE : pLog->GetLayer( bestLayer )->GetSegmentInterpolationSetting( m_TimeState.m_tPreviousTime, DMETIME_INVALID, false );
  2630. if( interpSetting == SEGMENT_INTERPOLATE ) //use existing behavior
  2631. {
  2632. if ( m_TimeState.m_tPreviousTime != time )
  2633. {
  2634. pLog->SetDuplicateKeyAtTime( m_TimeState.m_tPreviousTime );
  2635. }
  2636. pLog->SetKey( time, pFromAttr, m_fromIndex.Get(), SEGMENT_INTERPOLATE, m_nNextCurveType );
  2637. }
  2638. else
  2639. {
  2640. //attempt to preserve the non-interpolated segment as it is. I believe that this will also work for the general case above. But I'm not 100% sure at the moment. Best not to break existing behavior
  2641. if ( m_TimeState.m_tPreviousTime != time )
  2642. {
  2643. pLog->InsertKeyAtTime( m_TimeState.m_tPreviousTime );
  2644. }
  2645. pLog->SetKey( time, pFromAttr, m_fromIndex.Get(), pLog->GetLayer( bestLayer )->GetSegmentInterpolationSetting( time ), m_nNextCurveType );
  2646. }
  2647. m_nNextCurveType = CURVE_DEFAULT;
  2648. }
  2649. // Output the data that's in the log
  2650. Play();
  2651. }
  2652. //-----------------------------------------------------------------------------
  2653. // Builds a clip stack that passes through root + shot
  2654. // Returns true if it succeeded
  2655. //-----------------------------------------------------------------------------
  2656. bool CDmeChannel::BuildClipStack( DmeClipStack_t *pClipStack, CDmeClip *pRoot, CDmeClip *pShot ) const
  2657. {
  2658. DmAttributeReferenceIterator_t it;
  2659. for ( it = g_pDataModel->FirstAttributeReferencingElement( GetHandle() );
  2660. it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
  2661. it = g_pDataModel->NextAttributeReferencingElement( it ) )
  2662. {
  2663. CDmAttribute *pAttribute = g_pDataModel->GetAttribute( it );
  2664. CDmElement *pElement = pAttribute->GetOwner();
  2665. CDmeChannelsClip *pChannelsClip = CastElement< CDmeChannelsClip >( pElement );
  2666. if ( !pChannelsClip )
  2667. continue;
  2668. if ( pChannelsClip->BuildClipStack( pClipStack, pRoot, pShot ) )
  2669. return true;
  2670. }
  2671. return false;
  2672. }
  2673. //-----------------------------------------------------------------------------
  2674. // Finds the owner clip for a channel which passes through the root
  2675. //-----------------------------------------------------------------------------
  2676. CDmeClip* CDmeChannel::FindOwnerClipForChannel( CDmeClip *pRoot )
  2677. {
  2678. DmeClipStack_t stack;
  2679. if ( BuildClipStack( &stack, pRoot, pRoot ) )
  2680. return stack.GetClip( stack.GetClipCount() - 1 );
  2681. return NULL;
  2682. }
  2683. void CDmeChannel::ScaleSampleTimes( float scale )
  2684. {
  2685. m_log->ScaleSampleTimes( scale );
  2686. }
  2687. void CDmeChannel::ClearAndAddSampleAtTime( DmeTime_t time )
  2688. {
  2689. m_log->ClearAndAddSampleAtTime( time );
  2690. }
  2691. void RemapFloatLogValues( CDmeChannel *pChannel, float flBias, float flScale )
  2692. {
  2693. if ( !pChannel )
  2694. return;
  2695. CDmeLog *pLog = pChannel->GetLog();
  2696. if ( !pLog )
  2697. return;
  2698. CDmeTypedLogLayer< float > *pLogLayer = CastElement< CDmeTypedLogLayer< float > >( pLog->GetLayer( pLog->GetTopmostLayer() ) );
  2699. if ( !pLogLayer )
  2700. return;
  2701. int nKeys = pLogLayer->GetKeyCount();
  2702. for ( int i = 0; i < nKeys; ++i )
  2703. {
  2704. float flValue = pLogLayer->GetKeyValue( i );
  2705. pLogLayer->SetKeyValue( i, flValue * flScale + flBias );
  2706. }
  2707. }
  2708. CDmeChannel *FindChannelTargetingAttribute( CDmAttribute *pTargetAttr )
  2709. {
  2710. if ( !pTargetAttr )
  2711. return NULL;
  2712. CDmElement *pTarget = pTargetAttr->GetOwner();
  2713. if ( !pTarget )
  2714. return NULL;
  2715. for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( pTarget->GetHandle() );
  2716. it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
  2717. it = g_pDataModel->NextAttributeReferencingElement( it ) )
  2718. {
  2719. CDmAttribute *pAttr = g_pDataModel->GetAttribute( it );
  2720. Assert( pAttr );
  2721. CDmeChannel *pChannel = CastElement< CDmeChannel >( pAttr->GetOwner() );
  2722. if ( pChannel && pChannel->GetToAttribute() == pTargetAttr )
  2723. return pChannel;
  2724. }
  2725. return NULL;
  2726. }