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.

532 lines
14 KiB

  1. //====== Copyright � 1996-2005, 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_Tracks.Init( this, "tracks", FATTRIB_MUSTCOPY | FATTRIB_HAS_CALLBACK );
  22. m_bIsVisible.InitAndSet( this, "visible", true );
  23. m_bMute.Init( this, "mute" );
  24. m_flDisplayScale.InitAndSet( this, "displayScale", 1.0f );
  25. m_bMinimized.InitAndSet( this, "minimized", true );
  26. m_nMaxTrackCount = INT_MAX;
  27. m_Volume.InitAndSet( this, "volume", 1.0 );
  28. m_bForceMultiTrack.InitAndSet( this, "forcemultitrack", false );
  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. CDmeClip *pFindClip = FindReferringElement< CDmeClip >( this, "subClipTrackGroup" );
  71. if ( !pFindClip )
  72. {
  73. pFindClip = FindReferringElement< CDmeClip >( this, "trackGroups" );
  74. }
  75. return pFindClip;
  76. }
  77. //-----------------------------------------------------------------------------
  78. // Are we a film track group?
  79. //-----------------------------------------------------------------------------
  80. bool CDmeTrackGroup::IsFilmTrackGroup()
  81. {
  82. CDmeClip *pOwnerClip = GetOwnerClip();
  83. if ( pOwnerClip )
  84. return pOwnerClip->GetFilmTrackGroup() == this;
  85. return m_nMaxTrackCount == 1;
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Is a particular clip typed able to be added?
  89. //-----------------------------------------------------------------------------
  90. bool CDmeTrackGroup::IsSubClipTypeAllowed( DmeClipType_t type )
  91. {
  92. if ( IsFilmTrackGroup() )
  93. {
  94. if ( type != DMECLIP_FILM )
  95. return false;
  96. }
  97. else
  98. {
  99. if ( type == DMECLIP_FILM )
  100. return false;
  101. }
  102. CDmeClip *pOwnerClip = GetOwnerClip();
  103. Assert( pOwnerClip );
  104. if ( !pOwnerClip )
  105. return true;
  106. return pOwnerClip->IsSubClipTypeAllowed( type );
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Track addition/removal
  110. //-----------------------------------------------------------------------------
  111. void CDmeTrackGroup::AddTrack( CDmeTrack *pTrack )
  112. {
  113. // FIXME: Should check if track with same name already exists???
  114. if ( GetTrackIndex( pTrack ) < 0 )
  115. {
  116. // Tracks can only exist in one track group
  117. Assert( GetTrackIndex( pTrack ) >= 0 );
  118. m_Tracks.AddToTail( pTrack );
  119. Assert( m_nMaxTrackCount >= m_Tracks.Count() );
  120. }
  121. }
  122. CDmeTrack* CDmeTrackGroup::AddTrack( const char *pTrackName, DmeClipType_t trackType )
  123. {
  124. CDmeTrack *pTrack = CreateElement< CDmeTrack >( pTrackName, GetFileId() );
  125. pTrack->SetClipType( trackType );
  126. pTrack->SetCollapsed( false );
  127. m_Tracks.AddToTail( pTrack );
  128. Assert( m_nMaxTrackCount >= m_Tracks.Count() );
  129. return pTrack;
  130. }
  131. CDmeTrack* CDmeTrackGroup::FindOrAddTrack( const char *pTrackName, DmeClipType_t trackType )
  132. {
  133. CDmeTrack *pTrack = FindTrack( pTrackName );
  134. if ( pTrack )
  135. {
  136. // If we found it, but it's the wrong type, no dice
  137. if ( pTrack->GetClipType() != trackType )
  138. return NULL;
  139. }
  140. else
  141. {
  142. pTrack = AddTrack( pTrackName, trackType );
  143. }
  144. return pTrack;
  145. }
  146. void CDmeTrackGroup::RemoveTrack( int nIndex )
  147. {
  148. m_Tracks.Remove( nIndex );
  149. }
  150. void CDmeTrackGroup::RemoveTrack( CDmeTrack *pTrack )
  151. {
  152. int i = GetTrackIndex( pTrack );
  153. if ( i >= 0 )
  154. {
  155. m_Tracks.Remove( i );
  156. }
  157. }
  158. void CDmeTrackGroup::RemoveTrack( const char *pTrackName )
  159. {
  160. if ( !pTrackName )
  161. {
  162. pTrackName = DMETRACK_DEFAULT_NAME;
  163. }
  164. int c = m_Tracks.Count();
  165. for ( int i = c; --i >= 0; )
  166. {
  167. if ( !Q_strcmp( m_Tracks[i]->GetName(), pTrackName ) )
  168. {
  169. m_Tracks.Remove( i );
  170. return;
  171. }
  172. }
  173. }
  174. //-----------------------------------------------------------------------------
  175. // Track finding
  176. //-----------------------------------------------------------------------------
  177. CDmeTrack *CDmeTrackGroup::FindTrack( const char *pTrackName ) const
  178. {
  179. if ( !pTrackName )
  180. {
  181. pTrackName = DMETRACK_DEFAULT_NAME;
  182. }
  183. int c = m_Tracks.Count();
  184. for ( int i = 0 ; i < c; ++i )
  185. {
  186. CDmeTrack *pTrack = m_Tracks[i];
  187. if ( !pTrack )
  188. continue;
  189. if ( !Q_strcmp( pTrack->GetName(), pTrackName ) )
  190. return pTrack;
  191. }
  192. return NULL;
  193. }
  194. int CDmeTrackGroup::GetTrackIndex( CDmeTrack *pTrack ) const
  195. {
  196. int nTracks = m_Tracks.Count();
  197. for ( int i = 0 ; i < nTracks; ++i )
  198. {
  199. if ( pTrack == m_Tracks[i] )
  200. return i;
  201. }
  202. return -1;
  203. }
  204. //-----------------------------------------------------------------------------
  205. // Creates the film track group [for internal use only]
  206. //-----------------------------------------------------------------------------
  207. CDmeTrack *CDmeTrackGroup::CreateFilmTrack()
  208. {
  209. Assert( GetTrackCount() == 0 );
  210. return AddTrack( "Film", DMECLIP_FILM );
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Returns the film track, if any
  214. //-----------------------------------------------------------------------------
  215. CDmeTrack *CDmeTrackGroup::GetFilmTrack()
  216. {
  217. if ( !IsFilmTrackGroup() )
  218. return NULL;
  219. if ( GetTrackCount() > 0 )
  220. {
  221. Assert( GetTrackCount() == 1 );
  222. return m_Tracks[0];
  223. }
  224. return NULL;
  225. }
  226. //-----------------------------------------------------------------------------
  227. // Adding/removing clips from tracks
  228. //-----------------------------------------------------------------------------
  229. CDmeTrack *CDmeTrackGroup::AddClip( CDmeClip *pClip, const char *pTrackName )
  230. {
  231. DmeClipType_t type = pClip->GetClipType();
  232. if ( !pTrackName )
  233. {
  234. pTrackName = DMETRACK_DEFAULT_NAME;
  235. }
  236. CDmeTrack *pTrack = FindOrAddTrack( pTrackName, type );
  237. if ( pTrack )
  238. {
  239. pTrack->AddClip( pClip );
  240. }
  241. return pTrack;
  242. }
  243. bool CDmeTrackGroup::RemoveClip( CDmeClip *pClip )
  244. {
  245. CDmeTrack *pTrack = FindTrackForClip( pClip );
  246. if ( pTrack )
  247. return pTrack->RemoveClip( pClip );
  248. return false;
  249. }
  250. //-----------------------------------------------------------------------------
  251. // Changing clip track
  252. //-----------------------------------------------------------------------------
  253. CDmeTrack *CDmeTrackGroup::ChangeTrack( CDmeClip *pClip, const char *pNewTrack )
  254. {
  255. // Add, then remove, to avoid refcount problems
  256. // Don't remove if it wasn't added for some reason.
  257. CDmeTrack *pOldTrack = FindTrackForClip( pClip );
  258. CDmeTrack *pTrack = AddClip( pClip, pNewTrack );
  259. if ( pTrack && pOldTrack )
  260. {
  261. pOldTrack->RemoveClip( pClip );
  262. }
  263. return pTrack;
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Finding clips in tracks
  267. //-----------------------------------------------------------------------------
  268. CDmeTrack *CDmeTrackGroup::FindTrackForClip( CDmeClip *pClip ) const
  269. {
  270. int nTrackIndex = -1;
  271. if ( !FindTrackForClip( pClip, &nTrackIndex, NULL ) )
  272. return NULL;
  273. return GetTrack( nTrackIndex );
  274. }
  275. bool CDmeTrackGroup::FindTrackForClip( CDmeClip *pClip, int *pTrackIndex, int *pClipIndex ) const
  276. {
  277. DmeClipType_t type = pClip->GetClipType();
  278. int c = GetTrackCount();
  279. for ( int i = 0; i < c; ++i )
  280. {
  281. CDmeTrack *pTrack = GetTrack( i );
  282. if ( !pTrack )
  283. continue;
  284. if ( pTrack->GetClipType() != type )
  285. continue;
  286. int nClipCount = pTrack->GetClipCount();
  287. for ( int j = 0; j < nClipCount; ++j )
  288. {
  289. if ( pTrack->GetClip( j ) == pClip )
  290. {
  291. if ( pTrackIndex )
  292. {
  293. *pTrackIndex = i;
  294. }
  295. if ( pClipIndex )
  296. {
  297. *pClipIndex = j;
  298. }
  299. return true;
  300. }
  301. }
  302. }
  303. return false;
  304. }
  305. //-----------------------------------------------------------------------------
  306. // Finding clips in tracks by time
  307. //-----------------------------------------------------------------------------
  308. void CDmeTrackGroup::FindClipsAtTime( DmeClipType_t clipType, DmeTime_t time, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const
  309. {
  310. if ( ( flags & DMESKIP_INVISIBLE ) && ( !IsVisible() || IsMinimized() ) )
  311. return;
  312. if ( ( flags & DMESKIP_MUTED ) && IsMute() )
  313. return;
  314. int c = GetTrackCount();
  315. for ( int i = 0; i < c; ++i )
  316. {
  317. CDmeTrack *pTrack = GetTrack( i );
  318. if ( !pTrack )
  319. continue;
  320. if ( ( clipType != DMECLIP_UNKNOWN ) && ( pTrack->GetClipType() != clipType ) )
  321. continue;
  322. pTrack->FindClipsAtTime( time, flags, clips );
  323. }
  324. }
  325. void CDmeTrackGroup::FindClipsIntersectingTime( DmeClipType_t clipType, DmeTime_t startTime, DmeTime_t endTime, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const
  326. {
  327. if ( ( flags & DMESKIP_INVISIBLE ) && ( !IsVisible() || IsMinimized() ) )
  328. return;
  329. if ( ( flags & DMESKIP_MUTED ) && IsMute() )
  330. return;
  331. int c = GetTrackCount();
  332. for ( int i = 0; i < c; ++i )
  333. {
  334. CDmeTrack *pTrack = GetTrack( i );
  335. if ( !pTrack )
  336. continue;
  337. if ( ( clipType != DMECLIP_UNKNOWN ) && ( pTrack->GetClipType() != clipType ) )
  338. continue;
  339. pTrack->FindClipsIntersectingTime( startTime, endTime, flags, clips );
  340. }
  341. }
  342. void CDmeTrackGroup::FindClipsWithinTime( DmeClipType_t clipType, DmeTime_t startTime, DmeTime_t endTime, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const
  343. {
  344. if ( ( flags & DMESKIP_INVISIBLE ) && ( !IsVisible() || IsMinimized() ) )
  345. return;
  346. if ( ( flags & DMESKIP_MUTED ) && IsMute() )
  347. return;
  348. int c = GetTrackCount();
  349. for ( int i = 0; i < c; ++i )
  350. {
  351. CDmeTrack *pTrack = GetTrack( i );
  352. if ( !pTrack )
  353. continue;
  354. if ( ( clipType != DMECLIP_UNKNOWN ) && ( pTrack->GetClipType() != clipType ) )
  355. continue;
  356. pTrack->FindClipsWithinTime( startTime, endTime, flags, clips );
  357. }
  358. }
  359. //-----------------------------------------------------------------------------
  360. // Removes empty tracks
  361. //-----------------------------------------------------------------------------
  362. void CDmeTrackGroup::RemoveEmptyTracks()
  363. {
  364. int tc = GetTrackCount();
  365. for ( int i = tc; --i >= 0; )
  366. {
  367. CDmeTrack *pTrack = GetTrack( i );
  368. if ( pTrack->GetClipCount() == 0 )
  369. {
  370. RemoveTrack( i );
  371. }
  372. }
  373. }
  374. //-----------------------------------------------------------------------------
  375. // Sort tracks by track type, then alphabetically
  376. //-----------------------------------------------------------------------------
  377. static int TrackLessFunc( const void * lhs, const void * rhs )
  378. {
  379. CDmeTrack *pInfo1 = *(CDmeTrack**)lhs;
  380. CDmeTrack *pInfo2 = *(CDmeTrack**)rhs;
  381. if ( pInfo1->GetClipType() < pInfo2->GetClipType() )
  382. return -1;
  383. if ( pInfo1->GetClipType() > pInfo2->GetClipType() )
  384. return 1;
  385. return Q_strcmp( pInfo1->GetName(), pInfo2->GetName() );
  386. }
  387. void CDmeTrackGroup::SortTracksByType()
  388. {
  389. int tc = GetTrackCount();
  390. if ( tc == 0 )
  391. return;
  392. CDmeTrack **ppTrack = (CDmeTrack**)_alloca( tc * sizeof(CDmeTrack*) );
  393. for ( int i = 0; i < tc; ++i )
  394. {
  395. ppTrack[i] = GetTrack(i);
  396. }
  397. qsort( ppTrack, tc, sizeof(CDmeTrack*), TrackLessFunc );
  398. m_Tracks.RemoveAll();
  399. for ( int i = 0; i < tc; ++i )
  400. {
  401. m_Tracks.AddToTail( ppTrack[i] );
  402. }
  403. }
  404. //-----------------------------------------------------------------------------
  405. // Returns the flattened clip count
  406. //-----------------------------------------------------------------------------
  407. int CDmeTrackGroup::GetSubClipCount() const
  408. {
  409. int nCount = 0;
  410. DMETRACKGROUP_FOREACH_CLIP_START( this, pTrack, pClip )
  411. ++nCount;
  412. DMETRACKGROUP_FOREACH_CLIP_END()
  413. return nCount;
  414. }
  415. void CDmeTrackGroup::GetSubClips( CDmeClip **ppClips )
  416. {
  417. int nCount = 0;
  418. DMETRACKGROUP_FOREACH_CLIP_START( this, pTrack, pClip )
  419. ppClips[nCount++] = pClip;
  420. DMETRACKGROUP_FOREACH_CLIP_END()
  421. }
  422. bool CDmeTrackGroup::GetForceMultiTrack() const
  423. {
  424. return const_cast< CDmeTrackGroup * >( this )->IsFilmTrackGroup() && m_bForceMultiTrack;
  425. }
  426. void CDmeTrackGroup::SetForceMultiTrack( bool bForce )
  427. {
  428. m_bForceMultiTrack = bForce;
  429. }
  430. //-----------------------------------------------------------------------------
  431. // helper methods
  432. //-----------------------------------------------------------------------------
  433. CDmeFilmClip *GetParentClip( CDmeTrackGroup *pTrackGroup )
  434. {
  435. DmAttributeReferenceIterator_t hAttr = g_pDataModel->FirstAttributeReferencingElement( pTrackGroup->GetHandle() );
  436. for ( ; hAttr != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; hAttr = g_pDataModel->NextAttributeReferencingElement( hAttr ) )
  437. {
  438. CDmAttribute *pAttr = g_pDataModel->GetAttribute( hAttr );
  439. if ( !pAttr )
  440. continue;
  441. CDmeFilmClip *pFilmClip = CastElement< CDmeFilmClip >( pAttr->GetOwner() );
  442. if ( pFilmClip )
  443. return pFilmClip;
  444. }
  445. return NULL;
  446. }