diff options
Diffstat (limited to 'movieobjects/dmetrackgroup.cpp')
| -rw-r--r-- | movieobjects/dmetrackgroup.cpp | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/movieobjects/dmetrackgroup.cpp b/movieobjects/dmetrackgroup.cpp new file mode 100644 index 0000000..0070329 --- /dev/null +++ b/movieobjects/dmetrackgroup.cpp @@ -0,0 +1,524 @@ +//========= Copyright 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_hOwner = DMELEMENT_HANDLE_INVALID; + + m_Tracks.Init( this, "tracks", FATTRIB_MUSTCOPY | FATTRIB_HAS_ARRAY_CALLBACK ); + m_bIsVisible.InitAndSet( this, "visible", true ); + m_bMute.Init( this, "mute" ); + m_nDisplaySize.InitAndSet( this, "displaySize", 110 ); + m_bMinimized.InitAndSet( this, "minimized", true ); + m_nMaxTrackCount = INT_MAX; + m_Volume.InitAndSet( this, "volume", 1.0 ); + +} + +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() +{ + return GetElement< CDmeClip >( m_hOwner ); +} + +void CDmeTrackGroup::SetOwnerClip( CDmeClip *pClip ) +{ + m_hOwner = pClip ? pClip->GetHandle() : DMELEMENT_HANDLE_INVALID; +} + + +//----------------------------------------------------------------------------- +// 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() +} + +//----------------------------------------------------------------------------- +// 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; +} |