void C_SceneEntity::PostDataUpdate( DataUpdateType_t updateType ) { BaseClass::PostDataUpdate( updateType ); char const *str = GetSceneFileName(); if ( updateType == DATA_UPDATE_CREATED ) { Assert( str && str[ 0 ] ); if ( str && str[ 0 ] ) { LoadSceneFromFile( str ); // Kill everything except flex events Assert( m_pScene ); if ( m_pScene ) { int types[ 2 ]; types[ 0 ] = CChoreoEvent::FLEXANIMATION; types[ 1 ] = CChoreoEvent::EXPRESSION; m_pScene->RemoveEventsExceptTypes( types, 2 ); } SetNextClientThink( CLIENT_THINK_ALWAYS ); } } // Playback state changed... if ( m_bWasPlaying != m_bIsPlayingBack ) { for(int i = 0; i < m_hActorList.Count() ; ++i ) { C_BaseFlex *actor = m_hActorList[ i ].Get(); if ( !actor ) continue; Assert( m_pScene ); if ( m_pScene ) { ClearSceneEvents( m_pScene, false ); if ( m_bIsPlayingBack ) { m_pScene->ResetSimulation(); actor->StartChoreoScene( m_pScene ); } else { m_pScene->ResetSimulation(); actor->RemoveChoreoScene( m_pScene ); } } } } }
//----------------------------------------------------------------------------- // Create binary compiled version of VCD. Stores to a dictionary for later // post processing //----------------------------------------------------------------------------- bool CreateTargetFile_VCD( const char *pSourceName, const char *pTargetName, bool bWriteToZip, bool bLittleEndian ) { CUtlBuffer sourceBuf; if ( !scriptlib->ReadFileToBuffer( pSourceName, sourceBuf ) ) { return false; } CRC32_t crcSource; CRC32_Init( &crcSource ); CRC32_ProcessBuffer( &crcSource, sourceBuf.Base(), sourceBuf.TellMaxPut() ); CRC32_Final( &crcSource ); ParseFromMemory( (char *)sourceBuf.Base(), sourceBuf.TellMaxPut() ); CChoreoScene *pChoreoScene = ChoreoLoadScene( pSourceName, NULL, &g_SceneTokenProcessor, Msg ); if ( !pChoreoScene ) { return false; } int iScene = g_SceneFiles.AddToTail(); g_SceneFiles[iScene].fileName.Set( pSourceName ); // Walk all events looking for SPEAK events CChoreoEvent *pEvent; for ( int i = 0; i < pChoreoScene->GetNumEvents(); ++i ) { pEvent = pChoreoScene->GetEvent( i ); FindSoundsInEvent( pEvent, g_SceneFiles[iScene].soundList ); } // calc duration g_SceneFiles[iScene].msecs = (unsigned int)( pChoreoScene->FindStopTime() * 1000.0f + 0.5f ); // compile to binary buffer g_SceneFiles[iScene].compiledBuffer.SetBigEndian( !bLittleEndian ); pChoreoScene->SaveToBinaryBuffer( g_SceneFiles[iScene].compiledBuffer, crcSource, &g_ChoreoStringPool ); unsigned int compressedSize; unsigned char *pCompressedBuffer = LZMA_Compress( (unsigned char *)g_SceneFiles[iScene].compiledBuffer.Base(), g_SceneFiles[iScene].compiledBuffer.TellMaxPut(), &compressedSize ); if ( pCompressedBuffer ) { // replace the compiled buffer with the compressed version g_SceneFiles[iScene].compiledBuffer.Purge(); g_SceneFiles[iScene].compiledBuffer.EnsureCapacity( compressedSize ); g_SceneFiles[iScene].compiledBuffer.Put( pCompressedBuffer, compressedSize ); free( pCompressedBuffer ); } delete pChoreoScene; return true; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_SceneEntity::DoThink( float frametime ) { if ( !m_pScene ) return; if ( !m_bIsPlayingBack ) { WipeQueuedEvents(); return; } CheckQueuedEvents(); if ( m_bPaused ) { return; } // Msg( "CL: %d, %f for %s\n", gpGlobals->tickcount, m_flCurrentTime, m_pScene->GetFilename() ); // Tell scene to go m_pScene->Think( m_flCurrentTime ); // Drive simulation time for scene m_flCurrentTime += gpGlobals->frametime; }
void CBaseEventPropertiesDialog::PopulateTagList( CEventParams *params ) { CChoreoScene *scene = params->m_pScene; if ( !scene ) return; HWND control = GetControl( IDC_TAGS ); if ( control ) { SendMessage( control, CB_RESETCONTENT, 0, 0 ); SendMessage( control, WM_SETTEXT , 0, (LPARAM)va( "\"%s\" \"%s\"", params->m_szTagName, params->m_szTagWav ) ); for ( int i = 0; i < scene->GetNumActors(); i++ ) { CChoreoActor *a = scene->GetActor( i ); if ( !a ) continue; for ( int j = 0; j < a->GetNumChannels(); j++ ) { CChoreoChannel *c = a->GetChannel( j ); if ( !c ) continue; for ( int k = 0 ; k < c->GetNumEvents(); k++ ) { CChoreoEvent *e = c->GetEvent( k ); if ( !e ) continue; if ( e->GetNumRelativeTags() <= 0 ) continue; // add each tag to combo box for ( int t = 0; t < e->GetNumRelativeTags(); t++ ) { CEventRelativeTag *tag = e->GetRelativeTag( t ); if ( !tag ) continue; SendMessage( control, CB_ADDSTRING, 0, (LPARAM)va( "\"%s\" \"%s\"", tag->GetName(), e->GetParameters() ) ); } } } } } }
CChoreoScene *C_SceneEntity::LoadScene( const char *filename ) { char loadfile[ 512 ]; Q_strncpy( loadfile, filename, sizeof( loadfile ) ); Q_SetExtension( loadfile, ".vcd", sizeof( loadfile ) ); Q_FixSlashes( loadfile ); char *pBuffer = NULL; size_t bufsize = scenefilecache->GetSceneBufferSize( loadfile ); if ( bufsize <= 0 ) return NULL; pBuffer = new char[ bufsize ]; if ( !scenefilecache->GetSceneData( filename, (byte *)pBuffer, bufsize ) ) { delete[] pBuffer; return NULL; } CChoreoScene *pScene; if ( IsBufferBinaryVCD( pBuffer, bufsize ) ) { pScene = new CChoreoScene( this ); CUtlBuffer buf( pBuffer, bufsize, CUtlBuffer::READ_ONLY ); if ( !pScene->RestoreFromBinaryBuffer( buf, loadfile, &g_ChoreoStringPool ) ) { Warning( "Unable to restore binary scene '%s'\n", loadfile ); delete pScene; pScene = NULL; } else { pScene->SetPrintFunc( Scene_Printf ); pScene->SetEventCallbackInterface( this ); } } else { g_TokenProcessor.SetBuffer( pBuffer ); pScene = ChoreoLoadScene( loadfile, this, &g_TokenProcessor, Scene_Printf ); } delete[] pBuffer; return pScene; }
//----------------------------------------------------------------------------- // Purpose: // Input : *actor - // *parameters - //----------------------------------------------------------------------------- void CBaseFlex::AddFlexSequence( CExpressionInfo *info ) { if ( !info ) return; CChoreoEvent *event = info->m_pEvent; if ( !event ) return; CChoreoScene *scene = info->m_pScene; if ( !scene ) return; if (info->m_iLayer >= 0) { SetLayerWeight( info->m_iLayer, event->GetIntensity( scene->GetTime() ) ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_SceneEntity::UnloadScene( void ) { WipeQueuedEvents(); if ( m_pScene ) { ClearSceneEvents( m_pScene, false ); for ( int i = 0 ; i < m_pScene->GetNumActors(); i++ ) { C_BaseFlex *pTestActor = FindNamedActor( m_pScene->GetActor( i ) ); if ( !pTestActor ) continue; pTestActor->RemoveChoreoScene( m_pScene ); } } delete m_pScene; m_pScene = NULL; }
void C_SceneEntity::ClearSceneEvents( CChoreoScene *scene, bool canceled ) { if ( !m_pScene ) return; Scene_Printf( "%s : %8.2f: clearing events\n", GetSceneFileName(), m_flCurrentTime ); int i; for ( i = 0 ; i < m_pScene->GetNumActors(); i++ ) { C_BaseFlex *pActor = FindNamedActor( m_pScene->GetActor( i ) ); if ( !pActor ) continue; // Clear any existing expressions pActor->ClearSceneEvents( scene, canceled ); } WipeQueuedEvents(); }
C_BaseFlex *C_SceneEntity::FindNamedActor( CChoreoActor *pChoreoActor ) { if ( !m_pScene ) return NULL; int idx = m_pScene->FindActorIndex( pChoreoActor ); if ( idx < 0 || idx >= m_hActorList.Count() ) return NULL; return m_hActorList[ idx ].Get(); }
//----------------------------------------------------------------------------- // Purpose: // Input : *actor - // *parameters - //----------------------------------------------------------------------------- void CBaseFlex::AddFlexGesture( CExpressionInfo *info ) { if ( !info ) return; CChoreoEvent *event = info->m_pEvent; if ( !event ) return; CChoreoScene *scene = info->m_pScene; if ( !scene ) return; if (info->m_iLayer >= 0) { // this happens after StudioFrameAdvance() float duration = event->GetDuration( ); float orig_duration = SequenceDuration( info->m_nSequence ); // when we come by again after StudioFrameAdvance() has moved forward 0.1 seconds, what frame should we be on? float flCycle = GetLayerCycle( info->m_iLayer ); float flNextCycle = event->GetShiftedTimeFromReferenceTime( (m_flAnimTime - info->m_flStartAnim + 0.1) / duration ); // FIXME: what time should this use? SetLayerWeight( info->m_iLayer, event->GetIntensity( scene->GetTime() ) ); float rate = (flNextCycle - flCycle) * orig_duration / 0.1; /* Msg( "%d : %.2f (%.2f) : %.3f %.3f : %.3f\n", info->m_iLayer, scene->GetTime(), (scene->GetTime() - event->GetStartTime()) / duration, flCycle, flNextCycle, rate ); */ SetLayerPlaybackRate( info->m_iLayer, rate ); } }
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 CSceneCache::Rebuild( char const *filename ) { msecs = 0; sounds.RemoveAll(); CChoreoScene *scene = BlockingLoadScene( filename ); if ( scene ) { // Walk all events looking for SPEAK events CChoreoEvent *event; int c = scene->GetNumEvents(); for ( int i = 0; i < c; ++i ) { event = scene->GetEvent( i ); PrecacheSceneEvent( event, sounds ); } // Update scene duration, too msecs = (int)( scene->FindStopTime() * 1000.0f + 0.5f ); delete scene; } }
void Init( void ) { if ( g_pChoreoView ) { CChoreoScene *scene = g_pChoreoView->GetScene(); if ( scene ) { char sz[ 256 ]; Q_snprintf( sz, sizeof( sz ), "%i fps", scene->GetSceneFPS() ); m_btnFPS->setLabel( sz ); Q_snprintf( sz, sizeof( sz ), "snap: %s", scene->IsUsingFrameSnap() ? "on" : "off" ); m_btnGridSnap->setLabel( sz ); m_btnFPS->setVisible( true ); m_btnGridSnap->setVisible( true ); return; } } m_btnFPS->setVisible( false ); m_btnGridSnap->setVisible( false ); }
virtual void ShowRightClickMenu( int mx, int my ) { mxPopupMenu *pop = new mxPopupMenu(); Assert( pop ); char const *current = ""; char const *filename = ""; int idx = getSelectedIndex(); if ( idx >= 0 ) { current = models->GetModelName( idx ); filename = models->GetModelFileName( idx ); } if ( models->Count() < MAX_FP_MODELS ) { pop->add( "Load Model...", IDC_MODELTAB_LOAD ); } if ( idx >= 0 ) { pop->add( va( "Close '%s'", current ), IDC_MODELTAB_CLOSE ); } if ( models->Count() > 0 ) { pop->add( "Close All", IDC_MODELTAB_CLOSEALL ); } if ( idx >= 0 ) { pop->addSeparator(); pop->add( va( "Center %s's face", current ), IDC_MODELTAB_CENTERONFACE ); CChoreoScene *scene = g_pChoreoView->GetScene(); if ( scene ) { // See if there is already an actor with this model associated int c = scene->GetNumActors(); bool hasassoc = false; for ( int i = 0; i < c; i++ ) { CChoreoActor *a = scene->GetActor( i ); Assert( a ); if ( stricmp( a->GetFacePoserModelName(), filename ) ) continue; hasassoc = true; break; } if ( hasassoc ) { pop->add( va( "Change associated actor for %s", current ), IDC_MODELTAB_ASSOCIATEACTOR ); } else { pop->add( va( "Associate actor to %s", current ), IDC_MODELTAB_ASSOCIATEACTOR ); } } pop->addSeparator(); bool visible = models->IsModelShownIn3DView( idx ); if ( visible ) { pop->add( va( "Remove %s from 3D View", current ), IDC_MODELTAB_TOGGLE3DVIEW ); } else { pop->add( va( "Show %s in 3D View", current ), IDC_MODELTAB_TOGGLE3DVIEW ); } } if ( models->Count() > 0 ) { pop->addSeparator(); pop->add( "Show All", IDC_MODELTAB_SHOWALL ); pop->add( "Hide All", IDC_MODELTAB_HIDEALL ); } // Convert click position POINT pt; pt.x = mx; pt.y = my; // Convert coordinate space pop->popup( this, pt.x, pt.y ); }
//----------------------------------------------------------------------------- // Purpose: // Input : *event - //----------------------------------------------------------------------------- void CBaseFlex::AddFlexAnimation( CExpressionInfo *info ) { if ( !info ) return; CChoreoEvent *event = info->m_pEvent; if ( !event ) return; CChoreoScene *scene = info->m_pScene; if ( !scene ) return; if ( !event->GetTrackLookupSet() ) { // Create lookup data for ( int i = 0; i < event->GetNumFlexAnimationTracks(); i++ ) { CFlexAnimationTrack *track = event->GetFlexAnimationTrack( i ); if ( !track ) continue; if ( track->IsComboType() ) { char name[ 512 ]; Q_strncpy( name, "right_" ,sizeof(name)); strcat( name, track->GetFlexControllerName() ); track->SetFlexControllerIndex( 0, FindFlexController( name ), 0 ); Q_strncpy( name, "left_" ,sizeof(name)); strcat( name, track->GetFlexControllerName() ); track->SetFlexControllerIndex( 0, FindFlexController( name ), 1 ); } else { track->SetFlexControllerIndex( 0, FindFlexController( (char *)track->GetFlexControllerName() ) ); } } event->SetTrackLookupSet( true ); } float scenetime = scene->GetTime(); float weight = event->GetIntensity( scenetime ); // Compute intensity for each track in animation and apply // Iterate animation tracks for ( int i = 0; i < event->GetNumFlexAnimationTracks(); i++ ) { CFlexAnimationTrack *track = event->GetFlexAnimationTrack( i ); if ( !track ) continue; // Disabled if ( !track->IsTrackActive() ) continue; // Map track flex controller to global name if ( track->IsComboType() ) { for ( int side = 0; side < 2; side++ ) { int controller = track->GetFlexControllerIndex( side ); // Get spline intensity for controller float flIntensity = track->GetIntensity( scenetime, side ); if ( controller >= 0 ) { float orig = GetFlexWeight( controller ); SetFlexWeight( controller, orig * (1 - weight) + flIntensity * weight ); } } } else { int controller = track->GetFlexControllerIndex( 0 ); // Get spline intensity for controller float flIntensity = track->GetIntensity( scenetime, 0 ); if ( controller >= 0 ) { float orig = GetFlexWeight( controller ); SetFlexWeight( controller, orig * (1 - weight) + flIntensity * weight ); } } } info->m_bStarted = true; }
virtual int handleEvent( mxEvent *event ) { int iret = 0; switch ( event->event ) { default: break; case mxEvent::Action: { iret = 1; switch ( event->action ) { default: iret = 0; break; case IDC_MODELTAB_SHOWALL: case IDC_MODELTAB_HIDEALL: { bool show = ( event->action == IDC_MODELTAB_SHOWALL ) ? true : false; int c = models->Count(); for ( int i = 0; i < c ; i++ ) { models->ShowModelIn3DView( i, show ); } } break; case IDC_MODELTAB_LOAD: { const char *ptr = mxGetOpenFileName( this, FacePoser_MakeWindowsSlashes( va( "%s/models/", GetGameDirectory() ) ), "*.mdl" ); if (ptr) { g_MDLViewer->LoadModelFile( ptr ); } } break; case IDC_MODELTAB_CLOSE: { int idx = getSelectedIndex(); if ( idx >= 0 ) { models->FreeModel( idx ); } } break; case IDC_MODELTAB_CLOSEALL: { models->CloseAllModels(); } break; case IDC_MODELTAB_CENTERONFACE: { g_pControlPanel->CenterOnFace(); } break; case IDC_MODELTAB_TOGGLE3DVIEW: { int idx = getSelectedIndex(); if ( idx >= 0 ) { bool visible = models->IsModelShownIn3DView( idx ); models->ShowModelIn3DView( idx, !visible ); } } break; case IDC_MODELTAB_ASSOCIATEACTOR: { int idx = getSelectedIndex(); if ( idx >= 0 ) { char const *modelname = models->GetModelFileName( idx ); CChoreoScene *scene = g_pChoreoView->GetScene(); if ( scene ) { CChoiceParams params; strcpy( params.m_szDialogTitle, "Associate Actor" ); params.m_bPositionDialog = false; params.m_nLeft = 0; params.m_nTop = 0; strcpy( params.m_szPrompt, "Choose actor:" ); params.m_Choices.RemoveAll(); params.m_nSelected = -1; int oldsel = -1; int c = scene->GetNumActors(); ChoiceText text; for ( int i = 0; i < c; i++ ) { CChoreoActor *a = scene->GetActor( i ); Assert( a ); strcpy( text.choice, a->GetName() ); if ( !stricmp( a->GetFacePoserModelName(), modelname ) ) { params.m_nSelected = i; oldsel = -1; } params.m_Choices.AddToTail( text ); } if ( ChoiceProperties( ¶ms ) && params.m_nSelected != oldsel ) { // Chose something new... CChoreoActor *a = scene->GetActor( params.m_nSelected ); g_pChoreoView->AssociateModelToActor( a, idx ); } } } } } } break; } if ( iret ) return iret; return BaseClass::handleEvent( event ); }
//----------------------------------------------------------------------------- // 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; } }
virtual int handleEvent( mxEvent *event ) { int iret = 0; switch ( event->event ) { default: break; case mxEvent::Size: { int leftedge = w2() * 0.45f; m_btnFPS->setBounds( 0, 0, leftedge, h2() ); m_btnGridSnap->setBounds( leftedge, 0, w2() - leftedge, h2() ); iret = 1; } break; case mxEvent::Action: { iret = 1; switch ( event->action ) { default: iret = 0; break; case IDC_GRIDSETTINGS_FPS: { if ( g_pChoreoView ) { CChoreoScene *scene = g_pChoreoView->GetScene(); if ( scene ) { int currentFPS = scene->GetSceneFPS(); CInputParams params; memset( ¶ms, 0, sizeof( params ) ); strcpy( params.m_szDialogTitle, "Change FPS" ); Q_snprintf( params.m_szInputText, sizeof( params.m_szInputText ), "%i", currentFPS ); strcpy( params.m_szPrompt, "Current FPS:" ); if ( InputProperties( ¶ms ) ) { int newFPS = atoi( params.m_szInputText ); if ( ( newFPS > 0 ) && ( newFPS != currentFPS ) ) { g_pChoreoView->SetDirty( true ); g_pChoreoView->PushUndo( "Change Scene FPS" ); scene->SetSceneFPS( newFPS ); g_pChoreoView->PushRedo( "Change Scene FPS" ); Init(); Con_Printf( "FPS changed to %i\n", newFPS ); } } } } } break; case IDC_GRIDSETTINGS_SNAP: { if ( g_pChoreoView ) { CChoreoScene *scene = g_pChoreoView->GetScene(); if ( scene ) { g_pChoreoView->SetDirty( true ); g_pChoreoView->PushUndo( "Change Snap Frame" ); scene->SetUsingFrameSnap( !scene->IsUsingFrameSnap() ); g_pChoreoView->PushRedo( "Change Snap Frame" ); Init(); Con_Printf( "Time frame snapping: %s\n", scene->IsUsingFrameSnap() ? "on" : "off" ); } } } break; } } } return iret; }
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; }