bool CChoreoChannel::GetSortedCombinedEventList( char const *cctoken, CUtlRBTree< CChoreoEvent * >& events ) { events.RemoveAll(); int i; // Sort items int c = GetNumEvents(); for ( i = 0; i < c; i++ ) { CChoreoEvent *e = GetEvent( i ); Assert( e ); if ( e->GetType() != CChoreoEvent::SPEAK ) continue; if ( e->GetCloseCaptionType() == CChoreoEvent::CC_DISABLED ) continue; // A master with no slaves is not a combined event if ( e->GetCloseCaptionType() == CChoreoEvent::CC_MASTER && e->GetNumSlaves() == 0 ) continue; char const *token = e->GetCloseCaptionToken(); if ( Q_stricmp( token, cctoken ) ) continue; events.Insert( e ); } return ( events.Count() > 0 ) ? true : false; }
bool GetFirstSoundInScene( const char *pSceneFilename, char *pSoundName, int soundNameLen ) { CChoreoScene *pScene = HammerLoadScene( pSceneFilename ); if ( !pScene ) return false; for ( int i = 0; i < pScene->GetNumEvents(); i++ ) { CChoreoEvent *e = pScene->GetEvent( i ); if ( !e || e->GetType() != CChoreoEvent::SPEAK ) continue; const char *pParameters = e->GetParameters(); V_strncpy( pSoundName, pParameters, soundNameLen ); delete pScene; return true; } delete pScene; return false; }
void CVCDFile::LoadSoundsFromScene( CChoreoScene *scene ) { if ( !scene ) return; CChoreoEvent *e; int c = scene->GetNumEvents(); for ( int i = 0; i < c; i++ ) { e = scene->GetEvent( i ); if ( !e ) continue; if ( e->GetType() != CChoreoEvent::SPEAK ) continue; CSoundEntry *se = new CSoundEntry( this, e->GetParameters() ); m_Sounds.AddToTail( se ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_SceneEntity::PrefetchAnimBlocks( CChoreoScene *pScene ) { if (!CommandLine()->FindParm("-hushasserts")) { Assert( pScene && m_bMultiplayer ); } if ( !pScene || !m_bMultiplayer ) return; // Build a fast lookup, too CUtlMap<CChoreoActor*,CBaseFlex*> actorMap( 0, 0, DefLessFunc( CChoreoActor* ) ); int nSpew = 0; int nResident = 0; int nChecked = 0; // Iterate events and precache necessary resources for ( int i = 0; i < pScene->GetNumEvents(); i++ ) { CChoreoEvent *pEvent = pScene->GetEvent( i ); if ( !pEvent ) continue; // load any necessary data switch ( pEvent->GetType() ) { default: break; case CChoreoEvent::SEQUENCE: case CChoreoEvent::GESTURE: { CChoreoActor *pActor = pEvent->GetActor(); if ( pActor ) { CBaseFlex *pFlex = NULL; int idx = actorMap.Find( pActor ); if ( idx == actorMap.InvalidIndex() ) { pFlex = FindNamedActor( pActor ); idx = actorMap.Insert( pActor, pFlex ); } else { pFlex = actorMap[ idx ]; } if ( pFlex ) { int iSequence = pFlex->LookupSequence( pEvent->GetParameters() ); if ( iSequence >= 0 ) { CStudioHdr *pStudioHdr = pFlex->GetModelPtr(); if ( pStudioHdr ) { // Now look up the animblock mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( iSequence ); for ( int i = 0 ; i < seqdesc.groupsize[ 0 ] ; ++i ) { for ( int j = 0; j < seqdesc.groupsize[ 1 ]; ++j ) { int iAnimation = seqdesc.anim( i, j ); int iBaseAnimation = pStudioHdr->iRelativeAnim( iSequence, iAnimation ); mstudioanimdesc_t &animdesc = pStudioHdr->pAnimdesc( iBaseAnimation ); ++nChecked; if ( nSpew != 0 ) { Msg( "%s checking block %d\n", pStudioHdr->pszName(), animdesc.animblock ); } // Async load the animation int iFrame = 0; const mstudioanim_t *panim = animdesc.pAnim( &iFrame ); if ( panim ) { ++nResident; if ( nSpew > 1 ) { Msg( "%s:%s[%i:%i] was resident\n", pStudioHdr->pszName(), animdesc.pszName(), i, j ); } } else { if ( nSpew != 0 ) { Msg( "%s:%s[%i:%i] async load\n", pStudioHdr->pszName(), animdesc.pszName(), i, j ); } } } } } } } } break; } } } if ( !nSpew || nChecked <= 0 ) return; Msg( "%d of %d animations resident\n", nResident, nChecked ); }
//----------------------------------------------------------------------------- // Redraw to screen //----------------------------------------------------------------------------- void CChoreoGlobalEventWidget::redraw( CChoreoWidgetDrawHelper& drawHelper ) { if ( !getVisible() ) return; CChoreoEvent *event = GetEvent(); if ( !event ) return; RECT rcTab; rcTab = getBounds(); bool isLoop = false; COLORREF pointColor = COLOR_CHOREO_SEGMENTDIVIDER; COLORREF clr = COLOR_CHOREO_SEGMENTDIVIDER_BG; switch ( event->GetType() ) { default: break; case CChoreoEvent::LOOP: { clr = COLOR_CHOREO_LOOPPOINT_BG; pointColor = COLOR_CHOREO_LOOPPOINT; isLoop = true; } break; case CChoreoEvent::STOPPOINT: { clr = COLOR_CHOREO_STOPPOINT_BG; pointColor = COLOR_CHOREO_STOPPOINT; } break; } if ( IsSelected() ) { InflateRect( &rcTab, 2, 2 ); drawHelper.DrawTriangleMarker( rcTab, pointColor ); InflateRect( &rcTab, -2, -2 ); drawHelper.DrawTriangleMarker( rcTab, RGB( 240, 240, 220 ) ); } else { drawHelper.DrawTriangleMarker( rcTab, pointColor ); } RECT rcClient; drawHelper.GetClientRect( rcClient ); RECT rcLine = rcTab; rcLine.top = rcTab.bottom + 2; rcLine.bottom = rcClient.bottom; rcLine.left = ( rcLine.left + rcLine.right ) / 2; rcLine.right = rcLine.left; if ( IsSelected() ) { drawHelper.DrawColoredLine( clr, PS_DOT, 2, rcLine.left, rcLine.top, rcLine.right, rcLine.bottom ); } else { drawHelper.DrawColoredLine( clr, PS_DOT, 1, rcLine.left, rcLine.top, rcLine.right, rcLine.bottom ); } if ( event->GetType() == CChoreoEvent::STOPPOINT ) { OffsetRect( &rcTab, -4, 15 ); mxbitmapdata_t *image = CChoreoEventWidget::GetImage( event->GetType() ); if ( image ) { drawHelper.OffsetSubRect( rcTab ); DrawBitmapToDC( drawHelper.GrabDC(), rcTab.left, rcTab.top, 16, 16, *image ); } } if ( !isLoop ) return; COLORREF labelText = COLOR_INFO_TEXT; DrawLabel( drawHelper, labelText, rcLine.left, rcLine.top + 2, false ); // Figure out loop spot float looptime = (float)atof( event->GetParameters() ); // Find pixel for that bool clipped = false; int x = m_pView->GetPixelForTimeValue( looptime, &clipped ); if ( clipped ) return; rcLine.left = x; rcLine.right = x; clr = COLOR_CHOREO_LOOPPOINT_START_BG; drawHelper.DrawColoredLine( clr, PS_SOLID, 1, rcLine.left, rcLine.top, rcLine.right, rcLine.top + 28); DrawLabel( drawHelper, labelText, rcLine.left, rcLine.top + 2, true ); }
//----------------------------------------------------------------------------- // Purpose: FIXME: This should either be embedded or we should draw the caption // here //----------------------------------------------------------------------------- void CChoreoEventWidget::redraw( CChoreoWidgetDrawHelper& drawHelper ) { if ( !getVisible() ) return; CChoreoEvent *event = GetEvent(); if ( !event ) return; int deflateborder = 1; int fontsize = 9; HDC dc = drawHelper.GrabDC(); RECT rcClient = getBounds(); RECT rcDC; drawHelper.GetClientRect( rcDC ); RECT dummy; if ( !IntersectRect( &dummy, &rcDC, &rcClient ) ) return; bool ramponly = m_pView->IsRampOnly(); if ( IsSelected() && !ramponly ) { InflateRect( &rcClient, 3, 1 ); //rcClient.bottom -= 1; rcClient.right += 1; RECT rcFrame = rcClient; RECT rcBorder = rcClient; rcFrame.bottom = rcFrame.top + 17; rcBorder.bottom = rcFrame.top + 17; COLORREF clrSelection = RGB( 0, 63, 63 ); COLORREF clrBorder = RGB( 100, 200, 255 ); HBRUSH brBorder = CreateSolidBrush( clrBorder ); HBRUSH brSelected = CreateHatchBrush( HS_FDIAGONAL, clrSelection ); for ( int i = 0; i < 2; i++ ) { FrameRect( dc, &rcFrame, brSelected ); InflateRect( &rcFrame, -1, -1 ); } FrameRect( dc, &rcBorder, brBorder ); FrameRect( dc, &rcFrame, brBorder ); DeleteObject( brSelected ); DeleteObject( brBorder ); rcClient.right -= 1; //rcClient.bottom += 1; InflateRect( &rcClient, -3, -1 ); } RECT rcEvent; rcEvent = rcClient; InflateRect( &rcEvent, 0, -deflateborder ); rcEvent.bottom = rcEvent.top + 10; if ( event->GetType() == CChoreoEvent::SPEAK && m_pWaveFile && !event->HasEndTime() ) { event->SetEndTime( event->GetStartTime() + m_pWaveFile->GetRunningLength() ); rcEvent.right = ( int )( m_pWaveFile->GetRunningLength() * m_pView->GetPixelsPerSecond() ); } if ( event->HasEndTime() ) { rcEvent.right = rcEvent.left + m_nDurationRightEdge; RECT rcEventLine = rcEvent; OffsetRect( &rcEventLine, 0, 1 ); if ( event->GetType() == CChoreoEvent::SPEAK ) { if ( m_pWaveFile ) { HBRUSH brEvent = CreateSolidBrush( COLOR_CHOREO_EVENT ); HBRUSH brBackground = CreateSolidBrush( COLOR_CHOREO_DARKBACKGROUND ); if ( !ramponly ) { FillRect( dc, &rcEventLine, brBackground ); } // Only draw wav form here if selected if ( IsSelected() ) { sound->RenderWavToDC( dc, rcEventLine, IsSelected() ? COLOR_CHOREO_EVENT_SELECTED : COLOR_CHOREO_EVENT, 0.0, m_pWaveFile->GetRunningLength(), m_pWaveFile ); } //FrameRect( dc, &rcEventLine, brEvent ); drawHelper.DrawColoredLine( COLOR_CHOREO_EVENT, PS_SOLID, 3, rcEventLine.left, rcEventLine.top, rcEventLine.left, rcEventLine.bottom ); drawHelper.DrawColoredLine( COLOR_CHOREO_EVENT, PS_SOLID, 3, rcEventLine.right, rcEventLine.top, rcEventLine.right, rcEventLine.bottom ); DeleteObject( brBackground ); DeleteObject( brEvent ); //rcEventLine.top -= 3; DrawRelativeTags( drawHelper, rcEventLine, m_pWaveFile->GetRunningLength(), event ); } } else { COLORREF clrEvent = IsSelected() ? COLOR_CHOREO_EVENT_SELECTED : COLOR_CHOREO_EVENT; if ( event->GetType() == CChoreoEvent::SUBSCENE ) { clrEvent = RGB( 200, 180, 200 ); } HBRUSH brEvent = CreateSolidBrush( clrEvent ); if ( !ramponly ) { FillRect( dc, &rcEventLine, brEvent ); } DeleteObject( brEvent ); if ( ramponly && IsSelected() ) { drawHelper.DrawOutlinedRect( RGB( 150, 180, 250 ), PS_SOLID, 1, rcEventLine ); } else { drawHelper.DrawColoredLine( RGB( 127, 127, 127 ), PS_SOLID, 1, rcEventLine.left, rcEventLine.bottom, rcEventLine.left, rcEventLine.top ); drawHelper.DrawColoredLine( RGB( 127, 127, 127 ), PS_SOLID, 1, rcEventLine.left, rcEventLine.top, rcEventLine.right, rcEventLine.top ); drawHelper.DrawColoredLine( RGB( 31, 31, 31 ), PS_SOLID, 1, rcEventLine.right, rcEventLine.top, rcEventLine.right, rcEventLine.bottom ); drawHelper.DrawColoredLine( RGB( 0, 0, 0 ), PS_SOLID, 1, rcEventLine.right, rcEventLine.bottom, rcEventLine.left, rcEventLine.bottom ); } g_pRampTool->DrawSamplesSimple( drawHelper, event, false, RGB( 63, 63, 63 ), rcEventLine ); DrawRelativeTags( drawHelper, rcEventLine, event->GetDuration(), event ); DrawAbsoluteTags( drawHelper, rcEventLine, event->GetDuration(), event ); } } else { RECT rcEventLine = rcEvent; OffsetRect( &rcEventLine, 0, 1 ); drawHelper.DrawColoredLine( COLOR_CHOREO_EVENT, PS_SOLID, 3, rcEventLine.left - 1, rcEventLine.top, rcEventLine.left - 1, rcEventLine.bottom ); } if ( event->IsUsingRelativeTag() ) { RECT rcTagName; rcTagName = rcClient; int length = drawHelper.CalcTextWidth( "Arial", 9, FW_NORMAL, event->GetRelativeTagName() ); rcTagName.right = rcTagName.left; rcTagName.left = rcTagName.right - length - 4; rcTagName.top += 3; rcTagName.bottom = rcTagName.top + 10; drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, RGB( 0, 100, 200 ), rcTagName, event->GetRelativeTagName() ); drawHelper.DrawFilledRect( RGB( 0, 100, 250 ), rcTagName.right-1, rcTagName.top-2, rcTagName.right+2, rcTagName.bottom + 2 ); } // Now draw the label RECT rcEventLabel; rcEventLabel = rcClient; InflateRect( &rcEventLabel, 0, -deflateborder ); rcEventLabel.top += 15; // rcEventLabel.bottom - 2 * ( fontsize + 2 ) - 1; rcEventLabel.bottom = rcEventLabel.top + fontsize + 2; rcEventLabel.left += 1; //rcEventLabel.left -= 8; int leftAdd = 16; if ( CChoreoEventWidget::GetImage( event->GetType() ) ) { mxbitmapdata_t *image = CChoreoEventWidget::GetImage( event->GetType() ); if ( image ) { DrawBitmapToDC( dc, rcEventLabel.left, rcEventLabel.top, leftAdd, leftAdd, *image ); } } if ( event->IsResumeCondition() ) { RECT rc = rcEventLabel; OffsetRect( &rc, leftAdd, 0 ); rc.right = rc.left + leftAdd; DrawBitmapToDC( dc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, *CChoreoEventWidget::GetPauseImage() ); } //rcEventLabel.left += 8; OffsetRect( &rcEventLabel, 18, 1 ); int len = drawHelper.CalcTextWidth( "Arial", fontsize, FW_NORMAL, event->GetName() ); rcEventLabel.right = rcEventLabel.left + len + 2; drawHelper.DrawColoredText( "Arial", fontsize, FW_NORMAL, RGB( 0, 0, 120 ), rcEventLabel, event->GetName() ); }
//----------------------------------------------------------------------------- // Purpose: // Input : drawHelper - // rcBounds - //----------------------------------------------------------------------------- void CChoreoEventWidget::redrawStatus( CChoreoWidgetDrawHelper& drawHelper, RECT& rcClient ) { if ( !getVisible() ) return; CChoreoEvent *event = GetEvent(); if ( !event ) return; int deflateborder = 1; int fontsize = 9; HDC dc = drawHelper.GrabDC(); // Now draw the label RECT rcEventLabel; rcEventLabel = rcClient; InflateRect( &rcEventLabel, 0, -deflateborder ); // rcEventLabel.top += 2; rcEventLabel.left += 2; //rcEventLabel.top = rcEventLabel.bottom - 2 * ( fontsize + 2 ) - 1; //rcEventLabel.bottom = rcEventLabel.top + fontsize + 2; int leftAdd = 16; if ( CChoreoEventWidget::GetImage( event->GetType() ) ) { mxbitmapdata_t *image = CChoreoEventWidget::GetImage( event->GetType() ); if ( image ) { RECT rcFixed = rcEventLabel; drawHelper.OffsetSubRect( rcFixed ); DrawBitmapToDC( dc, rcFixed.left, rcFixed.top, leftAdd, leftAdd, *image ); } } if ( event->IsResumeCondition() ) { RECT rc = rcEventLabel; OffsetRect( &rc, 16, 0 ); rc.right = rc.left + 16; RECT rcFixed = rc; drawHelper.OffsetSubRect( rcFixed ); DrawBitmapToDC( dc, rcFixed.left, rcFixed.top, rcFixed.right - rcFixed.left, rcFixed.bottom - rcFixed.top, *CChoreoEventWidget::GetPauseImage() ); } // Draw Type Name: //rcEventLabel.top -= 4; rcEventLabel.left = rcClient.left + 32; rcEventLabel.bottom = rcEventLabel.top + fontsize + 2; // OffsetRect( &rcEventLabel, 0, 2 ); int len = drawHelper.CalcTextWidth( "Arial", fontsize, FW_NORMAL, "%s event \"%s\"", event->NameForType( event->GetType() ), event->GetName() ); drawHelper.DrawColoredText( "Arial", fontsize, FW_NORMAL, COLOR_INFO_TEXT, rcEventLabel, "%s event \"%s\"", event->NameForType( event->GetType() ), event->GetName() ); OffsetRect( &rcEventLabel, 0, fontsize + 2 ); drawHelper.DrawColoredText( "Arial", fontsize, FW_NORMAL, COLOR_INFO_TEXT, rcEventLabel, "parameters \"%s\"", GetLabelText() ); }
void ProcessVCD( CUtlDict< VCDList, int >& database, CUtlSymbol& vcdname ) { // vprint( 0, "Processing '%s'\n", g_Analysis.symbols.String( vcdname ) ); // Load the .vcd char fullname[ 512 ]; Q_snprintf( fullname, sizeof( fullname ), "%s", g_Analysis.symbols.String( vcdname ) ); LoadScriptFile( fullname ); CChoreoScene *scene = ChoreoLoadScene( fullname, NULL, &g_TokenProcessor, Con_Printf ); if ( scene ) { bool first = true; // Now iterate the events looking for speak events int c = scene->GetNumEvents(); for ( int i = 0; i < c; i++ ) { CChoreoEvent *e = scene->GetEvent( i ); if ( e->GetType() == CChoreoEvent::MOVETO ) { SpewMoveto( first, fullname, e ); first = false; } if ( e->GetType() != CChoreoEvent::SPEAK ) continue; // Look up sound in sound emitter system char const *wavename = soundemitter->GetWavFileForSound( e->GetParameters(), NULL ); if ( !wavename || !wavename[ 0 ] ) { continue; } char fullwavename[ 512 ]; Q_snprintf( fullwavename, sizeof( fullwavename ), "%ssound\\%s", gamedir, wavename ); Q_FixSlashes( fullwavename ); // Now add to proper slot VCDList *entry = NULL; // Add vcd to database int slot = database.Find( fullwavename ); if ( slot == database.InvalidIndex() ) { VCDList nullEntry; slot = database.Insert( fullwavename, nullEntry ); } entry = &database[ slot ]; if ( entry->vcds.Find( vcdname ) == entry->vcds.InvalidIndex() ) { entry->vcds.AddToTail( vcdname ); } } if ( vcdonly ) { CheckForOverlappingFlexTracks( scene ); } } delete scene; }
void CheckForOverlappingFlexTracks( CChoreoScene *scene ) { for ( int a = 0; a < scene->GetNumActors(); ++a ) { CChoreoActor *actor = scene->GetActor( a ); CUtlRBTree< CChoreoEvent * > actorFlexEvents( 0, 0, ChoreEventStartTimeLessFunc ); for ( int c = 0; c < actor->GetNumChannels(); ++c ) { CChoreoChannel *channel = actor->GetChannel( c ); for ( int e = 0 ; e < channel->GetNumEvents(); ++e ) { CChoreoEvent *event = channel->GetEvent( e ); if ( event->GetType() != CChoreoEvent::FLEXANIMATION ) continue; actorFlexEvents.Insert( event ); } } CUtlVector< CUtlLinkedList< CChoreoEvent*, int > > rows; bool done = false; int i; // Now check for overlaps for ( i = actorFlexEvents.FirstInorder(); i != actorFlexEvents.InvalidIndex() && !done; i = actorFlexEvents.NextInorder( i ) ) { CChoreoEvent *e = actorFlexEvents[ i ]; if ( !rows.Count() ) { rows.AddToTail(); CUtlLinkedList< CChoreoEvent*, int >& list = rows[ 0 ]; list.AddToHead( e ); continue; } // Does it come totally after what's in rows[0]? int rowCount = rows.Count(); bool addrow = true; for ( int j = 0; j < rowCount; j++ ) { CUtlLinkedList< CChoreoEvent*, int >& list = rows[ j ]; char offender[ 256 ]; if ( !EventCollidesWithRows( list, e, offender, sizeof( offender ) ) ) { // Update row event list list.AddToHead( e ); addrow = false; break; } else { Msg( "[%s] has overlapping events for actor [%s] [%s] [flex: %s]\n", scene->GetFilename(), actor->GetName(), e->GetName(), offender ); done = true; } } if ( addrow ) { // Add a new row int idx = rows.AddToTail(); CUtlLinkedList< CChoreoEvent *, int >& list = rows[ idx ]; list.AddToHead( e ); } } // Assert( rows.Count() <= 1 ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBaseFlex::AddSceneExpressions( void ) { // Iterate expressions and look for active slots for ( int i = 0; i < m_Expressions.Count(); i++ ) { CExpressionInfo *info = &m_Expressions[ i ]; Assert( info ); // FIXME: Need a safe handle to m_pEvent in case of memory deletion? CChoreoEvent *event = info->m_pEvent; Assert( event ); CChoreoScene *scene = info->m_pScene; Assert( scene ); switch ( event->GetType() ) { case CChoreoEvent::FLEXANIMATION: { if ( event->HasEndTime() ) { AddFlexAnimation( info ); } } break; case CChoreoEvent::EXPRESSION: { // Expressions have to have an end time!!! if ( event->HasEndTime() ) { // Look up the actual strings const char *scenefile = event->GetParameters(); const char *name = event->GetParameters2(); // Have to find both strings if ( scenefile && name ) { // Find the scene file flexsettinghdr_t *pExpHdr = ( flexsettinghdr_t * )FindSceneFile( scenefile ); if ( pExpHdr ) { flexsettinghdr_t *pOverrideHdr = NULL; // Find overrides, if any exist studiohdr_t *hdr = GetModelPtr(); if ( hdr && scene_allowoverrides.GetBool() ) { char overridefile[ 512 ]; char shortname[ 128 ]; char modelname[ 128 ]; //Q_strncpy( modelname, modelinfo->GetModelName( model ) ,sizeof(modelname)); Q_strncpy( modelname, hdr->name ,sizeof(modelname)); // Fix up the name Extract_FileBase( modelname, shortname ); Q_snprintf( overridefile,sizeof(overridefile), "%s/%s", shortname, scenefile ); pOverrideHdr = ( flexsettinghdr_t * )FindSceneFile( overridefile ); } float scenetime = scene->GetTime(); float scale = event->GetIntensity( scenetime ); // Add the named expression AddExpression( name, scale, pExpHdr, pOverrideHdr, !info->m_bStarted ); } } } } break; case CChoreoEvent::SEQUENCE: { AddFlexSequence( info ); } break; case CChoreoEvent::GESTURE: { AddFlexGesture( info ); } break; default: break; } /* float scenetime = scene->GetTime(); float scale = event->GetIntensity( scenetime ); Msg( "%s %f : ", event->GetName(), scale ); // Add the named expression AddExpression( name, scale, pExpHdr, pOverrideHdr, !info->m_bStarted ); */ info->m_bStarted = true; } }
// Compute master/slave, count, endtime info for close captioning data //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CChoreoChannel::ReconcileCloseCaption() { // Create a dictionary based on the combined token name CUtlDict< EventGroup, int > validSpeakEventsGroupedByName; int i; // Sort items int c = GetNumEvents(); for ( i = 0; i < c; i++ ) { CChoreoEvent *e = GetEvent( i ); Assert( e ); if ( e->GetType() != CChoreoEvent::SPEAK ) continue; CChoreoEvent::CLOSECAPTION type; type = e->GetCloseCaptionType(); if ( type == CChoreoEvent::CC_DISABLED ) { e->SetUsingCombinedFile( false ); e->SetRequiredCombinedChecksum( 0 ); e->SetNumSlaves( 0 ); e->SetLastSlaveEndTime( 0.0f ); continue; } char const *name = e->GetCloseCaptionToken(); if ( !name || !name[0] ) { // Fixup invalid slave tag if ( type == CChoreoEvent::CC_SLAVE ) { e->SetCloseCaptionType( CChoreoEvent::CC_MASTER ); e->SetUsingCombinedFile( false ); e->SetRequiredCombinedChecksum( 0 ); e->SetNumSlaves( 0 ); e->SetLastSlaveEndTime( 0.0f ); } continue; } int idx = validSpeakEventsGroupedByName.Find( name ); if ( idx == validSpeakEventsGroupedByName.InvalidIndex() ) { EventGroup eg; eg.timeSortedEvents.Insert( e ); validSpeakEventsGroupedByName.Insert( name, eg ); } else { EventGroup & eg = validSpeakEventsGroupedByName[ idx ]; eg.timeSortedEvents.Insert( e ); } } c = validSpeakEventsGroupedByName.Count(); // Now walk list of events by group if ( !c ) { return; } for ( i = 0; i < c; ++i ) { EventGroup & eg = validSpeakEventsGroupedByName[ i ]; int sortedEventInGroup = eg.timeSortedEvents.Count(); // If there's only one, just mark it valid if ( sortedEventInGroup <= 1 ) { CChoreoEvent *e = eg.timeSortedEvents[ 0 ]; Assert( e ); // Make sure it's the master e->SetCloseCaptionType( CChoreoEvent::CC_MASTER ); // Since it's by itself, can't be using "combined" file e->SetUsingCombinedFile( false ); e->SetRequiredCombinedChecksum( 0 ); e->SetNumSlaves( 0 ); e->SetLastSlaveEndTime( 0.0f ); continue; } // Okay, read them back in of start time int j = eg.timeSortedEvents.FirstInorder(); CChoreoEvent *master = NULL; while ( j != eg.timeSortedEvents.InvalidIndex() ) { CChoreoEvent *e = eg.timeSortedEvents[ j ]; if ( !master ) { master = e; e->SetCloseCaptionType( CChoreoEvent::CC_MASTER ); //e->SetUsingCombinedFile( true ); e->SetRequiredCombinedChecksum( 0 ); e->SetNumSlaves( sortedEventInGroup - 1 ); e->SetLastSlaveEndTime( e->GetEndTime() ); } else { // Keep bumping out the end time master->SetLastSlaveEndTime( e->GetEndTime() ); e->SetCloseCaptionType( CChoreoEvent::CC_SLAVE ); e->SetUsingCombinedFile( master->IsUsingCombinedFile() ); e->SetRequiredCombinedChecksum( 0 ); e->SetLastSlaveEndTime( 0.0f ); } j = eg.timeSortedEvents.NextInorder( j ); } } }
void CChoreoChannel::ReconcileGestureTimes() { // Sort gesture events within channel by starting time CUtlRBTree< CChoreoEvent * > sortedGestures( 0, 0, ChoreEventStartTimeLessFunc ); int i; // Sort items int c = GetNumEvents(); for ( i = 0; i < c; i++ ) { CChoreoEvent *e = GetEvent( i ); Assert( e ); if ( e->GetType() != CChoreoEvent::GESTURE ) continue; sortedGestures.Insert( e ); } // Now walk list of gestures if ( !sortedGestures.Count() ) return; CChoreoEvent *previous = NULL; for ( i = sortedGestures.FirstInorder(); i != sortedGestures.InvalidIndex(); i = sortedGestures.NextInorder( i ) ) { CChoreoEvent *event = sortedGestures[ i ]; if ( !previous ) { // event->SetStartTime( 0.0f ); } else if ( previous->GetSyncToFollowingGesture() ) { // TODO: ask the sequence for what tags to match CEventAbsoluteTag *pEntryTag = event->FindEntryTag( CChoreoEvent::PLAYBACK ); CEventAbsoluteTag *pExitTag = previous->FindExitTag( CChoreoEvent::PLAYBACK ); if (pEntryTag && pExitTag) { float entryTime = pEntryTag->GetAbsoluteTime( ); // get current decay rate of previous gesture float duration = previous->GetDuration(); float decayTime = (1.0 - pExitTag->GetPercentage()) * duration; // adjust the previous gestures end time to current apex + existing decay rate previous->RescaleGestureTimes( previous->GetStartTime(), entryTime + decayTime, true ); previous->SetEndTime( entryTime + decayTime ); // set the previous gestures end tag to the current apex pExitTag->SetAbsoluteTime( entryTime ); event->PreventTagOverlap( ); previous->PreventTagOverlap( ); } // BUG: Tracker 3298: ywb 1/31/04 // I think this fixes the issue with abutting past NULL gestures on paste: // Here's the bug report: // ------------------------- // When copying and pasteing posture and gesture clips in face poser the beginings of the clips stretch // to the begining of the scene even if there is a null gesture in place at the begining. // ------------------------- /* else if ( pEntryTag && !Q_stricmp( previous->GetName(), "NULL" ) ) { // If the previous was a null event, then do a bit of fixup event->SetStartTime( previous->GetEndTime() ); event->PreventTagOverlap( ); } */ // The previous event decays from it's end dispaly end time to the current event's display start time // The next event starts just after the display end time of the previous event } previous = event; } if ( previous ) { CChoreoScene *scene = previous->GetScene(); if ( scene ) { // HACK: Could probably do better by allowing user to drag the blue "end time" bar //float finish = scene->FindStopTime(); //previous->RescaleGestureTimes( previous->GetStartTime(), finish ); //previous->SetEndTime( finish ); } } /* c = 0; for ( i = sortedGestures.FirstInorder(); i != sortedGestures.InvalidIndex(); i = sortedGestures.NextInorder( i ) ) { CChoreoEvent *event = sortedGestures[ i ]; Msg( "event %i start %f disp %f dispend %f end %f\n", c + 1, event->GetStartTime( CChoreoEvent::SIMULATION ), event->GetStartTime( CChoreoEvent::DISPLAY ), event->GetEndTime( CChoreoEvent::DISPLAY ), event->GetEndTime( CChoreoEvent::SIMULATION ) ); c++; } */ }