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

1007 lines
26 KiB

  1. //========= Copyright 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 "datamodel/dmelementfactoryhelper.h"
  10. #include "datamodel/dmehandle.h"
  11. #include "datamodel/dmattribute.h"
  12. #include "tier0/vprof.h"
  13. #include "tier1/KeyValues.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. //-----------------------------------------------------------------------------
  17. //
  18. // CDmeChannelRecordingMgr
  19. //
  20. //-----------------------------------------------------------------------------
  21. //-----------------------------------------------------------------------------
  22. // Globals
  23. //-----------------------------------------------------------------------------
  24. static CDmeChannelRecordingMgr s_ChannelRecordingMgr;
  25. CDmeChannelRecordingMgr *g_pChannelRecordingMgr = &s_ChannelRecordingMgr;
  26. //-----------------------------------------------------------------------------
  27. // Constructor
  28. //-----------------------------------------------------------------------------
  29. CDmeChannelRecordingMgr::CDmeChannelRecordingMgr()
  30. {
  31. m_bActive = false;
  32. m_bSavedUndoState = false;
  33. m_bUseTimeSelection = false;
  34. m_nRevealType = PROCEDURAL_PRESET_NOT;
  35. m_pRevealTarget = NULL;
  36. }
  37. //-----------------------------------------------------------------------------
  38. // Activates, deactivates layer recording.
  39. //-----------------------------------------------------------------------------
  40. void CDmeChannelRecordingMgr::StartLayerRecording( const char *pUndoRedoDesc, const DmeLog_TimeSelection_t *pTimeSelection )
  41. {
  42. g_pDataModel->StartUndo( pUndoRedoDesc, pUndoRedoDesc );
  43. m_bSavedUndoState = g_pDataModel->IsUndoEnabled();
  44. g_pDataModel->SetUndoEnabled( false );
  45. Assert( !m_bActive );
  46. Assert( m_LayerChannels.Count() == 0 );
  47. m_LayerChannels.Purge();
  48. m_bActive = true;
  49. m_bUseTimeSelection = ( pTimeSelection != NULL );
  50. if ( pTimeSelection )
  51. {
  52. m_TimeSelection = *pTimeSelection;
  53. }
  54. else
  55. {
  56. // Slam to default value
  57. m_TimeSelection = DmeLog_TimeSelection_t();
  58. }
  59. m_TimeSelection.ResetTimeAdvancing();
  60. }
  61. void CDmeChannelRecordingMgr::FinishLayerRecording( float flThreshhold, bool bFlattenLayers /*=true*/ )
  62. {
  63. Assert( m_bActive );
  64. RemoveAllChannelsFromRecordingLayer();
  65. m_bUseTimeSelection = false;
  66. m_TimeSelection.ResetTimeAdvancing();
  67. g_pDataModel->SetUndoEnabled( m_bSavedUndoState );
  68. if ( bFlattenLayers )
  69. {
  70. FlattenLayers( flThreshhold );
  71. }
  72. g_pDataModel->FinishUndo();
  73. m_bActive = false;
  74. m_LayerChannels.Purge();
  75. m_nRevealType = PROCEDURAL_PRESET_NOT;
  76. m_pRevealTarget = NULL;
  77. m_PasteTarget.RemoveAll();
  78. }
  79. //-----------------------------------------------------------------------------
  80. // Adds a channel to the recording layer
  81. //-----------------------------------------------------------------------------
  82. void CDmeChannelRecordingMgr::AddChannelToRecordingLayer( CDmeChannel *pChannel, CDmeClip *pRoot, CDmeClip *pShot )
  83. {
  84. Assert( pChannel->m_nRecordLayerIndex == -1 );
  85. CDmeLog *pLog = pChannel->GetLog();
  86. if ( !pLog )
  87. return;
  88. int nRecordLayerIndex = m_LayerChannels.AddToTail();
  89. LayerChannelInfo_t& info = m_LayerChannels[nRecordLayerIndex];
  90. info.m_Channel = pChannel;
  91. if ( pRoot )
  92. {
  93. if ( !pChannel->BuildClipStack( &info.m_ClipStack, pRoot, pShot ) )
  94. {
  95. m_LayerChannels.Remove( nRecordLayerIndex );
  96. return;
  97. }
  98. }
  99. pChannel->m_nRecordLayerIndex = nRecordLayerIndex;
  100. // This operation is undoable
  101. CEnableUndoScopeGuard guard;
  102. pLog->AddNewLayer();
  103. pChannel->SetMode( CM_RECORD );
  104. }
  105. //-----------------------------------------------------------------------------
  106. // Removes all channels from the recording layer
  107. //-----------------------------------------------------------------------------
  108. void CDmeChannelRecordingMgr::RemoveAllChannelsFromRecordingLayer( )
  109. {
  110. int c = m_LayerChannels.Count();
  111. for ( int i = 0 ; i < c; ++i )
  112. {
  113. CDmeChannel *pChannel = m_LayerChannels[ i ].m_Channel.Get();
  114. if ( !pChannel )
  115. continue;
  116. CDmeLog *pLog = pChannel->GetLog();
  117. if ( pLog && IsUsingTimeSelection() )
  118. {
  119. // Computes local times for the time selection
  120. DmeLog_TimeSelection_t timeSelection;
  121. GetLocalTimeSelection( timeSelection, pChannel->m_nRecordLayerIndex );
  122. pLog->FinishTimeSelection( pChannel->GetCurrentTime(), timeSelection );
  123. }
  124. pChannel->m_nRecordLayerIndex = -1;
  125. pChannel->SetMode( CM_PLAY );
  126. }
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Flattens recorded layers into the base layer
  130. //-----------------------------------------------------------------------------
  131. void CDmeChannelRecordingMgr::FlattenLayers( float flThreshhold )
  132. {
  133. int nFlags = 0;
  134. if ( IsUsingDetachedTimeSelection() && IsTimeAdvancing() )
  135. {
  136. nFlags |= CDmeLog::FLATTEN_NODISCONTINUITY_FIXUP;
  137. }
  138. int c = m_LayerChannels.Count();
  139. for ( int i = 0 ; i < c; ++i )
  140. {
  141. CDmeChannel *pChannel = m_LayerChannels[ i ].m_Channel.Get();
  142. if ( !pChannel )
  143. continue;
  144. CDmeLog *pLog = pChannel->GetLog();
  145. Assert( pLog );
  146. if ( !pLog )
  147. continue;
  148. pLog->FlattenLayers( flThreshhold, nFlags );
  149. }
  150. }
  151. //-----------------------------------------------------------------------------
  152. // Used to iterate over all channels currently being recorded
  153. //-----------------------------------------------------------------------------
  154. int CDmeChannelRecordingMgr::GetLayerRecordingChannelCount()
  155. {
  156. return m_LayerChannels.Count();
  157. }
  158. CDmeChannel* CDmeChannelRecordingMgr::GetLayerRecordingChannel( int nIndex )
  159. {
  160. return m_LayerChannels[nIndex].m_Channel.Get();
  161. }
  162. //-----------------------------------------------------------------------------
  163. // Computes time selection info in log time for a particular recorded channel
  164. //-----------------------------------------------------------------------------
  165. void CDmeChannelRecordingMgr::GetLocalTimeSelection( DmeLog_TimeSelection_t& selection, int nIndex )
  166. {
  167. Assert( m_bUseTimeSelection );
  168. LayerChannelInfo_t& info = m_LayerChannels[nIndex];
  169. selection = m_TimeSelection;
  170. for ( int i = 0; i < TS_TIME_COUNT; ++i )
  171. {
  172. selection.m_nTimes[i] = CDmeClip::ToChildMediaTime( info.m_ClipStack, selection.m_nTimes[i], false );
  173. }
  174. selection.m_pPresetValue = info.m_pPresetValue;
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Methods which control various aspects of recording
  178. //-----------------------------------------------------------------------------
  179. void CDmeChannelRecordingMgr::UpdateTimeAdvancing( bool bPaused, DmeTime_t tCurTime )
  180. {
  181. Assert( m_bActive && m_bUseTimeSelection );
  182. if ( !bPaused && !m_TimeSelection.IsTimeAdvancing() )
  183. {
  184. m_TimeSelection.StartTimeAdvancing();
  185. // blow away logs after curtime
  186. int nCount = m_LayerChannels.Count();
  187. for ( int i = 0; i < nCount; ++i )
  188. {
  189. LayerChannelInfo_t& info = m_LayerChannels[i];
  190. DmeTime_t t = CDmeClip::ToChildMediaTime( info.m_ClipStack, tCurTime, false );
  191. info.m_Channel->GetLog()->RemoveKeys( t, DMETIME_MAXTIME );
  192. }
  193. }
  194. }
  195. void CDmeChannelRecordingMgr::UpdateRecordingTimeSelectionTimes( const DmeLog_TimeSelection_t& timeSelection )
  196. {
  197. Assert( m_bActive );
  198. for ( int i = 0; i < TS_TIME_COUNT; ++i )
  199. {
  200. m_TimeSelection.m_nTimes[i] = timeSelection.m_nTimes[i];
  201. }
  202. m_TimeSelection.m_nResampleInterval = timeSelection.m_nResampleInterval;
  203. }
  204. void CDmeChannelRecordingMgr::SetIntensityOnAllLayers( float flIntensity )
  205. {
  206. m_TimeSelection.m_flIntensity = flIntensity;
  207. }
  208. void CDmeChannelRecordingMgr::SetRecordingMode( RecordingMode_t mode )
  209. {
  210. m_TimeSelection.SetRecordingMode( mode );
  211. }
  212. void CDmeChannelRecordingMgr::SetPresetValue( CDmeChannel* pChannel, CDmAttribute *pPresetValue )
  213. {
  214. Assert( pChannel->m_nRecordLayerIndex != -1 );
  215. m_LayerChannels[ pChannel->m_nRecordLayerIndex ].m_pPresetValue = pPresetValue;
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Methods to query aspects of recording
  219. //-----------------------------------------------------------------------------
  220. bool CDmeChannelRecordingMgr::IsUsingDetachedTimeSelection() const
  221. {
  222. Assert( m_bActive );
  223. return !m_TimeSelection.m_bAttachedMode;
  224. }
  225. bool CDmeChannelRecordingMgr::IsTimeAdvancing() const
  226. {
  227. Assert( m_bActive );
  228. return m_TimeSelection.IsTimeAdvancing();
  229. }
  230. bool CDmeChannelRecordingMgr::IsUsingTimeSelection() const
  231. {
  232. return m_bUseTimeSelection;
  233. }
  234. bool CDmeChannelRecordingMgr::ShouldRecordUsingTimeSelection() const
  235. {
  236. return m_bUseTimeSelection && m_bActive;
  237. }
  238. void CDmeChannelRecordingMgr::SetProceduralTarget( int nProceduralMode, const CDmAttribute *pTarget )
  239. {
  240. m_nRevealType = nProceduralMode;
  241. m_pRevealTarget = pTarget;
  242. m_PasteTarget.RemoveAll();
  243. }
  244. void CDmeChannelRecordingMgr::SetProceduralTarget( int nProceduralMode, const CUtlVector< KeyValues * >& list )
  245. {
  246. m_nRevealType = nProceduralMode;
  247. m_pRevealTarget = NULL;
  248. m_PasteTarget.RemoveAll();
  249. for ( int i = 0; i < list.Count(); ++i )
  250. {
  251. m_PasteTarget.AddToTail( list[ i ] );
  252. }
  253. }
  254. int CDmeChannelRecordingMgr::GetProceduralType() const
  255. {
  256. return m_nRevealType;
  257. }
  258. const CDmAttribute *CDmeChannelRecordingMgr::GetProceduralTarget() const
  259. {
  260. Assert( m_pRevealTarget );
  261. return m_pRevealTarget;
  262. }
  263. const CUtlVector< KeyValues * > &CDmeChannelRecordingMgr::GetPasteTarget() const
  264. {
  265. return m_PasteTarget;
  266. }
  267. //-----------------------------------------------------------------------------
  268. // Expose this class to the scene database
  269. //-----------------------------------------------------------------------------
  270. IMPLEMENT_ELEMENT_FACTORY( DmeChannel, CDmeChannel );
  271. //-----------------------------------------------------------------------------
  272. // Purpose:
  273. //-----------------------------------------------------------------------------
  274. void CDmeChannel::OnConstruction()
  275. {
  276. m_nRecordLayerIndex = -1;
  277. m_nNextCurveType = CURVE_DEFAULT;
  278. m_tCurrentTime = DMETIME_INVALID;
  279. m_tPreviousTime = DMETIME_INVALID;
  280. m_timeOutsideTimeframe = DMETIME_INVALID;
  281. m_fromElement .Init( this, "fromElement", FATTRIB_HAS_CALLBACK | FATTRIB_NEVERCOPY );
  282. m_fromAttribute .Init( this, "fromAttribute", FATTRIB_TOPOLOGICAL | FATTRIB_HAS_CALLBACK );
  283. m_fromIndex .Init( this, "fromIndex", FATTRIB_TOPOLOGICAL );
  284. m_toElement .Init( this, "toElement", FATTRIB_HAS_CALLBACK | FATTRIB_NEVERCOPY );
  285. m_toAttribute .Init( this, "toAttribute", FATTRIB_TOPOLOGICAL | FATTRIB_HAS_CALLBACK );
  286. m_toIndex .Init( this, "toIndex", FATTRIB_TOPOLOGICAL );
  287. m_mode .InitAndSet( this, "mode", (int)CM_PASS );
  288. m_log .Init( this, "log" );
  289. m_FromAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  290. m_ToAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  291. }
  292. void CDmeChannel::OnDestruction()
  293. {
  294. }
  295. int CDmeChannel::GetFromArrayIndex() const
  296. {
  297. return m_fromIndex;
  298. }
  299. int CDmeChannel::GetToArrayIndex() const
  300. {
  301. return m_toIndex;
  302. }
  303. void CDmeChannel::Play()
  304. {
  305. CDmAttribute *pToAttr = GetToAttribute();
  306. if ( pToAttr == NULL )
  307. return;
  308. CDmeLog *pLog = GetLog();
  309. if ( !pLog )
  310. return;
  311. DmeTime_t time = GetCurrentTime();
  312. DmeTime_t t0 = pLog->GetBeginTime();
  313. DmeTime_t tn = pLog->GetEndTime();
  314. PlayMode_t pmode = PM_HOLD;
  315. switch ( pmode )
  316. {
  317. case PM_HOLD:
  318. time = clamp( time, t0, tn );
  319. break;
  320. case PM_LOOP:
  321. if ( tn == t0 )
  322. {
  323. time = t0;
  324. }
  325. else
  326. {
  327. time -= t0;
  328. time = time % ( tn - t0 );
  329. time += t0;
  330. }
  331. break;
  332. }
  333. // 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
  334. #if 1
  335. if ( pLog->IsEmpty() && !pLog->HasDefaultValue() &&
  336. GetFromAttribute() != NULL )
  337. {
  338. Pass();
  339. return;
  340. }
  341. #endif
  342. pLog->GetValue( time, pToAttr, m_toIndex.Get() );
  343. }
  344. void CDmeChannel::Pass()
  345. {
  346. CDmAttribute *pFromAttr = GetFromAttribute();
  347. CDmAttribute *pToAttr = GetToAttribute();
  348. if ( !pFromAttr || !pToAttr )
  349. return;
  350. if ( pFromAttr == pToAttr )
  351. return;
  352. DmAttributeType_t type = pFromAttr->GetType();
  353. const void *pValue = NULL;
  354. if ( IsArrayType( type ) )
  355. {
  356. CDmrGenericArray array( pFromAttr );
  357. pValue = array.GetUntyped( m_fromIndex.Get() );
  358. type = ArrayTypeToValueType( type );
  359. }
  360. else
  361. {
  362. pValue = pFromAttr->GetValueUntyped();
  363. }
  364. if ( IsArrayType( pToAttr->GetType() ) )
  365. {
  366. CDmrGenericArray array( pToAttr );
  367. array.Set( m_toIndex.Get(), type, pValue );
  368. }
  369. else
  370. {
  371. pToAttr->SetValue( type, pValue );
  372. }
  373. }
  374. //-----------------------------------------------------------------------------
  375. // IsDirty - ie needs to operate
  376. //-----------------------------------------------------------------------------
  377. bool CDmeChannel::IsDirty()
  378. {
  379. if ( BaseClass::IsDirty() )
  380. return true;
  381. switch( GetMode() )
  382. {
  383. case CM_PLAY:
  384. return true;
  385. case CM_RECORD:
  386. if ( m_nRecordLayerIndex != -1 )
  387. return true;
  388. // NOTE: Fall through!
  389. case CM_PASS:
  390. {
  391. CDmAttribute *pFromAttr = GetFromAttribute();
  392. if ( pFromAttr && pFromAttr->IsFlagSet( FATTRIB_OPERATOR_DIRTY ) )
  393. return true;
  394. }
  395. break;
  396. default:
  397. break;
  398. }
  399. return false;
  400. }
  401. void CDmeChannel::Operate()
  402. {
  403. VPROF( "CDmeChannel::Operate" );
  404. switch ( GetMode() )
  405. {
  406. case CM_OFF:
  407. return;
  408. case CM_PLAY:
  409. Play();
  410. return;
  411. case CM_RECORD:
  412. Record();
  413. return;
  414. case CM_PASS:
  415. Pass();
  416. return;
  417. }
  418. }
  419. void CDmeChannel::GetInputAttributes( CUtlVector< CDmAttribute * > &attrs )
  420. {
  421. ChannelMode_t mode = GetMode();
  422. if ( mode == CM_OFF || mode == CM_PLAY )
  423. return; // off and play ignore inputs
  424. CDmAttribute *pAttr = GetFromAttribute();
  425. if ( pAttr != NULL )
  426. {
  427. attrs.AddToTail( pAttr );
  428. }
  429. }
  430. void CDmeChannel::GetOutputAttributes( CUtlVector< CDmAttribute * > &attrs )
  431. {
  432. ChannelMode_t mode = GetMode();
  433. if ( mode == CM_OFF )
  434. return; // off ignores inputs
  435. if ( mode == CM_RECORD || mode == CM_PASS )
  436. {
  437. if ( GetFromAttribute() == GetToAttribute() )
  438. return; // record/pass from and to the same attribute doesn't write anything
  439. }
  440. CDmAttribute *pAttr = GetToAttribute();
  441. if ( pAttr != NULL )
  442. {
  443. attrs.AddToTail( pAttr );
  444. }
  445. }
  446. //-----------------------------------------------------------------------------
  447. // accessors
  448. //-----------------------------------------------------------------------------
  449. CDmElement *CDmeChannel::GetFromElement() const
  450. {
  451. return m_fromElement;
  452. }
  453. CDmElement *CDmeChannel::GetToElement() const
  454. {
  455. return m_toElement;
  456. }
  457. void CDmeChannel::SetLog( CDmeLog *pLog )
  458. {
  459. m_log = pLog;
  460. }
  461. CDmeLog *CDmeChannel::CreateLog( DmAttributeType_t type )
  462. {
  463. CDmeLog *log = CDmeLog::CreateLog( type, GetFileId() );
  464. m_log.Set( log );
  465. return log;
  466. }
  467. // 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
  468. // up an attribute from some other element or vice versa.
  469. void CDmeChannel::SetInput( CDmElement* pElement, const char* pAttribute, int index )
  470. {
  471. m_fromElement.Set( pElement );
  472. m_fromAttribute.Set( pAttribute );
  473. m_fromIndex.Set( index );
  474. SetupFromAttribute();
  475. }
  476. void CDmeChannel::SetOutput( CDmElement* pElement, const char* pAttribute, int index )
  477. {
  478. m_toElement.Set( pElement );
  479. m_toAttribute.Set( pAttribute );
  480. m_toIndex.Set( index );
  481. SetupToAttribute();
  482. }
  483. void CDmeChannel::SetInput( CDmAttribute *pAttribute, int index )
  484. {
  485. if ( pAttribute )
  486. {
  487. SetInput( pAttribute->GetOwner(), pAttribute->GetName(), index );
  488. }
  489. else
  490. {
  491. SetInput( NULL, "", index );
  492. }
  493. }
  494. void CDmeChannel::SetOutput( CDmAttribute *pAttribute, int index )
  495. {
  496. if ( pAttribute )
  497. {
  498. SetOutput( pAttribute->GetOwner(), pAttribute->GetName(), index );
  499. }
  500. else
  501. {
  502. SetOutput( NULL, "", index );
  503. }
  504. }
  505. ChannelMode_t CDmeChannel::GetMode()
  506. {
  507. return static_cast< ChannelMode_t >( m_mode.Get() );
  508. }
  509. void CDmeChannel::SetMode( ChannelMode_t mode )
  510. {
  511. if ( mode != m_mode )
  512. {
  513. m_mode.Set( static_cast< int >( mode ) );
  514. m_tPreviousTime = DMETIME_INVALID;
  515. }
  516. }
  517. void CDmeChannel::ClearLog()
  518. {
  519. GetLog()->ClearKeys();
  520. }
  521. CDmeLog *CDmeChannel::GetLog()
  522. {
  523. if ( !m_log.GetElement() && ( m_FromAttributeHandle == DMATTRIBUTE_HANDLE_INVALID ) )
  524. {
  525. // NOTE: This will generate a new log based on the from attribute
  526. SetupFromAttribute();
  527. }
  528. return m_log.GetElement();
  529. }
  530. //-----------------------------------------------------------------------------
  531. // Used to cache off handles to attributes
  532. //-----------------------------------------------------------------------------
  533. CDmAttribute *CDmeChannel::SetupFromAttribute()
  534. {
  535. m_FromAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  536. CDmElement *pObject = m_fromElement.GetElement();
  537. const char *pName = m_fromAttribute.Get();
  538. if ( pObject == NULL || pName == NULL || !pName[0] )
  539. return NULL;
  540. CDmAttribute *pAttr = pObject->GetAttribute( pName );
  541. if ( !pAttr )
  542. return NULL;
  543. m_FromAttributeHandle = pAttr->GetHandle();
  544. DmAttributeType_t fromType = pAttr->GetType();
  545. if ( IsArrayType( fromType ) )
  546. {
  547. fromType = ArrayTypeToValueType( fromType );
  548. }
  549. CDmeLog *pLog = m_log.GetElement();
  550. if ( pLog == NULL )
  551. {
  552. CreateLog( fromType );
  553. return pAttr;
  554. }
  555. DmAttributeType_t logType = pLog->GetDataType();
  556. if ( IsArrayType( logType ) )
  557. {
  558. logType = ArrayTypeToValueType( logType );
  559. }
  560. if ( logType != fromType )
  561. {
  562. // NOTE: This will release the current log
  563. CreateLog( fromType );
  564. }
  565. return pAttr;
  566. }
  567. CDmAttribute *CDmeChannel::SetupToAttribute()
  568. {
  569. m_ToAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  570. CDmElement *pObject = m_toElement.GetElement();
  571. const char *pName = m_toAttribute.Get();
  572. if ( pObject == NULL || pName == NULL || !pName[0] )
  573. return NULL;
  574. CDmAttribute *pAttr = pObject->GetAttribute( pName );
  575. if ( !pAttr )
  576. return NULL;
  577. m_ToAttributeHandle = pAttr->GetHandle();
  578. return pAttr;
  579. }
  580. //-----------------------------------------------------------------------------
  581. // This function gets called whenever an attribute changes
  582. //-----------------------------------------------------------------------------
  583. void CDmeChannel::OnAttributeChanged( CDmAttribute *pAttribute )
  584. {
  585. if ( ( pAttribute == m_fromElement .GetAttribute() ) ||
  586. ( pAttribute == m_fromAttribute.GetAttribute() ) )
  587. {
  588. // NOTE: This will force a recache of the attribute handle
  589. m_FromAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  590. return;
  591. }
  592. if ( ( pAttribute == m_toElement .GetAttribute() ) ||
  593. ( pAttribute == m_toAttribute.GetAttribute() ) )
  594. {
  595. m_ToAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  596. return;
  597. }
  598. BaseClass::OnAttributeChanged( pAttribute );
  599. }
  600. DmeTime_t CDmeChannel::GetCurrentTime() const
  601. {
  602. return m_tCurrentTime;
  603. }
  604. //-----------------------------------------------------------------------------
  605. // Simple version. Only works if multiple active channels clips
  606. // do not reference the same channels
  607. //-----------------------------------------------------------------------------
  608. void CDmeChannel::SetCurrentTime( DmeTime_t time )
  609. {
  610. m_tPreviousTime = m_tCurrentTime;
  611. m_tCurrentTime = time;
  612. m_timeOutsideTimeframe = DMETIME_ZERO;
  613. }
  614. //-----------------------------------------------------------------------------
  615. // SetCurrentTime sets the current time on the clip,
  616. // choosing the time closest to (and after) a timeframe if multiple sets in a frame
  617. //-----------------------------------------------------------------------------
  618. void CDmeChannel::SetCurrentTime( DmeTime_t time, DmeTime_t start, DmeTime_t end )
  619. {
  620. m_tPreviousTime = m_tCurrentTime;
  621. DmeTime_t dt( 0 );
  622. if ( time < start )
  623. {
  624. dt = time - start;
  625. time = start;
  626. }
  627. else if ( time >= end )
  628. {
  629. dt = time - end;
  630. time = end;
  631. }
  632. DmeTime_t totf = m_timeOutsideTimeframe;
  633. const DmeTime_t t0( 0 );
  634. if ( ( dt < t0 && totf < t0 && dt < totf ) || // both prior to clip, old totf closer
  635. ( dt < t0 && totf >= t0 ) || // new dt prior to clip, old totf in or after
  636. ( dt >= t0 && totf >= t0 && dt > totf ) ) // both after clip, old totf closer
  637. return; // if old todt is a better match, don't update channel time
  638. m_tCurrentTime = time;
  639. m_timeOutsideTimeframe = dt;
  640. }
  641. //-----------------------------------------------------------------------------
  642. // ClearTimeMetric marks m_timeOutsideTimeframe invalid (-inf is the worst possible match)
  643. //-----------------------------------------------------------------------------
  644. void CDmeChannel::ClearTimeMetric()
  645. {
  646. m_timeOutsideTimeframe = DmeTime_t::MinTime();
  647. }
  648. void CDmeChannel::SetChannelToPlayToSelf( const char *outputAttributeName, float defaultValue, bool force /*= false*/ )
  649. {
  650. if ( !HasAttribute( outputAttributeName ) )
  651. {
  652. AddAttribute( outputAttributeName, AT_FLOAT );
  653. }
  654. CDmeTypedLog< bool > *log = static_cast< CDmeTypedLog< bool >* >( GetLog() );
  655. // Usually we won't put it into playback if it's empty, we'll just read the default value continously
  656. if ( force || ( log && !log->IsEmpty() && !log->HasDefaultValue() ) )
  657. {
  658. SetMode( CM_PLAY );
  659. SetOutput( this, outputAttributeName );
  660. }
  661. SetValue( outputAttributeName, defaultValue );
  662. }
  663. void CDmeChannel::SetNextKeyCurveType( int nCurveType )
  664. {
  665. m_nNextCurveType = nCurveType;
  666. }
  667. CDmeLogLayer *FindLayerInSnapshot( const CDmrElementArray<CDmElement>& snapshotArray, CDmeLog *origLog )
  668. {
  669. if ( !snapshotArray.IsValid() )
  670. return NULL;
  671. int c = snapshotArray.Count();
  672. for ( int i = 0; i < c; ++i )
  673. {
  674. CDmeLogLayer *layer = CastElement< CDmeLogLayer >( snapshotArray[ i ] );
  675. if ( !layer )
  676. continue;
  677. CDmeLog *pLog = layer->GetValueElement< CDmeLog >( "origLog" );
  678. if ( !pLog )
  679. {
  680. Assert( 0 );
  681. continue;
  682. }
  683. if ( pLog == origLog )
  684. return layer;
  685. }
  686. return NULL;
  687. }
  688. KeyValues *FindLayerInPasteData( const CUtlVector< KeyValues * > &list, CDmeLog *log )
  689. {
  690. int c = list.Count();
  691. for ( int i = 0; i < c; ++i )
  692. {
  693. CDisableUndoScopeGuard noundo;
  694. KeyValues *kv = list[ i ];
  695. Assert( kv );
  696. if ( Q_stricmp( kv->GetName(), "ControlLayers" ) )
  697. continue;
  698. LayerSelectionData_t *data = reinterpret_cast< LayerSelectionData_t * >( kv->GetPtr( "LayerData" ) );
  699. if ( !data )
  700. continue;
  701. CDmeChannel *ch = data->m_hChannel;
  702. if ( !ch )
  703. continue;
  704. CDmeLog *chLog = ch->GetLog();
  705. if ( chLog == log )
  706. return kv;
  707. }
  708. return NULL;
  709. }
  710. static int FindSpanningLayerAndSetIntensity( DmeLog_TimeSelection_t &ts, LayerSelectionData_t *data )
  711. {
  712. Assert( data->m_vecData.Count() >= 2 );
  713. float frac = ts.m_flIntensity;
  714. int i = 0;
  715. for ( ; i < data->m_vecData.Count() - 1; ++i )
  716. {
  717. LayerSelectionData_t::DataLayer_t *current = &data->m_vecData[ i ];
  718. LayerSelectionData_t::DataLayer_t *next = &data->m_vecData[ i + 1 ];
  719. if ( frac >= current->m_flStartFraction && frac <= next->m_flStartFraction )
  720. {
  721. frac = RemapVal( frac, current->m_flStartFraction, next->m_flStartFraction, 0.0f, 1.0f );
  722. ts.m_flIntensity = frac;
  723. break;
  724. }
  725. }
  726. return i;
  727. }
  728. void CDmeChannel::Record()
  729. {
  730. VPROF( "CDmeChannel::Record" );
  731. CDmAttribute *pFromAttr = GetFromAttribute();
  732. if ( pFromAttr == NULL )
  733. return; // or clear out the log?
  734. CDmeLog *pLog = GetLog();
  735. DmeTime_t time = GetCurrentTime();
  736. if ( m_tPreviousTime == DMETIME_INVALID )
  737. {
  738. m_tPreviousTime = time;
  739. }
  740. if ( g_pChannelRecordingMgr->ShouldRecordUsingTimeSelection() )
  741. {
  742. Assert( m_nRecordLayerIndex != -1 );
  743. // Computes local times for the time selection
  744. DmeLog_TimeSelection_t timeSelection;
  745. g_pChannelRecordingMgr->GetLocalTimeSelection( timeSelection, m_nRecordLayerIndex );
  746. int nType = g_pChannelRecordingMgr->GetProceduralType();
  747. switch ( nType )
  748. {
  749. default:
  750. case PROCEDURAL_PRESET_NOT:
  751. {
  752. pLog->StampKeyAtHead( time, m_tPreviousTime, timeSelection, pFromAttr, m_fromIndex.Get() );
  753. }
  754. break;
  755. case PROCEDURAL_PRESET_REVEAL:
  756. {
  757. // Find the matching layer in the "target" data array
  758. const CDmrElementArray<CDmElement> snapshotArray = const_cast< CDmAttribute * >( g_pChannelRecordingMgr->GetProceduralTarget() );
  759. CDmeLogLayer *snapshotLayer = FindLayerInSnapshot( snapshotArray, pLog );
  760. if ( snapshotLayer )
  761. {
  762. Assert( pLog );
  763. pLog->RevealUsingTimeSelection( timeSelection, snapshotLayer );
  764. }
  765. }
  766. break;
  767. case PROCEDURAL_PRESET_JITTER:
  768. case PROCEDURAL_PRESET_SMOOTH:
  769. case PROCEDURAL_PRESET_SHARPEN:
  770. case PROCEDURAL_PRESET_SOFTEN:
  771. case PROCEDURAL_PRESET_STAGGER:
  772. case PROCEDURAL_PRESET_PASTE:
  773. {
  774. const CUtlVector< KeyValues * > &pasteTarget = g_pChannelRecordingMgr->GetPasteTarget();
  775. KeyValues *layer = FindLayerInPasteData( pasteTarget, pLog );
  776. if ( layer )
  777. {
  778. LayerSelectionData_t *data = reinterpret_cast< LayerSelectionData_t * >( layer->GetPtr( "LayerData" ) );
  779. Assert( data );
  780. int iSourceLayer = FindSpanningLayerAndSetIntensity( timeSelection, data );
  781. CDmeLogLayer *sourceLayer = data->m_vecData[ iSourceLayer ].m_hData.Get();
  782. CDmeLogLayer *targetLayer = data->m_vecData[ iSourceLayer + 1 ].m_hData.Get();
  783. if ( sourceLayer && sourceLayer->GetKeyCount() > 0 &&
  784. targetLayer && targetLayer->GetKeyCount() > 0 &&
  785. sourceLayer->GetKeyCount() == targetLayer->GetKeyCount() )
  786. {
  787. Assert( pLog->GetNumLayers() >= 2 );
  788. CDmeLogLayer *outputLayer = pLog->GetLayer( pLog->GetTopmostLayer() );
  789. if ( nType == PROCEDURAL_PRESET_STAGGER )
  790. {
  791. pLog->BlendTimesUsingTimeSelection( sourceLayer, targetLayer, outputLayer, timeSelection, data->m_tStartOffset );
  792. }
  793. else
  794. {
  795. pLog->BlendLayersUsingTimeSelection( sourceLayer, targetLayer, outputLayer, timeSelection, false, data->m_tStartOffset );
  796. }
  797. }
  798. }
  799. }
  800. break;
  801. }
  802. }
  803. else
  804. {
  805. if ( m_tPreviousTime != time )
  806. {
  807. pLog->SetDuplicateKeyAtTime( m_tPreviousTime );
  808. }
  809. pLog->SetKey( time, pFromAttr, m_fromIndex.Get(), m_nNextCurveType );
  810. m_nNextCurveType = CURVE_DEFAULT;
  811. }
  812. // Output the data that's in the log
  813. Play();
  814. }
  815. //-----------------------------------------------------------------------------
  816. // Builds a clip stack that passes through root + shot
  817. // Returns true if it succeeded
  818. //-----------------------------------------------------------------------------
  819. bool CDmeChannel::BuildClipStack( DmeClipStack_t *pClipStack, CDmeClip *pRoot, CDmeClip *pShot )
  820. {
  821. DmAttributeReferenceIterator_t it;
  822. for ( it = g_pDataModel->FirstAttributeReferencingElement( GetHandle() );
  823. it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
  824. it = g_pDataModel->NextAttributeReferencingElement( it ) )
  825. {
  826. CDmAttribute *pAttribute = g_pDataModel->GetAttribute( it );
  827. CDmElement *pElement = pAttribute->GetOwner();
  828. CDmeChannelsClip *pChannelsClip = CastElement< CDmeChannelsClip >( pElement );
  829. if ( !pChannelsClip )
  830. continue;
  831. if ( pChannelsClip->BuildClipStack( pClipStack, pRoot, pShot ) )
  832. return true;
  833. }
  834. return false;
  835. }
  836. //-----------------------------------------------------------------------------
  837. // Finds the owner clip for a channel which passes through the root
  838. //-----------------------------------------------------------------------------
  839. CDmeClip* CDmeChannel::FindOwnerClipForChannel( CDmeClip *pRoot )
  840. {
  841. DmeClipStack_t stack;
  842. if ( BuildClipStack( &stack, pRoot, pRoot ) )
  843. return stack[ stack.Count() - 1 ];
  844. return NULL;
  845. }