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.

524 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "movieobjects/dmetrackgroup.h"
  7. #include <limits.h>
  8. #include "tier0/dbg.h"
  9. #include "datamodel/dmelementfactoryhelper.h"
  10. #include "movieobjects/dmetrack.h"
  11. #include "movieobjects/dmeclip.h"
  12. #include "movieobjects_interfaces.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. //-----------------------------------------------------------------------------
  16. // CDmeTrackGroup - contains a list of tracks
  17. //-----------------------------------------------------------------------------
  18. IMPLEMENT_ELEMENT_FACTORY( DmeTrackGroup, CDmeTrackGroup );
  19. void CDmeTrackGroup::OnConstruction()
  20. {
  21. m_hOwner = DMELEMENT_HANDLE_INVALID;
  22. m_Tracks.Init( this, "tracks", FATTRIB_MUSTCOPY | FATTRIB_HAS_ARRAY_CALLBACK );
  23. m_bIsVisible.InitAndSet( this, "visible", true );
  24. m_bMute.Init( this, "mute" );
  25. m_nDisplaySize.InitAndSet( this, "displaySize", 110 );
  26. m_bMinimized.InitAndSet( this, "minimized", true );
  27. m_nMaxTrackCount = INT_MAX;
  28. m_Volume.InitAndSet( this, "volume", 1.0 );
  29. }
  30. void CDmeTrackGroup::OnDestruction()
  31. {
  32. // NOTE: The track owner handles may still be pointing to us when we get destructed,
  33. // but their handles will be invalid, so GetTrackGroup on a track
  34. // will correctly return NULL.
  35. }
  36. //-----------------------------------------------------------------------------
  37. // Max track count
  38. //-----------------------------------------------------------------------------
  39. void CDmeTrackGroup::SetMaxTrackCount( int nCount )
  40. {
  41. m_nMaxTrackCount = nCount;
  42. }
  43. //-----------------------------------------------------------------------------
  44. // Mute
  45. //-----------------------------------------------------------------------------
  46. void CDmeTrackGroup::SetMute( bool state )
  47. {
  48. m_bMute = state;
  49. }
  50. bool CDmeTrackGroup::IsMute( ) const
  51. {
  52. return m_bMute;
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Volume
  56. //-----------------------------------------------------------------------------
  57. void CDmeTrackGroup::SetVolume( float state )
  58. {
  59. m_Volume = state;
  60. }
  61. float CDmeTrackGroup::GetVolume() const
  62. {
  63. return m_Volume.Get();
  64. }
  65. //-----------------------------------------------------------------------------
  66. // Owning clip
  67. //-----------------------------------------------------------------------------
  68. CDmeClip *CDmeTrackGroup::GetOwnerClip()
  69. {
  70. return GetElement< CDmeClip >( m_hOwner );
  71. }
  72. void CDmeTrackGroup::SetOwnerClip( CDmeClip *pClip )
  73. {
  74. m_hOwner = pClip ? pClip->GetHandle() : DMELEMENT_HANDLE_INVALID;
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Are we a film track group?
  78. //-----------------------------------------------------------------------------
  79. bool CDmeTrackGroup::IsFilmTrackGroup()
  80. {
  81. CDmeClip *pOwnerClip = GetOwnerClip();
  82. if ( pOwnerClip )
  83. return pOwnerClip->GetFilmTrackGroup() == this;
  84. return m_nMaxTrackCount == 1;
  85. }
  86. //-----------------------------------------------------------------------------
  87. // Is a particular clip typed able to be added?
  88. //-----------------------------------------------------------------------------
  89. bool CDmeTrackGroup::IsSubClipTypeAllowed( DmeClipType_t type )
  90. {
  91. if ( IsFilmTrackGroup() )
  92. {
  93. if ( type != DMECLIP_FILM )
  94. return false;
  95. }
  96. else
  97. {
  98. if ( type == DMECLIP_FILM )
  99. return false;
  100. }
  101. CDmeClip *pOwnerClip = GetOwnerClip();
  102. Assert( pOwnerClip );
  103. if ( !pOwnerClip )
  104. return true;
  105. return pOwnerClip->IsSubClipTypeAllowed( type );
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Track addition/removal
  109. //-----------------------------------------------------------------------------
  110. void CDmeTrackGroup::AddTrack( CDmeTrack *pTrack )
  111. {
  112. // FIXME: Should check if track with same name already exists???
  113. if ( GetTrackIndex( pTrack ) < 0 )
  114. {
  115. // Tracks can only exist in one track group
  116. Assert( GetTrackIndex( pTrack ) >= 0 );
  117. m_Tracks.AddToTail( pTrack );
  118. Assert( m_nMaxTrackCount >= m_Tracks.Count() );
  119. }
  120. }
  121. CDmeTrack* CDmeTrackGroup::AddTrack( const char *pTrackName, DmeClipType_t trackType )
  122. {
  123. CDmeTrack *pTrack = CreateElement< CDmeTrack >( pTrackName, GetFileId() );
  124. pTrack->SetClipType( trackType );
  125. pTrack->SetCollapsed( false );
  126. m_Tracks.AddToTail( pTrack );
  127. Assert( m_nMaxTrackCount >= m_Tracks.Count() );
  128. return pTrack;
  129. }
  130. CDmeTrack* CDmeTrackGroup::FindOrAddTrack( const char *pTrackName, DmeClipType_t trackType )
  131. {
  132. CDmeTrack *pTrack = FindTrack( pTrackName );
  133. if ( pTrack )
  134. {
  135. // If we found it, but it's the wrong type, no dice
  136. if ( pTrack->GetClipType() != trackType )
  137. return NULL;
  138. }
  139. else
  140. {
  141. pTrack = AddTrack( pTrackName, trackType );
  142. }
  143. return pTrack;
  144. }
  145. void CDmeTrackGroup::RemoveTrack( int nIndex )
  146. {
  147. m_Tracks.Remove( nIndex );
  148. }
  149. void CDmeTrackGroup::RemoveTrack( CDmeTrack *pTrack )
  150. {
  151. int i = GetTrackIndex( pTrack );
  152. if ( i >= 0 )
  153. {
  154. m_Tracks.Remove( i );
  155. }
  156. }
  157. void CDmeTrackGroup::RemoveTrack( const char *pTrackName )
  158. {
  159. if ( !pTrackName )
  160. {
  161. pTrackName = DMETRACK_DEFAULT_NAME;
  162. }
  163. int c = m_Tracks.Count();
  164. for ( int i = c; --i >= 0; )
  165. {
  166. if ( !Q_strcmp( m_Tracks[i]->GetName(), pTrackName ) )
  167. {
  168. m_Tracks.Remove( i );
  169. return;
  170. }
  171. }
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Track finding
  175. //-----------------------------------------------------------------------------
  176. CDmeTrack *CDmeTrackGroup::FindTrack( const char *pTrackName ) const
  177. {
  178. if ( !pTrackName )
  179. {
  180. pTrackName = DMETRACK_DEFAULT_NAME;
  181. }
  182. int c = m_Tracks.Count();
  183. for ( int i = 0 ; i < c; ++i )
  184. {
  185. CDmeTrack *pTrack = m_Tracks[i];
  186. if ( !pTrack )
  187. continue;
  188. if ( !Q_strcmp( pTrack->GetName(), pTrackName ) )
  189. return pTrack;
  190. }
  191. return NULL;
  192. }
  193. int CDmeTrackGroup::GetTrackIndex( CDmeTrack *pTrack ) const
  194. {
  195. int nTracks = m_Tracks.Count();
  196. for ( int i = 0 ; i < nTracks; ++i )
  197. {
  198. if ( pTrack == m_Tracks[i] )
  199. return i;
  200. }
  201. return -1;
  202. }
  203. //-----------------------------------------------------------------------------
  204. // Creates the film track group [for internal use only]
  205. //-----------------------------------------------------------------------------
  206. CDmeTrack *CDmeTrackGroup::CreateFilmTrack()
  207. {
  208. Assert( GetTrackCount() == 0 );
  209. return AddTrack( "Film", DMECLIP_FILM );
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Returns the film track, if any
  213. //-----------------------------------------------------------------------------
  214. CDmeTrack *CDmeTrackGroup::GetFilmTrack()
  215. {
  216. if ( !IsFilmTrackGroup() )
  217. return NULL;
  218. if ( GetTrackCount() > 0 )
  219. {
  220. Assert( GetTrackCount() == 1 );
  221. return m_Tracks[0];
  222. }
  223. return NULL;
  224. }
  225. //-----------------------------------------------------------------------------
  226. // Adding/removing clips from tracks
  227. //-----------------------------------------------------------------------------
  228. CDmeTrack *CDmeTrackGroup::AddClip( CDmeClip *pClip, const char *pTrackName )
  229. {
  230. DmeClipType_t type = pClip->GetClipType();
  231. if ( !pTrackName )
  232. {
  233. pTrackName = DMETRACK_DEFAULT_NAME;
  234. }
  235. CDmeTrack *pTrack = FindOrAddTrack( pTrackName, type );
  236. if ( pTrack )
  237. {
  238. pTrack->AddClip( pClip );
  239. }
  240. return pTrack;
  241. }
  242. bool CDmeTrackGroup::RemoveClip( CDmeClip *pClip )
  243. {
  244. CDmeTrack *pTrack = FindTrackForClip( pClip );
  245. if ( pTrack )
  246. return pTrack->RemoveClip( pClip );
  247. return false;
  248. }
  249. //-----------------------------------------------------------------------------
  250. // Changing clip track
  251. //-----------------------------------------------------------------------------
  252. CDmeTrack *CDmeTrackGroup::ChangeTrack( CDmeClip *pClip, const char *pNewTrack )
  253. {
  254. // Add, then remove, to avoid refcount problems
  255. // Don't remove if it wasn't added for some reason.
  256. CDmeTrack *pOldTrack = FindTrackForClip( pClip );
  257. CDmeTrack *pTrack = AddClip( pClip, pNewTrack );
  258. if ( pTrack && pOldTrack )
  259. {
  260. pOldTrack->RemoveClip( pClip );
  261. }
  262. return pTrack;
  263. }
  264. //-----------------------------------------------------------------------------
  265. // Finding clips in tracks
  266. //-----------------------------------------------------------------------------
  267. CDmeTrack *CDmeTrackGroup::FindTrackForClip( CDmeClip *pClip ) const
  268. {
  269. int nTrackIndex = -1;
  270. if ( !FindTrackForClip( pClip, &nTrackIndex, NULL ) )
  271. return NULL;
  272. return GetTrack( nTrackIndex );
  273. }
  274. bool CDmeTrackGroup::FindTrackForClip( CDmeClip *pClip, int *pTrackIndex, int *pClipIndex ) const
  275. {
  276. DmeClipType_t type = pClip->GetClipType();
  277. int c = GetTrackCount();
  278. for ( int i = 0; i < c; ++i )
  279. {
  280. CDmeTrack *pTrack = GetTrack( i );
  281. if ( !pTrack )
  282. continue;
  283. if ( pTrack->GetClipType() != type )
  284. continue;
  285. int nClipCount = pTrack->GetClipCount();
  286. for ( int j = 0; j < nClipCount; ++j )
  287. {
  288. if ( pTrack->GetClip( j ) == pClip )
  289. {
  290. if ( pTrackIndex )
  291. {
  292. *pTrackIndex = i;
  293. }
  294. if ( pClipIndex )
  295. {
  296. *pClipIndex = j;
  297. }
  298. return true;
  299. }
  300. }
  301. }
  302. return false;
  303. }
  304. //-----------------------------------------------------------------------------
  305. // Finding clips in tracks by time
  306. //-----------------------------------------------------------------------------
  307. void CDmeTrackGroup::FindClipsAtTime( DmeClipType_t clipType, DmeTime_t time, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const
  308. {
  309. if ( ( flags & DMESKIP_INVISIBLE ) && ( !IsVisible() || IsMinimized() ) )
  310. return;
  311. if ( ( flags & DMESKIP_MUTED ) && IsMute() )
  312. return;
  313. int c = GetTrackCount();
  314. for ( int i = 0; i < c; ++i )
  315. {
  316. CDmeTrack *pTrack = GetTrack( i );
  317. if ( !pTrack )
  318. continue;
  319. if ( ( clipType != DMECLIP_UNKNOWN ) && ( pTrack->GetClipType() != clipType ) )
  320. continue;
  321. pTrack->FindClipsAtTime( time, flags, clips );
  322. }
  323. }
  324. void CDmeTrackGroup::FindClipsIntersectingTime( DmeClipType_t clipType, DmeTime_t startTime, DmeTime_t endTime, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const
  325. {
  326. if ( ( flags & DMESKIP_INVISIBLE ) && ( !IsVisible() || IsMinimized() ) )
  327. return;
  328. if ( ( flags & DMESKIP_MUTED ) && IsMute() )
  329. return;
  330. int c = GetTrackCount();
  331. for ( int i = 0; i < c; ++i )
  332. {
  333. CDmeTrack *pTrack = GetTrack( i );
  334. if ( !pTrack )
  335. continue;
  336. if ( ( clipType != DMECLIP_UNKNOWN ) && ( pTrack->GetClipType() != clipType ) )
  337. continue;
  338. pTrack->FindClipsIntersectingTime( startTime, endTime, flags, clips );
  339. }
  340. }
  341. void CDmeTrackGroup::FindClipsWithinTime( DmeClipType_t clipType, DmeTime_t startTime, DmeTime_t endTime, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const
  342. {
  343. if ( ( flags & DMESKIP_INVISIBLE ) && ( !IsVisible() || IsMinimized() ) )
  344. return;
  345. if ( ( flags & DMESKIP_MUTED ) && IsMute() )
  346. return;
  347. int c = GetTrackCount();
  348. for ( int i = 0; i < c; ++i )
  349. {
  350. CDmeTrack *pTrack = GetTrack( i );
  351. if ( !pTrack )
  352. continue;
  353. if ( ( clipType != DMECLIP_UNKNOWN ) && ( pTrack->GetClipType() != clipType ) )
  354. continue;
  355. pTrack->FindClipsWithinTime( startTime, endTime, flags, clips );
  356. }
  357. }
  358. //-----------------------------------------------------------------------------
  359. // Removes empty tracks
  360. //-----------------------------------------------------------------------------
  361. void CDmeTrackGroup::RemoveEmptyTracks()
  362. {
  363. int tc = GetTrackCount();
  364. for ( int i = tc; --i >= 0; )
  365. {
  366. CDmeTrack *pTrack = GetTrack( i );
  367. if ( pTrack->GetClipCount() == 0 )
  368. {
  369. RemoveTrack( i );
  370. }
  371. }
  372. }
  373. //-----------------------------------------------------------------------------
  374. // Sort tracks by track type, then alphabetically
  375. //-----------------------------------------------------------------------------
  376. static int TrackLessFunc( const void * lhs, const void * rhs )
  377. {
  378. CDmeTrack *pInfo1 = *(CDmeTrack**)lhs;
  379. CDmeTrack *pInfo2 = *(CDmeTrack**)rhs;
  380. if ( pInfo1->GetClipType() < pInfo2->GetClipType() )
  381. return -1;
  382. if ( pInfo1->GetClipType() > pInfo2->GetClipType() )
  383. return 1;
  384. return Q_strcmp( pInfo1->GetName(), pInfo2->GetName() );
  385. }
  386. void CDmeTrackGroup::SortTracksByType()
  387. {
  388. int tc = GetTrackCount();
  389. if ( tc == 0 )
  390. return;
  391. CDmeTrack **ppTrack = (CDmeTrack**)_alloca( tc * sizeof(CDmeTrack*) );
  392. for ( int i = 0; i < tc; ++i )
  393. {
  394. ppTrack[i] = GetTrack(i);
  395. }
  396. qsort( ppTrack, tc, sizeof(CDmeTrack*), TrackLessFunc );
  397. m_Tracks.RemoveAll();
  398. for ( int i = 0; i < tc; ++i )
  399. {
  400. m_Tracks.AddToTail( ppTrack[i] );
  401. }
  402. }
  403. //-----------------------------------------------------------------------------
  404. // Returns the flattened clip count
  405. //-----------------------------------------------------------------------------
  406. int CDmeTrackGroup::GetSubClipCount() const
  407. {
  408. int nCount = 0;
  409. DMETRACKGROUP_FOREACH_CLIP_START( this, pTrack, pClip )
  410. ++nCount;
  411. DMETRACKGROUP_FOREACH_CLIP_END()
  412. return nCount;
  413. }
  414. void CDmeTrackGroup::GetSubClips( CDmeClip **ppClips )
  415. {
  416. int nCount = 0;
  417. DMETRACKGROUP_FOREACH_CLIP_START( this, pTrack, pClip )
  418. ppClips[nCount++] = pClip;
  419. DMETRACKGROUP_FOREACH_CLIP_END()
  420. }
  421. //-----------------------------------------------------------------------------
  422. // helper methods
  423. //-----------------------------------------------------------------------------
  424. CDmeFilmClip *GetParentClip( CDmeTrackGroup *pTrackGroup )
  425. {
  426. DmAttributeReferenceIterator_t hAttr = g_pDataModel->FirstAttributeReferencingElement( pTrackGroup->GetHandle() );
  427. for ( ; hAttr != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; hAttr = g_pDataModel->NextAttributeReferencingElement( hAttr ) )
  428. {
  429. CDmAttribute *pAttr = g_pDataModel->GetAttribute( hAttr );
  430. if ( !pAttr )
  431. continue;
  432. CDmeFilmClip *pFilmClip = CastElement< CDmeFilmClip >( pAttr->GetOwner() );
  433. if ( pFilmClip )
  434. return pFilmClip;
  435. }
  436. return NULL;
  437. }