Team Fortress 2 Source Code as on 22/4/2020
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.

1051 lines
32 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "movieobjects/dmx_to_vcd.h"
  7. #include "movieobjects/movieobjects.h"
  8. #include "choreoscene.h"
  9. #include "choreoactor.h"
  10. #include "choreochannel.h"
  11. #include "choreoevent.h"
  12. #include "iscenetokenprocessor.h"
  13. #include "characterset.h"
  14. bool ConvertEventToDmx( CChoreoEvent *event, CDmeChannelsClip *clip )
  15. {
  16. clip->SetName( event->GetName() );
  17. clip->SetValue( "eventtype", CChoreoEvent::NameForType( event->GetType() ) );
  18. CDmeTimeFrame *tf = clip->GetTimeFrame();
  19. Assert( tf );
  20. if ( tf )
  21. {
  22. tf->SetStartTime( DmeTime_t( event->GetStartTime() ) );
  23. tf->SetDuration( DmeTime_t( event->GetDuration() ) );
  24. }
  25. clip->SetValue( "parameters", event->GetParameters() );
  26. clip->SetValue( "parameters2", event->GetParameters2() );
  27. // event_ramp is a channel under the event's channels clip
  28. CDmrElementArray<> array( clip, "channels" );
  29. Assert( array.IsValid() );
  30. if ( array.IsValid() )
  31. {
  32. CDmeChannel *channel = CreateElement< CDmeChannel >( "event_ramp", clip->GetFileId() );
  33. array.AddToTail( channel );
  34. // Fill in values..., just log for now
  35. channel->CreateLog( AT_FLOAT );
  36. CDmeTypedLog<float> *ramp = static_cast< CDmeTypedLog<float> * >( channel->GetLog() );
  37. if ( ramp )
  38. {
  39. CDmeFloatCurveInfo *pCurveInfo = CreateElement< CDmeFloatCurveInfo >( "floatcurveinfo", clip->GetFileId() );
  40. pCurveInfo->SetDefaultCurveType( MAKE_CURVE_TYPE( INTERPOLATE_CATMULL_ROM_NORMALIZE, INTERPOLATE_CATMULL_ROM_NORMALIZE ) );
  41. pCurveInfo->SetRightEdgeTime( DmeTime_t( event->GetDuration() ) );
  42. pCurveInfo->SetUseEdgeInfo( true );
  43. pCurveInfo->SetDefaultEdgeZeroValue( 0.0f );
  44. // Left edge
  45. pCurveInfo->SetEdgeInfo( 0,
  46. event->GetRamp()->IsEdgeActive( true ),
  47. event->GetRamp()->GetEdgeZeroValue( true ),
  48. event->GetRamp()->GetEdgeCurveType( true ) );
  49. // Right edge
  50. pCurveInfo->SetEdgeInfo( 1,
  51. event->GetRamp()->IsEdgeActive( false ),
  52. event->GetRamp()->GetEdgeZeroValue( false ),
  53. event->GetRamp()->GetEdgeCurveType( false ) );
  54. ramp->SetCurveInfo( pCurveInfo );
  55. int rampCount = event->GetRampCount();
  56. for ( int j = 0; j < rampCount; ++j )
  57. {
  58. CExpressionSample *sample = event->GetRamp( j );
  59. ramp->SetKey( DmeTime_t( sample->time ), sample->value, sample->GetCurveType() );
  60. }
  61. }
  62. }
  63. clip->SetValue< float >( "pitch", event->GetPitch() );
  64. clip->SetValue< float >( "yaw", event->GetYaw() );
  65. clip->SetValue< bool >( "resumecondition", event->IsResumeCondition() );
  66. clip->SetValue< bool >( "lockbodyfacing", event->IsLockBodyFacing() );
  67. clip->SetValue< float >( "distancetotarget", event->GetDistanceToTarget() );
  68. clip->SetValue< bool >( "fixedlength", event->IsFixedLength() );
  69. clip->SetValue< bool >( "forceshortmovement", event->GetForceShortMovement() );
  70. clip->SetValue< bool >( "active", event->GetActive() );
  71. // Relative tags
  72. if ( event->GetNumRelativeTags() > 0 )
  73. {
  74. CDmElement *tags = CreateElement< CDmElement >( "relative_tags", clip->GetFileId() );
  75. if ( tags )
  76. {
  77. clip->SetValue< CDmElement >( "tags", tags );
  78. // Now create arrays for the name and percentages
  79. CDmrStringArray names( tags, "tagname", true );
  80. CDmrArray<float> percentages( tags, "tagpercentage", true );
  81. Assert( names.IsValid() && percentages.IsValid() );
  82. for ( int t = 0; t < event->GetNumRelativeTags(); t++ )
  83. {
  84. CEventRelativeTag *rt = event->GetRelativeTag( t );
  85. Assert( rt );
  86. names.AddToTail( rt->GetName() );
  87. percentages.AddToTail( rt->GetPercentage() );
  88. }
  89. }
  90. }
  91. // Timing tags
  92. if ( event->GetNumTimingTags() > 0 )
  93. {
  94. CDmElement *tags = CreateElement< CDmElement >( "timing_tags", clip->GetFileId() );
  95. if ( tags )
  96. {
  97. clip->SetValue< CDmElement >( "flextimingtags", tags );
  98. // Now create arrays for the name and percentages
  99. CDmrStringArray names( tags, "tagname", true );
  100. CDmrArray<float> percentages( tags, "tagpercentage", true );
  101. CDmrArray<bool> lockstates( tags, "lockedstate", true );
  102. Assert( names.IsValid() && percentages.IsValid() && lockstates.IsValid() );
  103. for ( int t = 0; t < event->GetNumTimingTags(); t++ )
  104. {
  105. CFlexTimingTag *tt = event->GetTimingTag( t );
  106. Assert( tt );
  107. names.AddToTail( tt->GetName() );
  108. percentages.AddToTail( tt->GetPercentage() );
  109. lockstates.AddToTail( tt->GetLocked() );
  110. }
  111. }
  112. }
  113. // Abs tags
  114. int tagtype;
  115. for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ )
  116. {
  117. if ( event->GetNumAbsoluteTags( (CChoreoEvent::AbsTagType)tagtype ) > 0 )
  118. {
  119. char sz[ 512 ];
  120. Q_snprintf( sz, sizeof( sz ), "absolutetags %s", CChoreoEvent::NameForAbsoluteTagType( (CChoreoEvent::AbsTagType)tagtype ) );
  121. CDmElement *tags = CreateElement< CDmElement >( sz, clip->GetFileId() );
  122. if ( tags )
  123. {
  124. clip->SetValue< CDmElement >( sz, tags );
  125. // Now create arrays for the name and percentages
  126. CDmrStringArray names( tags, "tagname", true );
  127. CDmrArray<float> percentages( tags, "tagpercentage", true );
  128. Assert( names.IsValid() && percentages.IsValid() );
  129. for ( int t = 0; t < event->GetNumAbsoluteTags( (CChoreoEvent::AbsTagType)tagtype ); t++ )
  130. {
  131. CEventAbsoluteTag *abstag = event->GetAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, t );
  132. Assert( abstag );
  133. names.AddToTail( abstag->GetName() );
  134. percentages.AddToTail( abstag->GetPercentage() );
  135. }
  136. }
  137. }
  138. }
  139. // IsUsingRelativeTag
  140. if ( event->IsUsingRelativeTag() )
  141. {
  142. CDmElement *relativeTag = CreateElement< CDmElement >( "relative_tag", clip->GetFileId() );
  143. if ( relativeTag )
  144. {
  145. clip->SetValue< CDmElement >( "relative_tag", relativeTag );
  146. relativeTag->SetValue( "tagname", event->GetRelativeTagName() );
  147. relativeTag->SetValue( "tagwav", event->GetRelativeWavName() );
  148. }
  149. }
  150. switch ( event->GetType() )
  151. {
  152. default:
  153. break;
  154. case CChoreoEvent::SPEAK:
  155. {
  156. CDmElement *speakProperties = CreateElement< CDmElement >( "SPEAK", clip->GetFileId() );
  157. if ( speakProperties )
  158. {
  159. clip->SetValue< CDmElement >( "SPEAK", speakProperties );
  160. speakProperties->SetValue( "closedcaption_type", CChoreoEvent::NameForCCType( event->GetCloseCaptionType() ) );
  161. speakProperties->SetValue( "closedcaption_token", event->GetCloseCaptionToken() );
  162. bool usingCombined = ( event->GetCloseCaptionType() != CChoreoEvent::CC_DISABLED && event->IsUsingCombinedFile() );
  163. speakProperties->SetValue< bool >( "closedcaption_usingcombinedfile", usingCombined );
  164. speakProperties->SetValue< bool >( "closedcaption_combinedusesgender", event->IsCombinedUsingGenderToken() );
  165. speakProperties->SetValue< bool >( "closedcaption_noattenuate", event->IsSuppressingCaptionAttenuation() );
  166. }
  167. }
  168. break;
  169. case CChoreoEvent::GESTURE:
  170. {
  171. CDmElement *gestureProperties = CreateElement< CDmElement >( "GESTURE", clip->GetFileId() );
  172. if ( gestureProperties )
  173. {
  174. clip->SetValue< CDmElement >( "GESTURE", gestureProperties );
  175. float duration;
  176. event->GetGestureSequenceDuration( duration );
  177. gestureProperties->SetValue< float >( "sequenceduration", duration );
  178. }
  179. }
  180. break;
  181. case CChoreoEvent::FLEXANIMATION:
  182. {
  183. // Save flex animation tracks as channels
  184. CDmrElementArray<> array( clip, "channels" );
  185. Assert( array.IsValid() );
  186. if ( array.IsValid() )
  187. {
  188. // Now add a DmeChannel for each flex controller
  189. int numTracks = event->GetNumFlexAnimationTracks();
  190. for ( int i = 0 ; i < numTracks; ++i )
  191. {
  192. CFlexAnimationTrack *track = event->GetFlexAnimationTrack( i );
  193. CDmeChannel *channel = CreateElement< CDmeChannel >( track->GetFlexControllerName(), clip->GetFileId() );
  194. array.AddToTail( channel );
  195. channel->SetValue< bool >( "flexchannel", true );
  196. channel->SetValue< bool >( "disabled", !track->IsTrackActive() );
  197. channel->SetValue< bool >( "combo", track->IsComboType() );
  198. channel->SetValue< float >( "rangemin", track->GetMin() );
  199. channel->SetValue< float >( "rangemax", track->GetMax() );
  200. channel->SetValue< bool >( "isbalancechannel", false );
  201. // Fill in values..., just log for now
  202. channel->CreateLog( AT_FLOAT );
  203. CDmeTypedLog<float> *log = static_cast< CDmeTypedLog<float> * >( channel->GetLog() );
  204. if ( log )
  205. {
  206. CDmeFloatCurveInfo *pCurveInfo = CreateElement< CDmeFloatCurveInfo >( "floatcurveinfo", clip->GetFileId() );
  207. pCurveInfo->SetDefaultCurveType( MAKE_CURVE_TYPE( INTERPOLATE_CATMULL_ROM_NORMALIZEX, INTERPOLATE_CATMULL_ROM_NORMALIZEX ) );
  208. pCurveInfo->SetRightEdgeTime( DmeTime_t( event->GetDuration() ) );
  209. pCurveInfo->SetUseEdgeInfo( true );
  210. pCurveInfo->SetDefaultEdgeZeroValue( 0.0f );
  211. // Left edge
  212. pCurveInfo->SetEdgeInfo( 0,
  213. track->IsEdgeActive( true ),
  214. track->GetEdgeZeroValue( true ),
  215. track->GetEdgeCurveType( true ) );
  216. // Right edge
  217. pCurveInfo->SetEdgeInfo( 1,
  218. track->IsEdgeActive( false ),
  219. track->GetEdgeZeroValue( false ),
  220. track->GetEdgeCurveType( false ) );
  221. log->SetCurveInfo( pCurveInfo );
  222. // Now set up edge properties
  223. int sampleCount = track->GetNumSamples();
  224. for ( int j = 0; j < sampleCount; ++j )
  225. {
  226. CExpressionSample *sample = track->GetSample( j );
  227. log->SetKey( DmeTime_t( sample->time ), sample->value, sample->GetCurveType() );
  228. }
  229. }
  230. // Right out the stereo "balance" curve
  231. if ( track->IsComboType() )
  232. {
  233. char balanceChannelName[ 512 ];
  234. Q_snprintf( balanceChannelName, sizeof( balanceChannelName ), "%s_balance", track->GetFlexControllerName() );
  235. CDmeChannel *balanceChannel = CreateElement< CDmeChannel >( balanceChannelName, clip->GetFileId() );
  236. array.AddToTail( balanceChannel );
  237. channel->SetValue( "balanceChannel", balanceChannel );
  238. balanceChannel->SetValue< bool >( "flexchannel", true );
  239. balanceChannel->SetValue< bool >( "disabled", !track->IsTrackActive() );
  240. balanceChannel->SetValue< bool >( "isbalancechannel", true );
  241. balanceChannel->CreateLog( AT_FLOAT );
  242. CDmeTypedLog< float > *balance = static_cast< CDmeTypedLog< float > * >( balanceChannel->GetLog() );
  243. if ( balance )
  244. {
  245. CDmeFloatCurveInfo *pCurveInfo = CreateElement< CDmeFloatCurveInfo >( "floatcurveinfo", clip->GetFileId() );
  246. pCurveInfo->SetDefaultCurveType( MAKE_CURVE_TYPE( INTERPOLATE_CATMULL_ROM_NORMALIZEX, INTERPOLATE_CATMULL_ROM_NORMALIZEX ) );
  247. pCurveInfo->SetRightEdgeTime( DmeTime_t( event->GetDuration() ) );
  248. pCurveInfo->SetUseEdgeInfo( false );
  249. pCurveInfo->SetDefaultEdgeZeroValue( 0.5f );
  250. /*
  251. // Don't need to support edge properties for balance curves?
  252. // Left edge
  253. pCurveInfo->SetEdgeInfo( 0,
  254. track->IsEdgeActive( true ),
  255. track->GetEdgeZeroValue( true ),
  256. track->GetEdgeCurveType( true ) );
  257. // Right edge
  258. pCurveInfo->SetEdgeInfo( 1,
  259. track->IsEdgeActive( false ),
  260. track->GetEdgeZeroValue( false ),
  261. track->GetEdgeCurveType( false ) );
  262. */
  263. balance->SetCurveInfo( pCurveInfo );
  264. // Now set up edge properties
  265. int sampleCount = track->GetNumSamples( 1 );
  266. for ( int j = 0; j < sampleCount; ++j )
  267. {
  268. CExpressionSample *sample = track->GetSample( j, 1 );
  269. balance->SetKey( DmeTime_t( sample->time ), sample->value, sample->GetCurveType() );
  270. }
  271. }
  272. }
  273. }
  274. }
  275. }
  276. break;
  277. case CChoreoEvent::LOOP:
  278. {
  279. CDmElement *loopProperties = CreateElement< CDmElement >( "LOOP", clip->GetFileId() );
  280. if ( loopProperties )
  281. {
  282. clip->SetValue< CDmElement >( "LOOP", loopProperties );
  283. loopProperties->SetValue< int >( "loopcount", event->GetLoopCount() );
  284. }
  285. }
  286. break;
  287. }
  288. return true;
  289. }
  290. bool ConvertSceneToDmx( CChoreoScene *scene, CDmeFilmClip *dmx )
  291. {
  292. bool bret = true;
  293. dmx->SetName( scene->GetFilename() );
  294. CDmeTimeFrame *tf = dmx->GetTimeFrame();
  295. Assert( tf );
  296. if ( tf )
  297. {
  298. tf->SetDuration( DmeTime_t( scene->FindStopTime() ) );
  299. }
  300. CDmElement *scaleSettings = CreateElement< CDmElement >( "scalesettings", dmx->GetFileId() );
  301. Assert( scaleSettings );
  302. CDmAttribute *scaleAttribute = dmx->AddAttributeElement< CDmElement >( "scalesettings" );
  303. Assert( scaleAttribute );
  304. scaleAttribute->SetValue( scaleSettings->GetHandle() );
  305. if ( scaleSettings )
  306. {
  307. for ( int i = scene->TimeZoomFirst(); i != scene->TimeZoomInvalid(); i = scene->TimeZoomNext( i ) )
  308. {
  309. const char *name = scene->TimeZoomName( i );
  310. int value = scene->GetTimeZoom( name );
  311. scaleSettings->SetValue< int >( name, value );
  312. }
  313. }
  314. CDmeTrackGroup *pTrackGroup = dmx->FindOrAddTrackGroup( VCD_SCENE_RAMP_TRACK_GROUP_NAME );
  315. CDmeTrack *track = pTrackGroup->FindOrAddTrack( VCD_SCENE_RAMP_TRACK_GROUP_NAME, DMECLIP_CHANNEL );
  316. Assert( track );
  317. // Set a CDmeChannel for the scene_ramp
  318. CDmeChannelsClip *pClip = CreateElement< CDmeChannelsClip >( VCD_SCENE_RAMP_TRACK_GROUP_NAME, dmx->GetFileId() );
  319. Assert( pClip );
  320. track->AddClip( pClip );
  321. int rampCount = scene->GetSceneRampCount();
  322. if ( rampCount > 0 )
  323. {
  324. // scene_ramp is a channels
  325. CDmrElementArray<> array( pClip, "channels" );
  326. Assert( array.IsValid() );
  327. if ( array.IsValid() )
  328. {
  329. CDmeChannel *channel = CreateElement< CDmeChannel >( VCD_SCENE_RAMP_TRACK_GROUP_NAME, dmx->GetFileId() );
  330. array.AddToTail( channel );
  331. // Fill in values..., just log for now
  332. channel->CreateLog( AT_FLOAT );
  333. CDmeTypedLog<float> *ramp = static_cast< CDmeTypedLog<float> * >( channel->GetLog() );
  334. if ( ramp )
  335. {
  336. CDmeFloatCurveInfo *pCurveInfo = CreateElement< CDmeFloatCurveInfo >( "floatcurveinfo", dmx->GetFileId() );
  337. pCurveInfo->SetDefaultCurveType( MAKE_CURVE_TYPE( INTERPOLATE_CATMULL_ROM_NORMALIZE, INTERPOLATE_CATMULL_ROM_NORMALIZE ) );
  338. pCurveInfo->SetRightEdgeTime( DmeTime_t( scene->FindStopTime() ) );
  339. pCurveInfo->SetUseEdgeInfo( true );
  340. pCurveInfo->SetDefaultEdgeZeroValue( 0.0f );
  341. // Left edge
  342. pCurveInfo->SetEdgeInfo( 0,
  343. scene->GetSceneRamp()->IsEdgeActive( true ),
  344. scene->GetSceneRamp()->GetEdgeZeroValue( true ),
  345. scene->GetSceneRamp()->GetEdgeCurveType( true ) );
  346. // Right edge
  347. pCurveInfo->SetEdgeInfo( 1,
  348. scene->GetSceneRamp()->IsEdgeActive( false ),
  349. scene->GetSceneRamp()->GetEdgeZeroValue( false ),
  350. scene->GetSceneRamp()->GetEdgeCurveType( false ) );
  351. ramp->SetCurveInfo( pCurveInfo );
  352. for ( int j = 0; j < rampCount; ++j )
  353. {
  354. CExpressionSample *sample = scene->GetSceneRamp( j );
  355. ramp->SetKey( DmeTime_t( sample->time ), sample->value, sample->GetCurveType() );
  356. }
  357. }
  358. }
  359. }
  360. // Walk the actors and channels
  361. int numActors = scene->GetNumActors();
  362. for ( int actor = 0; actor < numActors; ++actor )
  363. {
  364. CChoreoActor *pActor = scene->GetActor( actor );
  365. Assert( pActor );
  366. if ( !pActor )
  367. continue;
  368. CDmeTrackGroup *pTrackGroup = dmx->FindOrAddTrackGroup( pActor->GetName() );
  369. Assert( pTrackGroup );
  370. pTrackGroup->SetValue< bool >( "isActor", true );
  371. pTrackGroup->SetValue< bool >( "actorDisabled", !pActor->GetActive() );
  372. pTrackGroup->SetValue( "actorModel", pActor->GetFacePoserModelName() );
  373. int numChannels = pActor->GetNumChannels();
  374. for ( int channel = 0; channel < numChannels; ++channel )
  375. {
  376. CChoreoChannel *pChannel = pActor->GetChannel( channel );
  377. Assert( pChannel );
  378. if ( !pChannel )
  379. continue;
  380. const char *channelName = pChannel->GetName();
  381. CDmeTrack *track = pTrackGroup->FindOrAddTrack( channelName, DMECLIP_CHANNEL );
  382. Assert( track );
  383. if ( !track )
  384. continue;
  385. track->SetMute( !pChannel->GetActive() );
  386. int numEvents = pChannel->GetNumEvents();
  387. for ( int event = 0; event < numEvents; ++event )
  388. {
  389. CChoreoEvent *pEvent = pChannel->GetEvent( event );
  390. Assert( pEvent );
  391. if ( !pEvent )
  392. continue;
  393. // Set up event
  394. CDmeChannelsClip *pClip = CreateElement< CDmeChannelsClip >( "", dmx->GetFileId() );
  395. Assert( pClip );
  396. track->AddClip( pClip );
  397. // Fill in data
  398. bool success = ConvertEventToDmx( pEvent, pClip );
  399. if ( !success )
  400. {
  401. bret = false;
  402. Assert( 0 );
  403. break;
  404. }
  405. }
  406. }
  407. }
  408. pTrackGroup = dmx->FindOrAddTrackGroup( VCD_GLOBAL_EVENTS_TRACK_GROUP_NAME );
  409. Assert( pTrackGroup );
  410. track = pTrackGroup->FindOrAddTrack( VCD_GLOBAL_EVENTS_TRACK_GROUP_NAME, DMECLIP_CHANNEL );
  411. Assert( track );
  412. // Now add global events
  413. int numEvents = scene->GetNumEvents();
  414. for ( int event = 0; event < numEvents; ++event )
  415. {
  416. CChoreoEvent *pEvent = scene->GetEvent( event );
  417. if ( !pEvent || pEvent->GetActor() )
  418. continue;
  419. // Set up event
  420. CDmeChannelsClip *pClip = CreateElement< CDmeChannelsClip >( "", dmx->GetFileId() );
  421. Assert( pClip );
  422. track->AddClip( pClip );
  423. // Fill in data
  424. bool success = ConvertEventToDmx( pEvent, pClip );
  425. if ( !success )
  426. {
  427. bret = false;
  428. Assert( 0 );
  429. break;
  430. }
  431. }
  432. dmx->SetValue( "associated_bsp", scene->GetMapname() );
  433. dmx->SetValue< float >( "fps", scene->GetSceneFPS() );
  434. dmx->SetValue< bool >( "snap", scene->IsUsingFrameSnap() );
  435. return bret;
  436. }
  437. void EnsureActorAndChannelForTrack( CChoreoScene *scene, CDmeTrackGroup *pActor, CDmeTrack *pChannel )
  438. {
  439. const char *actorName = pActor->GetName();
  440. const char *channelName = pChannel->GetName();
  441. CChoreoActor *a = scene->FindActor( actorName );
  442. if ( !a )
  443. {
  444. a = scene->AllocActor();
  445. Assert( a );
  446. a->SetName( actorName );
  447. a->SetActive( !pActor->GetValue< bool >( "actorDisabled" ) );
  448. a->SetFacePoserModelName( pActor->GetValueString( "actorModel" ) );
  449. }
  450. CChoreoChannel *c = a->FindChannel( channelName );
  451. if ( !c )
  452. {
  453. c = scene->AllocChannel();
  454. Assert( c );
  455. c->SetName( channelName );
  456. c->SetActor( a );
  457. c->SetActive( !pChannel->IsMute() );
  458. a->AddChannel( c );
  459. }
  460. }
  461. template< class T >
  462. T *FindAttributeInArray( const CDmrElementArray<> &array, const char *elementName )
  463. {
  464. int c = array.Count();
  465. for ( int i = 0; i < c; ++i )
  466. {
  467. T *element = CastElement< T >( array[ i ] );
  468. if ( !element )
  469. continue;
  470. if ( !Q_stricmp( element->GetName(), elementName ) )
  471. return element;
  472. }
  473. return NULL;
  474. }
  475. bool ConvertDmxToEvent( CChoreoScene *scene, CDmeTrackGroup *pActor, CDmeTrack *pChannel, CDmeChannelsClip *clip, bool globalEvent )
  476. {
  477. bool bret = true;
  478. // Allocate choreo event
  479. CChoreoEvent *event = scene->AllocEvent();
  480. Assert( event );
  481. if ( !event )
  482. {
  483. bret = false;
  484. return bret;
  485. }
  486. event->SetName( clip->GetName() );
  487. event->SetType( CChoreoEvent::TypeForName( clip->GetValueString( "eventtype" ) ) );
  488. if ( !globalEvent )
  489. {
  490. EnsureActorAndChannelForTrack( scene, pActor, pChannel );
  491. const char *actorName = pActor->GetName();
  492. const char *channelName = pChannel->GetName();
  493. CChoreoActor *a = scene->FindActor( actorName );
  494. Assert( a );
  495. CChoreoChannel *c = a->FindChannel( channelName );
  496. Assert( c );
  497. if ( !a || !c )
  498. {
  499. bret = false;
  500. return bret;
  501. }
  502. event->SetActor( a );
  503. event->SetChannel( c );
  504. c->AddEvent( event );
  505. }
  506. // Set timeframe info
  507. CDmeTimeFrame *tf = clip->GetTimeFrame();
  508. Assert( tf );
  509. if ( tf )
  510. {
  511. event->SetStartTime( tf->GetStartTime().GetSeconds() );
  512. float duration = tf->GetDuration().GetSeconds();
  513. if ( duration <= 0.0f )
  514. {
  515. event->SetEndTime( -1.0f );
  516. }
  517. else
  518. {
  519. event->SetEndTime( event->GetStartTime() + duration );
  520. }
  521. }
  522. event->SetParameters( clip->GetValueString( "parameters" ) );
  523. event->SetParameters2( clip->GetValueString( "parameters2" ) );
  524. const CDmrElementArray<> array( clip, "channels" );
  525. Assert( array.IsValid() );
  526. if ( array.IsValid() )
  527. {
  528. int c = array.Count();
  529. for ( int i = 0 ; i < c; ++i )
  530. {
  531. CDmeChannel *channel = CastElement< CDmeChannel >( array[i] );
  532. if ( !channel || Q_stricmp( channel->GetName(), "event_ramp" ) )
  533. continue;
  534. CDmeTypedLog< float > *ramp = static_cast< CDmeTypedLog< float > * >( channel->GetLog() );
  535. if ( !ramp )
  536. continue;
  537. bool active[ 2 ];
  538. float value[ 2 ];
  539. int curveType[ 2 ];
  540. ramp->GetEdgeInfo( 0, active[ 0 ], value[ 0 ], curveType[ 0 ] );
  541. ramp->GetEdgeInfo( 1, active[ 1 ], value[ 1 ], curveType[ 1 ] );
  542. event->GetRamp()->SetEdgeActive( true, active[ 0 ] );
  543. event->GetRamp()->SetEdgeActive( false, active[ 1 ] );
  544. event->GetRamp()->SetEdgeInfo( true, curveType[ 0 ], value[ 0 ] );
  545. event->GetRamp()->SetEdgeInfo( false, curveType[ 1 ], value[ 1 ] );
  546. int rampCount = ramp->GetKeyCount();
  547. for ( int j = 0; j < rampCount; ++j )
  548. {
  549. CExpressionSample *sample = event->AddRamp( ramp->GetKeyTime( j ).GetSeconds(), ramp->GetKeyValue( j ), false );
  550. sample->SetCurveType( ramp->GetKeyCurveType( j ) );
  551. }
  552. }
  553. }
  554. event->SetPitch( clip->GetValue< float >( "pitch" ) );
  555. event->SetYaw( clip->GetValue< float >( "yaw" ) );
  556. event->SetResumeCondition( clip->GetValue< bool >( "resumecondition" ) );
  557. event->SetLockBodyFacing( clip->GetValue< bool >( "lockbodyfacing" ) );
  558. event->SetDistanceToTarget( clip->GetValue< float >( "distancetotarget" ) );
  559. event->SetFixedLength( clip->GetValue< bool >( "fixedlength" ) );
  560. event->SetForceShortMovement( clip->GetValue< bool >( "forceshortmovement" ) );
  561. event->SetActive( clip->GetValue< bool >( "active" ) );
  562. if ( clip->HasAttribute( "tags" ) )
  563. {
  564. CDmElement *tags = clip->GetValueElement< CDmElement >( "tags" );
  565. if ( tags )
  566. {
  567. // Now create arrays for the name and percentages
  568. const CDmrStringArray names( tags, "tagname" );
  569. const CDmrArray<float> percentages( tags, "tagpercentage" );
  570. Assert( names.IsValid() && percentages.IsValid() );
  571. Assert( names.Count() == percentages.Count() );
  572. for ( int t = 0; t < names.Count(); t++ )
  573. {
  574. event->AddRelativeTag( names[t], percentages[t] );
  575. }
  576. }
  577. }
  578. if ( clip->HasAttribute( "timing_tags" ) )
  579. {
  580. CDmElement *tags = clip->GetValueElement< CDmElement >( "timing_tags" );
  581. if ( tags )
  582. {
  583. // Now create arrays for the name and percentages
  584. const CDmrStringArray names( tags, "tagname" );
  585. const CDmrArray<float> percentages( tags, "tagpercentage" );
  586. const CDmrArray<bool> lockstates( tags, "lockedstate" );
  587. Assert( names.IsValid() && percentages.IsValid() && lockstates.IsValid() );
  588. Assert( names.Count() == percentages.Count() && names.Count() == lockstates.Count() );
  589. for ( int t = 0; t < names.Count(); t++ )
  590. {
  591. event->AddTimingTag( names[ t ], percentages[ t ], lockstates[ t ] );
  592. }
  593. }
  594. }
  595. // Abs tags
  596. int tagtype;
  597. for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ )
  598. {
  599. char sz[ 512 ];
  600. Q_snprintf( sz, sizeof( sz ), "absolutetags %s", CChoreoEvent::NameForAbsoluteTagType( (CChoreoEvent::AbsTagType)tagtype ) );
  601. if ( clip->HasAttribute( sz ) )
  602. {
  603. CDmElement *tags = clip->GetValueElement< CDmElement >( sz );
  604. if ( tags )
  605. {
  606. // Now create arrays for the name and percentages
  607. const CDmrStringArray names( tags, "tagname" );
  608. const CDmrArray<float> percentages( tags, "tagpercentage" );
  609. Assert( names.IsValid() && percentages.IsValid() );
  610. Assert( names.Count() == percentages.Count() );
  611. for ( int t = 0; t < names.Count(); t++ )
  612. {
  613. event->AddAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, names[ t ], percentages[ t ] );
  614. }
  615. }
  616. }
  617. }
  618. if ( clip->HasAttribute( "relative_tag" ) )
  619. {
  620. CDmElement *relativeTag = clip->GetValueElement< CDmElement >( "relative_tag" );
  621. if ( relativeTag )
  622. {
  623. event->SetUsingRelativeTag
  624. (
  625. true,
  626. relativeTag->GetValueString( "tagname" ),
  627. relativeTag->GetValueString( "tagwav" )
  628. );
  629. }
  630. }
  631. switch ( event->GetType() )
  632. {
  633. default:
  634. break;
  635. case CChoreoEvent::SPEAK:
  636. {
  637. CDmElement *speakProperties = NULL;
  638. if ( clip->HasAttribute( "SPEAK" ) )
  639. {
  640. speakProperties = clip->GetValueElement< CDmElement >( "SPEAK" );
  641. }
  642. if ( speakProperties )
  643. {
  644. event->SetCloseCaptionType( CChoreoEvent::CCTypeForName( speakProperties->GetValueString( "closedcaption_type" ) ) );
  645. event->SetCloseCaptionToken( speakProperties->GetValueString( "closedcaption_token" ) );
  646. event->SetUsingCombinedFile( speakProperties->GetValue< bool >( "closedcaption_usingcombinedfile" ) );
  647. event->SetCombinedUsingGenderToken( speakProperties->GetValue< bool >( "closedcaption_combinedusesgender" ) );
  648. event->SetSuppressingCaptionAttenuation( speakProperties->GetValue< bool >( "closedcaption_noattenuate" ) );
  649. }
  650. }
  651. break;
  652. case CChoreoEvent::GESTURE:
  653. {
  654. CDmElement *gestureProperties = NULL;
  655. if ( clip->HasAttribute( "GESTURE" ) )
  656. {
  657. gestureProperties = clip->GetValueElement< CDmElement >( "GESTURE" );
  658. }
  659. if ( gestureProperties )
  660. {
  661. if ( Q_stricmp( clip->GetName(), "NULL" ) )
  662. {
  663. event->SetGestureSequenceDuration( gestureProperties->GetValue< float >( "sequenceduration" ) );
  664. }
  665. }
  666. }
  667. break;
  668. case CChoreoEvent::FLEXANIMATION:
  669. {
  670. // Save flex animation tracks as channels
  671. const CDmrElementArray<> array( clip, "channels" );
  672. if ( array.IsValid() )
  673. {
  674. // Now add a DmeChannel for each flex controller
  675. int numTracks = array.Count();
  676. for ( int i = 0 ; i < numTracks; ++i )
  677. {
  678. CDmeChannel *channel = CastElement< CDmeChannel >( array[ i ] );
  679. Assert( channel );
  680. if ( !channel )
  681. {
  682. bret = false;
  683. break;
  684. }
  685. if ( !channel->HasAttribute( "flexchannel" ) )
  686. continue;
  687. // Skip all helper channels, only care about flexchannels
  688. if ( !channel->GetValue< bool >( "flexchannel" ) )
  689. continue;
  690. // Skip the balance channels, we'll pull their data below
  691. if ( channel->GetValue< bool >( "isbalancechannel" ) )
  692. continue;
  693. Assert( !Q_stristr( channel->GetName(), "_balance" ) );
  694. CFlexAnimationTrack *track = event->AddTrack( channel->GetName() );
  695. Assert( track );
  696. if ( !track )
  697. {
  698. bret = false;
  699. break;
  700. }
  701. track->SetTrackActive( !channel->GetValue< bool >( "disabled" ) );
  702. track->SetComboType( channel->GetValue< bool >( "combo" ) );
  703. track->SetMin( channel->GetValue< float >( "rangemin" ) );
  704. track->SetMax( channel->GetValue< float >( "rangemax" ) );
  705. CDmeTypedLog<float> *log = static_cast< CDmeTypedLog<float> * >( channel->GetLog() );
  706. if ( log )
  707. {
  708. bool active[ 2 ];
  709. float value[ 2 ];
  710. int curveType[ 2 ];
  711. log->GetEdgeInfo( 0, active[ 0 ], value[ 0 ], curveType[ 0 ] );
  712. log->GetEdgeInfo( 1, active[ 1 ], value[ 1 ], curveType[ 1 ] );
  713. track->SetEdgeActive( true, active[ 0 ] );
  714. track->SetEdgeActive( false, active[ 1 ] );
  715. track->SetEdgeInfo( true, curveType[ 0 ], value[ 0 ] );
  716. track->SetEdgeInfo( false, curveType[ 1 ], value[ 1 ] );
  717. int sampleCount = log->GetKeyCount();
  718. for ( int j = 0; j < sampleCount; ++j )
  719. {
  720. int curveType = log->GetKeyCurveType( j );
  721. float value = log->GetKeyValue( j );
  722. DmeTime_t time = log->GetKeyTime( j );
  723. CExpressionSample *sample = track->AddSample( time.GetSeconds(), value, 0 );
  724. sample->SetCurveType( curveType );
  725. }
  726. }
  727. // Right out the stereo "balance" curve
  728. if ( track->IsComboType() )
  729. {
  730. char balanceChannelName[ 512 ];
  731. Q_snprintf( balanceChannelName, sizeof( balanceChannelName ), "%s_balance", track->GetFlexControllerName() );
  732. // Find the balance data
  733. CDmeChannel *balanceChannel = FindAttributeInArray< CDmeChannel >( array, balanceChannelName );
  734. if ( balanceChannel )
  735. {
  736. CDmeTypedLog< float > *balance = static_cast< CDmeTypedLog< float > * >( balanceChannel->GetLog() );
  737. if ( balance )
  738. {
  739. // Now set up edge properties
  740. int sampleCount = balance->GetKeyCount();
  741. for ( int j = 0; j < sampleCount; ++j )
  742. {
  743. int curveType = balance->GetKeyCurveType( j );
  744. float value = balance->GetKeyValue( j );
  745. DmeTime_t time = balance->GetKeyTime( j );
  746. CExpressionSample *sample = track->AddSample( time.GetSeconds(), value, 1 );
  747. sample->SetCurveType( curveType );
  748. }
  749. }
  750. else
  751. {
  752. char msg[ 512 ];
  753. Q_snprintf( msg, sizeof( msg ), "Error: Missing balance channel for combo flex track (%s) in (%s)\n", track->GetFlexControllerName(), event->GetName() );
  754. Warning( msg );
  755. }
  756. }
  757. }
  758. }
  759. }
  760. }
  761. break;
  762. case CChoreoEvent::LOOP:
  763. {
  764. CDmElement *loopProperties = NULL;
  765. if ( clip->HasAttribute( "LOOP" ) )
  766. {
  767. loopProperties = clip->GetValueElement< CDmElement >( "LOOP" );
  768. }
  769. if ( loopProperties )
  770. {
  771. event->SetLoopCount( loopProperties->GetValue< int >( "loopcount" ) );
  772. }
  773. }
  774. break;
  775. }
  776. return true;
  777. }
  778. bool ConvertDmxToScene( CDmeFilmClip *dmx, CChoreoScene *scene )
  779. {
  780. bool bret = true;
  781. // This should have been created correctly already
  782. // Assert( !Q_stricmp( scene->GetFilename(), dmx->GetName() ) );
  783. CDmElement *scaleSettings = dmx->GetValueElement< CDmElement >( "scalesettings" );
  784. Assert( scaleSettings );
  785. if ( scaleSettings )
  786. {
  787. CDmAttribute *setting = scaleSettings->FirstAttribute();
  788. for ( ; setting ; setting = setting->NextAttribute() )
  789. {
  790. if ( setting->GetType() != AT_INT )
  791. continue;
  792. scene->SetTimeZoom( setting->GetName(), setting->GetValue<int>() );
  793. }
  794. }
  795. // Deal with the scene ramp
  796. CDmeTrackGroup *pTrackGroup = dmx->FindTrackGroup( VCD_SCENE_RAMP_TRACK_GROUP_NAME );
  797. if ( pTrackGroup )
  798. {
  799. CDmeTrack *track = pTrackGroup->FindTrack( VCD_SCENE_RAMP_TRACK_GROUP_NAME );
  800. if ( track )
  801. {
  802. CDmeChannelsClip *pClip = CastElement< CDmeChannelsClip >( track->FindNamedClip( VCD_SCENE_RAMP_TRACK_GROUP_NAME ) );
  803. if ( pClip )
  804. {
  805. // scene_ramp should be the first subchannel
  806. const CDmrElementArray<> array( pClip, "channels" );
  807. Assert( array.IsValid() );
  808. if ( array.IsValid() && ( array.Count() > 0 ) )
  809. {
  810. CDmeChannel *channel = CastElement< CDmeChannel >( array[0] );
  811. if ( channel )
  812. {
  813. CDmeTypedLog< float > *ramp = static_cast< CDmeTypedLog< float > * >( channel->GetLog() );
  814. if ( ramp )
  815. {
  816. bool active[ 2 ];
  817. float value[ 2 ];
  818. int curveType[ 2 ];
  819. ramp->GetEdgeInfo( 0, active[ 0 ], value[ 0 ], curveType[ 0 ] );
  820. ramp->GetEdgeInfo( 1, active[ 1 ], value[ 1 ], curveType[ 1 ] );
  821. scene->GetSceneRamp()->SetEdgeActive( true, active[ 0 ] );
  822. scene->GetSceneRamp()->SetEdgeActive( false, active[ 1 ] );
  823. scene->GetSceneRamp()->SetEdgeInfo( true, curveType[ 0 ], value[ 0 ] );
  824. scene->GetSceneRamp()->SetEdgeInfo( false, curveType[ 1 ], value[ 1 ] );
  825. int rampCount = ramp->GetKeyCount();
  826. for ( int j = 0; j < rampCount; ++j )
  827. {
  828. CExpressionSample *sample = scene->AddSceneRamp( ramp->GetKeyTime( j ).GetSeconds(), ramp->GetKeyValue( j ), false );
  829. sample->SetCurveType( ramp->GetKeyCurveType( j ) );
  830. }
  831. }
  832. }
  833. }
  834. }
  835. }
  836. }
  837. // Deal with global events
  838. pTrackGroup = dmx->FindTrackGroup( VCD_GLOBAL_EVENTS_TRACK_GROUP_NAME );
  839. if ( pTrackGroup )
  840. {
  841. CDmeTrack *pTrack = pTrackGroup->FindTrack( VCD_GLOBAL_EVENTS_TRACK_GROUP_NAME );
  842. if ( pTrack )
  843. {
  844. // Now add global events
  845. int numEvents = pTrack->GetClipCount();
  846. for ( int event = 0; event < numEvents; ++event )
  847. {
  848. CDmeChannelsClip *pClip = CastElement< CDmeChannelsClip >( pTrack->GetClip( event ) );
  849. if ( !pClip )
  850. continue;
  851. bool success = ConvertDmxToEvent( scene, pTrackGroup, pTrack, pClip, true );
  852. if ( !success )
  853. {
  854. bret = false;
  855. Assert( 0 );
  856. break;
  857. }
  858. }
  859. }
  860. }
  861. int nNumTrackGroups = dmx->GetTrackGroupCount();
  862. for ( int i = 0; i < nNumTrackGroups; ++i )
  863. {
  864. CDmeTrackGroup *pTrackGroup = dmx->GetTrackGroup( i );
  865. if ( !pTrackGroup->GetValue< bool >( "isActor" ) )
  866. continue;
  867. // Walk the track groups
  868. int nNumTracks = pTrackGroup->GetTrackCount();
  869. for ( int j = 0 ; j < nNumTracks; ++j )
  870. {
  871. CDmeTrack *pTrack = pTrackGroup->GetTrack( j );
  872. EnsureActorAndChannelForTrack( scene, pTrackGroup, pTrack );
  873. int numEvents = pTrack->GetClipCount();
  874. for ( int clip = 0; clip < numEvents; ++clip )
  875. {
  876. CDmeChannelsClip *pClip = CastElement< CDmeChannelsClip >( pTrack->GetClip( clip ) );
  877. if ( !pClip )
  878. continue;
  879. bool success = ConvertDmxToEvent( scene, pTrackGroup, pTrack, pClip, false );
  880. if ( !success )
  881. {
  882. bret = false;
  883. Assert( 0 );
  884. break;
  885. }
  886. }
  887. }
  888. }
  889. scene->SetMapname( dmx->GetValueString( "associated_bsp" ) );
  890. scene->SetSceneFPS( dmx->GetValue< float >( "fps" ) );
  891. scene->SetUsingFrameSnap( dmx->GetValue< bool >( "snap" ) );
  892. return bret;
  893. }