summaryrefslogtreecommitdiff
path: root/movieobjects/dmx_to_vcd.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /movieobjects/dmx_to_vcd.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'movieobjects/dmx_to_vcd.cpp')
-rw-r--r--movieobjects/dmx_to_vcd.cpp1052
1 files changed, 1052 insertions, 0 deletions
diff --git a/movieobjects/dmx_to_vcd.cpp b/movieobjects/dmx_to_vcd.cpp
new file mode 100644
index 0000000..a0037bc
--- /dev/null
+++ b/movieobjects/dmx_to_vcd.cpp
@@ -0,0 +1,1052 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "movieobjects/dmx_to_vcd.h"
+#include "movieobjects/movieobjects.h"
+#include "choreoscene.h"
+#include "choreoactor.h"
+#include "choreochannel.h"
+#include "choreoevent.h"
+#include "iscenetokenprocessor.h"
+#include "characterset.h"
+
+
+bool ConvertEventToDmx( CChoreoEvent *event, CDmeChannelsClip *clip )
+{
+ clip->SetName( event->GetName() );
+ clip->SetValue( "eventtype", CChoreoEvent::NameForType( event->GetType() ) );
+
+ CDmeTimeFrame *tf = clip->GetTimeFrame();
+ Assert( tf );
+ if ( tf )
+ {
+ tf->SetStartTime( DmeTime_t( event->GetStartTime() ) );
+ tf->SetDuration( DmeTime_t( event->GetDuration() ) );
+ }
+
+ clip->SetValue( "parameters", event->GetParameters() );
+ clip->SetValue( "parameters2", event->GetParameters2() );
+
+ // event_ramp is a channel under the event's channels clip
+ CDmrElementArray<> array( clip, "channels" );
+ Assert( array.IsValid() );
+ if ( array.IsValid() )
+ {
+ CDmeChannel *channel = CreateElement< CDmeChannel >( "event_ramp", clip->GetFileId() );
+ array.AddToTail( channel );
+
+ // Fill in values..., just log for now
+ channel->CreateLog( AT_FLOAT );
+ CDmeTypedLog<float> *ramp = static_cast< CDmeTypedLog<float> * >( channel->GetLog() );
+ if ( ramp )
+ {
+ CDmeFloatCurveInfo *pCurveInfo = CreateElement< CDmeFloatCurveInfo >( "floatcurveinfo", clip->GetFileId() );
+
+ pCurveInfo->SetDefaultCurveType( MAKE_CURVE_TYPE( INTERPOLATE_CATMULL_ROM_NORMALIZE, INTERPOLATE_CATMULL_ROM_NORMALIZE ) );
+ pCurveInfo->SetRightEdgeTime( DmeTime_t( event->GetDuration() ) );
+
+ pCurveInfo->SetUseEdgeInfo( true );
+ pCurveInfo->SetDefaultEdgeZeroValue( 0.0f );
+ // Left edge
+ pCurveInfo->SetEdgeInfo( 0,
+ event->GetRamp()->IsEdgeActive( true ),
+ event->GetRamp()->GetEdgeZeroValue( true ),
+ event->GetRamp()->GetEdgeCurveType( true ) );
+ // Right edge
+ pCurveInfo->SetEdgeInfo( 1,
+ event->GetRamp()->IsEdgeActive( false ),
+ event->GetRamp()->GetEdgeZeroValue( false ),
+ event->GetRamp()->GetEdgeCurveType( false ) );
+
+ ramp->SetCurveInfo( pCurveInfo );
+
+ int rampCount = event->GetRampCount();
+ for ( int j = 0; j < rampCount; ++j )
+ {
+ CExpressionSample *sample = event->GetRamp( j );
+ ramp->SetKey( DmeTime_t( sample->time ), sample->value, sample->GetCurveType() );
+ }
+ }
+ }
+
+ clip->SetValue< float >( "pitch", event->GetPitch() );
+ clip->SetValue< float >( "yaw", event->GetYaw() );
+
+ clip->SetValue< bool >( "resumecondition", event->IsResumeCondition() );
+ clip->SetValue< bool >( "lockbodyfacing", event->IsLockBodyFacing() );
+ clip->SetValue< float >( "distancetotarget", event->GetDistanceToTarget() );
+ clip->SetValue< bool >( "fixedlength", event->IsFixedLength() );
+ clip->SetValue< bool >( "forceshortmovement", event->GetForceShortMovement() );
+ clip->SetValue< bool >( "active", event->GetActive() );
+
+ // Relative tags
+ if ( event->GetNumRelativeTags() > 0 )
+ {
+ CDmElement *tags = CreateElement< CDmElement >( "relative_tags", clip->GetFileId() );
+ if ( tags )
+ {
+ clip->SetValue< CDmElement >( "tags", tags );
+
+ // Now create arrays for the name and percentages
+ CDmrStringArray names( tags, "tagname", true );
+ CDmrArray<float> percentages( tags, "tagpercentage", true );
+ Assert( names.IsValid() && percentages.IsValid() );
+
+ for ( int t = 0; t < event->GetNumRelativeTags(); t++ )
+ {
+ CEventRelativeTag *rt = event->GetRelativeTag( t );
+ Assert( rt );
+
+ names.AddToTail( rt->GetName() );
+ percentages.AddToTail( rt->GetPercentage() );
+ }
+ }
+ }
+
+ // Timing tags
+ if ( event->GetNumTimingTags() > 0 )
+ {
+ CDmElement *tags = CreateElement< CDmElement >( "timing_tags", clip->GetFileId() );
+ if ( tags )
+ {
+ clip->SetValue< CDmElement >( "flextimingtags", tags );
+
+ // Now create arrays for the name and percentages
+ CDmrStringArray names( tags, "tagname", true );
+ CDmrArray<float> percentages( tags, "tagpercentage", true );
+ CDmrArray<bool> lockstates( tags, "lockedstate", true );
+ Assert( names.IsValid() && percentages.IsValid() && lockstates.IsValid() );
+
+ for ( int t = 0; t < event->GetNumTimingTags(); t++ )
+ {
+ CFlexTimingTag *tt = event->GetTimingTag( t );
+ Assert( tt );
+
+ names.AddToTail( tt->GetName() );
+ percentages.AddToTail( tt->GetPercentage() );
+ lockstates.AddToTail( tt->GetLocked() );
+ }
+ }
+ }
+
+ // Abs tags
+ int tagtype;
+ for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ )
+ {
+ if ( event->GetNumAbsoluteTags( (CChoreoEvent::AbsTagType)tagtype ) > 0 )
+ {
+ char sz[ 512 ];
+
+ Q_snprintf( sz, sizeof( sz ), "absolutetags %s", CChoreoEvent::NameForAbsoluteTagType( (CChoreoEvent::AbsTagType)tagtype ) );
+
+ CDmElement *tags = CreateElement< CDmElement >( sz, clip->GetFileId() );
+ if ( tags )
+ {
+ clip->SetValue< CDmElement >( sz, tags );
+
+ // Now create arrays for the name and percentages
+ CDmrStringArray names( tags, "tagname", true );
+ CDmrArray<float> percentages( tags, "tagpercentage", true );
+ Assert( names.IsValid() && percentages.IsValid() );
+ for ( int t = 0; t < event->GetNumAbsoluteTags( (CChoreoEvent::AbsTagType)tagtype ); t++ )
+ {
+ CEventAbsoluteTag *abstag = event->GetAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, t );
+ Assert( abstag );
+
+ names.AddToTail( abstag->GetName() );
+ percentages.AddToTail( abstag->GetPercentage() );
+ }
+ }
+ }
+ }
+
+ // IsUsingRelativeTag
+ if ( event->IsUsingRelativeTag() )
+ {
+ CDmElement *relativeTag = CreateElement< CDmElement >( "relative_tag", clip->GetFileId() );
+ if ( relativeTag )
+ {
+ clip->SetValue< CDmElement >( "relative_tag", relativeTag );
+
+ relativeTag->SetValue( "tagname", event->GetRelativeTagName() );
+ relativeTag->SetValue( "tagwav", event->GetRelativeWavName() );
+ }
+ }
+
+ switch ( event->GetType() )
+ {
+ default:
+ break;
+ case CChoreoEvent::SPEAK:
+ {
+ CDmElement *speakProperties = CreateElement< CDmElement >( "SPEAK", clip->GetFileId() );
+ if ( speakProperties )
+ {
+ clip->SetValue< CDmElement >( "SPEAK", speakProperties );
+
+ speakProperties->SetValue( "closedcaption_type", CChoreoEvent::NameForCCType( event->GetCloseCaptionType() ) );
+ speakProperties->SetValue( "closedcaption_token", event->GetCloseCaptionToken() );
+ bool usingCombined = ( event->GetCloseCaptionType() != CChoreoEvent::CC_DISABLED && event->IsUsingCombinedFile() );
+ speakProperties->SetValue< bool >( "closedcaption_usingcombinedfile", usingCombined );
+ speakProperties->SetValue< bool >( "closedcaption_combinedusesgender", event->IsCombinedUsingGenderToken() );
+ speakProperties->SetValue< bool >( "closedcaption_noattenuate", event->IsSuppressingCaptionAttenuation() );
+ }
+ }
+ break;
+ case CChoreoEvent::GESTURE:
+ {
+ CDmElement *gestureProperties = CreateElement< CDmElement >( "GESTURE", clip->GetFileId() );
+ if ( gestureProperties )
+ {
+ clip->SetValue< CDmElement >( "GESTURE", gestureProperties );
+
+ float duration;
+ event->GetGestureSequenceDuration( duration );
+ gestureProperties->SetValue< float >( "sequenceduration", duration );
+ }
+ }
+ break;
+ case CChoreoEvent::FLEXANIMATION:
+ {
+ // Save flex animation tracks as channels
+ CDmrElementArray<> array( clip, "channels" );
+ Assert( array.IsValid() );
+ if ( array.IsValid() )
+ {
+ // Now add a DmeChannel for each flex controller
+ int numTracks = event->GetNumFlexAnimationTracks();
+ for ( int i = 0 ; i < numTracks; ++i )
+ {
+ CFlexAnimationTrack *track = event->GetFlexAnimationTrack( i );
+
+ CDmeChannel *channel = CreateElement< CDmeChannel >( track->GetFlexControllerName(), clip->GetFileId() );
+ array.AddToTail( channel );
+
+ channel->SetValue< bool >( "flexchannel", true );
+
+ channel->SetValue< bool >( "disabled", !track->IsTrackActive() );
+ channel->SetValue< bool >( "combo", track->IsComboType() );
+
+ channel->SetValue< float >( "rangemin", track->GetMin() );
+ channel->SetValue< float >( "rangemax", track->GetMax() );
+
+ channel->SetValue< bool >( "isbalancechannel", false );
+
+ // Fill in values..., just log for now
+ channel->CreateLog( AT_FLOAT );
+ CDmeTypedLog<float> *log = static_cast< CDmeTypedLog<float> * >( channel->GetLog() );
+ if ( log )
+ {
+ CDmeFloatCurveInfo *pCurveInfo = CreateElement< CDmeFloatCurveInfo >( "floatcurveinfo", clip->GetFileId() );
+
+ pCurveInfo->SetDefaultCurveType( MAKE_CURVE_TYPE( INTERPOLATE_CATMULL_ROM_NORMALIZEX, INTERPOLATE_CATMULL_ROM_NORMALIZEX ) );
+ pCurveInfo->SetRightEdgeTime( DmeTime_t( event->GetDuration() ) );
+
+ pCurveInfo->SetUseEdgeInfo( true );
+ pCurveInfo->SetDefaultEdgeZeroValue( 0.0f );
+ // Left edge
+ pCurveInfo->SetEdgeInfo( 0,
+ track->IsEdgeActive( true ),
+ track->GetEdgeZeroValue( true ),
+ track->GetEdgeCurveType( true ) );
+ // Right edge
+ pCurveInfo->SetEdgeInfo( 1,
+ track->IsEdgeActive( false ),
+ track->GetEdgeZeroValue( false ),
+ track->GetEdgeCurveType( false ) );
+
+ log->SetCurveInfo( pCurveInfo );
+
+ // Now set up edge properties
+
+ int sampleCount = track->GetNumSamples();
+ for ( int j = 0; j < sampleCount; ++j )
+ {
+ CExpressionSample *sample = track->GetSample( j );
+ log->SetKey( DmeTime_t( sample->time ), sample->value, sample->GetCurveType() );
+ }
+ }
+
+ // Right out the stereo "balance" curve
+ if ( track->IsComboType() )
+ {
+ char balanceChannelName[ 512 ];
+ Q_snprintf( balanceChannelName, sizeof( balanceChannelName ), "%s_balance", track->GetFlexControllerName() );
+
+ CDmeChannel *balanceChannel = CreateElement< CDmeChannel >( balanceChannelName, clip->GetFileId() );
+ array.AddToTail( balanceChannel );
+
+ channel->SetValue( "balanceChannel", balanceChannel );
+
+ balanceChannel->SetValue< bool >( "flexchannel", true );
+
+ balanceChannel->SetValue< bool >( "disabled", !track->IsTrackActive() );
+ balanceChannel->SetValue< bool >( "isbalancechannel", true );
+
+ balanceChannel->CreateLog( AT_FLOAT );
+ CDmeTypedLog< float > *balance = static_cast< CDmeTypedLog< float > * >( balanceChannel->GetLog() );
+ if ( balance )
+ {
+ CDmeFloatCurveInfo *pCurveInfo = CreateElement< CDmeFloatCurveInfo >( "floatcurveinfo", clip->GetFileId() );
+
+ pCurveInfo->SetDefaultCurveType( MAKE_CURVE_TYPE( INTERPOLATE_CATMULL_ROM_NORMALIZEX, INTERPOLATE_CATMULL_ROM_NORMALIZEX ) );
+ pCurveInfo->SetRightEdgeTime( DmeTime_t( event->GetDuration() ) );
+
+ pCurveInfo->SetUseEdgeInfo( false );
+ pCurveInfo->SetDefaultEdgeZeroValue( 0.5f );
+
+ /*
+ // Don't need to support edge properties for balance curves?
+ // Left edge
+ pCurveInfo->SetEdgeInfo( 0,
+ track->IsEdgeActive( true ),
+ track->GetEdgeZeroValue( true ),
+ track->GetEdgeCurveType( true ) );
+ // Right edge
+ pCurveInfo->SetEdgeInfo( 1,
+ track->IsEdgeActive( false ),
+ track->GetEdgeZeroValue( false ),
+ track->GetEdgeCurveType( false ) );
+ */
+
+ balance->SetCurveInfo( pCurveInfo );
+
+ // Now set up edge properties
+
+ int sampleCount = track->GetNumSamples( 1 );
+ for ( int j = 0; j < sampleCount; ++j )
+ {
+ CExpressionSample *sample = track->GetSample( j, 1 );
+ balance->SetKey( DmeTime_t( sample->time ), sample->value, sample->GetCurveType() );
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case CChoreoEvent::LOOP:
+ {
+ CDmElement *loopProperties = CreateElement< CDmElement >( "LOOP", clip->GetFileId() );
+ if ( loopProperties )
+ {
+ clip->SetValue< CDmElement >( "LOOP", loopProperties );
+
+ loopProperties->SetValue< int >( "loopcount", event->GetLoopCount() );
+ }
+ }
+ break;
+ }
+
+ return true;
+}
+
+bool ConvertSceneToDmx( CChoreoScene *scene, CDmeFilmClip *dmx )
+{
+ bool bret = true;
+
+ dmx->SetName( scene->GetFilename() );
+
+ CDmeTimeFrame *tf = dmx->GetTimeFrame();
+ Assert( tf );
+ if ( tf )
+ {
+ tf->SetDuration( DmeTime_t( scene->FindStopTime() ) );
+ }
+
+ CDmElement *scaleSettings = CreateElement< CDmElement >( "scalesettings", dmx->GetFileId() );
+ Assert( scaleSettings );
+ CDmAttribute *scaleAttribute = dmx->AddAttributeElement< CDmElement >( "scalesettings" );
+ Assert( scaleAttribute );
+ scaleAttribute->SetValue( scaleSettings->GetHandle() );
+ if ( scaleSettings )
+ {
+ for ( int i = scene->TimeZoomFirst(); i != scene->TimeZoomInvalid(); i = scene->TimeZoomNext( i ) )
+ {
+ const char *name = scene->TimeZoomName( i );
+ int value = scene->GetTimeZoom( name );
+
+ scaleSettings->SetValue< int >( name, value );
+ }
+ }
+
+ CDmeTrackGroup *pTrackGroup = dmx->FindOrAddTrackGroup( VCD_SCENE_RAMP_TRACK_GROUP_NAME );
+ CDmeTrack *track = pTrackGroup->FindOrAddTrack( VCD_SCENE_RAMP_TRACK_GROUP_NAME, DMECLIP_CHANNEL );
+ Assert( track );
+
+ // Set a CDmeChannel for the scene_ramp
+ CDmeChannelsClip *pClip = CreateElement< CDmeChannelsClip >( VCD_SCENE_RAMP_TRACK_GROUP_NAME, dmx->GetFileId() );
+ Assert( pClip );
+ track->AddClip( pClip );
+
+ int rampCount = scene->GetSceneRampCount();
+ if ( rampCount > 0 )
+ {
+ // scene_ramp is a channels
+ CDmrElementArray<> array( pClip, "channels" );
+ Assert( array.IsValid() );
+ if ( array.IsValid() )
+ {
+ CDmeChannel *channel = CreateElement< CDmeChannel >( VCD_SCENE_RAMP_TRACK_GROUP_NAME, dmx->GetFileId() );
+ array.AddToTail( channel );
+
+ // Fill in values..., just log for now
+ channel->CreateLog( AT_FLOAT );
+ CDmeTypedLog<float> *ramp = static_cast< CDmeTypedLog<float> * >( channel->GetLog() );
+ if ( ramp )
+ {
+ CDmeFloatCurveInfo *pCurveInfo = CreateElement< CDmeFloatCurveInfo >( "floatcurveinfo", dmx->GetFileId() );
+
+ pCurveInfo->SetDefaultCurveType( MAKE_CURVE_TYPE( INTERPOLATE_CATMULL_ROM_NORMALIZE, INTERPOLATE_CATMULL_ROM_NORMALIZE ) );
+ pCurveInfo->SetRightEdgeTime( DmeTime_t( scene->FindStopTime() ) );
+
+ pCurveInfo->SetUseEdgeInfo( true );
+ pCurveInfo->SetDefaultEdgeZeroValue( 0.0f );
+ // Left edge
+ pCurveInfo->SetEdgeInfo( 0,
+ scene->GetSceneRamp()->IsEdgeActive( true ),
+ scene->GetSceneRamp()->GetEdgeZeroValue( true ),
+ scene->GetSceneRamp()->GetEdgeCurveType( true ) );
+ // Right edge
+ pCurveInfo->SetEdgeInfo( 1,
+ scene->GetSceneRamp()->IsEdgeActive( false ),
+ scene->GetSceneRamp()->GetEdgeZeroValue( false ),
+ scene->GetSceneRamp()->GetEdgeCurveType( false ) );
+
+ ramp->SetCurveInfo( pCurveInfo );
+
+ for ( int j = 0; j < rampCount; ++j )
+ {
+ CExpressionSample *sample = scene->GetSceneRamp( j );
+ ramp->SetKey( DmeTime_t( sample->time ), sample->value, sample->GetCurveType() );
+ }
+ }
+ }
+ }
+
+ // Walk the actors and channels
+ int numActors = scene->GetNumActors();
+ for ( int actor = 0; actor < numActors; ++actor )
+ {
+ CChoreoActor *pActor = scene->GetActor( actor );
+ Assert( pActor );
+ if ( !pActor )
+ continue;
+
+ CDmeTrackGroup *pTrackGroup = dmx->FindOrAddTrackGroup( pActor->GetName() );
+ Assert( pTrackGroup );
+
+ pTrackGroup->SetValue< bool >( "isActor", true );
+ pTrackGroup->SetValue< bool >( "actorDisabled", !pActor->GetActive() );
+ pTrackGroup->SetValue( "actorModel", pActor->GetFacePoserModelName() );
+
+ int numChannels = pActor->GetNumChannels();
+ for ( int channel = 0; channel < numChannels; ++channel )
+ {
+ CChoreoChannel *pChannel = pActor->GetChannel( channel );
+ Assert( pChannel );
+ if ( !pChannel )
+ continue;
+
+ const char *channelName = pChannel->GetName();
+ CDmeTrack *track = pTrackGroup->FindOrAddTrack( channelName, DMECLIP_CHANNEL );
+ Assert( track );
+ if ( !track )
+ continue;
+
+ track->SetMute( !pChannel->GetActive() );
+
+ int numEvents = pChannel->GetNumEvents();
+ for ( int event = 0; event < numEvents; ++event )
+ {
+ CChoreoEvent *pEvent = pChannel->GetEvent( event );
+ Assert( pEvent );
+ if ( !pEvent )
+ continue;
+
+ // Set up event
+ CDmeChannelsClip *pClip = CreateElement< CDmeChannelsClip >( "", dmx->GetFileId() );
+ Assert( pClip );
+ track->AddClip( pClip );
+
+ // Fill in data
+ bool success = ConvertEventToDmx( pEvent, pClip );
+ if ( !success )
+ {
+ bret = false;
+ Assert( 0 );
+ break;
+ }
+ }
+ }
+ }
+
+ pTrackGroup = dmx->FindOrAddTrackGroup( VCD_GLOBAL_EVENTS_TRACK_GROUP_NAME );
+ Assert( pTrackGroup );
+
+ track = pTrackGroup->FindOrAddTrack( VCD_GLOBAL_EVENTS_TRACK_GROUP_NAME, DMECLIP_CHANNEL );
+ Assert( track );
+
+ // Now add global events
+ int numEvents = scene->GetNumEvents();
+ for ( int event = 0; event < numEvents; ++event )
+ {
+ CChoreoEvent *pEvent = scene->GetEvent( event );
+ if ( !pEvent || pEvent->GetActor() )
+ continue;
+
+ // Set up event
+ CDmeChannelsClip *pClip = CreateElement< CDmeChannelsClip >( "", dmx->GetFileId() );
+ Assert( pClip );
+
+ track->AddClip( pClip );
+
+ // Fill in data
+ bool success = ConvertEventToDmx( pEvent, pClip );
+ if ( !success )
+ {
+ bret = false;
+ Assert( 0 );
+ break;
+ }
+ }
+
+ dmx->SetValue( "associated_bsp", scene->GetMapname() );
+ dmx->SetValue< float >( "fps", scene->GetSceneFPS() );
+ dmx->SetValue< bool >( "snap", scene->IsUsingFrameSnap() );
+
+ return bret;
+}
+
+void EnsureActorAndChannelForTrack( CChoreoScene *scene, CDmeTrackGroup *pActor, CDmeTrack *pChannel )
+{
+ const char *actorName = pActor->GetName();
+ const char *channelName = pChannel->GetName();
+
+ CChoreoActor *a = scene->FindActor( actorName );
+ if ( !a )
+ {
+ a = scene->AllocActor();
+ Assert( a );
+ a->SetName( actorName );
+ a->SetActive( !pActor->GetValue< bool >( "actorDisabled" ) );
+ a->SetFacePoserModelName( pActor->GetValueString( "actorModel" ) );
+ }
+
+ CChoreoChannel *c = a->FindChannel( channelName );
+ if ( !c )
+ {
+ c = scene->AllocChannel();
+ Assert( c );
+ c->SetName( channelName );
+ c->SetActor( a );
+ c->SetActive( !pChannel->IsMute() );
+ a->AddChannel( c );
+ }
+}
+
+template< class T >
+T *FindAttributeInArray( const CDmrElementArray<> &array, const char *elementName )
+{
+ int c = array.Count();
+ for ( int i = 0; i < c; ++i )
+ {
+ T *element = CastElement< T >( array[ i ] );
+ if ( !element )
+ continue;
+
+ if ( !Q_stricmp( element->GetName(), elementName ) )
+ return element;
+ }
+
+ return NULL;
+}
+
+bool ConvertDmxToEvent( CChoreoScene *scene, CDmeTrackGroup *pActor, CDmeTrack *pChannel, CDmeChannelsClip *clip, bool globalEvent )
+{
+ bool bret = true;
+
+ // Allocate choreo event
+ CChoreoEvent *event = scene->AllocEvent();
+ Assert( event );
+ if ( !event )
+ {
+ bret = false;
+ return bret;
+ }
+
+ event->SetName( clip->GetName() );
+ event->SetType( CChoreoEvent::TypeForName( clip->GetValueString( "eventtype" ) ) );
+
+ if ( !globalEvent )
+ {
+ EnsureActorAndChannelForTrack( scene, pActor, pChannel );
+
+ const char *actorName = pActor->GetName();
+ const char *channelName = pChannel->GetName();
+
+ CChoreoActor *a = scene->FindActor( actorName );
+ Assert( a );
+ CChoreoChannel *c = a->FindChannel( channelName );
+ Assert( c );
+
+ if ( !a || !c )
+ {
+ bret = false;
+ return bret;
+ }
+
+ event->SetActor( a );
+ event->SetChannel( c );
+ c->AddEvent( event );
+ }
+
+ // Set timeframe info
+ CDmeTimeFrame *tf = clip->GetTimeFrame();
+ Assert( tf );
+ if ( tf )
+ {
+ event->SetStartTime( tf->GetStartTime().GetSeconds() );
+ float duration = tf->GetDuration().GetSeconds();
+ if ( duration <= 0.0f )
+ {
+ event->SetEndTime( -1.0f );
+ }
+ else
+ {
+ event->SetEndTime( event->GetStartTime() + duration );
+ }
+ }
+
+ event->SetParameters( clip->GetValueString( "parameters" ) );
+ event->SetParameters2( clip->GetValueString( "parameters2" ) );
+
+ const CDmrElementArray<> array( clip, "channels" );
+ Assert( array.IsValid() );
+ if ( array.IsValid() )
+ {
+ int c = array.Count();
+ for ( int i = 0 ; i < c; ++i )
+ {
+ CDmeChannel *channel = CastElement< CDmeChannel >( array[i] );
+ if ( !channel || Q_stricmp( channel->GetName(), "event_ramp" ) )
+ continue;
+
+ CDmeTypedLog< float > *ramp = static_cast< CDmeTypedLog< float > * >( channel->GetLog() );
+ if ( !ramp )
+ continue;
+
+ bool active[ 2 ];
+ float value[ 2 ];
+ int curveType[ 2 ];
+
+ ramp->GetEdgeInfo( 0, active[ 0 ], value[ 0 ], curveType[ 0 ] );
+ ramp->GetEdgeInfo( 1, active[ 1 ], value[ 1 ], curveType[ 1 ] );
+
+ event->GetRamp()->SetEdgeActive( true, active[ 0 ] );
+ event->GetRamp()->SetEdgeActive( false, active[ 1 ] );
+
+ event->GetRamp()->SetEdgeInfo( true, curveType[ 0 ], value[ 0 ] );
+ event->GetRamp()->SetEdgeInfo( false, curveType[ 1 ], value[ 1 ] );
+
+ int rampCount = ramp->GetKeyCount();
+ for ( int j = 0; j < rampCount; ++j )
+ {
+ CExpressionSample *sample = event->AddRamp( ramp->GetKeyTime( j ).GetSeconds(), ramp->GetKeyValue( j ), false );
+ sample->SetCurveType( ramp->GetKeyCurveType( j ) );
+ }
+ }
+ }
+
+ event->SetPitch( clip->GetValue< float >( "pitch" ) );
+ event->SetYaw( clip->GetValue< float >( "yaw" ) );
+
+ event->SetResumeCondition( clip->GetValue< bool >( "resumecondition" ) );
+ event->SetLockBodyFacing( clip->GetValue< bool >( "lockbodyfacing" ) );
+ event->SetDistanceToTarget( clip->GetValue< float >( "distancetotarget" ) );
+ event->SetFixedLength( clip->GetValue< bool >( "fixedlength" ) );
+ event->SetForceShortMovement( clip->GetValue< bool >( "forceshortmovement" ) );
+ event->SetActive( clip->GetValue< bool >( "active" ) );
+
+ if ( clip->HasAttribute( "tags" ) )
+ {
+ CDmElement *tags = clip->GetValueElement< CDmElement >( "tags" );
+ if ( tags )
+ {
+ // Now create arrays for the name and percentages
+ const CDmrStringArray names( tags, "tagname" );
+ const CDmrArray<float> percentages( tags, "tagpercentage" );
+ Assert( names.IsValid() && percentages.IsValid() );
+
+ Assert( names.Count() == percentages.Count() );
+ for ( int t = 0; t < names.Count(); t++ )
+ {
+ event->AddRelativeTag( names[t], percentages[t] );
+ }
+ }
+ }
+
+ if ( clip->HasAttribute( "timing_tags" ) )
+ {
+ CDmElement *tags = clip->GetValueElement< CDmElement >( "timing_tags" );
+ if ( tags )
+ {
+ // Now create arrays for the name and percentages
+ const CDmrStringArray names( tags, "tagname" );
+ const CDmrArray<float> percentages( tags, "tagpercentage" );
+ const CDmrArray<bool> lockstates( tags, "lockedstate" );
+
+ Assert( names.IsValid() && percentages.IsValid() && lockstates.IsValid() );
+ Assert( names.Count() == percentages.Count() && names.Count() == lockstates.Count() );
+
+ for ( int t = 0; t < names.Count(); t++ )
+ {
+ event->AddTimingTag( names[ t ], percentages[ t ], lockstates[ t ] );
+ }
+ }
+ }
+
+
+ // Abs tags
+ int tagtype;
+ for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ )
+ {
+ char sz[ 512 ];
+ Q_snprintf( sz, sizeof( sz ), "absolutetags %s", CChoreoEvent::NameForAbsoluteTagType( (CChoreoEvent::AbsTagType)tagtype ) );
+
+ if ( clip->HasAttribute( sz ) )
+ {
+ CDmElement *tags = clip->GetValueElement< CDmElement >( sz );
+ if ( tags )
+ {
+ // Now create arrays for the name and percentages
+ const CDmrStringArray names( tags, "tagname" );
+ const CDmrArray<float> percentages( tags, "tagpercentage" );
+
+ Assert( names.IsValid() && percentages.IsValid() );
+ Assert( names.Count() == percentages.Count() );
+
+ for ( int t = 0; t < names.Count(); t++ )
+ {
+ event->AddAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, names[ t ], percentages[ t ] );
+ }
+ }
+ }
+ }
+
+ if ( clip->HasAttribute( "relative_tag" ) )
+ {
+ CDmElement *relativeTag = clip->GetValueElement< CDmElement >( "relative_tag" );
+ if ( relativeTag )
+ {
+ event->SetUsingRelativeTag
+ (
+ true,
+ relativeTag->GetValueString( "tagname" ),
+ relativeTag->GetValueString( "tagwav" )
+ );
+ }
+ }
+
+ switch ( event->GetType() )
+ {
+ default:
+ break;
+ case CChoreoEvent::SPEAK:
+ {
+ CDmElement *speakProperties = NULL;
+ if ( clip->HasAttribute( "SPEAK" ) )
+ {
+ speakProperties = clip->GetValueElement< CDmElement >( "SPEAK" );
+ }
+ if ( speakProperties )
+ {
+ event->SetCloseCaptionType( CChoreoEvent::CCTypeForName( speakProperties->GetValueString( "closedcaption_type" ) ) );
+ event->SetCloseCaptionToken( speakProperties->GetValueString( "closedcaption_token" ) );
+ event->SetUsingCombinedFile( speakProperties->GetValue< bool >( "closedcaption_usingcombinedfile" ) );
+ event->SetCombinedUsingGenderToken( speakProperties->GetValue< bool >( "closedcaption_combinedusesgender" ) );
+ event->SetSuppressingCaptionAttenuation( speakProperties->GetValue< bool >( "closedcaption_noattenuate" ) );
+ }
+ }
+ break;
+ case CChoreoEvent::GESTURE:
+ {
+ CDmElement *gestureProperties = NULL;
+ if ( clip->HasAttribute( "GESTURE" ) )
+ {
+ gestureProperties = clip->GetValueElement< CDmElement >( "GESTURE" );
+ }
+ if ( gestureProperties )
+ {
+ if ( Q_stricmp( clip->GetName(), "NULL" ) )
+ {
+ event->SetGestureSequenceDuration( gestureProperties->GetValue< float >( "sequenceduration" ) );
+ }
+ }
+ }
+ break;
+ case CChoreoEvent::FLEXANIMATION:
+ {
+ // Save flex animation tracks as channels
+ const CDmrElementArray<> array( clip, "channels" );
+ if ( array.IsValid() )
+ {
+ // Now add a DmeChannel for each flex controller
+ int numTracks = array.Count();
+ for ( int i = 0 ; i < numTracks; ++i )
+ {
+ CDmeChannel *channel = CastElement< CDmeChannel >( array[ i ] );
+ Assert( channel );
+ if ( !channel )
+ {
+ bret = false;
+ break;
+ }
+
+ if ( !channel->HasAttribute( "flexchannel" ) )
+ continue;
+
+ // Skip all helper channels, only care about flexchannels
+ if ( !channel->GetValue< bool >( "flexchannel" ) )
+ continue;
+
+ // Skip the balance channels, we'll pull their data below
+ if ( channel->GetValue< bool >( "isbalancechannel" ) )
+ continue;
+
+ Assert( !Q_stristr( channel->GetName(), "_balance" ) );
+
+ CFlexAnimationTrack *track = event->AddTrack( channel->GetName() );
+ Assert( track );
+
+ if ( !track )
+ {
+ bret = false;
+ break;
+ }
+
+ track->SetTrackActive( !channel->GetValue< bool >( "disabled" ) );
+ track->SetComboType( channel->GetValue< bool >( "combo" ) );
+
+ track->SetMin( channel->GetValue< float >( "rangemin" ) );
+ track->SetMax( channel->GetValue< float >( "rangemax" ) );
+
+ CDmeTypedLog<float> *log = static_cast< CDmeTypedLog<float> * >( channel->GetLog() );
+ if ( log )
+ {
+ bool active[ 2 ];
+ float value[ 2 ];
+ int curveType[ 2 ];
+
+ log->GetEdgeInfo( 0, active[ 0 ], value[ 0 ], curveType[ 0 ] );
+ log->GetEdgeInfo( 1, active[ 1 ], value[ 1 ], curveType[ 1 ] );
+
+ track->SetEdgeActive( true, active[ 0 ] );
+ track->SetEdgeActive( false, active[ 1 ] );
+
+ track->SetEdgeInfo( true, curveType[ 0 ], value[ 0 ] );
+ track->SetEdgeInfo( false, curveType[ 1 ], value[ 1 ] );
+
+ int sampleCount = log->GetKeyCount();
+ for ( int j = 0; j < sampleCount; ++j )
+ {
+ int curveType = log->GetKeyCurveType( j );
+ float value = log->GetKeyValue( j );
+ DmeTime_t time = log->GetKeyTime( j );
+
+ CExpressionSample *sample = track->AddSample( time.GetSeconds(), value, 0 );
+ sample->SetCurveType( curveType );
+ }
+ }
+
+ // Right out the stereo "balance" curve
+ if ( track->IsComboType() )
+ {
+ char balanceChannelName[ 512 ];
+ Q_snprintf( balanceChannelName, sizeof( balanceChannelName ), "%s_balance", track->GetFlexControllerName() );
+
+ // Find the balance data
+ CDmeChannel *balanceChannel = FindAttributeInArray< CDmeChannel >( array, balanceChannelName );
+ if ( balanceChannel )
+ {
+ CDmeTypedLog< float > *balance = static_cast< CDmeTypedLog< float > * >( balanceChannel->GetLog() );
+ if ( balance )
+ {
+ // Now set up edge properties
+ int sampleCount = balance->GetKeyCount();
+ for ( int j = 0; j < sampleCount; ++j )
+ {
+ int curveType = balance->GetKeyCurveType( j );
+ float value = balance->GetKeyValue( j );
+ DmeTime_t time = balance->GetKeyTime( j );
+
+ CExpressionSample *sample = track->AddSample( time.GetSeconds(), value, 1 );
+ sample->SetCurveType( curveType );
+ }
+ }
+ else
+ {
+ char msg[ 512 ];
+ Q_snprintf( msg, sizeof( msg ), "Error: Missing balance channel for combo flex track (%s) in (%s)\n", track->GetFlexControllerName(), event->GetName() );
+ Warning( msg );
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case CChoreoEvent::LOOP:
+ {
+ CDmElement *loopProperties = NULL;
+ if ( clip->HasAttribute( "LOOP" ) )
+ {
+ loopProperties = clip->GetValueElement< CDmElement >( "LOOP" );
+ }
+ if ( loopProperties )
+ {
+ event->SetLoopCount( loopProperties->GetValue< int >( "loopcount" ) );
+ }
+ }
+ break;
+ }
+
+ return true;
+}
+
+bool ConvertDmxToScene( CDmeFilmClip *dmx, CChoreoScene *scene )
+{
+ bool bret = true;
+
+ // This should have been created correctly already
+ // Assert( !Q_stricmp( scene->GetFilename(), dmx->GetName() ) );
+
+ CDmElement *scaleSettings = dmx->GetValueElement< CDmElement >( "scalesettings" );
+ Assert( scaleSettings );
+ if ( scaleSettings )
+ {
+ CDmAttribute *setting = scaleSettings->FirstAttribute();
+ for ( ; setting ; setting = setting->NextAttribute() )
+ {
+ if ( setting->GetType() != AT_INT )
+ continue;
+
+ scene->SetTimeZoom( setting->GetName(), setting->GetValue<int>() );
+ }
+ }
+
+ // Deal with the scene ramp
+ CDmeTrackGroup *pTrackGroup = dmx->FindTrackGroup( VCD_SCENE_RAMP_TRACK_GROUP_NAME );
+ if ( pTrackGroup )
+ {
+ CDmeTrack *track = pTrackGroup->FindTrack( VCD_SCENE_RAMP_TRACK_GROUP_NAME );
+ if ( track )
+ {
+ CDmeChannelsClip *pClip = CastElement< CDmeChannelsClip >( track->FindNamedClip( VCD_SCENE_RAMP_TRACK_GROUP_NAME ) );
+ if ( pClip )
+ {
+ // scene_ramp should be the first subchannel
+ const CDmrElementArray<> array( pClip, "channels" );
+ Assert( array.IsValid() );
+ if ( array.IsValid() && ( array.Count() > 0 ) )
+ {
+ CDmeChannel *channel = CastElement< CDmeChannel >( array[0] );
+ if ( channel )
+ {
+ CDmeTypedLog< float > *ramp = static_cast< CDmeTypedLog< float > * >( channel->GetLog() );
+ if ( ramp )
+ {
+ bool active[ 2 ];
+ float value[ 2 ];
+ int curveType[ 2 ];
+
+ ramp->GetEdgeInfo( 0, active[ 0 ], value[ 0 ], curveType[ 0 ] );
+ ramp->GetEdgeInfo( 1, active[ 1 ], value[ 1 ], curveType[ 1 ] );
+
+ scene->GetSceneRamp()->SetEdgeActive( true, active[ 0 ] );
+ scene->GetSceneRamp()->SetEdgeActive( false, active[ 1 ] );
+
+ scene->GetSceneRamp()->SetEdgeInfo( true, curveType[ 0 ], value[ 0 ] );
+ scene->GetSceneRamp()->SetEdgeInfo( false, curveType[ 1 ], value[ 1 ] );
+
+ int rampCount = ramp->GetKeyCount();
+ for ( int j = 0; j < rampCount; ++j )
+ {
+ CExpressionSample *sample = scene->AddSceneRamp( ramp->GetKeyTime( j ).GetSeconds(), ramp->GetKeyValue( j ), false );
+ sample->SetCurveType( ramp->GetKeyCurveType( j ) );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Deal with global events
+ pTrackGroup = dmx->FindTrackGroup( VCD_GLOBAL_EVENTS_TRACK_GROUP_NAME );
+ if ( pTrackGroup )
+ {
+ CDmeTrack *pTrack = pTrackGroup->FindTrack( VCD_GLOBAL_EVENTS_TRACK_GROUP_NAME );
+ if ( pTrack )
+ {
+ // Now add global events
+ int numEvents = pTrack->GetClipCount();
+ for ( int event = 0; event < numEvents; ++event )
+ {
+ CDmeChannelsClip *pClip = CastElement< CDmeChannelsClip >( pTrack->GetClip( event ) );
+ if ( !pClip )
+ continue;
+
+ bool success = ConvertDmxToEvent( scene, pTrackGroup, pTrack, pClip, true );
+ if ( !success )
+ {
+ bret = false;
+ Assert( 0 );
+ break;
+ }
+ }
+ }
+ }
+
+ int nNumTrackGroups = dmx->GetTrackGroupCount();
+ for ( int i = 0; i < nNumTrackGroups; ++i )
+ {
+ CDmeTrackGroup *pTrackGroup = dmx->GetTrackGroup( i );
+ if ( !pTrackGroup->GetValue< bool >( "isActor" ) )
+ continue;
+
+ // Walk the track groups
+ int nNumTracks = pTrackGroup->GetTrackCount();
+ for ( int j = 0 ; j < nNumTracks; ++j )
+ {
+ CDmeTrack *pTrack = pTrackGroup->GetTrack( j );
+
+ EnsureActorAndChannelForTrack( scene, pTrackGroup, pTrack );
+
+ int numEvents = pTrack->GetClipCount();
+ for ( int clip = 0; clip < numEvents; ++clip )
+ {
+ CDmeChannelsClip *pClip = CastElement< CDmeChannelsClip >( pTrack->GetClip( clip ) );
+ if ( !pClip )
+ continue;
+
+ bool success = ConvertDmxToEvent( scene, pTrackGroup, pTrack, pClip, false );
+ if ( !success )
+ {
+ bret = false;
+ Assert( 0 );
+ break;
+ }
+ }
+ }
+ }
+
+ scene->SetMapname( dmx->GetValueString( "associated_bsp" ) );
+ scene->SetSceneFPS( dmx->GetValue< float >( "fps" ) );
+ scene->SetUsingFrameSnap( dmx->GetValue< bool >( "snap" ) );
+
+ return bret;
+} \ No newline at end of file