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
532 lines
14 KiB
//====== 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;
|
|
}
|