diff options
Diffstat (limited to 'movieobjects/dmeclip.cpp')
| -rw-r--r-- | movieobjects/dmeclip.cpp | 1725 |
1 files changed, 1725 insertions, 0 deletions
diff --git a/movieobjects/dmeclip.cpp b/movieobjects/dmeclip.cpp new file mode 100644 index 0000000..b97c5cb --- /dev/null +++ b/movieobjects/dmeclip.cpp @@ -0,0 +1,1725 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= +#include "movieobjects/dmeclip.h" + +#include "tier0/dbg.h" +#include "datamodel/dmelementfactoryhelper.h" +#include "datamodel/dmehandle.h" + +#include "movieobjects/dmetimeframe.h" +#include "movieobjects/dmebookmark.h" +#include "movieobjects/dmesound.h" +#include "movieobjects/dmechannel.h" +#include "movieobjects/dmecamera.h" +#include "movieobjects/dmelight.h" +#include "movieobjects/dmedag.h" +#include "movieobjects/dmeinput.h" +#include "movieobjects/dmeoperator.h" +#include "movieobjects/dmematerial.h" +#include "movieobjects/dmetrack.h" +#include "movieobjects/dmetrackgroup.h" +#include "movieobjects/dmematerialoverlayfxclip.h" +#include "movieobjects/dmeanimationset.h" +#include "movieobjects_interfaces.h" + +#include "materialsystem/imaterialsystem.h" +#include "materialsystem/imaterial.h" +#include "materialsystem/imesh.h" +#include "tier3/tier3.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// String to clip type + back +//----------------------------------------------------------------------------- +static const char *s_pClipTypeNames[DMECLIP_TYPE_COUNT] = +{ + "Channel", + "Audio", + "Effects", + "Film", +}; + +DmeClipType_t ClipTypeFromString( const char *pName ) +{ + for ( DmeClipType_t i = DMECLIP_FIRST; i <= DMECLIP_LAST; ++i ) + { + if ( !Q_stricmp( pName, s_pClipTypeNames[i] ) ) + return i; + } + return DMECLIP_UNKNOWN; +} + +const char *ClipTypeToString( DmeClipType_t type ) +{ + if ( type >= DMECLIP_FIRST && type <= DMECLIP_LAST ) + return s_pClipTypeNames[ type ]; + return "Unknown"; +} + + +//----------------------------------------------------------------------------- +// CDmeClip - common base class for filmclips, soundclips, and channelclips +//----------------------------------------------------------------------------- +IMPLEMENT_ELEMENT_FACTORY( DmeClip, CDmeClip ); + +void CDmeClip::OnConstruction() +{ + m_TimeFrame.InitAndCreate( this, "timeFrame" ); + m_ClipColor.InitAndSet( this, "color", Color( 0, 0, 0, 0 ) ); + m_ClipText.Init( this, "text" ); + m_bMute.Init( this, "mute" ); + m_TrackGroups.Init( this, "trackGroups", FATTRIB_MUSTCOPY | FATTRIB_HAS_ARRAY_CALLBACK ); +} + +void CDmeClip::OnDestruction() +{ +} + + +//----------------------------------------------------------------------------- +// Inherited from IDmElement +//----------------------------------------------------------------------------- +void CDmeClip::OnAttributeArrayElementAdded( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ) +{ + BaseClass::OnAttributeArrayElementAdded( pAttribute, nFirstElem, nLastElem ); + if ( pAttribute == m_TrackGroups.GetAttribute() ) + { + for ( int i = nFirstElem; i <= nLastElem; ++i ) + { + CDmeTrackGroup *pTrackGroup = m_TrackGroups[ i ]; + if ( pTrackGroup ) + { + pTrackGroup->SetOwnerClip( this ); + } + } + return; + } +} + +void CDmeClip::OnAttributeArrayElementRemoved( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ) +{ + BaseClass::OnAttributeArrayElementRemoved( pAttribute, nFirstElem, nLastElem ); + if ( pAttribute == m_TrackGroups.GetAttribute() ) + { + for ( int i = nFirstElem; i <= nLastElem; ++i ) + { + CDmeTrackGroup *pTrackGroup = m_TrackGroups[ i ]; + if ( pTrackGroup ) + { + pTrackGroup->SetOwnerClip( NULL ); + } + } + return; + } +} + + +//----------------------------------------------------------------------------- +// Clip color +//----------------------------------------------------------------------------- +void CDmeClip::SetClipColor( const Color& clr ) +{ + m_ClipColor.Set( clr ); +} + +Color CDmeClip::GetClipColor() const +{ + return m_ClipColor.Get(); +} + + +//----------------------------------------------------------------------------- +// Clip text +//----------------------------------------------------------------------------- +void CDmeClip::SetClipText( const char *pText ) +{ + m_ClipText = pText; +} + +const char* CDmeClip::GetClipText() const +{ + return m_ClipText; +} + + +//----------------------------------------------------------------------------- +// Returns the time frame +//----------------------------------------------------------------------------- +CDmeTimeFrame *CDmeClip::GetTimeFrame() const +{ + return m_TimeFrame.GetElement(); +} + +DmeTime_t CDmeClip::ToChildMediaTime( DmeTime_t t, bool bClamp ) const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->ToChildMediaTime( t, bClamp ) : DmeTime_t( 0 ); +} + +DmeTime_t CDmeClip::FromChildMediaTime( DmeTime_t t, bool bClamp ) const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->FromChildMediaTime( t, bClamp ) : DmeTime_t( 0 ); +} + +DmeTime_t CDmeClip::ToChildMediaDuration( DmeTime_t dt ) const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->ToChildMediaDuration( dt ) : DmeTime_t( 0 ); +} + +DmeTime_t CDmeClip::FromChildMediaDuration( DmeTime_t dt ) const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->FromChildMediaDuration( dt ) : DmeTime_t( 0 ); +} + +DmeTime_t CDmeClip::GetTimeOffset() const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->GetTimeOffset() : DmeTime_t( 0 ); +} + +float CDmeClip::GetTimeScale() const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->GetTimeScale() : 0.0f; +} + +DmeTime_t CDmeClip::GetStartTime() const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->GetStartTime() : DmeTime_t( 0 ); +} + +DmeTime_t CDmeClip::GetEndTime() const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->GetStartTime() + tf->GetDuration() : DmeTime_t( 0 ); +} + +DmeTime_t CDmeClip::GetDuration() const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->GetDuration() : DmeTime_t( 0 ); +} + +DmeTime_t CDmeClip::GetStartInChildMediaTime() const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->GetStartInChildMediaTime() : DmeTime_t( 0 ); +} + +DmeTime_t CDmeClip::GetEndInChildMediaTime() const +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + return tf ? tf->GetEndInChildMediaTime() : DmeTime_t( 0 ); +} + +void CDmeClip::SetTimeOffset( DmeTime_t t ) +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + if ( tf ) + { + tf->SetTimeOffset( t ); + } +} + +void CDmeClip::SetTimeScale( float s ) +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + if ( tf ) + { + tf->SetTimeScale( s ); + } +} + +void CDmeClip::SetStartTime( DmeTime_t t ) +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + if ( tf ) + { + tf->SetStartTime( t ); + } +} + +void CDmeClip::SetDuration( DmeTime_t t ) +{ + CDmeTimeFrame *tf = m_TimeFrame.GetElement(); + if ( tf ) + { + tf->SetDuration( t ); + } +} + + +//----------------------------------------------------------------------------- +// Track iteration +//----------------------------------------------------------------------------- +const CUtlVector< DmElementHandle_t > &CDmeClip::GetTrackGroups( ) const +{ + return m_TrackGroups.Get(); +} + +int CDmeClip::GetTrackGroupCount( ) const +{ + // Make sure no invalid clip types have snuck in + return m_TrackGroups.Count(); +} + +CDmeTrackGroup *CDmeClip::GetTrackGroup( int nIndex ) const +{ + if ( ( nIndex >= 0 ) && ( nIndex < m_TrackGroups.Count() ) ) + return m_TrackGroups[ nIndex ]; + return NULL; +} + +//----------------------------------------------------------------------------- +// Is a track group valid to add? +//----------------------------------------------------------------------------- +bool CDmeClip::IsTrackGroupValid( CDmeTrackGroup *pTrackGroup ) +{ + // FIXME: If track groups have allowed types, we can check for validity + for ( DmeClipType_t i = DMECLIP_FIRST; i <= DMECLIP_LAST; ++i ) + { + if ( !IsSubClipTypeAllowed( i ) && pTrackGroup->IsSubClipTypeAllowed( i ) ) + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Track group addition/removal +//----------------------------------------------------------------------------- +void CDmeClip::AddTrackGroup( CDmeTrackGroup *pTrackGroup ) +{ + if ( !IsTrackGroupValid( pTrackGroup ) ) + return; + + // FIXME: Should check if track with same name already exists??? + if ( GetTrackGroupIndex( pTrackGroup ) < 0 ) + { + m_TrackGroups.AddToTail( pTrackGroup ); + } +} + +void CDmeClip::AddTrackGroupBefore( CDmeTrackGroup *pTrackGroup, CDmeTrackGroup *pBefore ) +{ + if ( !IsTrackGroupValid( pTrackGroup ) ) + return; + + // FIXME: Should check if track with same name already exists??? + if ( GetTrackGroupIndex( pTrackGroup ) < 0 ) + { + int nBeforeIndex = pBefore ? GetTrackGroupIndex( pBefore ) : GetTrackGroupCount(); + if ( nBeforeIndex >= 0 ) + { + m_TrackGroups.InsertBefore( nBeforeIndex, pTrackGroup ); + } + } +} + + +CDmeTrackGroup *CDmeClip::AddTrackGroup( const char *pTrackGroupName ) +{ + CDmeTrackGroup *pTrackGroup = CreateElement< CDmeTrackGroup >( pTrackGroupName, GetFileId() ); + pTrackGroup->SetMinimized( false ); + m_TrackGroups.AddToTail( pTrackGroup ); + return pTrackGroup; +} + +void CDmeClip::RemoveTrackGroup( int nIndex ) +{ + Assert( nIndex >= 0 && nIndex < m_TrackGroups.Count() ); + + m_TrackGroups.Remove( nIndex ); +} + +void CDmeClip::RemoveTrackGroup( CDmeTrackGroup *pTrackGroup ) +{ + int i = GetTrackGroupIndex( pTrackGroup ); + if ( i < 0 ) + return; + + m_TrackGroups.Remove( i ); +} + +void CDmeClip::RemoveTrackGroup( const char *pTrackGroupName ) +{ + if ( !pTrackGroupName ) + { + pTrackGroupName = DMETRACKGROUP_DEFAULT_NAME; + } + + int c = m_TrackGroups.Count(); + for ( int i = c; --i >= 0; ) + { + if ( !Q_strcmp( m_TrackGroups[i]->GetName(), pTrackGroupName ) ) + { + m_TrackGroups.Remove( i ); + return; + } + } +} + + +//----------------------------------------------------------------------------- +// Swap track groups +//----------------------------------------------------------------------------- +void CDmeClip::SwapOrder( CDmeTrackGroup *pTrackGroup1, CDmeTrackGroup *pTrackGroup2 ) +{ + if ( pTrackGroup1 == pTrackGroup2 ) + return; + if ( pTrackGroup1->IsFilmTrackGroup() || pTrackGroup2->IsFilmTrackGroup() ) + return; + + int nIndex1 = -1, nIndex2 = -1; + int c = m_TrackGroups.Count(); + for ( int i = c; --i >= 0; ) + { + if ( m_TrackGroups[i] == pTrackGroup1 ) + { + nIndex1 = i; + } + if ( m_TrackGroups[i] == pTrackGroup2 ) + { + nIndex2 = i; + } + } + if ( ( nIndex1 < 0 ) || ( nIndex2 < 0 ) ) + return; + + m_TrackGroups.Swap( nIndex1, nIndex2 ); +} + + +//----------------------------------------------------------------------------- +// Track group finding +//----------------------------------------------------------------------------- +CDmeTrackGroup *CDmeClip::FindTrackGroup( const char *pTrackGroupName ) const +{ + if ( !pTrackGroupName ) + { + pTrackGroupName = DMETRACKGROUP_DEFAULT_NAME; + } + + int c = m_TrackGroups.Count(); + for ( int i = 0 ; i < c; ++i ) + { + CDmeTrackGroup *pTrackGroup = m_TrackGroups[i]; + if ( !pTrackGroup ) + continue; + + if ( !Q_strcmp( pTrackGroup->GetName(), pTrackGroupName ) ) + return pTrackGroup; + } + return NULL; +} + +int CDmeClip::GetTrackGroupIndex( CDmeTrackGroup *pTrackGroup ) const +{ + int nTrackGroups = m_TrackGroups.Count(); + for ( int i = 0 ; i < nTrackGroups; ++i ) + { + if ( pTrackGroup == m_TrackGroups[i] ) + return i; + } + return -1; +} + + +//----------------------------------------------------------------------------- +// Find or create a track group +//----------------------------------------------------------------------------- +CDmeTrackGroup *CDmeClip::FindOrAddTrackGroup( const char *pTrackGroupName ) +{ + CDmeTrackGroup *pTrackGroup = FindTrackGroup( pTrackGroupName ); + if ( !pTrackGroup ) + { + pTrackGroup = AddTrackGroup( pTrackGroupName ); + } + return pTrackGroup; +} + + +//----------------------------------------------------------------------------- +// Finding clips in track groups +//----------------------------------------------------------------------------- +CDmeTrack *CDmeClip::FindTrackForClip( CDmeClip *pClip, CDmeTrackGroup **ppTrackGroup /*= NULL*/ ) const +{ +// DmeClipType_t type = pClip->GetClipType(); + int c = m_TrackGroups.Count(); + for ( int i = 0 ; i < c; ++i ) + { + // FIXME: If trackgroups have valid types, can early out here + CDmeTrack *pTrack = m_TrackGroups[i]->FindTrackForClip( pClip ); + if ( pTrack ) + { + if ( ppTrackGroup ) + { + *ppTrackGroup = m_TrackGroups[i]; + } + return pTrack; + } + } + + return NULL; +} + +bool CDmeClip::FindMultiTrackGroupForClip( CDmeClip *pClip, int *pTrackGroupIndex, int *pTrackIndex, int *pClipIndex ) const +{ + int nTrackGroups = m_TrackGroups.Count(); + for ( int gi = 0 ; gi < nTrackGroups; ++gi ) + { + CDmeTrackGroup *pTrackGroup = m_TrackGroups[ gi ]; + if ( !pTrackGroup ) + continue; + + if ( !pTrackGroup->FindTrackForClip( pClip, pTrackIndex, pClipIndex ) ) + continue; + + if ( pTrackGroupIndex ) + { + *pTrackGroupIndex = gi; + } + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Finding clips in tracks by time +//----------------------------------------------------------------------------- +void CDmeClip::FindClipsAtTime( DmeClipType_t clipType, DmeTime_t time, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const +{ + if ( clipType == DMECLIP_FILM ) + return; + + int gc = GetTrackGroupCount(); + for ( int i = 0; i < gc; ++i ) + { + CDmeTrackGroup *pTrackGroup = GetTrackGroup( i ); + if ( !pTrackGroup ) + continue; + + pTrackGroup->FindClipsAtTime( clipType, time, flags, clips ); + } +} + +void CDmeClip::FindClipsWithinTime( DmeClipType_t clipType, DmeTime_t startTime, DmeTime_t endTime, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const +{ + if ( clipType == DMECLIP_FILM ) + return; + + int gc = GetTrackGroupCount(); + for ( int i = 0; i < gc; ++i ) + { + CDmeTrackGroup *pTrackGroup = GetTrackGroup( i ); + if ( !pTrackGroup ) + continue; + + pTrackGroup->FindClipsWithinTime( clipType, startTime, endTime, flags, clips ); + } +} + + +//----------------------------------------------------------------------------- +// Build a list of all referring clips +//----------------------------------------------------------------------------- +static int BuildReferringClipList( CDmeClip *pClip, CDmeClip** ppParents, int nMaxCount ) +{ + int nCount = 0; + + DmAttributeReferenceIterator_t it, it2, it3; + for ( it = g_pDataModel->FirstAttributeReferencingElement( pClip->GetHandle() ); + it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; + it = g_pDataModel->NextAttributeReferencingElement( it ) ) + { + CDmAttribute *pAttribute = g_pDataModel->GetAttribute( it ); + const char *pName = pAttribute->GetName(); + CDmElement *pElement = pAttribute->GetOwner(); + CDmeTrack *pTrack = CastElement< CDmeTrack >( pElement ); + if ( !pTrack ) + continue; + + for ( it2 = g_pDataModel->FirstAttributeReferencingElement( pTrack->GetHandle() ); + it2 != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; + it2 = g_pDataModel->NextAttributeReferencingElement( it2 ) ) + { + pAttribute = g_pDataModel->GetAttribute( it2 ); + pName = pAttribute->GetName(); + pElement = pAttribute->GetOwner(); + CDmeTrackGroup *pTrackGroup = CastElement< CDmeTrackGroup >( pElement ); + if ( !pTrackGroup ) + continue; + + for ( it3 = g_pDataModel->FirstAttributeReferencingElement( pTrackGroup->GetHandle() ); + it3 != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; + it3 = g_pDataModel->NextAttributeReferencingElement( it3 ) ) + { + pAttribute = g_pDataModel->GetAttribute( it3 ); + pName = pAttribute->GetName(); + pElement = pAttribute->GetOwner(); + CDmeClip *pParent = CastElement< CDmeClip >( pElement ); + if ( !pParent ) + continue; + + Assert( nCount < nMaxCount ); + if ( nCount >= nMaxCount ) + return nCount; + ppParents[nCount++] = pParent; + } + } + } + return nCount; +} + + +//----------------------------------------------------------------------------- +// Clip stack +//----------------------------------------------------------------------------- +static bool BuildClipStack_R( DmeClipStack_t* pStack, CDmeClip *pMovie, CDmeClip *pShot, CDmeClip *pCurrent ) +{ + // Add this clip to the stack + int nIndex = pStack->AddToHead( CDmeHandle< CDmeClip >( pCurrent ) ); + + // Is this clip the shot? We don't need to look for it any more. + if ( pCurrent == pShot ) + { + pShot = NULL; + } + + // Is this clip the movie? We succeeded if we already found the shot! + if ( pCurrent == pMovie ) + { + if ( !pShot ) + return true; + } + else + { + // NOTE: This algorithm assumes a clip can never appear twice under another clip + // at a single level of hierarchy. + CDmeClip* ppParents[1024]; + int nCount = BuildReferringClipList( pCurrent, ppParents, 1024 ); + for ( int i = 0; i < nCount; ++i ) + { + // Can we find a path to the root through the shot? We succeeded! + if ( BuildClipStack_R( pStack, pMovie, pShot, ppParents[i] ) ) + return true; + } + } + + // This clip didn't work out for us. Remove it. + pStack->Remove( nIndex ); + + return false; +} + +bool CDmeClip::BuildClipStack( DmeClipStack_t* pStack, CDmeClip *pMovie, CDmeClip *pShot ) +{ + // Walk through each shot in the movie and look for the subClip, if don't find it recurse into each shot + return BuildClipStack_R( pStack, pMovie, pShot, this ); +} + +DmeTime_t CDmeClip::ToChildMediaTime( const DmeClipStack_t& stack, DmeTime_t globalTime, bool bClamp /* = true */ ) +{ + DmeTime_t time = globalTime; + + int nClips = stack.Count(); + for ( int i = 0; i < nClips; ++i ) + { + time = stack[ i ]->ToChildMediaTime( time, bClamp ); + } + + return time; +} + +DmeTime_t CDmeClip::FromChildMediaTime( const DmeClipStack_t& stack, DmeTime_t localTime, bool bClamp /* = true */ ) +{ + DmeTime_t time = localTime; + + int nClips = stack.Count(); + for ( int i = nClips-1; i >= 0; --i ) + { + time = stack[ i ]->FromChildMediaTime( time, bClamp ); + } + + return time; +} + +DmeTime_t CDmeClip::ToChildMediaDuration( const DmeClipStack_t& stack, DmeTime_t globalDuration ) +{ + DmeTime_t duration = globalDuration; + + int nClips = stack.Count(); + for ( int i = 0; i < nClips; ++i ) + { + duration = stack[ i ]->ToChildMediaDuration( duration ); + } + + return duration; +} + +DmeTime_t CDmeClip::FromChildMediaDuration( const DmeClipStack_t& stack, DmeTime_t localDuration ) +{ + DmeTime_t duration = localDuration; + + int nClips = stack.Count(); + for ( int i = nClips-1; i >= 0; --i ) + { + duration = stack[ i ]->FromChildMediaDuration( duration ); + } + + return duration; +} + + +void CDmeClip::ToChildMediaTime( DmeLog_TimeSelection_t ¶ms, const DmeClipStack_t& stack ) +{ + for ( int i = 0; i < TS_TIME_COUNT; ++i ) + { + params.m_nTimes[i] = ToChildMediaTime( stack, params.m_nTimes[i], false ); + } +} + + +//----------------------------------------------------------------------------- +// +// CDmeSoundClip - timeframe view into a dmesound +// +//----------------------------------------------------------------------------- +IMPLEMENT_ELEMENT_FACTORY( DmeSoundClip, CDmeSoundClip ); + +void CDmeSoundClip::OnConstruction() +{ + m_Sound.Init( this, "sound" ); + m_bShowWave.InitAndSet( this, "showwave", false ); +} + +void CDmeSoundClip::OnDestruction() +{ +} + +void CDmeSoundClip::SetShowWave( bool state ) +{ + m_bShowWave = state; +} + +bool CDmeSoundClip::ShouldShowWave( ) const +{ + return m_bShowWave; +} + +//----------------------------------------------------------------------------- +// CDmeChannelsClip - timeframe view into a set of channels +//----------------------------------------------------------------------------- +IMPLEMENT_ELEMENT_FACTORY( DmeChannelsClip, CDmeChannelsClip ); + +void CDmeChannelsClip::OnConstruction() +{ + m_Channels.Init( this, "channels" ); +} + +void CDmeChannelsClip::OnDestruction() +{ +} + +CDmeChannel *CDmeChannelsClip::CreatePassThruConnection( char const *passThruName, + CDmElement *pFrom, char const *pFromAttribute, + CDmElement *pTo, char const *pToAttribute, int index /*= 0*/ ) +{ + CDmeChannel *helper = CreateElement< CDmeChannel >( passThruName, GetFileId() ); + Assert( helper ); + + helper->SetMode( CM_PASS ); + helper->SetInput( pFrom, pFromAttribute ); + helper->SetOutput( pTo, pToAttribute, index ); + + m_Channels.AddToTail( helper ); + + return helper; +} + +void CDmeChannelsClip::RemoveChannel( CDmeChannel *pChannel ) +{ + int nCount = m_Channels.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( pChannel == m_Channels[i] ) + { + m_Channels.Remove( i ); + break; + } + } +} + + + +//----------------------------------------------------------------------------- +// CDmeFXClip - timeframe view into an effect +//----------------------------------------------------------------------------- +IMPLEMENT_ELEMENT_FACTORY( DmeFXClip, CDmeFXClip ); + +void CDmeFXClip::OnConstruction() +{ +} + +void CDmeFXClip::OnDestruction() +{ +} + + +//----------------------------------------------------------------------------- +// Global list of FX clip types +//----------------------------------------------------------------------------- +const char *CDmeFXClip::s_pFXClipTypes[MAX_FXCLIP_TYPES]; +const char *CDmeFXClip::s_pFXClipDescriptions[MAX_FXCLIP_TYPES]; +int CDmeFXClip::s_nFXClipTypeCount = 0; + +void CDmeFXClip::InstallFXClipType( const char *pElementType, const char *pDescription ) +{ + s_pFXClipTypes[s_nFXClipTypeCount] = pElementType; + s_pFXClipDescriptions[s_nFXClipTypeCount] = pDescription; + ++s_nFXClipTypeCount; +} + +int CDmeFXClip::FXClipTypeCount() +{ + return s_nFXClipTypeCount; +} + +const char *CDmeFXClip::FXClipType( int nIndex ) +{ + Assert( s_nFXClipTypeCount > nIndex ); + return s_pFXClipTypes[nIndex]; +} + +const char *CDmeFXClip::FXClipDescription( int nIndex ) +{ + Assert( s_nFXClipTypeCount > nIndex ); + return s_pFXClipDescriptions[nIndex]; +} + + +//----------------------------------------------------------------------------- +// CDmeFilmClip - hierarchical clip (movie, sequence or shot) w/ scene info +//----------------------------------------------------------------------------- +IMPLEMENT_ELEMENT_FACTORY( DmeFilmClip, CDmeFilmClip ); + +void CDmeFilmClip::OnConstruction() +{ + m_MaterialOverlayEffect.Init( this, "materialOverlay" ); + + m_MapName.Init( this, "mapname" ); + m_Camera.Init( this, "camera" ); + m_MonitorCameras.Init( this, "monitorCameras" ); + m_nActiveMonitor.InitAndSet( this, "activeMonitor", -1 ); + m_Lights.Init( this, "lights" ); + m_Scene.Init( this, "scene" ); + m_AVIFile.Init( this, "aviFile" ); + m_fadeInDuration .InitAndSet( this, "fadeIn", 0 ); + m_fadeOutDuration.InitAndSet( this, "fadeOut", 0 ); + + m_Inputs.Init( this, "inputs" ); + m_Operators.Init( this, "operators" ); + m_bIsUsingCachedVersion.Init( this, "useAviFile" ); + m_AnimationSets.Init( this, "animationSets" ); + m_Bookmarks.Init( this, "bookmarks" ); + m_FilmTrackGroup.Init( this, "subClipTrackGroup", FATTRIB_HAS_CALLBACK | FATTRIB_HAS_PRE_CALLBACK ); + m_Volume.InitAndSet( this, "volume", 1.0); + + m_pCachedVersion = NULL; + m_bIsUsingCachedVersion = false; + m_bReloadCachedVersion = false; +} + +void CDmeFilmClip::OnDestruction() +{ + if ( g_pVideo != NULL && m_pCachedVersion != NULL ) + { + g_pVideo->DestroyVideoMaterial( m_pCachedVersion ); + m_pCachedVersion = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Returns the special film track group +//----------------------------------------------------------------------------- +CDmeTrackGroup *CDmeFilmClip::GetFilmTrackGroup() const +{ + return m_FilmTrackGroup; +} + +//----------------------------------------------------------------------------- +// Returns the special film track +//----------------------------------------------------------------------------- +CDmeTrack *CDmeFilmClip::GetFilmTrack() const +{ + CDmeTrackGroup *pTrackGroup = m_FilmTrackGroup.GetElement(); + if ( pTrackGroup ) + return pTrackGroup->GetFilmTrack(); + return NULL; +} + +CDmeTrackGroup *CDmeFilmClip::FindOrCreateFilmTrackGroup() +{ + if ( !m_FilmTrackGroup ) + { + m_FilmTrackGroup = CreateElement< CDmeTrackGroup >( "subClipTrackGroup", GetFileId() ); + m_FilmTrackGroup->SetMinimized( false ); + m_FilmTrackGroup->SetMaxTrackCount( 1 ); + m_FilmTrackGroup->SetOwnerClip( this ); + } + return m_FilmTrackGroup; +} + +CDmeTrack *CDmeFilmClip::FindOrCreateFilmTrack() +{ + CDmeTrackGroup *pTrackGroup = FindOrCreateFilmTrackGroup(); + CDmeTrack *pTrack = pTrackGroup->GetFilmTrack(); + return pTrack ? pTrack : m_FilmTrackGroup->CreateFilmTrack(); +} + + +//----------------------------------------------------------------------------- +// Finding clips in track groups +//----------------------------------------------------------------------------- +CDmeTrack *CDmeFilmClip::FindTrackForClip( CDmeClip *pClip, CDmeTrackGroup **ppTrackGroup /*= NULL*/ ) const +{ + if ( m_FilmTrackGroup.GetElement() ) + { + CDmeTrack *pTrack = m_FilmTrackGroup->FindTrackForClip( pClip ); + if ( pTrack ) + { + if ( ppTrackGroup ) + { + *ppTrackGroup = m_FilmTrackGroup; + } + return pTrack; + } + } + + return CDmeClip::FindTrackForClip( pClip, ppTrackGroup ); +} + +//----------------------------------------------------------------------------- +// Finding clips in tracks by time +//----------------------------------------------------------------------------- +void CDmeFilmClip::FindClipsAtTime( DmeClipType_t clipType, DmeTime_t time, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const +{ + if ( ( clipType == DMECLIP_FILM ) || ( clipType == DMECLIP_UNKNOWN ) ) + { + if ( m_FilmTrackGroup ) + { + m_FilmTrackGroup->FindClipsAtTime( clipType, time, flags, clips ); + } + } + + CDmeClip::FindClipsAtTime( clipType, time, flags, clips ); +} + +void CDmeFilmClip::FindClipsWithinTime( DmeClipType_t clipType, DmeTime_t startTime, DmeTime_t endTime, DmeClipSkipFlag_t flags, CUtlVector< CDmeClip * >& clips ) const +{ + if ( ( clipType == DMECLIP_FILM ) || ( clipType == DMECLIP_UNKNOWN ) ) + { + if ( m_FilmTrackGroup ) + { + m_FilmTrackGroup->FindClipsWithinTime( clipType, startTime, endTime, flags, clips ); + } + } + + CDmeClip::FindClipsWithinTime( clipType, startTime, endTime, flags, clips ); +} + + +//----------------------------------------------------------------------------- +// Volume +//----------------------------------------------------------------------------- +void CDmeFilmClip::SetVolume( float state ) +{ + m_Volume = state; +} +float CDmeFilmClip::GetVolume() const +{ + return m_Volume.Get(); +} + +//----------------------------------------------------------------------------- +// mapname helper methods +//----------------------------------------------------------------------------- +const char *CDmeFilmClip::GetMapName() +{ + return m_MapName.Get(); +} + +void CDmeFilmClip::SetMapName( const char *pMapName ) +{ + m_MapName.Set( pMapName ); +} + + +//----------------------------------------------------------------------------- +// Attribute changed +//----------------------------------------------------------------------------- +void CDmeFilmClip::PreAttributeChanged( CDmAttribute *pAttribute ) +{ + BaseClass::PreAttributeChanged( pAttribute ); + if ( pAttribute == m_FilmTrackGroup.GetAttribute() ) + { + if ( m_FilmTrackGroup.GetElement() ) + { + m_FilmTrackGroup->SetOwnerClip( NULL ); + } + return; + } +} + +void CDmeFilmClip::OnAttributeChanged( CDmAttribute *pAttribute ) +{ + BaseClass::OnAttributeChanged( pAttribute ); + if ( pAttribute == m_FilmTrackGroup.GetAttribute() ) + { + if ( m_FilmTrackGroup.GetElement() ) + { + m_FilmTrackGroup->SetMaxTrackCount( 1 ); + m_FilmTrackGroup->SetOwnerClip( this ); + } + } + else if ( pAttribute->GetOwner() == m_TimeFrame.GetElement() ) + { + InvokeOnAttributeChangedOnReferrers( GetHandle(), pAttribute ); + } +} + +void CDmeFilmClip::OnElementUnserialized( ) +{ + BaseClass::OnElementUnserialized(); + + CDmeTrackGroup *pFilmTrackGroup = m_FilmTrackGroup.GetElement(); + if ( pFilmTrackGroup ) + { + pFilmTrackGroup->SetMaxTrackCount( 1 ); + if ( pFilmTrackGroup->GetTrackCount() == 0 ) + { + pFilmTrackGroup->CreateFilmTrack(); + } + } + + // this conversion code went in on 10/31/2005 + // I'm hoping we don't care about any files that old - if we ever hit this, we should move this code into an unserialization converter + Assert( !HasAttribute( "overlay" ) && !HasAttribute( "overlayalpha" ) ); + if ( HasAttribute( "overlay" ) || HasAttribute( "overlayalpha" ) ) + { + Warning( "CDmeFilmClip %s is an old version that has overlay and/or overlayalpha attributes!\n", GetName() ); + + // Backward compat conversion + // If this is an older file with an overlay attribute, strip it out into materialoverlay + CDmAttribute *pOverlayAttribute = GetAttribute( "overlay" ); + if ( !pOverlayAttribute ) + goto cleanUp; + + const char *pName = pOverlayAttribute->GetValueString(); + if ( !pName || !pName[0] ) + goto cleanUp; + + // If we don't yet have a material overlay, create one + if ( m_MaterialOverlayEffect.GetElement() == NULL ) + { + m_MaterialOverlayEffect = CreateElement<CDmeMaterialOverlayFXClip>( "materialOverlay", GetFileId() ); + } + + m_MaterialOverlayEffect->SetOverlayEffect( pName ); + + // If this is an older file with an overlayalpha attribute, strip it out into materialoverlay + CDmAttribute *pOverlayAlphaAttribute = GetAttribute( "overlayalpha" ); + if ( pOverlayAlphaAttribute ) + { + float alpha = pOverlayAlphaAttribute->GetValue<float>(); + m_MaterialOverlayEffect->SetAlpha( alpha ); + } + +cleanUp: + // Always strip out the old overlay attribute + RemoveAttribute( "overlay" ); + RemoveAttribute( "overlayalpha" ); + } +} + + +//----------------------------------------------------------------------------- +// Resolve +//----------------------------------------------------------------------------- +void CDmeFilmClip::Resolve() +{ + BaseClass::Resolve(); + if ( m_AVIFile.IsDirty() ) + { + m_bReloadCachedVersion = true; + m_AVIFile.GetAttribute()->RemoveFlag( FATTRIB_DIRTY ); + } +} + + +//----------------------------------------------------------------------------- +// Helper for overlays +//----------------------------------------------------------------------------- +void CDmeFilmClip::SetOverlay( const char *pMaterialName ) +{ + if ( pMaterialName && pMaterialName[0] ) + { + if ( !m_MaterialOverlayEffect.GetElement() ) + { + m_MaterialOverlayEffect = CreateElement<CDmeMaterialOverlayFXClip>( "materialOverlay", GetFileId() ); + } + + m_MaterialOverlayEffect->SetOverlayEffect( pMaterialName ); + } + else + { + m_MaterialOverlayEffect.Set( NULL ); + } +} + +IMaterial *CDmeFilmClip::GetOverlayMaterial() +{ + return m_MaterialOverlayEffect.GetElement() ? m_MaterialOverlayEffect->GetMaterial() : NULL; +} + +float CDmeFilmClip::GetOverlayAlpha() +{ + return m_MaterialOverlayEffect.GetElement() ? m_MaterialOverlayEffect->GetAlpha() : 0.0f; +} + +void CDmeFilmClip::SetOverlayAlpha( float alpha ) +{ + if ( m_MaterialOverlayEffect.GetElement() ) + { + m_MaterialOverlayEffect->SetAlpha( alpha ); + } +} + +bool CDmeFilmClip::HasOpaqueOverlay( void ) +{ + if ( m_MaterialOverlayEffect->GetMaterial()->IsTranslucent() || + ( m_MaterialOverlayEffect->GetAlpha() < 1.0f ) ) + { + return false; + } + + return true; +} + +void CDmeFilmClip::DrawOverlay( DmeTime_t time, Rect_t ¤tRect, Rect_t &totalRect ) +{ + if ( m_MaterialOverlayEffect.GetElement() ) + { + m_MaterialOverlayEffect->ApplyEffect( ToChildMediaTime( time ), currentRect, totalRect, NULL ); + } + + DmeTime_t fadeIn( m_fadeInDuration ); + DmeTime_t fadeOut( m_fadeOutDuration ); + + float fade = 1.0f; + if ( time < GetStartTime() + fadeIn ) + { + fade = ( time - GetStartTime() ) / fadeIn; + } + if ( time > GetEndTime() - fadeOut ) + { + fade = min( fade, ( GetEndTime() - time ) / fadeOut ); + } + if ( fade < 1.0f ) + { + if ( !m_FadeMaterial.IsValid() ) + { + m_FadeMaterial.Init( "engine\\singlecolor.vmt", NULL, false ); + } + + float r, g, b; + m_FadeMaterial->GetColorModulation( &r, &g, &b ); + float a = m_FadeMaterial->GetAlphaModulation(); + + m_FadeMaterial->ColorModulate( 0.0f, 0.0f, 0.0f ); + m_FadeMaterial->AlphaModulate( 1.0f - fade ); + + CMatRenderContextPtr pRenderContext( materials ); + pRenderContext->Bind( m_FadeMaterial ); + + float w = currentRect.width; + float h = currentRect.height; + + IMesh *pMesh = pRenderContext->GetDynamicMesh(); + CMeshBuilder meshBuilder; + meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 ); + + meshBuilder.Position3f( 0.0f, 0.0f, 0.0f ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3f( 0.0f, h, 0.0f ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3f( w, 0.0f, 0.0f ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3f( w, h, 0.0f ); + meshBuilder.AdvanceVertex(); + + meshBuilder.End(); + pMesh->Draw(); + + m_FadeMaterial->ColorModulate( r, g, b ); + m_FadeMaterial->AlphaModulate( a ); + } +} + + +//----------------------------------------------------------------------------- +// AVI tape out +//----------------------------------------------------------------------------- +void CDmeFilmClip::UseCachedVersion( bool bUseCachedVersion ) +{ + m_bIsUsingCachedVersion = bUseCachedVersion; +} + +bool CDmeFilmClip::IsUsingCachedVersion() const +{ + return m_bIsUsingCachedVersion; +} + +IVideoMaterial *CDmeFilmClip::GetCachedVideoMaterial() +{ + if ( m_bReloadCachedVersion ) + { + if ( g_pVideo ) + { + if ( m_pCachedVersion != NULL ) + { + g_pVideo->DestroyVideoMaterial( m_pCachedVersion ); + m_pCachedVersion = NULL; + } + if ( m_AVIFile[0] ) + { + m_pCachedVersion = g_pVideo->CreateVideoMaterial( m_AVIFile, m_AVIFile, "MOD" ); + } + + } + m_bReloadCachedVersion = false; + } + return m_pCachedVersion; +} + +void CDmeFilmClip::SetCachedAVI( const char *pAVIFile ) +{ + m_AVIFile = pAVIFile; + m_bReloadCachedVersion = true; +} + + +//----------------------------------------------------------------------------- +// Camera helper methods +//----------------------------------------------------------------------------- +CDmeCamera *CDmeFilmClip::GetCamera() +{ + return m_Camera; +} + +void CDmeFilmClip::SetCamera( CDmeCamera *pCamera ) +{ + m_Camera = pCamera; +} + + +//----------------------------------------------------------------------------- +// Returns the monitor camera associated with the clip (for now, only 1 supported) +//----------------------------------------------------------------------------- +CDmeCamera *CDmeFilmClip::GetMonitorCamera() +{ + if ( m_nActiveMonitor < 0 ) + return NULL; + return m_MonitorCameras[ m_nActiveMonitor ]; +} + +void CDmeFilmClip::AddMonitorCamera( CDmeCamera *pCamera ) +{ + m_MonitorCameras.AddToTail( pCamera ); +} + +int CDmeFilmClip::FindMonitorCamera( CDmeCamera *pCamera ) +{ + return m_MonitorCameras.Find( pCamera->GetHandle() ); +} + +void CDmeFilmClip::RemoveMonitorCamera( CDmeCamera *pCamera ) +{ + int i = m_MonitorCameras.Find( pCamera->GetHandle() ); + if ( i >= 0 ) + { + if ( m_nActiveMonitor == i ) + { + m_nActiveMonitor = -1; + } + m_MonitorCameras.FastRemove( i ); + } +} + +void CDmeFilmClip::SelectMonitorCamera( CDmeCamera *pCamera ) +{ + m_nActiveMonitor = pCamera ? m_MonitorCameras.Find( pCamera->GetHandle() ) : -1; +} + + +//----------------------------------------------------------------------------- +// Light helper methods +//----------------------------------------------------------------------------- +int CDmeFilmClip::GetLightCount() +{ + return m_Lights.Count(); +} + +CDmeLight *CDmeFilmClip::GetLight( int nIndex ) +{ + if ( ( nIndex < 0 ) || ( nIndex >= m_Lights.Count() ) ) + return NULL; + + return m_Lights[ nIndex ]; +} + +void CDmeFilmClip::AddLight( CDmeLight *pLight ) +{ + m_Lights.AddToTail( pLight ); +} + + +//----------------------------------------------------------------------------- +// Scene / Dag helper methods +//----------------------------------------------------------------------------- +CDmeDag *CDmeFilmClip::GetScene() +{ + return m_Scene.GetElement(); +} + +void CDmeFilmClip::SetScene( CDmeDag *pDag ) +{ + m_Scene.Set( pDag ); +} + + +//----------------------------------------------------------------------------- +// helper for inputs and operators +//----------------------------------------------------------------------------- +int CDmeFilmClip::GetInputCount() +{ + return m_Inputs.Count(); +} + +CDmeInput *CDmeFilmClip::GetInput( int nIndex ) +{ + if ( nIndex < 0 || nIndex >= m_Inputs.Count() ) + return NULL; + + return m_Inputs[ nIndex ]; +} + +void CDmeFilmClip::AddInput( CDmeInput *pInput ) +{ + m_Inputs.AddToTail( pInput ); +} + +void CDmeFilmClip::RemoveAllInputs() +{ + m_Inputs.RemoveAll(); +} + +void CDmeFilmClip::AddOperator( CDmeOperator *pOperator ) +{ + m_Operators.AddToTail( pOperator ); +} + +void CDmeFilmClip::CollectOperators( CUtlVector< DmElementHandle_t > &operators ) +{ + int numInputs = m_Inputs.Count(); + for ( int i = 0; i < numInputs; ++i ) + { + operators.AddToTail( m_Inputs[ i ]->GetHandle() ); + } + + int numOperators = m_Operators.Count(); + for ( int i = 0; i < numOperators; ++i ) + { + operators.AddToTail( m_Operators[ i ]->GetHandle() ); + } +} + +int CDmeFilmClip::GetAnimationSetCount() +{ + // yes, this is nasty perf-wise, but since we only have a dozen or so animation sets, + // and we're about to rewrite the entire structure of animation sets vs. clips vs. scene + // it's not worth polluting the leaf code just to save a couple cycles short term + + int nCount = 0; + + int nElements = m_AnimationSets.Count(); + for ( int i = 0; i < nElements; ++i ) + { + CDmElement *pElement = m_AnimationSets.Get( i ); + if ( !pElement ) + continue; + + CDmeAnimationSet *pAnimSet = CastElement< CDmeAnimationSet >( pElement ); + if ( pAnimSet ) + { + ++nCount; + } + else + { + const CDmAttribute *pChildren = pElement->GetAttribute( "children", AT_ELEMENT_ARRAY ); + if ( !pChildren ) + continue; + + CDmrElementArrayConst< CDmElement > array( pChildren ); + nCount += array.Count(); + } + } + + return nCount; +} + +CDmeAnimationSet *CDmeFilmClip::GetAnimationSet( int idx ) +{ + // yes, this is nasty perf-wise, but since we only have a dozen or so animation sets, + // and we're about to rewrite the entire structure of animation sets vs. clips vs. scene + // it's not worth polluting the leaf code just to save a couple cycles short term + + int nElements = m_AnimationSets.Count(); + for ( int i = 0; i < nElements; ++i ) + { + CDmElement *pElement = m_AnimationSets.Get( i ); + if ( !pElement ) + continue; + + CDmeAnimationSet *pAnimSet = CastElement< CDmeAnimationSet >( pElement ); + if ( pAnimSet ) + { + if ( idx == 0 ) + return pAnimSet; + --idx; + } + else + { + const CDmAttribute *pChildren = pElement->GetAttribute( "children", AT_ELEMENT_ARRAY ); + if ( !pChildren ) + continue; + + CDmrElementArrayConst< CDmElement > array( pChildren ); + int nChildren = array.Count(); + + if ( idx < nChildren ) + return CastElement< CDmeAnimationSet >( array[ idx ] ); + idx -= nChildren; + } + } + + return NULL; +} + +void CDmeFilmClip::AddAnimationSet( CDmeAnimationSet *element ) +{ + m_AnimationSets.AddToTail( element ); +} + +void CDmeFilmClip::RemoveAllAnimationSets() +{ + m_AnimationSets.RemoveAll(); +} + +CDmaElementArray< CDmElement > &CDmeFilmClip::GetAnimationSets() +{ + return m_AnimationSets; +} + +const CDmaElementArray< CDmElement > &CDmeFilmClip::GetAnimationSets() const +{ + return m_AnimationSets; +} + + +const CDmaElementArray< CDmeBookmark > &CDmeFilmClip::GetBookmarks() const +{ + return m_Bookmarks; +} + +CDmaElementArray< CDmeBookmark > &CDmeFilmClip::GetBookmarks() +{ + return m_Bookmarks; +} + + +//----------------------------------------------------------------------------- +// Used to move clips in non-film track groups with film clips +// Call BuildClipAssociations before modifying the film track, +// then UpdateAssociatedClips after modifying it. +//----------------------------------------------------------------------------- +void CDmeFilmClip::BuildClipAssociations( CUtlVector< ClipAssociation_t > &association, bool bHandleGaps ) +{ + association.RemoveAll(); + + CDmeTrack *pFilmTrack = GetFilmTrack(); + if ( !pFilmTrack ) + return; + + int c = pFilmTrack->GetClipCount(); + int gc = GetTrackGroupCount(); + if ( c == 0 || gc == 0 ) + return; + + DmeTime_t clipStartTime = GetStartInChildMediaTime(); + DmeTime_t clipEndTime = GetEndInChildMediaTime(); + + // These slugs will be removed in UpdateAssociatedClips + if ( bHandleGaps ) + { + pFilmTrack->FillAllGapsWithSlugs( "__tempSlug__", clipStartTime, clipEndTime ); + } + + for ( int i = 0; i < gc; ++i ) + { + CDmeTrackGroup *pTrackGroup = GetTrackGroup( i ); + int tc = pTrackGroup->GetTrackCount(); + for ( int j = 0; j < tc; ++j ) + { + CDmeTrack *pTrack = pTrackGroup->GetTrack( j ); + if ( !pTrack->IsSynched() ) + continue; + + // Only have visible tracks now + int cc = pTrack->GetClipCount(); + association.EnsureCapacity( association.Count() + cc ); + for ( int k = 0; k < cc; ++k ) + { + CDmeClip *pClip = pTrack->GetClip( k ); + CDmeClip *pFilmClip = pFilmTrack->FindFilmClipAtTime( pClip->GetStartTime() ); + + int nIndex = association.AddToTail(); + association[nIndex].m_hClip = pClip; + association[nIndex].m_hAssociation = pFilmClip; + if ( pFilmClip ) + { + association[nIndex].m_offset = pClip->GetStartTime() - pFilmClip->GetStartTime(); + association[nIndex].m_nType = ClipAssociation_t::HAS_CLIP; + continue; + } + + // Handle edge cases + if ( pClip->GetStartTime() <= clipStartTime ) + { + association[nIndex].m_offset = pClip->GetStartTime() - clipStartTime; + association[nIndex].m_nType = ClipAssociation_t::BEFORE_START; + continue; + } + + if ( pClip->GetStartTime() >= clipEndTime ) + { + association[nIndex].m_offset = pClip->GetStartTime() - clipEndTime; + association[nIndex].m_nType = ClipAssociation_t::AFTER_END; + continue; + } + + association[nIndex].m_offset = DmeTime_t( 0 ); + association[nIndex].m_nType = ClipAssociation_t::NO_MOVEMENT; + } + } + } +} + + +//----------------------------------------------------------------------------- +// Rolls associated clips so they remain in the same relative time +//----------------------------------------------------------------------------- +void CDmeFilmClip::RollAssociatedClips( CDmeClip *pClip, CUtlVector< ClipAssociation_t > &association, DmeTime_t dt ) +{ + int c = association.Count(); + for ( int i = 0; i < c; ++i ) + { + if ( association[i].m_nType != ClipAssociation_t::HAS_CLIP ) + continue; + + if ( association[i].m_hAssociation.Get() != pClip ) + continue; + + DmeTime_t newStartTime = association[i].m_hClip->GetStartTime() - dt; + association[i].m_hClip->SetStartTime( newStartTime ); + } +} + +//----------------------------------------------------------------------------- +// Rolls associated clips so they remain in the same relative time +//----------------------------------------------------------------------------- +void CDmeFilmClip::ScaleAssociatedClips( CDmeClip *pClip, CUtlVector< ClipAssociation_t > &association, float ratio, DmeTime_t oldOffset ) +{ + int c = association.Count(); + for ( int i = 0; i < c; ++i ) + { + if ( association[i].m_nType != ClipAssociation_t::HAS_CLIP ) + continue; + + if ( association[i].m_hAssociation.Get() != pClip ) + continue; + + DmeTime_t clipStartTime = pClip->GetStartTime(); + DmeTime_t oldStartTime = association[i].m_hClip->GetStartTime(); + DmeTime_t newStartTime = ( oldStartTime - clipStartTime + oldOffset ) / ratio + clipStartTime - pClip->GetTimeOffset(); + association[i].m_hClip->SetStartTime( newStartTime ); + } +} + +void CDmeFilmClip::UpdateAssociatedClips( CUtlVector< ClipAssociation_t > &association ) +{ + int i; + + CDmeTrack *pFilmTrack = GetFilmTrack(); + if ( !pFilmTrack ) + return; + + int c = association.Count(); + if ( c > 0 ) + { + DmeTime_t clipStartTime = GetStartInChildMediaTime(); + DmeTime_t clipEndTime = GetEndInChildMediaTime(); + + for ( i = 0; i < c; ++i ) + { + ClipAssociation_t &curr = association[i]; + if ( !curr.m_hClip.Get() ) + continue; + + switch( curr.m_nType ) + { + case ClipAssociation_t::HAS_CLIP: + if ( curr.m_hAssociation.Get() ) + { + curr.m_hClip->SetStartTime( curr.m_hAssociation->GetStartTime() + curr.m_offset ); + } + break; + + case ClipAssociation_t::BEFORE_START: + curr.m_hClip->SetStartTime( clipStartTime + curr.m_offset ); + break; + + case ClipAssociation_t::AFTER_END: + curr.m_hClip->SetStartTime( clipEndTime + curr.m_offset ); + break; + } + } + } + + c = pFilmTrack->GetClipCount(); + for ( i = c; --i >= 0; ) + { + CDmeClip *pClip = pFilmTrack->GetClip(i); + if ( !Q_strcmp( pClip->GetName(), "__tempSlug__" ) ) + { + pFilmTrack->RemoveClip( i ); + } + } +} + + +//----------------------------------------------------------------------------- +// Creates a slug clip +//----------------------------------------------------------------------------- +CDmeFilmClip *CreateSlugClip( const char *pClipName, DmeTime_t startTime, DmeTime_t endTime, DmFileId_t fileid ) +{ + CDmeFilmClip *pSlugClip = CreateElement<CDmeFilmClip>( pClipName, fileid ); + pSlugClip->GetTimeFrame()->SetName( "timeframe" ); + pSlugClip->SetStartTime( startTime ); + pSlugClip->SetDuration( endTime - startTime ); + pSlugClip->SetTimeOffset( DmeTime_t( 0 ) ); + pSlugClip->SetTimeScale( 1.0f ); + pSlugClip->SetClipColor( Color( 0, 0, 0, 128 ) ); + pSlugClip->SetOverlay( "vgui/black" ); + return pSlugClip; +} + +//----------------------------------------------------------------------------- +// helper methods +//----------------------------------------------------------------------------- +CDmeTrack *GetParentTrack( CDmeClip *pClip ) +{ + DmAttributeReferenceIterator_t hAttr = g_pDataModel->FirstAttributeReferencingElement( pClip->GetHandle() ); + for ( ; hAttr != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; hAttr = g_pDataModel->NextAttributeReferencingElement( hAttr ) ) + { + CDmAttribute *pAttr = g_pDataModel->GetAttribute( hAttr ); + if ( !pAttr ) + continue; + + CDmeTrack *pTrack = CastElement< CDmeTrack >( pAttr->GetOwner() ); + if ( pTrack ) + return pTrack; + } + return NULL; +} + + +//----------------------------------------------------------------------------- +// Finds a channel in a channel or film clip targetting a particular element +//----------------------------------------------------------------------------- +CDmeChannel *FindChannelTargetingElement( CDmeChannelsClip *pChannelsClip, CDmElement *pElement, const char *pAttributeName ) +{ + int nChannels = pChannelsClip->m_Channels.Count(); + for ( int i = 0; i < nChannels; ++i ) + { + CDmeChannel *pChannel = pChannelsClip->m_Channels[ i ]; + CDmElement *toElement = pChannel->GetToElement(); + if ( toElement != pElement ) + continue; + + if ( pAttributeName && ( Q_stricmp( pChannel->GetToAttribute()->GetName(), pAttributeName ) != 0 ) ) + continue; + + return pChannel; + } + + return NULL; +} + +CDmeChannel *FindChannelTargetingElement( CDmeFilmClip *pClip, CDmElement *pElement, const char *pAttributeName, CDmeChannelsClip **ppChannelsClip, CDmeTrack **ppTrack, CDmeTrackGroup **ppTrackGroup ) +{ + int gc = pClip->GetTrackGroupCount(); + for ( int i = 0; i < gc; ++i ) + { + CDmeTrackGroup *pTrackGroup = pClip->GetTrackGroup( i ); + DMETRACKGROUP_FOREACH_CLIP_TYPE_START( CDmeChannelsClip, pTrackGroup, pTrack, pChannelsClip ) + + CDmeChannel *pChannel = FindChannelTargetingElement( pChannelsClip, pElement, pAttributeName ); + if ( !pChannel ) + continue; + + if ( ppChannelsClip ) + { + *ppChannelsClip = pChannelsClip; + } + if ( ppTrack ) + { + *ppTrack = pTrack; + } + if ( ppTrackGroup ) + { + *ppTrackGroup = pTrackGroup; + } + return pChannel; + + DMETRACKGROUP_FOREACH_CLIP_TYPE_END() + } + + return NULL; +} |