assetManager.cpp
Engine/source/assets/assetManager.cpp
Public Variables
Public Functions
Detailed Description
Public Variables
AssetManager AssetDatabase
Public Functions
descendingAssetDefinitionLoadCount(const void * a, const void * b)
IMPLEMENT_CONOBJECT(AssetManager )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2013 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "assetManager.h" 25 26#ifndef _ASSET_PTR_H_ 27#include "assetPtr.h" 28#endif 29 30#ifndef _REFERENCED_ASSETS_H_ 31#include "assets/referencedAssets.h" 32#endif 33 34#ifndef _DECLARED_ASSETS_H_ 35#include "assets/declaredAssets.h" 36#endif 37 38#ifndef _TAML_ASSET_REFERENCED_VISITOR_H_ 39#include "tamlAssetReferencedVisitor.h" 40#endif 41 42#ifndef _TAML_ASSET_DECLARED_VISITOR_H_ 43#include "tamlAssetDeclaredVisitor.h" 44#endif 45 46#ifndef _TAML_ASSET_DECLARED_UPDATE_VISITOR_H_ 47#include "tamlAssetDeclaredUpdateVisitor.h" 48#endif 49 50#ifndef _TAML_ASSET_REFERENCED_UPDATE_VISITOR_H_ 51#include "tamlAssetReferencedUpdateVisitor.h" 52#endif 53 54#ifndef _CONSOLETYPES_H_ 55#include "console/consoleTypes.h" 56#endif 57 58#ifndef _AUTOLOAD_ASSETS_H_ 59#include "assets/autoloadAssets.h" 60#endif 61 62#ifndef GUI_ASSET_H 63#include "T3D/assets/GUIAsset.h" 64#endif 65#ifndef SCRIPT_ASSET_H 66#include "T3D/assets/ScriptAsset.h" 67#endif 68#ifndef MATERIALASSET_H 69#include "T3D/assets/MaterialAsset.h" 70#endif 71#ifndef GAME_OBJECT_ASSET_H 72#include "T3D/assets/GameObjectAsset.h" 73#endif 74 75// Script bindings. 76#include "assetManager_ScriptBinding.h" 77 78//----------------------------------------------------------------------------- 79 80IMPLEMENT_CONOBJECT( AssetManager ); 81 82//----------------------------------------------------------------------------- 83 84AssetManager AssetDatabase; 85 86//----------------------------------------------------------------------------- 87 88AssetManager::AssetManager() : 89 mLoadedInternalAssetsCount( 0 ), 90 mLoadedExternalAssetsCount( 0 ), 91 mLoadedPrivateAssetsCount( 0 ), 92 mMaxLoadedInternalAssetsCount( 0 ), 93 mMaxLoadedExternalAssetsCount( 0 ), 94 mEchoInfo( false ), 95 mAcquiredReferenceCount( 0 ), 96 mMaxLoadedPrivateAssetsCount( 0 ), 97 mIgnoreAutoUnload( true ) 98{ 99} 100 101//----------------------------------------------------------------------------- 102 103bool AssetManager::onAdd() 104{ 105 // Call parent. 106 if ( !Parent::onAdd() ) 107 return false; 108 109 return true; 110} 111 112//----------------------------------------------------------------------------- 113 114void AssetManager::onRemove() 115{ 116 // Do we have an asset tags manifest? 117 if ( !mAssetTagsManifest.isNull() ) 118 { 119 // Yes, so remove it. 120 mAssetTagsManifest->deleteObject(); 121 } 122 123 // Call parent. 124 Parent::onRemove(); 125} 126 127//----------------------------------------------------------------------------- 128 129void AssetManager::initPersistFields() 130{ 131 // Call parent. 132 Parent::initPersistFields(); 133 134 addField( "EchoInfo", TypeBool, false, Offset(mEchoInfo, AssetManager), "Whether the asset manager echos extra information to the console or not." ); 135 addField( "IgnoreAutoUnload", TypeBool, true, Offset(mIgnoreAutoUnload, AssetManager), "Whether the asset manager should ignore unloading of auto-unload assets or not." ); 136} 137 138//----------------------------------------------------------------------------- 139 140bool AssetManager::compileReferencedAssets( ModuleDefinition* pModuleDefinition ) 141{ 142 // Debug Profiling. 143 PROFILE_SCOPE(AssetManager_CompileReferencedAsset); 144 145 // Sanity! 146 AssertFatal( pModuleDefinition != NULL, "Cannot add declared assets using a NULL module definition" ); 147 148 // Clear referenced assets. 149 mReferencedAssets.clear(); 150 151 // Iterate the module definition children. 152 for( SimSet::iterator itr = pModuleDefinition->begin(); itr != pModuleDefinition->end(); ++itr ) 153 { 154 // Fetch the referenced assets. 155 ReferencedAssets* pReferencedAssets = dynamic_cast<ReferencedAssets*>( *itr ); 156 157 // Skip if it's not a referenced assets location. 158 if ( pReferencedAssets == NULL ) 159 continue; 160 161 // Expand asset manifest location. 162 char filePathBuffer[1024]; 163 dSprintf( filePathBuffer, sizeof(filePathBuffer), "%s/%s", pModuleDefinition->getModulePath(), pReferencedAssets->getPath() ); 164 165 // Scan referenced assets at location. 166 if ( !scanReferencedAssets( filePathBuffer, pReferencedAssets->getExtension(), pReferencedAssets->getRecurse() ) ) 167 { 168 // Warn. 169 Con::warnf( "AssetManager::compileReferencedAssets() - Could not scan for referenced assets at location '%s' with extension '%s'.", filePathBuffer, pReferencedAssets->getExtension() ); 170 } 171 } 172 173 return true; 174} 175 176//----------------------------------------------------------------------------- 177 178bool AssetManager::addModuleDeclaredAssets( ModuleDefinition* pModuleDefinition ) 179{ 180 // Debug Profiling. 181 PROFILE_SCOPE(AssetManager_AddDeclaredAssets); 182 183 // Sanity! 184 AssertFatal( pModuleDefinition != NULL, "Cannot add declared assets using a NULL module definition" ); 185 186 // Does the module have any assets associated with it? 187 if ( pModuleDefinition->getModuleAssets().size() > 0 ) 188 { 189 // Yes, so warn. 190 Con::warnf( "Asset Manager: Cannot add declared assets to module '%s' as it already has existing assets.", pModuleDefinition->getSignature() ); 191 return false; 192 } 193 194 // Iterate the module definition children. 195 for( SimSet::iterator itr = pModuleDefinition->begin(); itr != pModuleDefinition->end(); ++itr ) 196 { 197 // Fetch the declared assets. 198 DeclaredAssets* pDeclaredAssets = dynamic_cast<DeclaredAssets*>( *itr ); 199 200 // Skip if it's not a declared assets location. 201 if ( pDeclaredAssets == NULL ) 202 continue; 203 204 // Expand asset manifest location. 205 char filePathBuffer[1024]; 206 String mdldfpth = pModuleDefinition->getModulePath(); 207 String astfpth = pDeclaredAssets->getPath(); 208 209 //dSprintf( filePathBuffer, sizeof(filePathBuffer), "%s/%s", pModuleDefinition->getModulePath(), pDeclaredAssets->getPath() ); 210 dSprintf(filePathBuffer, sizeof(filePathBuffer), "%s/%s", pModuleDefinition->getModulePath(), pDeclaredAssets->getPath()); 211 212 // Scan declared assets at location. 213 if ( !scanDeclaredAssets( filePathBuffer, pDeclaredAssets->getExtension(), pDeclaredAssets->getRecurse(), pModuleDefinition ) ) 214 { 215 // Warn. 216 Con::warnf( "AssetManager::addModuleDeclaredAssets() - Could not scan for declared assets at location '%s' with extension '%s'.", filePathBuffer, pDeclaredAssets->getExtension() ); 217 } 218 } 219 220 return true; 221} 222 223bool AssetManager::loadModuleAutoLoadAssets(ModuleDefinition* pModuleDefinition) 224{ 225 // Debug Profiling. 226 PROFILE_SCOPE(AssetManager_loadModuleAutoLoadAssets); 227 228 // Sanity! 229 AssertFatal(pModuleDefinition != NULL, "Cannot auto load assets using a NULL module definition"); 230 231 // Does the module have any assets associated with it? 232 if (pModuleDefinition->getModuleAssets().empty() && mEchoInfo) 233 { 234 // Yes, so warn. 235 Con::warnf("Asset Manager: Cannot auto load assets to module '%s' as it has no existing assets.", pModuleDefinition->getSignature()); 236 return false; 237 } 238 239 U32 assetCount = pModuleDefinition->getModuleAssets().size(); 240 241 // Iterate the module definition children. 242 for (SimSet::iterator itr = pModuleDefinition->begin(); itr != pModuleDefinition->end(); ++itr) 243 { 244 // Fetch the declared assets. 245 AutoloadAssets* pAutoloadAssets = dynamic_cast<AutoloadAssets*>(*itr); 246 247 // Skip if it's not a declared assets location. 248 if (pAutoloadAssets == NULL) 249 continue; 250 251 for (U32 i = 0; i < assetCount; ++i) 252 { 253 AssetDefinition* assetDef = pModuleDefinition->getModuleAssets()[i]; 254 255 if (assetDef->mAssetType == pAutoloadAssets->getAssetType()) 256 { 257 String assetPath = assetDef->mAssetBaseFilePath; 258 assetPath.replace("//", "/"); 259 260 String autoLoadPath = pModuleDefinition->getModulePath(); 261 autoLoadPath += "/"; 262 autoLoadPath += pAutoloadAssets->getPath(); 263 264 if (pAutoloadAssets->getPath() == StringTable->EmptyString() || assetPath.startsWith(autoLoadPath.c_str())) 265 { 266 AssetBase* assetBase = dynamic_cast<AssetBase*>(mTaml.read(assetDef->mAssetBaseFilePath)); 267 268 //load the asset now if valid 269 if (assetBase) 270 { 271 assetBase->setOwned(this, assetDef); 272 } 273 } 274 } 275 } 276 } 277 278 return true; 279} 280//----------------------------------------------------------------------------- 281 282bool AssetManager::addDeclaredAsset( ModuleDefinition* pModuleDefinition, const char* pAssetFilePath ) 283{ 284 // Debug Profiling. 285 PROFILE_SCOPE(AssetManager_AddSingleDeclaredAsset); 286 287 // Sanity! 288 AssertFatal( pModuleDefinition != NULL, "Cannot add single declared asset using a NULL module definition" ); 289 AssertFatal( pAssetFilePath != NULL, "Cannot add single declared asset using a NULL asset file-path." ); 290 291 // Expand asset file-path. 292 char assetFilePathBuffer[1024]; 293 Con::expandPath( assetFilePathBuffer, sizeof(assetFilePathBuffer), pAssetFilePath ); 294 295 // Find the final slash which should be just before the file. 296 char* pFileStart = dStrrchr( assetFilePathBuffer, '/' ); 297 298 // Did we find the final slash? 299 if ( pFileStart == NULL ) 300 { 301 // No, so warn. 302 Con::warnf( "AssetManager::addDeclaredAsset() - Could not add single declared asset file '%s' as file-path '%s' is not valid.", 303 assetFilePathBuffer, 304 pModuleDefinition->getModulePath() ); 305 return false; 306 } 307 308 // Terminate path at slash. 309 *pFileStart = 0; 310 311 // Move to next character which should be the file start. 312 pFileStart++; 313 314 // Scan declared assets at location. 315 if ( !scanDeclaredAssets( assetFilePathBuffer, pFileStart, false, pModuleDefinition ) ) 316 { 317 // Warn. 318 Con::warnf( "AssetManager::addDeclaredAsset() - Could not scan declared assets at location '%s' with extension '%s'.", assetFilePathBuffer, pFileStart ); 319 return false; 320 } 321 322 return true; 323} 324 325//----------------------------------------------------------------------------- 326 327StringTableEntry AssetManager::addPrivateAsset( AssetBase* pAssetBase ) 328{ 329 // Debug Profiling. 330 PROFILE_SCOPE(AssetManager_AddPrivateAsset); 331 332 // Sanity! 333 AssertFatal( pAssetBase != NULL, "Cannot add a NULL private asset." ); 334 335 // Is the asset already added? 336 if (pAssetBase->mpAssetDefinition->mAssetId != StringTable->EmptyString()) 337 { 338 // Yes, so warn. 339 Con::warnf( "Cannot add private asset '%d' as it has already been assigned.", pAssetBase->mpAssetDefinition->mAssetId ); 340 return StringTable->EmptyString(); 341 } 342 343 static U32 masterPrivateAssetId = 1; 344 345 // Create asset definition. 346 AssetDefinition* pAssetDefinition = new AssetDefinition(); 347 348 // Fetch source asset definition. 349 AssetDefinition* pSourceAssetDefinition = pAssetBase->mpAssetDefinition; 350 351 // Configure asset. 352 pAssetDefinition->mpAssetBase = pAssetBase; 353 pAssetDefinition->mAssetDescription = pSourceAssetDefinition->mAssetDescription; 354 pAssetDefinition->mAssetCategory = pSourceAssetDefinition->mAssetCategory; 355 pAssetDefinition->mAssetAutoUnload = true; 356 pAssetDefinition->mAssetRefreshEnable = false; 357 pAssetDefinition->mAssetType = StringTable->insert( pAssetBase->getClassName() ); 358 pAssetDefinition->mAssetLoadedCount = 0; 359 pAssetDefinition->mAssetInternal = false; 360 pAssetDefinition->mAssetPrivate = true; 361 362 // Format asset name. 363 char assetNameBuffer[256]; 364 dSprintf(assetNameBuffer, sizeof(assetNameBuffer), "%s_%d", pAssetDefinition->mAssetType, masterPrivateAssetId++ ); 365 366 // Set asset identity. 367 pAssetDefinition->mAssetName = StringTable->insert( assetNameBuffer ); 368 pAssetDefinition->mAssetId = pAssetDefinition->mAssetName; 369 370 // Ensure that the source asset is fully synchronized with the new asset definition. 371 pSourceAssetDefinition->mAssetName = pAssetDefinition->mAssetName; 372 pSourceAssetDefinition->mAssetAutoUnload = pAssetDefinition->mAssetAutoUnload; 373 pSourceAssetDefinition->mAssetInternal = pAssetDefinition->mAssetInternal; 374 375 // Set ownership by asset manager. 376 pAssetDefinition->mpAssetBase->setOwned( this, pAssetDefinition ); 377 378 // Store in declared assets. 379 mDeclaredAssets.insert( pAssetDefinition->mAssetId, pAssetDefinition ); 380 381 // Increase the private loaded asset count. 382 if ( ++mLoadedPrivateAssetsCount > mMaxLoadedPrivateAssetsCount ) 383 mMaxLoadedPrivateAssetsCount = mLoadedPrivateAssetsCount; 384 385 return pAssetDefinition->mAssetId; 386} 387 388//----------------------------------------------------------------------------- 389 390bool AssetManager::removeDeclaredAssets( ModuleDefinition* pModuleDefinition ) 391{ 392 // Debug Profiling. 393 PROFILE_SCOPE(AssetManager_RemoveDeclaredAssets); 394 395 // Sanity! 396 AssertFatal( pModuleDefinition != NULL, "Cannot remove declared assets using a NULL module definition" ); 397 398 // Fetch module assets. 399 ModuleDefinition::typeModuleAssetsVector& moduleAssets = pModuleDefinition->getModuleAssets(); 400 401 // Remove all module assets. 402 while ( moduleAssets.size() > 0 ) 403 { 404 // Fetch asset definition. 405 AssetDefinition* pAssetDefinition = *moduleAssets.begin(); 406 407 // Remove this asset. 408 removeDeclaredAsset( pAssetDefinition->mAssetId ); 409 } 410 411 // Info. 412 if ( mEchoInfo ) 413 Con::printSeparator(); 414 415 return true; 416} 417 418//----------------------------------------------------------------------------- 419 420bool AssetManager::removeDeclaredAsset( const char* pAssetId ) 421{ 422 // Debug Profiling. 423 PROFILE_SCOPE(AssetManager_RemoveSingleDeclaredAsset); 424 425 // Sanity! 426 AssertFatal( pAssetId != NULL, "Cannot remove single declared asset using NULL asset Id." ); 427 428 // Fetch asset Id. 429 StringTableEntry assetId = StringTable->insert( pAssetId ); 430 431 // Find declared asset. 432 typeDeclaredAssetsHash::iterator declaredAssetItr = mDeclaredAssets.find( assetId ); 433 434 // Did we find the declared asset? 435 if ( declaredAssetItr == mDeclaredAssets.end() ) 436 { 437 // No, so warn. 438 Con::warnf( "Asset Manager: Cannot remove single asset Id '%s' it could not be found.", assetId ); 439 return false; 440 } 441 442 // Fetch asset definition. 443 AssetDefinition* pAssetDefinition = declaredAssetItr->value; 444 445 // Is the asset private? 446 if ( !pAssetDefinition->mAssetPrivate ) 447 { 448 // No, so fetch module assets. 449 ModuleDefinition::typeModuleAssetsVector& moduleAssets = pAssetDefinition->mpModuleDefinition->getModuleAssets(); 450 451 // Remove module asset. 452 for ( ModuleDefinition::typeModuleAssetsVector::iterator moduleAssetItr = moduleAssets.begin(); moduleAssetItr != moduleAssets.end(); ++moduleAssetItr ) 453 { 454 if ( *moduleAssetItr == pAssetDefinition ) 455 { 456 moduleAssets.erase( moduleAssetItr ); 457 break; 458 } 459 } 460 461 // Remove asset dependencies. 462 removeAssetDependencies( pAssetId ); 463 } 464 465 // Do we have an asset loaded? 466 if ( pAssetDefinition->mpAssetBase != NULL ) 467 { 468 // Yes, so delete it. 469 // NOTE: If anything is using this then this'll cause a crash. Objects should always use safe reference methods however. 470 pAssetDefinition->mpAssetBase->deleteObject(); 471 } 472 473 // Remove from declared assets. 474 mDeclaredAssets.erase( declaredAssetItr ); 475 476 // Info. 477 if ( mEchoInfo ) 478 { 479 Con::printf( "Asset Manager: Removing Asset Id '%s' of type '%s' in asset file '%s'.", 480 pAssetDefinition->mAssetId, 481 pAssetDefinition->mAssetType, 482 pAssetDefinition->mAssetBaseFilePath ); 483 } 484 485 // Destroy asset definition. 486 delete pAssetDefinition; 487 488 return true; 489} 490 491//----------------------------------------------------------------------------- 492 493StringTableEntry AssetManager::getAssetName( const char* pAssetId ) 494{ 495 // Find asset definition. 496 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 497 498 // Did we find the asset? 499 if ( pAssetDefinition == NULL ) 500 { 501 // No, so warn. 502 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 503 return NULL; 504 } 505 506 return pAssetDefinition->mAssetName; 507} 508 509//----------------------------------------------------------------------------- 510 511StringTableEntry AssetManager::getAssetDescription( const char* pAssetId ) 512{ 513 // Find asset definition. 514 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 515 516 // Did we find the asset? 517 if ( pAssetDefinition == NULL ) 518 { 519 // No, so warn. 520 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 521 return NULL; 522 } 523 524 return pAssetDefinition->mAssetDescription; 525} 526 527//----------------------------------------------------------------------------- 528 529StringTableEntry AssetManager::getAssetCategory( const char* pAssetId ) 530{ 531 // Find asset definition. 532 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 533 534 // Did we find the asset? 535 if ( pAssetDefinition == NULL ) 536 { 537 // No, so warn. 538 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 539 return NULL; 540 } 541 542 return pAssetDefinition->mAssetCategory; 543} 544 545//----------------------------------------------------------------------------- 546 547StringTableEntry AssetManager::getAssetType( const char* pAssetId ) 548{ 549 // Find asset definition. 550 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 551 552 // Did we find the asset? 553 if ( pAssetDefinition == NULL ) 554 { 555 // No, so warn. 556 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 557 return NULL; 558 } 559 560 return pAssetDefinition->mAssetType; 561} 562 563//----------------------------------------------------------------------------- 564 565StringTableEntry AssetManager::getAssetFilePath( const char* pAssetId ) 566{ 567 // Find asset definition. 568 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 569 570 // Did we find the asset? 571 if ( pAssetDefinition == NULL ) 572 { 573 // No, so warn. 574 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 575 return StringTable->EmptyString(); 576 } 577 578 return pAssetDefinition->mAssetBaseFilePath; 579} 580 581//----------------------------------------------------------------------------- 582 583StringTableEntry AssetManager::getAssetPath( const char* pAssetId ) 584{ 585 // Debug Profiling. 586 PROFILE_SCOPE(AssetManager_GetAssetPath); 587 588 // Fetch asset file-path. 589 StringTableEntry assetFilePath = getAssetFilePath( pAssetId ); 590 591 // Finish if no file-path. 592 if ( assetFilePath == StringTable->EmptyString() ) 593 return assetFilePath; 594 595 // Find the final slash which should be just before the file. 596 const char* pFinalSlash = dStrrchr( assetFilePath, '/' ); 597 598 // Sanity! 599 AssertFatal( pFinalSlash != NULL, "Should always be able to find final slash in the asset file-path." ); 600 601 // Fetch asset path. 602 return StringTable->insertn( assetFilePath, (U32)(pFinalSlash - assetFilePath) ); 603} 604 605//----------------------------------------------------------------------------- 606 607ModuleDefinition* AssetManager::getAssetModuleDefinition( const char* pAssetId ) 608{ 609 // Find asset definition. 610 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 611 612 // Did we find the asset? 613 if ( pAssetDefinition == NULL ) 614 { 615 // No, so warn. 616 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 617 return NULL; 618 } 619 620 return pAssetDefinition->mpModuleDefinition; 621} 622 623//----------------------------------------------------------------------------- 624 625bool AssetManager::isAssetInternal( const char* pAssetId ) 626{ 627 // Find asset definition. 628 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 629 630 // Did we find the asset? 631 if ( pAssetDefinition == NULL ) 632 { 633 // No, so warn. 634 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 635 return false; 636 } 637 638 return pAssetDefinition->mAssetInternal; 639} 640 641//----------------------------------------------------------------------------- 642 643bool AssetManager::isAssetPrivate( const char* pAssetId ) 644{ 645 // Find asset definition. 646 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 647 648 // Did we find the asset? 649 if ( pAssetDefinition == NULL ) 650 { 651 // No, so warn. 652 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 653 return false; 654 } 655 656 return pAssetDefinition->mAssetPrivate; 657} 658 659//----------------------------------------------------------------------------- 660 661bool AssetManager::isAssetAutoUnload( const char* pAssetId ) 662{ 663 // Find asset definition. 664 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 665 666 // Did we find the asset? 667 if ( pAssetDefinition == NULL ) 668 { 669 // No, so warn. 670 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 671 return false; 672 } 673 674 return pAssetDefinition->mAssetAutoUnload; 675} 676 677//----------------------------------------------------------------------------- 678 679bool AssetManager::isAssetLoaded( const char* pAssetId ) 680{ 681 // Find asset definition. 682 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 683 684 // Did we find the asset? 685 if ( pAssetDefinition == NULL ) 686 { 687 // No, so warn. 688 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 689 return false; 690 } 691 692 return pAssetDefinition->mpAssetBase != NULL; 693} 694 695 696//----------------------------------------------------------------------------- 697 698bool AssetManager::isDeclaredAsset( const char* pAssetId ) 699{ 700 return findAsset( pAssetId ) != NULL; 701} 702 703//----------------------------------------------------------------------------- 704 705bool AssetManager::doesAssetDependOn( const char* pAssetId, const char* pDependsOnAssetId ) 706{ 707 // Debug Profiling. 708 PROFILE_SCOPE(AssetManager_DoesAssetDependOn); 709 710 // Sanity! 711 AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." ); 712 AssertFatal( pDependsOnAssetId != NULL, "Cannot use NULL depends-on asset Id." ); 713 714 // Fetch asset Id. 715 StringTableEntry assetId = StringTable->insert( pAssetId ); 716 717 // Fetch depends-on asset Id. 718 StringTableEntry dependsOnAssetId = StringTable->insert( pDependsOnAssetId ); 719 720 // Find depends-on entry. 721 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find( assetId ); 722 723 // Iterate all dependencies. 724 while( dependsOnItr != mAssetDependsOn.end() && dependsOnItr->key == assetId ) 725 { 726 // Finish if a depends on. 727 if ( dependsOnItr->value == dependsOnAssetId ) 728 return true; 729 730 // Next dependency. 731 dependsOnItr++; 732 } 733 734 return false; 735} 736 737//----------------------------------------------------------------------------- 738 739bool AssetManager::isAssetDependedOn( const char* pAssetId, const char* pDependedOnByAssetId ) 740{ 741 // Debug Profiling. 742 PROFILE_SCOPE(AssetManager_IsAssetDependedOn); 743 744 // Sanity! 745 AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." ); 746 AssertFatal( pDependedOnByAssetId != NULL, "Cannot use NULL depended-on-by asset Id." ); 747 748 // Fetch asset Id. 749 StringTableEntry assetId = StringTable->insert( pAssetId ); 750 751 // Fetch depended-on-by asset Id. 752 StringTableEntry dependedOnByAssetId = StringTable->insert( pDependedOnByAssetId ); 753 754 // Find depended-on-by entry. 755 typeAssetDependsOnHash::Iterator dependedOnItr = mAssetIsDependedOn.find(assetId); 756 757 // Iterate all dependencies. 758 while( dependedOnItr != mAssetIsDependedOn.end() && dependedOnItr->key == assetId ) 759 { 760 // Finish if depended-on. 761 if ( dependedOnItr->value == dependedOnByAssetId ) 762 return true; 763 764 // Next dependency. 765 dependedOnItr++; 766 } 767 768 return false; 769} 770 771//----------------------------------------------------------------------------- 772 773bool AssetManager::isReferencedAsset( const char* pAssetId ) 774{ 775 // Debug Profiling. 776 PROFILE_SCOPE(AssetManager_IsReferencedAsset); 777 778 // Sanity! 779 AssertFatal( pAssetId != NULL, "Cannot check if NULL asset Id is referenced." ); 780 781 // Fetch asset Id. 782 StringTableEntry assetId = StringTable->insert( pAssetId ); 783 784 // Is asset Id the correct format? 785 if ( StringUnit::getUnitCount( assetId, ASSET_SCOPE_TOKEN ) != 2 ) 786 { 787 // No, so warn. 788 Con::warnf( "Asset Manager: Cannot check if asset Id '%s' is referenced as it is not the correct format.", assetId ); 789 return false; 790 } 791 792 return mReferencedAssets.count( assetId ) > 0; 793} 794 795//----------------------------------------------------------------------------- 796 797bool AssetManager::renameDeclaredAsset( const char* pAssetIdFrom, const char* pAssetIdTo ) 798{ 799 // Debug Profiling. 800 PROFILE_SCOPE(AssetManager_RenameDeclaredAsset); 801 802 // Sanity! 803 AssertFatal( pAssetIdFrom != NULL, "Cannot rename from NULL asset Id." ); 804 AssertFatal( pAssetIdTo != NULL, "Cannot rename to NULL asset Id." ); 805 806 // Fetch asset Ids. 807 StringTableEntry assetIdFrom = StringTable->insert( pAssetIdFrom ); 808 StringTableEntry assetIdTo = StringTable->insert( pAssetIdTo ); 809 810 // Is asset Id from the correct format? 811 if ( StringUnit::getUnitCount( assetIdFrom, ASSET_SCOPE_TOKEN ) != 2 ) 812 { 813 // No, so warn. 814 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as source asset Id is not the correct format.", assetIdFrom, assetIdTo ); 815 return false; 816 } 817 818 // Is asset Id to the correct format? 819 if ( StringUnit::getUnitCount( assetIdTo, ASSET_SCOPE_TOKEN ) != 2 ) 820 { 821 // No, so warn. 822 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as target asset Id is not the correct format.", assetIdFrom, assetIdTo ); 823 return false; 824 } 825 826 // Does the asset Id from exist? 827 if ( !mDeclaredAssets.contains( assetIdFrom ) ) 828 { 829 // No, so warn. 830 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as source asset Id is not declared.", assetIdFrom, assetIdTo ); 831 return false; 832 } 833 834 // Does the asset Id to exist? 835 if ( mDeclaredAssets.contains( assetIdTo ) ) 836 { 837 // No, so warn. 838 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as target asset Id is already declared.", assetIdFrom, assetIdTo ); 839 return false; 840 } 841 842 // Split module Ids from asset Ids. 843 StringTableEntry moduleIdFrom = StringTable->insert( StringUnit::getUnit( assetIdFrom, 0, ASSET_SCOPE_TOKEN ) ); 844 StringTableEntry moduleIdTo = StringTable->insert( StringUnit::getUnit( assetIdTo, 0, ASSET_SCOPE_TOKEN ) ); 845 846 // Are the module Ids the same? 847 if ( moduleIdFrom != moduleIdTo ) 848 { 849 // No, so warn. 850 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as the module Id cannot be changed.", assetIdFrom, assetIdTo ); 851 return false; 852 } 853 854 // Find asset definition. 855 typeDeclaredAssetsHash::iterator assetDefinitionItr = mDeclaredAssets.find( assetIdFrom ); 856 857 // Sanity! 858 AssertFatal( assetDefinitionItr != mDeclaredAssets.end(), "Asset Manager: Failed to find asset." ); 859 860 // Fetch asset definition. 861 AssetDefinition* pAssetDefinition = assetDefinitionItr->value; 862 863 // Is this a private asset? 864 if ( pAssetDefinition->mAssetPrivate ) 865 { 866 // Yes, so warn. 867 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as the source asset is private.", assetIdFrom, assetIdTo ); 868 return false; 869 } 870 871 // Setup declared update visitor. 872 TamlAssetDeclaredUpdateVisitor assetDeclaredUpdateVisitor; 873 assetDeclaredUpdateVisitor.setAssetIdFrom( assetIdFrom ); 874 assetDeclaredUpdateVisitor.setAssetIdTo( assetIdTo ); 875 876 // Update asset file declaration. 877 if ( !mTaml.parse( pAssetDefinition->mAssetBaseFilePath, assetDeclaredUpdateVisitor ) ) 878 { 879 // No, so warn. 880 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as the declared asset file could not be parsed: %s", 881 assetIdFrom, assetIdTo, pAssetDefinition->mAssetBaseFilePath ); 882 return false; 883 } 884 885 // Update asset definition. 886 pAssetDefinition->mAssetId = assetIdTo; 887 pAssetDefinition->mAssetName = StringTable->insert( StringUnit::getUnit( assetIdTo, 1, ASSET_SCOPE_TOKEN ) ); 888 889 // Reinsert declared asset. 890 mDeclaredAssets.erase( assetIdFrom ); 891 mDeclaredAssets.insert( assetIdTo, pAssetDefinition ); 892 893 // Info. 894 if ( mEchoInfo ) 895 { 896 Con::printf( "Asset Manager: Renaming declared Asset Id '%s' to Asset Id '%s'.", assetIdFrom, assetIdTo ); 897 Con::printSeparator(); 898 } 899 900 // Rename asset dependencies. 901 renameAssetDependencies( assetIdFrom, assetIdTo ); 902 903 // Do we have an asset tags manifest? 904 if ( !mAssetTagsManifest.isNull() ) 905 { 906 // Yes, so rename any assets. 907 mAssetTagsManifest->renameAssetId( pAssetIdFrom, pAssetIdTo ); 908 909 // Save the asset tags. 910 saveAssetTags(); 911 } 912 913 return true; 914} 915 916//----------------------------------------------------------------------------- 917 918bool AssetManager::renameReferencedAsset( const char* pAssetIdFrom, const char* pAssetIdTo ) 919{ 920 // Debug Profiling. 921 PROFILE_SCOPE(AssetManager_RenameReferencedAsset); 922 923 // Sanity! 924 AssertFatal( pAssetIdFrom != NULL, "Cannot rename from NULL asset Id." ); 925 AssertFatal( pAssetIdTo != NULL, "Cannot rename to NULL asset Id." ); 926 927 // Fetch asset Ids. 928 StringTableEntry assetIdFrom = StringTable->insert( pAssetIdFrom ); 929 StringTableEntry assetIdTo = StringTable->insert( pAssetIdTo ); 930 931 // Is asset Id from the correct format? 932 if ( StringUnit::getUnitCount( assetIdFrom, ASSET_SCOPE_TOKEN ) != 2 ) 933 { 934 // No, so warn. 935 Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as source asset Id is not the correct format.", assetIdFrom, assetIdTo ); 936 return false; 937 } 938 939 // Is asset Id to the correct format? 940 if ( StringUnit::getUnitCount( assetIdTo, ASSET_SCOPE_TOKEN ) != 2 ) 941 { 942 // No, so warn. 943 Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as target asset Id is not the correct format.", assetIdFrom, assetIdTo ); 944 return false; 945 } 946 947 // Does the asset Id to exist? 948 if ( !mDeclaredAssets.contains( assetIdTo ) ) 949 { 950 // No, so warn. 951 Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as target asset Id is not declared.", assetIdFrom, assetIdTo ); 952 return false; 953 } 954 955 // Rename asset references. 956 renameAssetReferences( assetIdFrom, assetIdTo ); 957 958 // Info. 959 if ( mEchoInfo ) 960 Con::printSeparator(); 961 962 return true; 963} 964 965//----------------------------------------------------------------------------- 966 967bool AssetManager::releaseAsset( const char* pAssetId ) 968{ 969 // Debug Profiling. 970 PROFILE_SCOPE(AssetManager_ReleaseAsset); 971 972 // Sanity! 973 AssertFatal( pAssetId != NULL, "Cannot release NULL asset Id." ); 974 975 // Find asset. 976 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 977 978 // Did we find the asset? 979 if ( pAssetDefinition == NULL ) 980 { 981 // No, so warn. 982 Con::warnf( "Asset Manager: Failed to release asset Id '%s' as it does not exist.", pAssetId ); 983 return false; 984 } 985 986 // Is the asset loaded? 987 if ( pAssetDefinition->mpAssetBase == NULL ) 988 { 989 // No, so warn. 990 Con::warnf( "Asset Manager: Failed to release asset Id '%s' as it is not acquired.", pAssetId ); 991 return false; 992 } 993 994 // Info. 995 if ( mEchoInfo ) 996 { 997 Con::printSeparator(); 998 Con::printf( "Asset Manager: Started releasing Asset Id '%s'...", pAssetId ); 999 } 1000 1001 // Release asset reference. 1002 if ( pAssetDefinition->mpAssetBase->releaseAssetReference() ) 1003 { 1004 // Are we ignoring auto-unloaded assets? 1005 if ( mIgnoreAutoUnload ) 1006 { 1007 // Yes, so info. 1008 if ( mEchoInfo ) 1009 { 1010 Con::printf( "Asset Manager: > Releasing to idle state." ); 1011 } 1012 } 1013 else 1014 { 1015 // No, so info. 1016 if ( mEchoInfo ) 1017 { 1018 Con::printf( "Asset Manager: > Unload the asset from memory." ); 1019 } 1020 1021 // Unload the asset. 1022 unloadAsset( pAssetDefinition ); 1023 } 1024 } 1025 // Info. 1026 else if ( mEchoInfo ) 1027 { 1028 Con::printf( "Asset Manager: > Reference count now '%d'.", pAssetDefinition->mpAssetBase->getAcquiredReferenceCount() ); 1029 } 1030 1031 // Info. 1032 if ( mEchoInfo ) 1033 { 1034 Con::printf( "Asset Manager: > Finished releasing Asset Id '%s'.", pAssetId ); 1035 Con::printSeparator(); 1036 } 1037 1038 return true; 1039} 1040 1041//----------------------------------------------------------------------------- 1042 1043void AssetManager::purgeAssets( void ) 1044{ 1045 // Debug Profiling. 1046 PROFILE_SCOPE(AssetManager_PurgeAssets); 1047 1048 // Info. 1049 if ( mEchoInfo ) 1050 { 1051 Con::printf( "Asset Manager: Started purging assets..." ); 1052 } 1053 1054 // Iterate asset definitions. 1055 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1056 { 1057 // Fetch asset definition. 1058 AssetDefinition* pAssetDefinition = assetItr->value; 1059 1060 // Skip asset if private, not loaded or referenced. 1061 if ( pAssetDefinition->mAssetPrivate || 1062 pAssetDefinition->mpAssetBase == NULL || 1063 pAssetDefinition->mpAssetBase->getAcquiredReferenceCount() > 0 ) 1064 continue; 1065 1066 // Info. 1067 if ( mEchoInfo ) 1068 { 1069 Con::printf( "Asset Manager: Purging asset Id '%s'...", pAssetDefinition->mAssetId ); 1070 } 1071 1072 // Unload the asset. 1073 unloadAsset( pAssetDefinition ); 1074 } 1075 1076 // Info. 1077 if ( mEchoInfo ) 1078 { 1079 Con::printf( "Asset Manager: ... Finished purging assets." ); 1080 } 1081} 1082 1083//----------------------------------------------------------------------------- 1084 1085bool AssetManager::deleteAsset( const char* pAssetId, const bool deleteLooseFiles, const bool deleteDependencies ) 1086{ 1087 // Debug Profiling. 1088 PROFILE_SCOPE(AssetManager_DeleteAsset); 1089 1090 // Sanity! 1091 AssertFatal( pAssetId != NULL, "Cannot delete NULL asset Id." ); 1092 1093 // Find asset. 1094 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 1095 1096 // Did we find the asset? 1097 if ( pAssetDefinition == NULL ) 1098 { 1099 // No, so warn. 1100 Con::warnf( "Asset Manager: Failed to delete asset Id '%s' as it does not exist.", pAssetId ); 1101 return false; 1102 } 1103 1104 // Info. 1105 if ( mEchoInfo ) 1106 { 1107 Con::printSeparator(); 1108 Con::printf( "Asset Manager: Started deleting Asset Id '%s'...", pAssetId ); 1109 } 1110 1111 // Fetch asset Id. 1112 StringTableEntry assetId = StringTable->insert( pAssetId ); 1113 1114 // Are we deleting dependencies? 1115 if ( deleteDependencies ) 1116 { 1117 Vector<typeAssetId> dependantAssets; 1118 1119 // Yes, so find depended-on-by entry. 1120 typeAssetDependsOnHash::Iterator dependedOnItr = mAssetIsDependedOn.find( assetId ); 1121 1122 // Iterate all dependencies. 1123 while( dependedOnItr != mAssetIsDependedOn.end() && dependedOnItr->key == assetId ) 1124 { 1125 // Store asset Id. 1126 dependantAssets.push_back( dependedOnItr->value ); 1127 1128 // Next dependency. 1129 dependedOnItr++; 1130 } 1131 1132 // Do we have any dependants? 1133 if ( dependantAssets.size() > 0 ) 1134 { 1135 // Yes, so iterate dependants. 1136 for( Vector<typeAssetId>::const_iterator assetItr = dependantAssets.begin(); assetItr != dependantAssets.end(); ++assetItr ) 1137 { 1138 StringTableEntry dependentAssetId = *assetItr; 1139 1140 // Info. 1141 if ( mEchoInfo ) 1142 { 1143 Con::printSeparator(); 1144 Con::printf( "Asset Manager: Deleting Asset Id '%s' dependant of '%s.'", pAssetId, dependentAssetId ); 1145 } 1146 1147 // Delete dependant. 1148 deleteAsset( dependentAssetId, deleteLooseFiles, deleteDependencies ); 1149 } 1150 } 1151 } 1152 1153 // Remove asset references. 1154 removeAssetReferences( assetId ); 1155 1156 // Are we deleting loose files? 1157 if ( deleteLooseFiles ) 1158 { 1159 // Yes, so remove loose files. 1160 Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles; 1161 for( Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr ) 1162 { 1163 // Fetch loose file. 1164 StringTableEntry looseFile = *looseFileItr; 1165 1166 // Delete the loose file. 1167 if ( !dFileDelete( looseFile ) ) 1168 { 1169 // Failed so warn. 1170 Con::warnf( "Asset Manager: Failed to delete the loose file '%s' while deleting asset Id '%s'.", looseFile, pAssetId ); 1171 } 1172 } 1173 } 1174 1175 // Fetch asset definition file. 1176 StringTableEntry assetDefinitionFile = pAssetDefinition->mAssetBaseFilePath; 1177 1178 // Remove reference here as we're about to remove the declared asset. 1179 pAssetDefinition = NULL; 1180 1181 // Remove asset. 1182 removeDeclaredAsset( pAssetId ); 1183 1184 // Delete the asset definition file. 1185 if ( !dFileDelete( assetDefinitionFile ) ) 1186 { 1187 // Failed so warn. 1188 Con::warnf( "Asset Manager: Failed to delete the asset definition file '%s' while deleting asset Id '%s'.", assetDefinitionFile, pAssetId ); 1189 } 1190 1191 // Info. 1192 if ( mEchoInfo ) 1193 { 1194 Con::printSeparator(); 1195 Con::printf( "Asset Manager: Finished deleting Asset Id '%s'.", pAssetId ); 1196 } 1197 1198 return true; 1199} 1200 1201//----------------------------------------------------------------------------- 1202 1203bool AssetManager::refreshAsset( const char* pAssetId ) 1204{ 1205 // Debug Profiling. 1206 PROFILE_SCOPE(AssetManager_RefreshAsset); 1207 1208 // Sanity! 1209 AssertFatal( pAssetId != NULL, "Cannot refresh NULL asset Id." ); 1210 1211 // Find asset. 1212 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 1213 1214 // Did we find the asset? 1215 if ( pAssetDefinition == NULL ) 1216 { 1217 // No, so warn. 1218 Con::warnf( "Asset Manager: Failed to refresh asset Id '%s' as it does not exist.", pAssetId ); 1219 return false; 1220 } 1221 1222 // Info. 1223 if ( mEchoInfo ) 1224 { 1225 Con::printSeparator(); 1226 Con::printf( "Asset Manager: Started refreshing Asset Id '%s'...", pAssetId ); 1227 } 1228 1229 // Fetch asset Id. 1230 StringTableEntry assetId = StringTable->insert( pAssetId ); 1231 1232 // Is the asset private? 1233 if ( pAssetDefinition->mAssetPrivate ) 1234 { 1235 // Yes, so notify asset of asset refresh only. 1236 pAssetDefinition->mpAssetBase->onAssetRefresh(); 1237 1238 // Asset refresh notifications. 1239 for( typeAssetPtrRefreshHash::iterator refreshNotifyItr = mAssetPtrRefreshNotifications.begin(); refreshNotifyItr != mAssetPtrRefreshNotifications.end(); ++refreshNotifyItr ) 1240 { 1241 // Fetch pointed asset. 1242 StringTableEntry pointedAsset = refreshNotifyItr->key->getAssetId(); 1243 1244 // Ignore if the pointed asset is not the asset or a dependency. 1245 if ( pointedAsset == StringTable->EmptyString() || ( pointedAsset != assetId && !doesAssetDependOn( pointedAsset, assetId ) ) ) 1246 continue; 1247 1248 // Perform refresh notification callback. 1249 refreshNotifyItr->value->onAssetRefreshed( refreshNotifyItr->key ); 1250 } 1251 } 1252 // Is the asset definition allowed to refresh? 1253 else if ( pAssetDefinition->mAssetRefreshEnable ) 1254 { 1255 // Yes, so fetch the asset. 1256 AssetBase* pAssetBase = pAssetDefinition->mpAssetBase; 1257 1258 // Is the asset loaded? 1259 if ( pAssetBase != NULL ) 1260 { 1261 // Yes, so notify asset of asset refresh. 1262 pAssetBase->onAssetRefresh(); 1263 1264 // Save asset. 1265 mTaml.write( pAssetBase, pAssetDefinition->mAssetBaseFilePath ); 1266 1267 // Remove asset dependencies. 1268 removeAssetDependencies( pAssetId ); 1269 1270 // Find any new dependencies. 1271 TamlAssetDeclaredVisitor assetDeclaredVisitor; 1272 1273 // Parse the filename. 1274 if ( !mTaml.parse( pAssetDefinition->mAssetBaseFilePath, assetDeclaredVisitor ) ) 1275 { 1276 // Warn. 1277 Con::warnf( "Asset Manager: Failed to parse file containing asset declaration: '%s'.\nDependencies are now incorrect!", pAssetDefinition->mAssetBaseFilePath ); 1278 return false; 1279 } 1280 1281 // Fetch asset dependencies. 1282 TamlAssetDeclaredVisitor::typeAssetIdVector& assetDependencies = assetDeclaredVisitor.getAssetDependencies(); 1283 1284 // Are there any asset dependences? 1285 if ( assetDependencies.size() > 0 ) 1286 { 1287 // Yes, so iterate dependencies. 1288 for( TamlAssetDeclaredVisitor::typeAssetIdVector::iterator assetDependencyItr = assetDependencies.begin(); assetDependencyItr != assetDependencies.end(); ++assetDependencyItr ) 1289 { 1290 // Fetch dependency asset Id. 1291 StringTableEntry dependencyAssetId = *assetDependencyItr; 1292 1293 // Insert depends-on. 1294 mAssetDependsOn.insertEqual( assetId, dependencyAssetId ); 1295 1296 // Insert is-depended-on. 1297 mAssetIsDependedOn.insertEqual( dependencyAssetId, assetId ); 1298 } 1299 } 1300 1301 // Fetch asset loose files. 1302 TamlAssetDeclaredVisitor::typeLooseFileVector& assetLooseFiles = assetDeclaredVisitor.getAssetLooseFiles(); 1303 1304 // Clear any existing loose files. 1305 pAssetDefinition->mAssetLooseFiles.clear(); 1306 1307 // Are there any loose files? 1308 if ( assetLooseFiles.size() > 0 ) 1309 { 1310 // Yes, so iterate loose files. 1311 for( TamlAssetDeclaredVisitor::typeLooseFileVector::iterator assetLooseFileItr = assetLooseFiles.begin(); assetLooseFileItr != assetLooseFiles.end(); ++assetLooseFileItr ) 1312 { 1313 // Store loose file. 1314 pAssetDefinition->mAssetLooseFiles.push_back( *assetLooseFileItr ); 1315 } 1316 } 1317 1318 // Asset refresh notifications. 1319 for( typeAssetPtrRefreshHash::iterator refreshNotifyItr = mAssetPtrRefreshNotifications.begin(); refreshNotifyItr != mAssetPtrRefreshNotifications.end(); ++refreshNotifyItr ) 1320 { 1321 // Fetch pointed asset. 1322 StringTableEntry pointedAsset = refreshNotifyItr->key->getAssetId(); 1323 1324 // Ignore if the pointed asset is not the asset or a dependency. 1325 if ( pointedAsset == StringTable->EmptyString() || ( pointedAsset != assetId && !doesAssetDependOn( pointedAsset, assetId ) ) ) 1326 continue; 1327 1328 // Perform refresh notification callback. 1329 refreshNotifyItr->value->onAssetRefreshed( refreshNotifyItr->key ); 1330 } 1331 1332 // Find is-depends-on entry. 1333 typeAssetIsDependedOnHash::Iterator isDependedOnItr = mAssetIsDependedOn.find( assetId ); 1334 1335 // Is asset depended on? 1336 if ( isDependedOnItr != mAssetIsDependedOn.end() ) 1337 { 1338 // Yes, so compiled them. 1339 Vector<typeAssetId> dependedOn; 1340 1341 // Iterate all dependencies. 1342 while( isDependedOnItr != mAssetIsDependedOn.end() && isDependedOnItr->key == assetId ) 1343 { 1344 dependedOn.push_back( isDependedOnItr->value ); 1345 1346 // Next dependency. 1347 isDependedOnItr++; 1348 } 1349 1350 // Refresh depended-on assets. 1351 for ( Vector<typeAssetId>::iterator refreshItr = dependedOn.begin(); refreshItr != dependedOn.end(); ++refreshItr) 1352 { 1353 // Refresh dependency asset. 1354 refreshAsset( *refreshItr); 1355 } 1356 } 1357 } 1358 } 1359 1360 // Info. 1361 if ( mEchoInfo ) 1362 { 1363 Con::printSeparator(); 1364 Con::printf( "Asset Manager: Finished refreshing Asset Id '%s'.", pAssetId ); 1365 } 1366 1367 return true; 1368} 1369 1370//----------------------------------------------------------------------------- 1371 1372void AssetManager::refreshAllAssets( const bool includeUnloaded ) 1373{ 1374 // Debug Profiling. 1375 PROFILE_SCOPE(AssetManager_RefreshAllAssets); 1376 1377 // Info. 1378 if ( mEchoInfo ) 1379 { 1380 Con::printSeparator(); 1381 Con::printf( "Asset Manager: Started refreshing ALL assets." ); 1382 } 1383 1384 Vector<typeAssetId> assetsToRelease; 1385 1386 // Are we including unloaded assets? 1387 if ( includeUnloaded ) 1388 { 1389 // Yes, so prepare a list of assets to release and load them. 1390 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1391 { 1392 // Fetch asset Id. 1393 typeAssetId assetId = assetItr->key; 1394 1395 // Skip if asset is loaded. 1396 if ( assetItr->value->mpAssetBase != NULL ) 1397 continue; 1398 1399 // Note asset as needing a release. 1400 assetsToRelease.push_back( assetId ); 1401 1402 // Acquire the asset. 1403 acquireAsset<AssetBase>( assetId ); 1404 } 1405 } 1406 1407 // Refresh the current loaded assets. 1408 // NOTE: This will result in some assets being refreshed more than once due to asset dependencies. 1409 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1410 { 1411 // Skip private assets. 1412 if ( assetItr->value->mAssetPrivate ) 1413 continue; 1414 1415 // Refresh asset if it's loaded. 1416 refreshAsset( assetItr->key ); 1417 } 1418 1419 // Are we including unloaded assets? 1420 if ( includeUnloaded ) 1421 { 1422 // Yes, so release the assets we loaded. 1423 for( Vector<typeAssetId>::iterator assetItr = assetsToRelease.begin(); assetItr != assetsToRelease.end(); ++assetItr ) 1424 { 1425 releaseAsset( *assetItr ); 1426 } 1427 } 1428 1429 // Info. 1430 if ( mEchoInfo ) 1431 { 1432 Con::printSeparator(); 1433 Con::printf( "Asset Manager: Finished refreshing ALL assets." ); 1434 } 1435} 1436 1437//----------------------------------------------------------------------------- 1438 1439void AssetManager::registerAssetPtrRefreshNotify( AssetPtrBase* pAssetPtrBase, AssetPtrCallback* pCallback ) 1440{ 1441 // Find an existing notification iterator. 1442 typeAssetPtrRefreshHash::iterator notificationItr = mAssetPtrRefreshNotifications.find( pAssetPtrBase ); 1443 1444 // Do we have one? 1445 if ( notificationItr != mAssetPtrRefreshNotifications.end() ) 1446 { 1447 // Yes, so update the callback. 1448 notificationItr->value = pCallback; 1449 return; 1450 } 1451 1452 // No, so add one. 1453 mAssetPtrRefreshNotifications.insert( pAssetPtrBase, pCallback ); 1454} 1455 1456//----------------------------------------------------------------------------- 1457 1458void AssetManager::unregisterAssetPtrRefreshNotify( AssetPtrBase* pAssetPtrBase ) 1459{ 1460 mAssetPtrRefreshNotifications.erase( pAssetPtrBase ); 1461} 1462 1463//----------------------------------------------------------------------------- 1464 1465bool AssetManager::loadAssetTags( ModuleDefinition* pModuleDefinition ) 1466{ 1467 // Sanity! 1468 AssertFatal( pModuleDefinition != NULL, "Cannot load asset tags manifest using a NULL module definition" ); 1469 1470 // Expand manifest location. 1471 char assetTagsManifestFilePathBuffer[1024]; 1472 Con::expandPath( assetTagsManifestFilePathBuffer, sizeof(assetTagsManifestFilePathBuffer), pModuleDefinition->getAssetTagsManifest() ); 1473 1474 // Do we already have a manifest? 1475 if ( !mAssetTagsManifest.isNull() ) 1476 { 1477 // Yes, so warn. 1478 Con::warnf( "Asset Manager: Cannot load asset tags manifest from module '%s' as one is already loaded.", pModuleDefinition->getSignature() ); 1479 return false; 1480 } 1481 1482 // Is the specified file valid? 1483 if ( Platform::isFile( assetTagsManifestFilePathBuffer ) ) 1484 { 1485 // Yes, so read asset tags manifest. 1486 mAssetTagsManifest = mTaml.read<AssetTagsManifest>( assetTagsManifestFilePathBuffer ); 1487 1488 // Did we read the manifest? 1489 if ( mAssetTagsManifest.isNull() ) 1490 { 1491 // No, so warn. 1492 Con::warnf( "Asset Manager: Failed to load asset tags manifest '%s' from module '%s'.", assetTagsManifestFilePathBuffer, pModuleDefinition->getSignature() ); 1493 return false; 1494 } 1495 1496 // Set asset tags module definition. 1497 mAssetTagsModuleDefinition = pModuleDefinition; 1498 } 1499 else 1500 { 1501 // No, so generate a new asset tags manifest. 1502 mAssetTagsManifest = new AssetTagsManifest(); 1503 mAssetTagsManifest->registerObject(); 1504 1505 // Set asset tags module definition. 1506 mAssetTagsModuleDefinition = pModuleDefinition; 1507 1508 // Save the asset tags. 1509 saveAssetTags(); 1510 } 1511 1512 return true; 1513} 1514 1515//----------------------------------------------------------------------------- 1516 1517bool AssetManager::saveAssetTags( void ) 1518{ 1519 // Do we have an asset tags manifest? 1520 if ( mAssetTagsManifest.isNull() || mAssetTagsModuleDefinition.isNull() ) 1521 { 1522 // No, so warn. 1523 Con::warnf( "Asset Manager: Failed to save asset tags manifest as one is not loaded." ); 1524 return false; 1525 } 1526 1527 // Expand manifest location. 1528 char assetTagsManifestFilePathBuffer[1024]; 1529 Con::expandPath( assetTagsManifestFilePathBuffer, sizeof(assetTagsManifestFilePathBuffer), mAssetTagsModuleDefinition->getAssetTagsManifest() ); 1530 1531 // Save asset tags manifest. 1532 if ( !mTaml.write( mAssetTagsManifest, assetTagsManifestFilePathBuffer ) ) 1533 { 1534 // Failed so warn. 1535 Con::warnf( "Asset Manager: Failed to save asset tags manifest '%s' from module '%s'.", assetTagsManifestFilePathBuffer, mAssetTagsModuleDefinition->getSignature() ); 1536 return false; 1537 } 1538 1539 return true; 1540} 1541 1542//----------------------------------------------------------------------------- 1543 1544bool AssetManager::restoreAssetTags( void ) 1545{ 1546 // Do we already have a manifest? 1547 if ( mAssetTagsManifest.isNull() ) 1548 { 1549 // No, so warn. 1550 Con::warnf( "Asset Manager: Cannot restore asset tags manifest as one is not already loaded." ); 1551 return false; 1552 } 1553 1554 // Sanity! 1555 AssertFatal( mAssetTagsModuleDefinition != NULL, "Cannot restore asset tags manifest as module definition is NULL." ); 1556 1557 // Delete existing asset tags manifest. 1558 mAssetTagsManifest->deleteObject(); 1559 1560 // Reload asset tags manifest. 1561 return loadAssetTags( mAssetTagsModuleDefinition ); 1562} 1563 1564//----------------------------------------------------------------------------- 1565 1566S32 QSORT_CALLBACK descendingAssetDefinitionLoadCount(const void* a, const void* b) 1567{ 1568 // Debug Profiling. 1569 PROFILE_SCOPE(AssetManager_DescendingAssetDefinitionLoadCount); 1570 1571 // Fetch asset definitions. 1572 const AssetDefinition* pAssetDefinitionA = *(AssetDefinition**)a; 1573 const AssetDefinition* pAssetDefinitionB = *(AssetDefinition**)b; 1574 1575 // Sort. 1576 return pAssetDefinitionB->mAssetLoadedCount - pAssetDefinitionA->mAssetLoadedCount; 1577} 1578 1579//----------------------------------------------------------------------------- 1580 1581void AssetManager::dumpDeclaredAssets( void ) const 1582{ 1583 Vector<const AssetDefinition*> assetDefinitions; 1584 1585 // Iterate asset definitions. 1586 for( typeDeclaredAssetsHash::const_iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1587 { 1588 assetDefinitions.push_back( assetItr->value ); 1589 } 1590 1591 // Sort asset definitions. 1592 dQsort( assetDefinitions.address(), assetDefinitions.size(), sizeof(const AssetDefinition*), descendingAssetDefinitionLoadCount ); 1593 1594 // Info. 1595 Con::printSeparator(); 1596 Con::printf( "Asset Manager: %d declared asset(s) dump as follows:", mDeclaredAssets.size() ); 1597 Con::printBlankLine(); 1598 1599 // Iterate sorted asset definitions. 1600 for ( Vector<const AssetDefinition*>::iterator assetItr = assetDefinitions.begin(); assetItr != assetDefinitions.end(); ++assetItr ) 1601 { 1602 // Fetch asset definition. 1603 const AssetDefinition* pAssetDefinition = *assetItr; 1604 1605 // Info. 1606 Con::printf( "AssetId:'%s', RefCount:%d, LoadCount:%d, UnloadCount:%d, AutoUnload:%d, Loaded:%d, Internal:%d, Private: %d, Type:'%s', Module/Version:'%s'/'%d', File:'%s'", 1607 pAssetDefinition->mAssetId, 1608 pAssetDefinition->mpAssetBase == NULL ? 0 : pAssetDefinition->mpAssetBase->getAcquiredReferenceCount(), 1609 pAssetDefinition->mAssetLoadedCount, 1610 pAssetDefinition->mAssetUnloadedCount, 1611 pAssetDefinition->mAssetAutoUnload, 1612 pAssetDefinition->mpAssetBase != NULL, 1613 pAssetDefinition->mAssetInternal, 1614 pAssetDefinition->mAssetPrivate, 1615 pAssetDefinition->mAssetType, 1616 pAssetDefinition->mpModuleDefinition->getModuleId(), 1617 pAssetDefinition->mpModuleDefinition->getVersionId(), 1618 pAssetDefinition->mAssetBaseFilePath ); 1619 } 1620 1621 // Info. 1622 Con::printSeparator(); 1623 Con::printBlankLine(); 1624} 1625 1626//----------------------------------------------------------------------------- 1627 1628S32 AssetManager::findAllAssets( AssetQuery* pAssetQuery, const bool ignoreInternal, const bool ignorePrivate ) 1629{ 1630 // Debug Profiling. 1631 PROFILE_SCOPE(AssetManager_FindAllAssets); 1632 1633 // Sanity! 1634 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1635 1636 // Reset result count. 1637 S32 resultCount = 0; 1638 1639 // Iterate declared assets. 1640 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1641 { 1642 // Fetch asset definition. 1643 AssetDefinition* pAssetDefinition = assetItr->value; 1644 1645 // Skip if internal and we're ignoring them. 1646 if ( ignoreInternal && pAssetDefinition->mAssetInternal ) 1647 continue; 1648 1649 // Skip if private and we're ignoring them. 1650 if ( ignorePrivate && pAssetDefinition->mAssetPrivate ) 1651 continue; 1652 1653 // Store as result. 1654 pAssetQuery->mAssetList.push_back( pAssetDefinition->mAssetId ); 1655 1656 // Increase result count. 1657 resultCount++; 1658 } 1659 1660 return resultCount; 1661} 1662 1663//----------------------------------------------------------------------------- 1664 1665S32 AssetManager::findAssetName( AssetQuery* pAssetQuery, const char* pAssetName, const bool partialName ) 1666{ 1667 // Debug Profiling. 1668 PROFILE_SCOPE(AssetManager_FindAssetName); 1669 1670 // Sanity! 1671 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1672 AssertFatal( pAssetName != NULL, "Cannot use NULL asset name." ); 1673 1674 // Reset asset name. 1675 StringTableEntry assetName = NULL; 1676 S32 partialAssetNameLength = 0; 1677 1678 // Are we doing partial name search? 1679 if ( partialName ) 1680 { 1681 // Yes, so fetch length of partial name. 1682 partialAssetNameLength = dStrlen( pAssetName ); 1683 } 1684 else 1685 { 1686 // No, so fetch asset name. 1687 assetName = StringTable->insert( pAssetName ); 1688 } 1689 1690 // Reset result count. 1691 S32 resultCount = 0; 1692 1693 // Iterate declared assets. 1694 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1695 { 1696 // Fetch asset definition. 1697 AssetDefinition* pAssetDefinition = assetItr->value; 1698 1699 // Are we doing partial name search? 1700 if ( partialName ) 1701 { 1702 // Yes, so fetch the length of this asset name. 1703 const S32 currentAssetNameLength = dStrlen( pAssetDefinition->mAssetName ); 1704 1705 // Skip if the query asset name is longer than the current asset name. 1706 if ( partialAssetNameLength > currentAssetNameLength ) 1707 continue; 1708 1709 // Skip if this is not the asset we want. 1710 if ( dStrnicmp( pAssetDefinition->mAssetName, pAssetName, partialAssetNameLength ) != 0 ) 1711 continue; 1712 } 1713 else 1714 { 1715 // No, so skip if this is not the asset we want. 1716 if ( assetName != pAssetDefinition->mAssetName ) 1717 continue; 1718 } 1719 1720 // Store as result. 1721 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1722 1723 // Increase result count. 1724 resultCount++; 1725 } 1726 1727 return resultCount; 1728} 1729 1730//----------------------------------------------------------------------------- 1731 1732S32 AssetManager::findAssetCategory( AssetQuery* pAssetQuery, const char* pAssetCategory, const bool assetQueryAsSource ) 1733{ 1734 // Debug Profiling. 1735 PROFILE_SCOPE(AssetManager_FindAssetCategory); 1736 1737 // Sanity! 1738 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1739 AssertFatal( pAssetCategory != NULL, "Cannot use NULL asset category." ); 1740 1741 // Fetch asset category. 1742 StringTableEntry assetCategory = StringTable->insert( pAssetCategory ); 1743 1744 // Reset result count. 1745 S32 resultCount = 0; 1746 1747 // Use asset-query as the source? 1748 if ( assetQueryAsSource ) 1749 { 1750 AssetQuery filteredAssets; 1751 1752 // Yes, so iterate asset query. 1753 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 1754 { 1755 // Fetch asset definition. 1756 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 1757 1758 // Skip if this is not the asset we want. 1759 if ( pAssetDefinition == NULL || 1760 pAssetDefinition->mAssetCategory != assetCategory ) 1761 continue; 1762 1763 // Store as result. 1764 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 1765 1766 // Increase result count. 1767 resultCount++; 1768 } 1769 1770 // Set asset query. 1771 pAssetQuery->set( filteredAssets ); 1772 } 1773 else 1774 { 1775 // No, so iterate declared assets. 1776 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1777 { 1778 // Fetch asset definition. 1779 AssetDefinition* pAssetDefinition = assetItr->value; 1780 1781 // Skip if this is not the asset we want. 1782 if ( assetCategory != pAssetDefinition->mAssetCategory ) 1783 continue; 1784 1785 // Store as result. 1786 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1787 1788 // Increase result count. 1789 resultCount++; 1790 } 1791 } 1792 1793 return resultCount; 1794} 1795 1796S32 AssetManager::findAssetAutoUnload( AssetQuery* pAssetQuery, const bool assetAutoUnload, const bool assetQueryAsSource ) 1797{ 1798 // Debug Profiling. 1799 PROFILE_SCOPE(AssetManager_FindAssetAutoUnload); 1800 1801 // Sanity! 1802 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1803 1804 // Reset result count. 1805 S32 resultCount = 0; 1806 1807 // Use asset-query as the source? 1808 if ( assetQueryAsSource ) 1809 { 1810 AssetQuery filteredAssets; 1811 1812 // Yes, so iterate asset query. 1813 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 1814 { 1815 // Fetch asset definition. 1816 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 1817 1818 // Skip if this is not the asset we want. 1819 if ( pAssetDefinition == NULL || 1820 pAssetDefinition->mAssetAutoUnload != assetAutoUnload ) 1821 continue; 1822 1823 // Store as result. 1824 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 1825 1826 // Increase result count. 1827 resultCount++; 1828 } 1829 1830 // Set asset query. 1831 pAssetQuery->set( filteredAssets ); 1832 } 1833 else 1834 { 1835 // No, so iterate declared assets. 1836 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1837 { 1838 // Fetch asset definition. 1839 AssetDefinition* pAssetDefinition = assetItr->value; 1840 1841 // Skip if this is not the asset we want. 1842 if ( assetAutoUnload != pAssetDefinition->mAssetAutoUnload ) 1843 continue; 1844 1845 // Store as result. 1846 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1847 1848 // Increase result count. 1849 resultCount++; 1850 } 1851 } 1852 1853 return resultCount; 1854} 1855 1856//----------------------------------------------------------------------------- 1857 1858S32 AssetManager::findAssetInternal( AssetQuery* pAssetQuery, const bool assetInternal, const bool assetQueryAsSource ) 1859{ 1860 // Debug Profiling. 1861 PROFILE_SCOPE(AssetManager_FindAssetInternal); 1862 1863 // Sanity! 1864 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1865 1866 // Reset result count. 1867 S32 resultCount = 0; 1868 1869 // Use asset-query as the source? 1870 if ( assetQueryAsSource ) 1871 { 1872 AssetQuery filteredAssets; 1873 1874 // Yes, so iterate asset query. 1875 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 1876 { 1877 // Fetch asset definition. 1878 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 1879 1880 // Skip if this is not the asset we want. 1881 if ( pAssetDefinition == NULL || 1882 pAssetDefinition->mAssetInternal != assetInternal ) 1883 continue; 1884 1885 // Store as result. 1886 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 1887 1888 // Increase result count. 1889 resultCount++; 1890 } 1891 1892 // Set asset query. 1893 pAssetQuery->set( filteredAssets ); 1894 } 1895 else 1896 { 1897 // No, so iterate declared assets. 1898 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1899 { 1900 // Fetch asset definition. 1901 AssetDefinition* pAssetDefinition = assetItr->value; 1902 1903 // Skip if this is not the asset we want. 1904 if ( assetInternal != pAssetDefinition->mAssetInternal ) 1905 continue; 1906 1907 // Store as result. 1908 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1909 1910 // Increase result count. 1911 resultCount++; 1912 } 1913 } 1914 1915 return resultCount; 1916} 1917 1918//----------------------------------------------------------------------------- 1919 1920S32 AssetManager::findAssetPrivate( AssetQuery* pAssetQuery, const bool assetPrivate, const bool assetQueryAsSource ) 1921{ 1922 // Debug Profiling. 1923 PROFILE_SCOPE(AssetManager_FindAssetPrivate); 1924 1925 // Sanity! 1926 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1927 1928 // Reset result count. 1929 S32 resultCount = 0; 1930 1931 // Use asset-query as the source? 1932 if ( assetQueryAsSource ) 1933 { 1934 AssetQuery filteredAssets; 1935 1936 // Yes, so iterate asset query. 1937 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 1938 { 1939 // Fetch asset definition. 1940 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 1941 1942 // Skip if this is not the asset we want. 1943 if ( pAssetDefinition == NULL || 1944 pAssetDefinition->mAssetPrivate != assetPrivate ) 1945 continue; 1946 1947 // Store as result. 1948 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 1949 1950 // Increase result count. 1951 resultCount++; 1952 } 1953 1954 // Set asset query. 1955 pAssetQuery->set( filteredAssets ); 1956 } 1957 else 1958 { 1959 // No, so iterate declared assets. 1960 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1961 { 1962 // Fetch asset definition. 1963 AssetDefinition* pAssetDefinition = assetItr->value; 1964 1965 // Skip if this is not the asset we want. 1966 if ( assetPrivate != pAssetDefinition->mAssetPrivate ) 1967 continue; 1968 1969 // Store as result. 1970 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1971 1972 // Increase result count. 1973 resultCount++; 1974 } 1975 } 1976 1977 return resultCount; 1978} 1979 1980//----------------------------------------------------------------------------- 1981 1982S32 AssetManager::findAssetType( AssetQuery* pAssetQuery, const char* pAssetType, const bool assetQueryAsSource ) 1983{ 1984 // Debug Profiling. 1985 PROFILE_SCOPE(AssetManager_FindAssetType); 1986 1987 // Sanity! 1988 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1989 AssertFatal( pAssetType != NULL, "Cannot use NULL asset type." ); 1990 1991 // Fetch asset type. 1992 StringTableEntry assetType = StringTable->insert( pAssetType ); 1993 1994 // Reset result count. 1995 S32 resultCount = 0; 1996 1997 // Use asset-query as the source? 1998 if ( assetQueryAsSource ) 1999 { 2000 AssetQuery filteredAssets; 2001 2002 // Yes, so iterate asset query. 2003 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 2004 { 2005 // Fetch asset definition. 2006 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 2007 2008 // Skip if this is not the asset we want. 2009 if ( pAssetDefinition == NULL || 2010 pAssetDefinition->mAssetType != assetType ) 2011 continue; 2012 2013 // Store as result. 2014 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 2015 2016 // Increase result count. 2017 resultCount++; 2018 } 2019 2020 // Set asset query. 2021 pAssetQuery->set( filteredAssets ); 2022 } 2023 else 2024 { 2025 // No, so iterate declared assets. 2026 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 2027 { 2028 // Fetch asset definition. 2029 AssetDefinition* pAssetDefinition = assetItr->value; 2030 2031 // Skip if this is not the asset we want. 2032 if ( assetType != pAssetDefinition->mAssetType ) 2033 continue; 2034 2035 // Store as result. 2036 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 2037 2038 // Increase result count. 2039 resultCount++; 2040 } 2041 } 2042 2043 return resultCount; 2044} 2045 2046//----------------------------------------------------------------------------- 2047 2048S32 AssetManager::findAssetDependsOn( AssetQuery* pAssetQuery, const char* pAssetId ) 2049{ 2050 // Debug Profiling. 2051 PROFILE_SCOPE(AssetManager_FindAssetDependsOn); 2052 2053 // Sanity! 2054 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 2055 AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." ); 2056 2057 // Fetch asset Id. 2058 StringTableEntry assetId = StringTable->insert( pAssetId ); 2059 2060 // Reset result count. 2061 S32 resultCount = 0; 2062 2063 // Find depends-on entry. 2064 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find( assetId ); 2065 2066 // Iterate all dependencies. 2067 while( dependsOnItr != mAssetDependsOn.end() && dependsOnItr->key == assetId ) 2068 { 2069 // Store as result. 2070 pAssetQuery->mAssetList.push_back(dependsOnItr->value); 2071 2072 // Next dependency. 2073 dependsOnItr++; 2074 2075 // Increase result count. 2076 resultCount++; 2077 } 2078 2079 return resultCount; 2080} 2081 2082//----------------------------------------------------------------------------- 2083 2084S32 AssetManager::findAssetIsDependedOn( AssetQuery* pAssetQuery, const char* pAssetId ) 2085{ 2086 // Debug Profiling. 2087 PROFILE_SCOPE(AssetManager_FindAssetIsDependedOn); 2088 2089 // Sanity! 2090 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 2091 AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." ); 2092 2093 // Fetch asset Id. 2094 StringTableEntry assetId = StringTable->insert( pAssetId ); 2095 2096 // Reset result count. 2097 S32 resultCount = 0; 2098 2099 // Find depended-on entry. 2100 typeAssetIsDependedOnHash::Iterator dependedOnItr = mAssetIsDependedOn.find( assetId ); 2101 2102 // Iterate all dependencies. 2103 while( dependedOnItr != mAssetIsDependedOn.end() && dependedOnItr->key == assetId ) 2104 { 2105 // Store as result. 2106 pAssetQuery->mAssetList.push_back(dependedOnItr->value); 2107 2108 // Next dependency. 2109 dependedOnItr++; 2110 2111 // Increase result count. 2112 resultCount++; 2113 } 2114 2115 return resultCount; 2116} 2117 2118//----------------------------------------------------------------------------- 2119 2120S32 AssetManager::findInvalidAssetReferences( AssetQuery* pAssetQuery ) 2121{ 2122 // Debug Profiling. 2123 PROFILE_SCOPE(AssetManager_FindInvalidAssetReferences); 2124 2125 // Sanity! 2126 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 2127 2128 // Reset result count. 2129 S32 resultCount = 0; 2130 2131 // Iterate referenced assets. 2132 for( typeReferencedAssetsHash::Iterator assetItr = mReferencedAssets.begin(); assetItr != mReferencedAssets.end(); ++assetItr ) 2133 { 2134 // Find asset definition. 2135 AssetDefinition* pAssetDefinition = findAsset( assetItr->key ); 2136 2137 // Skip if the asset definition was found. 2138 if ( pAssetDefinition != NULL ) 2139 continue; 2140 2141 // Store as result. 2142 pAssetQuery->mAssetList.push_back(assetItr->key); 2143 2144 // Increase result count. 2145 resultCount++; 2146 } 2147 2148 return resultCount; 2149} 2150 2151//----------------------------------------------------------------------------- 2152 2153S32 AssetManager::findTaggedAssets( AssetQuery* pAssetQuery, const char* pAssetTagNames, const bool assetQueryAsSource ) 2154{ 2155 // Debug Profiling. 2156 PROFILE_SCOPE(AssetManager_FindTaggedAssets); 2157 2158 // Sanity! 2159 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 2160 AssertFatal( pAssetTagNames != NULL, "Cannot use NULL asset tag name(s)." ); 2161 2162 // Do we have an asset tag manifest? 2163 if ( mAssetTagsManifest.isNull() ) 2164 { 2165 // No, so warn. 2166 Con::warnf( "Asset Manager: Cannot find tagged assets as no asset tag manifest is present." ); 2167 return 0; 2168 } 2169 2170 // Reset result count. 2171 S32 resultCount = 0; 2172 2173 const char* pTagSeparators = " ,\t\n"; 2174 2175 // Fetch tag count. 2176 U32 assetTagCount = StringUnit::getUnitCount( pAssetTagNames, pTagSeparators ); 2177 2178 // Fetch asset tags. 2179 Vector<AssetTagsManifest::AssetTag*> assetTags; 2180 for( U32 tagIndex = 0; tagIndex < assetTagCount; ++tagIndex ) 2181 { 2182 // Fetch asset tag name. 2183 const char* pTagName = StringUnit::getUnit( pAssetTagNames, tagIndex, pTagSeparators ); 2184 2185 // Fetch asset tag. 2186 AssetTagsManifest::AssetTag* pAssetTag = mAssetTagsManifest->findAssetTag( pTagName ); 2187 2188 // Did we find the asset tag? 2189 if ( pAssetTag == NULL ) 2190 { 2191 // No, so warn. 2192 Con::warnf( "AssetTagsManifest: Asset Manager: Cannot find tagged assets of '%s' as it does not exist. Ignoring tag.", pTagName ); 2193 continue; 2194 } 2195 2196 assetTags.push_back( pAssetTag ); 2197 } 2198 2199 // Fetch found asset tag count. 2200 assetTagCount = assetTags.size(); 2201 2202 // Did we find any tags? 2203 if ( assetTagCount == 0 ) 2204 { 2205 // No, so warn. 2206 Con::warnf( "AssetTagsManifest: Asset Manager: No specified tagged assets found in '%s'.", pAssetTagNames ); 2207 return 0; 2208 } 2209 2210 // Use asset-query as the source? 2211 if ( assetQueryAsSource ) 2212 { 2213 AssetQuery filteredAssets; 2214 2215 // Yes, so iterate asset query. 2216 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 2217 { 2218 // Fetch asset Id. 2219 StringTableEntry assetId = *assetItr; 2220 2221 // Skip if asset is not valid. 2222 if ( !isDeclaredAsset( assetId ) ) 2223 continue; 2224 2225 // Reset matched flag. 2226 bool assetTagMatched = false; 2227 2228 // Iterate asset tags. 2229 for ( Vector<AssetTagsManifest::AssetTag*>::iterator assetTagItr = assetTags.begin(); assetTagItr != assetTags.end(); ++assetTagItr ) 2230 { 2231 // Fetch asset tag. 2232 AssetTagsManifest::AssetTag* pAssetTag = *assetTagItr; 2233 2234 // Skip if asset is not tagged. 2235 if ( !pAssetTag->containsAsset( assetId ) ) 2236 continue; 2237 2238 // Flag as matched. 2239 assetTagMatched = true; 2240 break; 2241 } 2242 2243 // Did we find a match? 2244 if ( assetTagMatched ) 2245 { 2246 // Yes, so is asset already present? 2247 if ( !filteredAssets.containsAsset( assetId ) ) 2248 { 2249 // No, so store as result. 2250 filteredAssets.mAssetList.push_back(assetId); 2251 2252 // Increase result count. 2253 resultCount++; 2254 } 2255 } 2256 } 2257 2258 // Set asset query. 2259 pAssetQuery->set( filteredAssets ); 2260 } 2261 else 2262 { 2263 // Iterate asset tags. 2264 for ( Vector<AssetTagsManifest::AssetTag*>::iterator assetTagItr = assetTags.begin(); assetTagItr != assetTags.end(); ++assetTagItr ) 2265 { 2266 // Fetch asset tag. 2267 AssetTagsManifest::AssetTag* pAssetTag = *assetTagItr; 2268 2269 // Iterate tagged assets. 2270 for ( Vector<typeAssetId>::iterator assetItr = pAssetTag->mAssets.begin(); assetItr != pAssetTag->mAssets.end(); ++assetItr ) 2271 { 2272 // Fetch asset Id. 2273 StringTableEntry assetId = *assetItr; 2274 2275 // Skip if asset Id is already present. 2276 if ( pAssetQuery->containsAsset( assetId ) ) 2277 continue; 2278 2279 // Store as result. 2280 pAssetQuery->mAssetList.push_back(assetId); 2281 2282 // Increase result count. 2283 resultCount++; 2284 } 2285 } 2286 } 2287 2288 return resultCount; 2289} 2290 2291//----------------------------------------------------------------------------- 2292 2293S32 AssetManager::findAssetLooseFile( AssetQuery* pAssetQuery, const char* pLooseFile, const bool assetQueryAsSource ) 2294{ 2295 // Debug Profiling. 2296 PROFILE_SCOPE(AssetManager_FindAssetLooseFile); 2297 2298 // Sanity! 2299 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 2300 AssertFatal( pLooseFile != NULL, "Cannot use NULL loose file." ); 2301 2302 // Expand loose file. 2303 char looseFileBuffer[1024]; 2304 Con::expandPath(looseFileBuffer, sizeof(looseFileBuffer), pLooseFile, NULL, false ); 2305 2306 // Fetch asset loose file. 2307 StringTableEntry looseFile = StringTable->insert( looseFileBuffer ); 2308 2309 // Reset result count. 2310 S32 resultCount = 0; 2311 2312 // Use asset-query as the source? 2313 if ( assetQueryAsSource ) 2314 { 2315 AssetQuery filteredAssets; 2316 2317 // Yes, so iterate asset query. 2318 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 2319 { 2320 // Fetch asset definition. 2321 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 2322 2323 // Fetch loose files. 2324 Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles; 2325 2326 // Skip if this asset has no loose files. 2327 if ( assetLooseFiles.size() == 0 ) 2328 continue; 2329 2330 // Search the assets loose files. 2331 for( Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr ) 2332 { 2333 // Is this the loose file we are searching for? 2334 if ( *looseFileItr != looseFile ) 2335 continue; 2336 2337 // Store as result. 2338 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 2339 2340 // Increase result count. 2341 resultCount++; 2342 2343 break; 2344 } 2345 } 2346 2347 // Set asset query. 2348 pAssetQuery->set( filteredAssets ); 2349 } 2350 else 2351 { 2352 // No, so iterate declared assets. 2353 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 2354 { 2355 // Fetch asset definition. 2356 AssetDefinition* pAssetDefinition = assetItr->value; 2357 2358 // Fetch loose files. 2359 Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles; 2360 2361 // Skip if this asset has no loose files. 2362 if ( assetLooseFiles.size() == 0 ) 2363 continue; 2364 2365 // Search the assets loose files. 2366 for( Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr ) 2367 { 2368 // Is this the loose file we are searching for? 2369 if ( *looseFileItr != looseFile ) 2370 continue; 2371 2372 // Store as result. 2373 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 2374 2375 // Increase result count. 2376 resultCount++; 2377 2378 break; 2379 } 2380 } 2381 } 2382 2383 return resultCount; 2384} 2385 2386//----------------------------------------------------------------------------- 2387 2388AssetManager::typeAssetDependsOnHash* AssetManager::getDependedOnAssets() 2389{ 2390 // Find any asset dependencies. 2391 return &mAssetDependsOn; 2392} 2393//----------------------------------------------------------------------------- 2394 2395bool AssetManager::scanDeclaredAssets( const char* pPath, const char* pExtension, const bool recurse, ModuleDefinition* pModuleDefinition ) 2396{ 2397 // Debug Profiling. 2398 PROFILE_SCOPE(AssetManager_ScanDeclaredAssets); 2399 2400 // Sanity! 2401 AssertFatal( pPath != NULL, "Cannot scan declared assets with NULL path." ); 2402 AssertFatal( pExtension != NULL, "Cannot scan declared assets with NULL extension." ); 2403 2404 // Expand path location. 2405 char pathBuffer[1024]; 2406 Con::expandPath( pathBuffer, sizeof(pathBuffer), pPath ); 2407 2408 // Find files. 2409 Vector<Platform::FileInfo> files; 2410 if ( !Platform::dumpPath( pathBuffer, files, recurse ? -1 : 0 ) ) 2411 { 2412 // Failed so warn. 2413 Con::warnf( "Asset Manager: Failed to scan declared assets in directory '%s'.", pathBuffer ); 2414 return false; 2415 } 2416 2417 // Is the asset file-path located within the specified module? 2418 if ( !Con::isBasePath( pathBuffer, pModuleDefinition->getModulePath() ) ) 2419 { 2420 // No, so warn. 2421 Con::warnf( "Asset Manager: Could not add declared asset file '%s' as file does not exist with module path '%s'", 2422 pathBuffer, 2423 pModuleDefinition->getModulePath() ); 2424 return false; 2425 } 2426 2427 // Info. 2428 if ( mEchoInfo ) 2429 { 2430 Con::printSeparator(); 2431 Con::printf( "Asset Manager: Scanning for declared assets in path '%s' for files with extension '%s'...", pathBuffer, pExtension ); 2432 } 2433 2434 // Fetch extension length. 2435 const U32 extensionLength = dStrlen( pExtension ); 2436 2437 // Fetch module assets. 2438 ModuleDefinition::typeModuleAssetsVector& moduleAssets = pModuleDefinition->getModuleAssets(); 2439 2440 TamlAssetDeclaredVisitor assetDeclaredVisitor; 2441 2442 // Iterate files. 2443 for ( Vector<Platform::FileInfo>::iterator fileItr = files.begin(); fileItr != files.end(); ++fileItr ) 2444 { 2445 // Fetch file info. 2446 Platform::FileInfo& fileInfo = *fileItr; 2447 2448 // Fetch filename. 2449 const char* pFilename = fileInfo.pFileName; 2450 2451 // Find filename length. 2452 const U32 filenameLength = dStrlen( pFilename ); 2453 2454 // Skip if extension is longer than filename. 2455 if ( extensionLength > filenameLength ) 2456 continue; 2457 2458 // Skip if extension not found. 2459 if ( dStricmp( pFilename + filenameLength - extensionLength, pExtension ) != 0 ) 2460 continue; 2461 2462 // Clear declared assets. 2463 assetDeclaredVisitor.clear(); 2464 2465 // Format full file-path. 2466 char assetFileBuffer[1024]; 2467 dSprintf( assetFileBuffer, sizeof(assetFileBuffer), "%s/%s", fileInfo.pFullPath, fileInfo.pFileName ); 2468 2469 // Parse the filename. 2470 if ( !mTaml.parse( assetFileBuffer, assetDeclaredVisitor ) ) 2471 { 2472 // Warn. 2473 Con::warnf( "Asset Manager: Failed to parse file containing asset declaration: '%s'.", assetFileBuffer ); 2474 continue; 2475 } 2476 2477 // Fetch asset definition. 2478 AssetDefinition& foundAssetDefinition = assetDeclaredVisitor.getAssetDefinition(); 2479 2480 // Did we get an asset name? 2481 if ( foundAssetDefinition.mAssetName == StringTable->EmptyString() ) 2482 { 2483 // No, so warn. 2484 Con::warnf( "Asset Manager: Parsed file '%s' but did not encounter an asset.", assetFileBuffer ); 2485 continue; 2486 } 2487 2488 // Set module definition. 2489 foundAssetDefinition.mpModuleDefinition = pModuleDefinition; 2490 2491 // Format asset Id. 2492 char assetIdBuffer[1024]; 2493 dSprintf(assetIdBuffer, sizeof(assetIdBuffer), "%s%s%s", 2494 pModuleDefinition->getModuleId(), 2495 ASSET_SCOPE_TOKEN, 2496 foundAssetDefinition.mAssetName ); 2497 2498 // Set asset Id. 2499 foundAssetDefinition.mAssetId = StringTable->insert( assetIdBuffer ); 2500 2501 // Does this asset already exist? 2502 if ( mDeclaredAssets.contains( foundAssetDefinition.mAssetId ) ) 2503 { 2504 // Yes, so warn. 2505 Con::warnf( "Asset Manager: Encountered asset Id '%s' in asset file '%s' but it conflicts with existing asset Id in asset file '%s'.", 2506 foundAssetDefinition.mAssetId, 2507 foundAssetDefinition.mAssetBaseFilePath, 2508 mDeclaredAssets.find( foundAssetDefinition.mAssetId )->value->mAssetBaseFilePath ); 2509 2510 continue; 2511 } 2512 2513 // Create new asset definition. 2514 AssetDefinition* pAssetDefinition = new AssetDefinition( foundAssetDefinition ); 2515 2516 // Store in declared assets. 2517 mDeclaredAssets.insert( pAssetDefinition->mAssetId, pAssetDefinition ); 2518 2519 // Store in module assets. 2520 moduleAssets.push_back( pAssetDefinition ); 2521 2522 // Info. 2523 if ( mEchoInfo ) 2524 { 2525 Con::printSeparator(); 2526 Con::printf( "Asset Manager: Adding Asset Id '%s' of type '%s' in asset file '%s'.", 2527 pAssetDefinition->mAssetId, 2528 pAssetDefinition->mAssetType, 2529 pAssetDefinition->mAssetBaseFilePath ); 2530 } 2531 2532 // Fetch asset Id. 2533 StringTableEntry assetId = pAssetDefinition->mAssetId; 2534 2535 // Fetch asset dependencies. 2536 TamlAssetDeclaredVisitor::typeAssetIdVector& assetDependencies = assetDeclaredVisitor.getAssetDependencies(); 2537 2538 // Are there any asset dependencies? 2539 if ( assetDependencies.size() > 0 ) 2540 { 2541 // Yes, so iterate dependencies. 2542 for( TamlAssetDeclaredVisitor::typeAssetIdVector::iterator assetDependencyItr = assetDependencies.begin(); assetDependencyItr != assetDependencies.end(); ++assetDependencyItr ) 2543 { 2544 // Fetch asset Ids. 2545 StringTableEntry dependencyAssetId = *assetDependencyItr; 2546 2547 // Insert depends-on. 2548 mAssetDependsOn.insertEqual( assetId, dependencyAssetId ); 2549 2550 // Insert is-depended-on. 2551 mAssetIsDependedOn.insertEqual( dependencyAssetId, assetId ); 2552 2553 // Info. 2554 if ( mEchoInfo ) 2555 { 2556 Con::printf( "Asset Manager: Asset Id '%s' has dependency of Asset Id '%s'", assetId, dependencyAssetId ); 2557 } 2558 } 2559 } 2560 2561 // Fetch asset loose files. 2562 TamlAssetDeclaredVisitor::typeLooseFileVector& assetLooseFiles = assetDeclaredVisitor.getAssetLooseFiles(); 2563 2564 // Are there any loose files? 2565 if ( assetLooseFiles.size() > 0 ) 2566 { 2567 // Yes, so iterate loose files. 2568 for( TamlAssetDeclaredVisitor::typeLooseFileVector::iterator assetLooseFileItr = assetLooseFiles.begin(); assetLooseFileItr != assetLooseFiles.end(); ++assetLooseFileItr ) 2569 { 2570 // Fetch loose file. 2571 StringTableEntry looseFile = *assetLooseFileItr; 2572 2573 // Info. 2574 if ( mEchoInfo ) 2575 { 2576 Con::printf( "Asset Manager: Asset Id '%s' has loose file '%s'.", assetId, looseFile ); 2577 } 2578 2579 // Store loose file. 2580 pAssetDefinition->mAssetLooseFiles.push_back( looseFile ); 2581 } 2582 } 2583 } 2584 2585 // Info. 2586 if ( mEchoInfo ) 2587 { 2588 Con::printSeparator(); 2589 Con::printf( "Asset Manager: ... Finished scanning for declared assets in path '%s' for files with extension '%s'.", pathBuffer, pExtension ); 2590 Con::printSeparator(); 2591 Con::printBlankLine(); 2592 } 2593 2594 return true; 2595} 2596 2597//----------------------------------------------------------------------------- 2598 2599bool AssetManager::scanReferencedAssets( const char* pPath, const char* pExtension, const bool recurse ) 2600{ 2601 // Debug Profiling. 2602 PROFILE_SCOPE(AssetManager_ScanReferencedAssets); 2603 2604 // Sanity! 2605 AssertFatal( pPath != NULL, "Cannot scan referenced assets with NULL path." ); 2606 AssertFatal( pExtension != NULL, "Cannot scan referenced assets with NULL extension." ); 2607 2608 // Expand path location. 2609 char pathBuffer[1024]; 2610 Con::expandPath( pathBuffer, sizeof(pathBuffer), pPath ); 2611 2612 // Find files. 2613 Vector<Platform::FileInfo> files; 2614 if ( !Platform::dumpPath( pathBuffer, files, recurse ? -1 : 0 ) ) 2615 { 2616 // Failed so warn. 2617 Con::warnf( "Asset Manager: Failed to scan referenced assets in directory '%s'.", pathBuffer ); 2618 return false; 2619 } 2620 2621 // Info. 2622 if ( mEchoInfo ) 2623 { 2624 Con::printSeparator(); 2625 Con::printf( "Asset Manager: Scanning for referenced assets in path '%s' for files with extension '%s'...", pathBuffer, pExtension ); 2626 } 2627 2628 // Fetch extension length. 2629 const U32 extensionLength = dStrlen( pExtension ); 2630 2631 TamlAssetReferencedVisitor assetReferencedVisitor; 2632 2633 // Iterate files. 2634 for ( Vector<Platform::FileInfo>::iterator fileItr = files.begin(); fileItr != files.end(); ++fileItr ) 2635 { 2636 // Fetch file info. 2637 Platform::FileInfo& fileInfo = *fileItr; 2638 2639 // Fetch filename. 2640 const char* pFilename = fileInfo.pFileName; 2641 2642 // Find filename length. 2643 const U32 filenameLength = dStrlen( pFilename ); 2644 2645 // Skip if extension is longer than filename. 2646 if ( extensionLength > filenameLength ) 2647 continue; 2648 2649 // Skip if extension not found. 2650 if ( dStricmp( pFilename + filenameLength - extensionLength, pExtension ) != 0 ) 2651 continue; 2652 2653 // Clear referenced assets. 2654 assetReferencedVisitor.clear(); 2655 2656 // Format full file-path. 2657 char assetFileBuffer[1024]; 2658 dSprintf( assetFileBuffer, sizeof(assetFileBuffer), "%s/%s", fileInfo.pFullPath, fileInfo.pFileName ); 2659 2660 // Format reference file-path. 2661 typeReferenceFilePath referenceFilePath = StringTable->insert( assetFileBuffer ); 2662 2663 // Parse the filename. 2664 if ( !mTaml.parse( referenceFilePath, assetReferencedVisitor ) ) 2665 { 2666 // Warn. 2667 Con::warnf( "Asset Manager: Failed to parse file containing asset references: '%s'.", referenceFilePath ); 2668 continue; 2669 } 2670 2671 // Fetch usage map. 2672 const TamlAssetReferencedVisitor::typeAssetReferencedHash& assetReferencedMap = assetReferencedVisitor.getAssetReferencedMap(); 2673 2674 // Do we have any asset references? 2675 if ( assetReferencedMap.size() > 0 ) 2676 { 2677 // Info. 2678 if ( mEchoInfo ) 2679 { 2680 Con::printSeparator(); 2681 } 2682 2683 // Iterate usage. 2684 for( TamlAssetReferencedVisitor::typeAssetReferencedHash::const_iterator usageItr = assetReferencedMap.begin(); usageItr != assetReferencedMap.end(); ++usageItr ) 2685 { 2686 // Fetch asset name. 2687 typeAssetId assetId = usageItr->key; 2688 2689 // Info. 2690 if ( mEchoInfo ) 2691 { 2692 Con::printf( "Asset Manager: Found referenced Asset Id '%s' in file '%s'.", assetId, referenceFilePath ); 2693 } 2694 2695 // Add referenced asset. 2696 addReferencedAsset( assetId, referenceFilePath ); 2697 } 2698 } 2699 } 2700 2701 // Info. 2702 if ( mEchoInfo ) 2703 { 2704 Con::printf( "Asset Manager: ... Finished scanning for referenced assets in path '%s' for files with extension '%s'.", pathBuffer, pExtension ); 2705 Con::printSeparator(); 2706 Con::printBlankLine(); 2707 } 2708 2709 return true; 2710} 2711 2712//----------------------------------------------------------------------------- 2713 2714AssetDefinition* AssetManager::findAsset( const char* pAssetId ) 2715{ 2716 // Debug Profiling. 2717 PROFILE_SCOPE(AssetManager_FindAsset); 2718 2719 // Sanity! 2720 AssertFatal( pAssetId != NULL, "Cannot find NULL asset Id." ); 2721 2722 // Fetch asset Id. 2723 StringTableEntry assetId = StringTable->insert( pAssetId ); 2724 2725 // Find declared asset. 2726 typeDeclaredAssetsHash::iterator declaredAssetItr = mDeclaredAssets.find( assetId ); 2727 2728 // Find if we didn't find a declared asset Id. 2729 if ( declaredAssetItr == mDeclaredAssets.end() ) 2730 return NULL; 2731 2732 return declaredAssetItr->value; 2733} 2734 2735//----------------------------------------------------------------------------- 2736 2737void AssetManager::addReferencedAsset( StringTableEntry assetId, StringTableEntry referenceFilePath ) 2738{ 2739 // Debug Profiling. 2740 PROFILE_SCOPE(AssetManager_AddReferencedAsset); 2741 2742 // Sanity! 2743 AssertFatal( assetId != NULL, "Cannot add referenced asset with NULL asset Id." ); 2744 AssertFatal( referenceFilePath != NULL, "Cannot add referenced asset with NULL reference file-path." ); 2745 2746 // Find referenced asset. 2747 typeReferencedAssetsHash::Iterator referencedAssetItr = mReferencedAssets.find( assetId ); 2748 2749 // Did we find the asset? 2750 if ( referencedAssetItr == mReferencedAssets.end() ) 2751 { 2752 // No, so add asset Id. 2753 mReferencedAssets.insertEqual( assetId, referenceFilePath ); 2754 } 2755 else 2756 { 2757 // Yes, so add asset Id with a unique file. 2758 while( true ) 2759 { 2760 // Finish if this file is already present. 2761 if ( referencedAssetItr->value == referenceFilePath ) 2762 return; 2763 2764 // Move to next asset Id. 2765 referencedAssetItr++; 2766 2767 // Is this the end of referenced assets or a different asset Id? 2768 if ( referencedAssetItr == mReferencedAssets.end() || 2769 referencedAssetItr->key != assetId ) 2770 { 2771 // Yes, so add asset reference. 2772 mReferencedAssets.insertEqual( assetId, referenceFilePath ); 2773 return; 2774 } 2775 }; 2776 } 2777} 2778 2779//----------------------------------------------------------------------------- 2780 2781void AssetManager::renameAssetReferences( StringTableEntry assetIdFrom, StringTableEntry assetIdTo ) 2782{ 2783 // Debug Profiling. 2784 PROFILE_SCOPE(AssetManager_RenameAssetReferences); 2785 2786 // Sanity! 2787 AssertFatal( assetIdFrom != NULL, "Cannot rename asset references using NULL asset Id from." ); 2788 AssertFatal( assetIdTo != NULL, "Cannot rename asset references using NULL asset Id to." ); 2789 2790 // Finish if the asset is not referenced. 2791 if ( !mReferencedAssets.count( assetIdFrom ) ) 2792 return; 2793 2794 // Setup referenced update visitor. 2795 TamlAssetReferencedUpdateVisitor assetReferencedUpdateVisitor; 2796 assetReferencedUpdateVisitor.setAssetIdFrom( assetIdFrom ); 2797 assetReferencedUpdateVisitor.setAssetIdTo( assetIdTo ); 2798 2799 // Find first referenced asset Id. 2800 typeReferencedAssetsHash::Iterator referencedAssetItr = mReferencedAssets.find( assetIdFrom ); 2801 2802 // Iterate references. 2803 while( true ) 2804 { 2805 // Finish if end of references. 2806 if ( referencedAssetItr == mReferencedAssets.end() || referencedAssetItr->key != assetIdFrom ) 2807 return; 2808 2809 // Info. 2810 if ( mEchoInfo ) 2811 { 2812 Con::printf( "Asset Manager: Renaming declared Asset Id '%s' to Asset Id '%s'. Updating referenced file '%s'", 2813 assetIdFrom, 2814 assetIdTo, 2815 referencedAssetItr->value ); 2816 } 2817 2818 // Update asset file declaration. 2819 if ( !mTaml.parse( referencedAssetItr->value, assetReferencedUpdateVisitor ) ) 2820 { 2821 // No, so warn. 2822 Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as the referenced asset file could not be parsed: %s", 2823 assetIdFrom, assetIdTo, referencedAssetItr->value ); 2824 } 2825 2826 // Move to next reference. 2827 referencedAssetItr++; 2828 } 2829} 2830 2831//----------------------------------------------------------------------------- 2832 2833void AssetManager::removeAssetReferences( StringTableEntry assetId ) 2834{ 2835 // Debug Profiling. 2836 PROFILE_SCOPE(AssetManager_RemoveAssetReferences); 2837 2838 // Sanity! 2839 AssertFatal( assetId != NULL, "Cannot rename asset references using NULL asset Id." ); 2840 2841 // Finish if the asset is not referenced. 2842 if ( !mReferencedAssets.count( assetId ) ) 2843 return; 2844 2845 // Setup referenced update visitor. 2846 TamlAssetReferencedUpdateVisitor assetReferencedUpdateVisitor; 2847 assetReferencedUpdateVisitor.setAssetIdFrom( assetId ); 2848 assetReferencedUpdateVisitor.setAssetIdTo( StringTable->EmptyString() ); 2849 2850 // Find first referenced asset Id. 2851 typeReferencedAssetsHash::Iterator referencedAssetItr = mReferencedAssets.find(assetId); 2852 2853 // Iterate references. 2854 while( true ) 2855 { 2856 // Finish if end of references. 2857 if ( referencedAssetItr == mReferencedAssets.end() || referencedAssetItr->key != assetId ) 2858 break; 2859 2860 // Info. 2861 if ( mEchoInfo ) 2862 { 2863 Con::printf( "Asset Manager: Removing Asset Id '%s' references from file '%s'", 2864 assetId, 2865 referencedAssetItr->value ); 2866 } 2867 2868 // Update asset file declaration. 2869 if ( !mTaml.parse( referencedAssetItr->value, assetReferencedUpdateVisitor ) ) 2870 { 2871 // No, so warn. 2872 Con::warnf("Asset Manager: Cannot remove referenced asset Id '%s' as the referenced asset file could not be parsed: %s", 2873 assetId, 2874 referencedAssetItr->value ); 2875 } 2876 2877 // Move to next reference. 2878 referencedAssetItr++; 2879 } 2880 2881 // Remove asset references. 2882 mReferencedAssets.erase( assetId ); 2883} 2884 2885//----------------------------------------------------------------------------- 2886 2887void AssetManager::renameAssetDependencies( StringTableEntry assetIdFrom, StringTableEntry assetIdTo ) 2888{ 2889 // Debug Profiling. 2890 PROFILE_SCOPE(AssetManager_RenameAssetDependencies); 2891 2892 // Sanity! 2893 AssertFatal( assetIdFrom != NULL, "Cannot rename asset dependencies using NULL asset Id from." ); 2894 AssertFatal( assetIdTo != NULL, "Cannot rename asset dependencies using NULL asset Id to." ); 2895 2896 // Rename via depends-on... 2897 while( mAssetDependsOn.count( assetIdFrom ) > 0 ) 2898 { 2899 // Find depends-on. 2900 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find(assetIdFrom); 2901 2902 // Fetch dependency asset Id. 2903 StringTableEntry dependencyAssetId = dependsOnItr->value; 2904 2905 // Find is-depends-on entry. 2906 typeAssetIsDependedOnHash::Iterator isDependedOnItr = mAssetIsDependedOn.find(dependencyAssetId); 2907 2908 // Sanity! 2909 AssertFatal( isDependedOnItr != mAssetIsDependedOn.end(), "Asset dependencies are corrupt!" ); 2910 2911 while( isDependedOnItr != mAssetIsDependedOn.end() && isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value != assetIdFrom ) 2912 { 2913 isDependedOnItr++; 2914 } 2915 2916 // Sanity! 2917 AssertFatal( isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value == assetIdFrom, "Asset dependencies are corrupt!" ); 2918 2919 // Remove is-depended-on. 2920 mAssetIsDependedOn.erase( isDependedOnItr ); 2921 2922 // Remove depends-on. 2923 mAssetDependsOn.erase( dependsOnItr ); 2924 2925 // Insert depends-on. 2926 mAssetDependsOn.insertEqual( assetIdTo, dependencyAssetId ); 2927 2928 // Insert is-depended-on. 2929 mAssetIsDependedOn.insertEqual( dependencyAssetId, assetIdTo ); 2930 } 2931 2932 // Rename via is-depended-on... 2933 while( mAssetIsDependedOn.count( assetIdFrom ) > 0 ) 2934 { 2935 // Find is-depended-on. 2936 typeAssetIsDependedOnHash::Iterator isdependedOnItr = mAssetIsDependedOn.find(assetIdFrom); 2937 2938 // Fetch dependency asset Id. 2939 StringTableEntry dependencyAssetId = isdependedOnItr->value; 2940 2941 // Find depends-on entry. 2942 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find(dependencyAssetId); 2943 2944 // Sanity! 2945 AssertFatal( dependsOnItr != mAssetDependsOn.end(), "Asset dependencies are corrupt!" ); 2946 2947 while( dependsOnItr != mAssetDependsOn.end() && dependsOnItr->key == dependencyAssetId && dependsOnItr->value != assetIdFrom ) 2948 { 2949 dependsOnItr++; 2950 } 2951 2952 // Sanity! 2953 AssertFatal( dependsOnItr->key == dependencyAssetId && dependsOnItr->value == assetIdFrom, "Asset dependencies are corrupt!" ); 2954 2955 // Remove is-depended-on. 2956 mAssetIsDependedOn.erase( isdependedOnItr ); 2957 2958 // Remove depends-on. 2959 mAssetDependsOn.erase( dependsOnItr ); 2960 2961 // Insert depends-on. 2962 mAssetDependsOn.insertEqual( dependencyAssetId, assetIdTo ); 2963 2964 // Insert is-depended-on. 2965 mAssetIsDependedOn.insertEqual( assetIdTo, dependencyAssetId ); 2966 } 2967} 2968 2969//----------------------------------------------------------------------------- 2970 2971void AssetManager::removeAssetDependencies( const char* pAssetId ) 2972{ 2973 // Debug Profiling. 2974 PROFILE_SCOPE(AssetManager_RemvoeAsetDependencies); 2975 2976 // Sanity! 2977 AssertFatal( pAssetId != NULL, "Cannot remove asset dependencies using NULL asset Id." ); 2978 2979 // Fetch asset Id. 2980 StringTableEntry assetId = StringTable->insert( pAssetId ); 2981 2982 // Remove from depends-on assets. 2983 while( mAssetDependsOn.count( assetId ) > 0 ) 2984 { 2985 // Find depends-on. 2986 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find(assetId); 2987 2988 // Fetch dependency asset Id. 2989 StringTableEntry dependencyAssetId = dependsOnItr->value; 2990 2991 // Find is-depends-on entry. 2992 typeAssetIsDependedOnHash::Iterator isDependedOnItr = mAssetIsDependedOn.find(dependencyAssetId); 2993 2994 // Sanity! 2995 AssertFatal( isDependedOnItr != mAssetIsDependedOn.end(), "Asset dependencies are corrupt!" ); 2996 2997 while( isDependedOnItr != mAssetIsDependedOn.end() && isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value != assetId ) 2998 { 2999 isDependedOnItr++; 3000 } 3001 3002 // Sanity! 3003 AssertFatal( isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value == assetId, "Asset dependencies are corrupt!" ); 3004 3005 // Remove is-depended-on. 3006 mAssetIsDependedOn.erase( isDependedOnItr ); 3007 3008 // Remove depends-on. 3009 mAssetDependsOn.erase( dependsOnItr ); 3010 } 3011} 3012 3013//----------------------------------------------------------------------------- 3014 3015void AssetManager::unloadAsset( AssetDefinition* pAssetDefinition ) 3016{ 3017 // Debug Profiling. 3018 PROFILE_SCOPE(AssetManager_UnloadAsset); 3019 3020 // Destroy the asset. 3021 pAssetDefinition->mpAssetBase->deleteObject(); 3022 3023 // Increase unloaded count. 3024 pAssetDefinition->mAssetUnloadedCount++; 3025 3026 // Is the asset internal? 3027 if ( pAssetDefinition->mAssetInternal ) 3028 { 3029 // Yes, so decrease internal loaded asset count. 3030 mLoadedInternalAssetsCount--; 3031 } 3032 else 3033 { 3034 // No, so decrease external loaded assets count. 3035 mLoadedExternalAssetsCount--; 3036 } 3037 3038 // Is the asset private? 3039 if ( pAssetDefinition->mAssetPrivate ) 3040 { 3041 // Yes, so decrease private loaded asset count. 3042 mLoadedPrivateAssetsCount--; 3043 3044 // Remove it completely. 3045 removeDeclaredAsset( pAssetDefinition->mAssetId ); 3046 } 3047} 3048 3049//----------------------------------------------------------------------------- 3050 3051void AssetManager::onModulePreLoad( ModuleDefinition* pModuleDefinition ) 3052{ 3053 // Debug Profiling. 3054 PROFILE_SCOPE(AssetManager_OnModulePreLoad); 3055 3056 // Add module declared assets. 3057 addModuleDeclaredAssets( pModuleDefinition ); 3058 3059 // Load any auto-loaded asset types 3060 loadModuleAutoLoadAssets(pModuleDefinition); 3061 3062 // Is an asset tags manifest specified? 3063 if ( pModuleDefinition->getAssetTagsManifest() != StringTable->EmptyString() ) 3064 { 3065 // Yes, so load the asset tags manifest. 3066 loadAssetTags( pModuleDefinition ); 3067 } 3068} 3069 3070//----------------------------------------------------------------------------- 3071 3072void AssetManager::onModulePreUnload( ModuleDefinition* pModuleDefinition ) 3073{ 3074 // Debug Profiling. 3075 PROFILE_SCOPE(AssetManager_OnModulePreUnload); 3076 3077 // Is an asset tags manifest specified? 3078 if ( pModuleDefinition->getAssetTagsManifest() != StringTable->EmptyString() ) 3079 { 3080 // Yes, so save the asset tags manifest. 3081 saveAssetTags(); 3082 3083 // Do we have an asset tags manifest? 3084 if ( !mAssetTagsManifest.isNull() ) 3085 { 3086 // Yes, so remove it. 3087 mAssetTagsManifest->deleteObject(); 3088 mAssetTagsModuleDefinition = NULL; 3089 } 3090 } 3091} 3092 3093//----------------------------------------------------------------------------- 3094 3095void AssetManager::onModulePostUnload( ModuleDefinition* pModuleDefinition ) 3096{ 3097 // Debug Profiling. 3098 PROFILE_SCOPE(AssetManager_OnModulePostUnload); 3099 3100 // Remove declared assets. 3101 removeDeclaredAssets( pModuleDefinition ); 3102} 3103