//////////////////////////////////////////////////////////////// // // CRenderWareSA::ModelInfoTXDLoadTextures // // Load textures from a TXD file // //////////////////////////////////////////////////////////////// bool CRenderWareSA::ModelInfoTXDLoadTextures ( SReplacementTextures* pReplacementTextures, const SString& strFilename, bool bFilteringEnabled ) { // Are we already loaded? if ( !pReplacementTextures->textures.empty () ) return false; if ( !g_pCore->GetNetwork ()->CheckFile ( "txd", strFilename ) ) return false; // Try to load it RwTexDictionary* pTxd = ReadTXD ( strFilename ); if ( pTxd ) { // Get the list of textures into our own list GetTxdTextures ( pReplacementTextures->textures, pTxd ); for ( uint i = 0 ; i < pReplacementTextures->textures.size () ; i++ ) { pReplacementTextures->textures[i]->txd = NULL; if ( bFilteringEnabled ) pReplacementTextures->textures[i]->flags = 0x1102; // Enable filtering (otherwise textures are pixely) } // Make the txd forget it has any textures and destroy it pTxd->textures.root.next = &pTxd->textures.root; pTxd->textures.root.prev = &pTxd->textures.root; RwTexDictionaryDestroy ( pTxd ); pTxd = NULL; // We succeeded if we got any textures return pReplacementTextures->textures.size () > 0; } return false; }
//////////////////////////////////////////////////////////////// // // CRenderWareSA::PulseWorldTextureWatch // // Process ms_txdStreamEventList // //////////////////////////////////////////////////////////////// void CRenderWareSA::PulseWorldTextureWatch ( void ) { FlushPendingAssociations (); // Go through ms_txdStreamEventList for ( std::vector < STxdStreamEvent >::const_iterator iter = ms_txdStreamEventList.begin () ; iter != ms_txdStreamEventList.end () ; ++iter ) { const STxdStreamEvent& action = *iter; if ( action.bAdded ) { // // New txd has been loaded // // Get list of texture names and data to add // Note: If txd has been unloaded since, textureList will be empty std::vector < RwTexture* > textureList; GetTxdTextures ( textureList, action.usTxdId ); for ( std::vector < RwTexture* > ::iterator iter = textureList.begin () ; iter != textureList.end () ; iter++ ) { RwTexture* texture = *iter; const char* szTextureName = texture->name; CD3DDUMMY* pD3DData = texture->raster ? (CD3DDUMMY*)texture->raster->renderResource : NULL; StreamingAddedTexture ( action.usTxdId, szTextureName, pD3DData ); } } else { // // Txd has been unloaded // StreamingRemovedTxd ( action.usTxdId ); } } ms_txdStreamEventList.clear (); }
//////////////////////////////////////////////////////////////// // // CRenderWareSA::GetModelTexturesInfo // // Find/create texture info for a modelid // //////////////////////////////////////////////////////////////// CModelTexturesInfo* CRenderWareSA::GetModelTexturesInfo ( ushort usModelId ) { if ( !pGame->GetModelInfo ( usModelId ) ) return NULL; ushort usTxdId = pGame->GetModelInfo ( usModelId )->GetTextureDictionaryID (); CModelTexturesInfo* pInfo = MapFind ( ms_ModelTexturesInfoMap, usTxdId ); if ( !pInfo ) { // Get txd RwTexDictionary* pTxd = CTxdStore_GetTxd ( usTxdId ); if ( !pTxd ) { pGame->GetModelInfo ( usModelId )->Request ( BLOCKING, "CRenderWareSA::GetModelTexturesInfo" ); CTxdStore_AddRef ( usTxdId ); ( (void (__cdecl *)(unsigned short))FUNC_RemoveModel )( usModelId ); pTxd = CTxdStore_GetTxd ( usTxdId ); } else { CTxdStore_AddRef ( usTxdId ); } if ( !pTxd ) return NULL; // Add new info MapSet ( ms_ModelTexturesInfoMap, usTxdId, CModelTexturesInfo () ); pInfo = MapFind ( ms_ModelTexturesInfoMap, usTxdId ); pInfo->usTxdId = usTxdId; pInfo->pTxd = pTxd; // Save original textures GetTxdTextures ( pInfo->originalTextures, pInfo->pTxd ); } return pInfo; }
//////////////////////////////////////////////////////////////// // // CRenderWareSA::ModelInfoTXDRemoveTextures // // Remove the textures from the txds that are using them. // //////////////////////////////////////////////////////////////// void CRenderWareSA::ModelInfoTXDRemoveTextures ( SReplacementTextures* pReplacementTextures ) { // For each using txd for ( uint i = 0 ; i < pReplacementTextures->perTxdList.size () ; i++ ) { SReplacementTextures::SPerTxd& perTxdInfo = pReplacementTextures->perTxdList[i]; // Get textures info ushort usTxdId = perTxdInfo.usTxdId; CModelTexturesInfo* pInfo = MapFind ( ms_ModelTexturesInfoMap, usTxdId ); // Validate dassert ( MapFind ( ms_ModelTexturesInfoMap, usTxdId ) ); dassert ( ListContains ( pInfo->usedByReplacements, pReplacementTextures ) ); // Remove replacement textures for ( uint i = 0 ; i < perTxdInfo.usingTextures.size () ; i++ ) { RwTexture* pOldTexture = perTxdInfo.usingTextures[i]; RwTexDictionaryRemoveTexture ( pInfo->pTxd, pOldTexture ); dassert ( !RwTexDictionaryContainsTexture ( pInfo->pTxd, pOldTexture ) ); if ( perTxdInfo.bTexturesAreCopies ) { // Destroy the copy (but not the raster as that was not copied) pOldTexture->raster = NULL; RwTextureDestroy ( pOldTexture ); } } // Ensure there are original named textures in the txd for ( uint i = 0 ; i < pInfo->originalTextures.size () ; i++ ) { RwTexture* pOriginalTexture = pInfo->originalTextures[i]; if ( !RwTexDictionaryFindNamedTexture ( pInfo->pTxd, pOriginalTexture->name ) ) RwTexDictionaryAddTexture ( pInfo->pTxd, pOriginalTexture ); } // Remove refs ListRemove ( pInfo->usedByReplacements, pReplacementTextures ); // If no refs left, check original state and then remove info if ( pInfo->usedByReplacements.empty () ) { // txd should now contain the same textures as 'originalTextures' #ifdef MTA_DEBUG std::vector < RwTexture* > currentTextures; GetTxdTextures ( currentTextures, pInfo->pTxd ); assert ( currentTextures.size () == pInfo->originalTextures.size () ); for ( uint i = 0 ; i < pInfo->originalTextures.size () ; i++ ) { RwTexture* pOriginalTexture = pInfo->originalTextures[i]; assert ( ListContains ( currentTextures, pOriginalTexture ) ); ListRemove ( currentTextures, pOriginalTexture ); } assert ( currentTextures.empty () ); #endif // Remove info CTxdStore_RemoveRef ( pInfo->usTxdId ); MapRemove ( ms_ModelTexturesInfoMap, usTxdId ); } } // Destroy replacement textures for ( uint i = 0 ; i < pReplacementTextures->textures.size () ; i++ ) { RwTexture* pOldTexture = pReplacementTextures->textures[i]; DestroyTexture ( pOldTexture ); } pReplacementTextures->textures.clear (); }