|
|
//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "movieobjects/dmetrackgroup.h"
#include <limits.h>
#include "tier0/dbg.h"
#include "datamodel/dmelementfactoryhelper.h"
#include "movieobjects/dmetrack.h"
#include "movieobjects/dmeclip.h"
#include "movieobjects_interfaces.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// CDmeTrackGroup - contains a list of tracks
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeTrackGroup, CDmeTrackGroup );
void CDmeTrackGroup::OnConstruction() { m_Tracks.Init( this, "tracks", FATTRIB_MUSTCOPY | FATTRIB_HAS_CALLBACK ); m_bIsVisible.InitAndSet( this, "visible", true ); m_bMute.Init( this, "mute" ); m_flDisplayScale.InitAndSet( this, "displayScale", 1.0f ); m_bMinimized.InitAndSet( this, "minimized", true ); m_nMaxTrackCount = INT_MAX; m_Volume.InitAndSet( this, "volume", 1.0 ); m_bForceMultiTrack.InitAndSet( this, "forcemultitrack", false ); }
void CDmeTrackGroup::OnDestruction() { // NOTE: The track owner handles may still be pointing to us when we get destructed,
// but their handles will be invalid, so GetTrackGroup on a track
// will correctly return NULL.
}
//-----------------------------------------------------------------------------
// Max track count
//-----------------------------------------------------------------------------
void CDmeTrackGroup::SetMaxTrackCount( int nCount ) { m_nMaxTrackCount = nCount; }
//-----------------------------------------------------------------------------
// Mute
//-----------------------------------------------------------------------------
void CDmeTrackGroup::SetMute( bool state ) { m_bMute = state; }
bool CDmeTrackGroup::IsMute( ) const { return m_bMute; }
//-----------------------------------------------------------------------------
// Volume
//-----------------------------------------------------------------------------
void CDmeTrackGroup::SetVolume( float state ) { m_Volume = state; } float CDmeTrackGroup::GetVolume() const { return m_Volume.Get(); }
//-----------------------------------------------------------------------------
// Owning clip
//-----------------------------------------------------------------------------
CDmeClip *CDmeTrackGroup::GetOwnerClip() { CDmeClip *pFindClip = FindReferringElement< CDmeClip >( this, "subClipTrackGroup" ); if ( !pFindClip ) { pFindClip = FindReferringElement< CDmeClip >( this, "trackGroups" ); } return pFindClip; }
//-----------------------------------------------------------------------------
// Are we a film track group?
//-----------------------------------------------------------------------------
bool CDmeTrackGroup::IsFilmTrackGroup() { CDmeClip *pOwnerClip = GetOwnerClip(); if ( pOwnerClip ) return pOwnerClip->GetFilmTrackGroup() == this; return m_nMaxTrackCount == 1; }
//-----------------------------------------------------------------------------
// Is a particular clip typed able to be added?
//-----------------------------------------------------------------------------
bool CDmeTrackGroup::IsSubClipTypeAllowed( DmeClipType_t type ) { if ( IsFilmTrackGroup() ) { if ( type != DMECLIP_FILM ) return false; } else { if ( type == DMECLIP_FILM ) return false; }
CDmeClip *pOwnerClip = GetOwnerClip(); Assert( pOwnerClip ); if ( !pOwnerClip ) return true;
return pOwnerClip->IsSubClipTypeAllowed( type ); }
//-----------------------------------------------------------------------------
// Track addition/removal
//-----------------------------------------------------------------------------
void CDmeTrackGroup::AddTrack( CDmeTrack *pTrack ) { // FIXME: Should check if track with same name already exists???
if ( GetTrackIndex( pTrack ) < 0 ) { // Tracks can only exist in one track group
Assert( GetTrackIndex( pTrack ) >= 0 ); m_Tracks.AddToTail( pTrack ); Assert( m_nMaxTrackCount >= m_Tracks.Count() ); } }
CDmeTrack* CDmeTrackGroup::AddTrack( const char *pTrackName, DmeClipType_t trackType ) { CDmeTrack *pTrack = CreateElement< CDmeTrack >( pTrackName, GetFileId() ); pTrack->SetClipType( trackType ); pTrack->SetCollapsed( false ); m_Tracks.AddToTail( pTrack ); Assert( m_nMaxTrackCount >= m_Tracks.Count() ); return pTrack; }
CDmeTrack* CDmeTrackGroup::FindOrAddTrack( const char *pTrackName, DmeClipType_t trackType ) { CDmeTrack *pTrack = FindTrack( pTrackName ); if ( pTrack ) { // If we found it, but it's the wrong type, no dice
if ( pTrack->GetClipType() != trackType ) return NULL; } else { pTrack = AddTrack( pTrackName, trackType ); } return pTrack; }
void CDmeTrackGroup::RemoveTrack( int nIndex ) { m_Tracks.Remove( nIndex ); }
void CDmeTrackGroup::RemoveTrack( CDmeTrack *pTrack ) { int i = GetTrackIndex( pTrack ); if ( i >= 0 ) { m_Tracks.Remove( i ); } }
void CDmeTrackGroup::RemoveTrack( const char *pTrackName ) { if ( !pTrackName ) { pTrackName = DMETRACK_DEFAULT_NAME; }
int c = m_Tracks.Count(); for ( int i = c; --i >= 0; ) { if ( !Q_strcmp( m_Tracks[i]->GetName(), pTrackName ) ) { m_Tracks.Remove( i ); return; } } }
//-----------------------------------------------------------------------------
// Track finding
//-----------------------------------------------------------------------------
CDmeTrack *CDmeTrackGroup::FindTrack( const char *pTrackName ) const { if ( !pTrackName ) { pTrackName = DMETRACK_DEFAULT_NAME; }
int c = m_Tracks.Count(); for ( int i = 0 ; i < c; ++i ) { CDmeTrack *pTrack = m_Tracks[i]; if ( !pTrack ) continue;
if ( !Q_strcmp( pTrack->GetName(), pTrackName ) ) return pTrack; } return NULL; }
int CDmeTrackGroup::GetTrackIndex( CDmeTrack *pTrack ) const { int nTracks = m_Tracks.Count(); for ( int i = 0 ; i < nTracks; ++i ) { if ( pTrack == m_Tracks[i] ) return i; } return -1; }
//-----------------------------------------------------------------------------
// Creates the film track group [for internal use only]
//-----------------------------------------------------------------------------
CDmeTrack *CDmeTrackGroup::CreateFilmTrack() { Assert( GetTrackCount() == 0 ); return AddTrack( "Film", DMECLIP_FILM ); }
//-----------------------------------------------------------------------------
// Returns the film track, if any
//-----------------------------------------------------------------------------
CDmeTrack *CDmeTrackGroup::GetFilmTrack() { if ( !IsFilmTrackGroup() ) return NULL;
if ( GetTrackCount() > 0 ) { Assert( GetTrackCount() == 1 ); return m_Tracks[0]; }
return NULL; }
//-----------------------------------------------------------------------------
// Adding/removing clips from tracks
//-----------------------------------------------------------------------------
CDmeTrack *CDmeTrackGroup::AddClip( CDmeClip *pClip, const char *pTrackName ) { DmeClipType_t type = pClip->GetClipType(); if ( !pTrackName ) { pTrackName = DMETRACK_DEFAULT_NAME; }
CDmeTrack *pTrack = FindOrAddTrack( pTrackName, type ); if ( pTrack ) { pTrack->AddClip( pClip ); } return pTrack; }
bool CDmeTrackGroup::RemoveClip( CDmeClip *pClip ) { CDmeTrack *pTrack = FindTrackForClip( pClip ); if ( pTrack ) return pTrack->RemoveClip( pClip ); return false; }
//-----------------------------------------------------------------------------
// Changing clip track
//-----------------------------------------------------------------------------
CDmeTrack *CDmeTrackGroup::ChangeTrack( CDmeClip *pClip, const char *pNewTrack ) { // Add, then remove, to avoid refcount problems
// Don't remove if it wasn't added for some reason.
CDmeTrack *pOldTrack = FindTrackForClip( pClip ); CDmeTrack *pTrack = AddClip( pClip, pNewTrack ); if ( pTrack && pOldTrack ) { pOldTrack->RemoveClip( pClip ); } return pTrack; }
//-----------------------------------------------------------------------------
// Finding clips in tracks
//-----------------------------------------------------------------------------
CDmeTrack *CDmeTrackGroup::FindTrackForClip( CDmeClip *pClip ) const { int nTrackIndex = -1; if ( !FindTrackForClip( pClip, &nTrackIndex, NULL ) ) return NULL;
return GetTrack( nTrackIndex ); }
bool CDmeTrackGroup::FindTrackForClip( CDmeClip *pClip, int *pTrackIndex, int *pClipIndex ) const { DmeClipType_t type = pClip->GetClipType(); int c = GetTrackCount(); for ( int i = 0; i < c; ++i ) { CDmeTrack *pTrack = GetTrack( i ); if ( !pTrack ) continue;
if ( pTrack->GetClipType() != type ) continue;
int nClipCount = pTrack->GetClipCount(); for ( int j = 0; j < nClipCount; ++j ) { if ( pTrack->GetClip( j ) == pClip ) { if ( pTrackIndex ) { *pTrackIndex = i; } if ( pClipIndex ) { *pClipIndex = j; } return true; } } } return false; }
//-----------------------------------------------------------------------------
// Finding clips in tracks by time
//-----------------------------------------------------------------------------
void CDmeTrackGroup::FindClipsAtTime( DmeClipType_t clipType, DmeTime_t time, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const { if ( ( flags & DMESKIP_INVISIBLE ) && ( !IsVisible() || IsMinimized() ) ) return;
if ( ( flags & DMESKIP_MUTED ) && IsMute() ) return;
int c = GetTrackCount(); for ( int i = 0; i < c; ++i ) { CDmeTrack *pTrack = GetTrack( i ); if ( !pTrack ) continue;
if ( ( clipType != DMECLIP_UNKNOWN ) && ( pTrack->GetClipType() != clipType ) ) continue;
pTrack->FindClipsAtTime( time, flags, clips ); } }
void CDmeTrackGroup::FindClipsIntersectingTime( DmeClipType_t clipType, DmeTime_t startTime, DmeTime_t endTime, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const { if ( ( flags & DMESKIP_INVISIBLE ) && ( !IsVisible() || IsMinimized() ) ) return;
if ( ( flags & DMESKIP_MUTED ) && IsMute() ) return;
int c = GetTrackCount(); for ( int i = 0; i < c; ++i ) { CDmeTrack *pTrack = GetTrack( i ); if ( !pTrack ) continue;
if ( ( clipType != DMECLIP_UNKNOWN ) && ( pTrack->GetClipType() != clipType ) ) continue;
pTrack->FindClipsIntersectingTime( startTime, endTime, flags, clips ); } }
void CDmeTrackGroup::FindClipsWithinTime( DmeClipType_t clipType, DmeTime_t startTime, DmeTime_t endTime, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const { if ( ( flags & DMESKIP_INVISIBLE ) && ( !IsVisible() || IsMinimized() ) ) return;
if ( ( flags & DMESKIP_MUTED ) && IsMute() ) return;
int c = GetTrackCount(); for ( int i = 0; i < c; ++i ) { CDmeTrack *pTrack = GetTrack( i ); if ( !pTrack ) continue;
if ( ( clipType != DMECLIP_UNKNOWN ) && ( pTrack->GetClipType() != clipType ) ) continue;
pTrack->FindClipsWithinTime( startTime, endTime, flags, clips ); } }
//-----------------------------------------------------------------------------
// Removes empty tracks
//-----------------------------------------------------------------------------
void CDmeTrackGroup::RemoveEmptyTracks() { int tc = GetTrackCount(); for ( int i = tc; --i >= 0; ) { CDmeTrack *pTrack = GetTrack( i ); if ( pTrack->GetClipCount() == 0 ) { RemoveTrack( i ); } } }
//-----------------------------------------------------------------------------
// Sort tracks by track type, then alphabetically
//-----------------------------------------------------------------------------
static int TrackLessFunc( const void * lhs, const void * rhs ) { CDmeTrack *pInfo1 = *(CDmeTrack**)lhs; CDmeTrack *pInfo2 = *(CDmeTrack**)rhs; if ( pInfo1->GetClipType() < pInfo2->GetClipType() ) return -1; if ( pInfo1->GetClipType() > pInfo2->GetClipType() ) return 1; return Q_strcmp( pInfo1->GetName(), pInfo2->GetName() ); }
void CDmeTrackGroup::SortTracksByType() { int tc = GetTrackCount(); if ( tc == 0 ) return;
CDmeTrack **ppTrack = (CDmeTrack**)_alloca( tc * sizeof(CDmeTrack*) ); for ( int i = 0; i < tc; ++i ) { ppTrack[i] = GetTrack(i); }
qsort( ppTrack, tc, sizeof(CDmeTrack*), TrackLessFunc );
m_Tracks.RemoveAll();
for ( int i = 0; i < tc; ++i ) { m_Tracks.AddToTail( ppTrack[i] ); } }
//-----------------------------------------------------------------------------
// Returns the flattened clip count
//-----------------------------------------------------------------------------
int CDmeTrackGroup::GetSubClipCount() const { int nCount = 0; DMETRACKGROUP_FOREACH_CLIP_START( this, pTrack, pClip ) ++nCount; DMETRACKGROUP_FOREACH_CLIP_END() return nCount; }
void CDmeTrackGroup::GetSubClips( CDmeClip **ppClips ) { int nCount = 0; DMETRACKGROUP_FOREACH_CLIP_START( this, pTrack, pClip ) ppClips[nCount++] = pClip; DMETRACKGROUP_FOREACH_CLIP_END() }
bool CDmeTrackGroup::GetForceMultiTrack() const { return const_cast< CDmeTrackGroup * >( this )->IsFilmTrackGroup() && m_bForceMultiTrack; }
void CDmeTrackGroup::SetForceMultiTrack( bool bForce ) { m_bForceMultiTrack = bForce; }
//-----------------------------------------------------------------------------
// helper methods
//-----------------------------------------------------------------------------
CDmeFilmClip *GetParentClip( CDmeTrackGroup *pTrackGroup ) { DmAttributeReferenceIterator_t hAttr = g_pDataModel->FirstAttributeReferencingElement( pTrackGroup->GetHandle() ); for ( ; hAttr != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; hAttr = g_pDataModel->NextAttributeReferencingElement( hAttr ) ) { CDmAttribute *pAttr = g_pDataModel->GetAttribute( hAttr ); if ( !pAttr ) continue;
CDmeFilmClip *pFilmClip = CastElement< CDmeFilmClip >( pAttr->GetOwner() ); if ( pFilmClip ) return pFilmClip; } return NULL; }
|