mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
3346 lines
108 KiB
C++
3346 lines
108 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2013 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "assetManager.h"
|
|
|
|
#ifndef _ASSET_PTR_H_
|
|
#include "assetPtr.h"
|
|
#endif
|
|
|
|
#ifndef _REFERENCED_ASSETS_H_
|
|
#include "assets/referencedAssets.h"
|
|
#endif
|
|
|
|
#ifndef _DECLARED_ASSETS_H_
|
|
#include "assets/declaredAssets.h"
|
|
#endif
|
|
|
|
#ifndef _TAML_ASSET_REFERENCED_VISITOR_H_
|
|
#include "tamlAssetReferencedVisitor.h"
|
|
#endif
|
|
|
|
#ifndef _TAML_ASSET_DECLARED_VISITOR_H_
|
|
#include "tamlAssetDeclaredVisitor.h"
|
|
#endif
|
|
|
|
#ifndef _TAML_ASSET_DECLARED_UPDATE_VISITOR_H_
|
|
#include "tamlAssetDeclaredUpdateVisitor.h"
|
|
#endif
|
|
|
|
#ifndef _TAML_ASSET_REFERENCED_UPDATE_VISITOR_H_
|
|
#include "tamlAssetReferencedUpdateVisitor.h"
|
|
#endif
|
|
|
|
#ifndef _CONSOLETYPES_H_
|
|
#include "console/consoleTypes.h"
|
|
#endif
|
|
|
|
#ifndef _AUTOLOAD_ASSETS_H_
|
|
#include "assets/autoloadAssets.h"
|
|
#endif
|
|
|
|
#ifndef GUI_ASSET_H
|
|
#include "T3D/assets/GUIAsset.h"
|
|
#endif
|
|
#ifndef SCRIPT_ASSET_H
|
|
#include "T3D/assets/ScriptAsset.h"
|
|
#endif
|
|
#ifndef MATERIALASSET_H
|
|
#include "T3D/assets/MaterialAsset.h"
|
|
#endif
|
|
#ifndef GAME_OBJECT_ASSET_H
|
|
#include "T3D/assets/GameObjectAsset.h"
|
|
#endif
|
|
|
|
// Script bindings.
|
|
#include "assetManager_ScriptBinding.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_CONOBJECT( AssetManager );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
AssetManager AssetDatabase;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
AssetManager::AssetManager() :
|
|
mLoadedInternalAssetsCount( 0 ),
|
|
mLoadedExternalAssetsCount( 0 ),
|
|
mLoadedPrivateAssetsCount( 0 ),
|
|
mMaxLoadedInternalAssetsCount( 0 ),
|
|
mMaxLoadedExternalAssetsCount( 0 ),
|
|
mEchoInfo( false ),
|
|
mAcquiredReferenceCount( 0 ),
|
|
mMaxLoadedPrivateAssetsCount( 0 ),
|
|
mIgnoreAutoUnload( true )
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::onAdd()
|
|
{
|
|
// Call parent.
|
|
if ( !Parent::onAdd() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::onRemove()
|
|
{
|
|
// Do we have an asset tags manifest?
|
|
if ( !mAssetTagsManifest.isNull() )
|
|
{
|
|
// Yes, so remove it.
|
|
mAssetTagsManifest->deleteObject();
|
|
}
|
|
|
|
purgeAssets();
|
|
|
|
// Call parent.
|
|
Parent::onRemove();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::initPersistFields()
|
|
{
|
|
docsURL;
|
|
// Call parent.
|
|
Parent::initPersistFields();
|
|
|
|
addField( "EchoInfo", TypeBool, false, Offset(mEchoInfo, AssetManager), "Whether the asset manager echos extra information to the console or not." );
|
|
addField( "IgnoreAutoUnload", TypeBool, true, Offset(mIgnoreAutoUnload, AssetManager), "Whether the asset manager should ignore unloading of auto-unload assets or not." );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::compileReferencedAssets( ModuleDefinition* pModuleDefinition )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_CompileReferencedAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pModuleDefinition != NULL, "Cannot add declared assets using a NULL module definition" );
|
|
|
|
// Clear referenced assets.
|
|
mReferencedAssets.clear();
|
|
|
|
// Iterate the module definition children.
|
|
for( SimSet::iterator itr = pModuleDefinition->begin(); itr != pModuleDefinition->end(); ++itr )
|
|
{
|
|
// Fetch the referenced assets.
|
|
ReferencedAssets* pReferencedAssets = dynamic_cast<ReferencedAssets*>( *itr );
|
|
|
|
// Skip if it's not a referenced assets location.
|
|
if ( pReferencedAssets == NULL )
|
|
continue;
|
|
|
|
// Expand asset manifest location.
|
|
char filePathBuffer[1024];
|
|
dSprintf( filePathBuffer, sizeof(filePathBuffer), "%s/%s", pModuleDefinition->getModulePath(), pReferencedAssets->getPath() );
|
|
|
|
// Scan referenced assets at location.
|
|
if ( !scanReferencedAssets( filePathBuffer, pReferencedAssets->getExtension(), pReferencedAssets->getRecurse() ) )
|
|
{
|
|
// Warn.
|
|
Con::warnf( "AssetManager::compileReferencedAssets() - Could not scan for referenced assets at location '%s' with extension '%s'.", filePathBuffer, pReferencedAssets->getExtension() );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::addModuleDeclaredAssets( ModuleDefinition* pModuleDefinition )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_AddDeclaredAssets);
|
|
|
|
// Sanity!
|
|
AssertFatal( pModuleDefinition != NULL, "Cannot add declared assets using a NULL module definition" );
|
|
|
|
// Does the module have any assets associated with it?
|
|
if ( pModuleDefinition->getModuleAssets().size() > 0 )
|
|
{
|
|
// Yes, so warn.
|
|
Con::warnf( "Asset Manager: Cannot add declared assets to module '%s' as it already has existing assets.", pModuleDefinition->getSignature() );
|
|
return false;
|
|
}
|
|
|
|
// Iterate the module definition children.
|
|
for( SimSet::iterator itr = pModuleDefinition->begin(); itr != pModuleDefinition->end(); ++itr )
|
|
{
|
|
// Fetch the declared assets.
|
|
DeclaredAssets* pDeclaredAssets = dynamic_cast<DeclaredAssets*>( *itr );
|
|
|
|
// Skip if it's not a declared assets location.
|
|
if ( pDeclaredAssets == NULL )
|
|
continue;
|
|
|
|
// Expand asset manifest location.
|
|
char filePathBuffer[1024], extensionBuffer[256];
|
|
String mdldfpth = pModuleDefinition->getModulePath();
|
|
String astfpth = pDeclaredAssets->getPath();
|
|
|
|
dSprintf(filePathBuffer, sizeof(filePathBuffer), "%s/%s", pModuleDefinition->getModulePath(), pDeclaredAssets->getPath());
|
|
dSprintf(extensionBuffer, sizeof(extensionBuffer), "*.%s", pDeclaredAssets->getExtension());
|
|
|
|
// Scan declared assets at location.
|
|
if ( !scanDeclaredAssets( filePathBuffer, extensionBuffer, pDeclaredAssets->getRecurse(), pModuleDefinition ) && mEchoInfo)
|
|
{
|
|
// Warn.
|
|
Con::warnf( "AssetManager::addModuleDeclaredAssets() - No assets found at location '%s' with extension '%s'.", filePathBuffer, pDeclaredAssets->getExtension() );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetManager::loadModuleAutoLoadAssets(ModuleDefinition* pModuleDefinition)
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_loadModuleAutoLoadAssets);
|
|
|
|
// Sanity!
|
|
AssertFatal(pModuleDefinition != NULL, "Cannot auto load assets using a NULL module definition");
|
|
|
|
// Does the module have any assets associated with it?
|
|
if (pModuleDefinition->getModuleAssets().empty() && mEchoInfo)
|
|
{
|
|
// Yes, so warn.
|
|
Con::warnf("Asset Manager: Cannot auto load assets to module '%s' as it has no existing assets.", pModuleDefinition->getSignature());
|
|
return false;
|
|
}
|
|
|
|
U32 assetCount = pModuleDefinition->getModuleAssets().size();
|
|
|
|
// Iterate the module definition children.
|
|
for (SimSet::iterator itr = pModuleDefinition->begin(); itr != pModuleDefinition->end(); ++itr)
|
|
{
|
|
// Fetch the declared assets.
|
|
AutoloadAssets* pAutoloadAssets = dynamic_cast<AutoloadAssets*>(*itr);
|
|
|
|
// Skip if it's not a declared assets location.
|
|
if (pAutoloadAssets == NULL)
|
|
continue;
|
|
|
|
for (U32 i = 0; i < assetCount; ++i)
|
|
{
|
|
AssetDefinition* assetDef = pModuleDefinition->getModuleAssets()[i];
|
|
|
|
if (assetDef->mAssetType == pAutoloadAssets->getAssetType())
|
|
{
|
|
String assetPath = assetDef->mAssetBaseFilePath;
|
|
assetPath.replace("//", "/");
|
|
|
|
String autoLoadPath = pModuleDefinition->getModulePath();
|
|
autoLoadPath += "/";
|
|
autoLoadPath += pAutoloadAssets->getPath();
|
|
|
|
if (pAutoloadAssets->getPath() == StringTable->EmptyString() || assetPath.startsWith(autoLoadPath.c_str()))
|
|
{
|
|
AssetBase* assetBase = dynamic_cast<AssetBase*>(mTaml.read(assetDef->mAssetBaseFilePath));
|
|
|
|
//load the asset now if valid
|
|
if (assetBase)
|
|
{
|
|
assetBase->setOwned(this, assetDef);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::addDeclaredAsset( ModuleDefinition* pModuleDefinition, const char* pAssetFilePath )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_AddSingleDeclaredAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pModuleDefinition != NULL, "Cannot add single declared asset using a NULL module definition" );
|
|
AssertFatal( pAssetFilePath != NULL, "Cannot add single declared asset using a NULL asset file-path." );
|
|
|
|
// Expand asset file-path.
|
|
char assetFilePathBuffer[1024];
|
|
dStrcpy(assetFilePathBuffer, Platform::makeRelativePathName(pAssetFilePath, NULL), sizeof(assetFilePathBuffer));
|
|
|
|
// Find the final slash which should be just before the file.
|
|
char* pFileStart = dStrrchr( assetFilePathBuffer, '/' );
|
|
|
|
// Did we find the final slash?
|
|
if ( pFileStart == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "AssetManager::addDeclaredAsset() - Could not add single declared asset file '%s' as file-path '%s' is not valid.",
|
|
assetFilePathBuffer,
|
|
pModuleDefinition->getModulePath() );
|
|
return false;
|
|
}
|
|
|
|
// Terminate path at slash.
|
|
*pFileStart = 0;
|
|
|
|
// Move to next character which should be the file start.
|
|
pFileStart++;
|
|
|
|
// Scan declared assets at location.
|
|
if ( !scanDeclaredAssets( assetFilePathBuffer, pFileStart, false, pModuleDefinition ) )
|
|
{
|
|
// Warn.
|
|
Con::warnf( "AssetManager::addDeclaredAsset() - Could not scan declared assets at location '%s' with extension '%s'.", assetFilePathBuffer, pFileStart );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
StringTableEntry AssetManager::addPrivateAsset( AssetBase* pAssetBase )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_AddPrivateAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetBase != NULL, "Cannot add a NULL private asset." );
|
|
|
|
// Is the asset already added?
|
|
if (pAssetBase->mpAssetDefinition->mAssetId != StringTable->EmptyString())
|
|
{
|
|
// Yes, so warn.
|
|
Con::warnf( "Cannot add private asset '%d' as it has already been assigned.", pAssetBase->mpAssetDefinition->mAssetId );
|
|
return StringTable->EmptyString();
|
|
}
|
|
|
|
static U32 masterPrivateAssetId = 1;
|
|
|
|
// Create asset definition.
|
|
AssetDefinition* pAssetDefinition = new AssetDefinition();
|
|
|
|
// Fetch source asset definition.
|
|
AssetDefinition* pSourceAssetDefinition = pAssetBase->mpAssetDefinition;
|
|
|
|
// Configure asset.
|
|
pAssetDefinition->mpAssetBase = pAssetBase;
|
|
pAssetDefinition->mAssetDescription = pSourceAssetDefinition->mAssetDescription;
|
|
pAssetDefinition->mAssetCategory = pSourceAssetDefinition->mAssetCategory;
|
|
pAssetDefinition->mAssetAutoUnload = true;
|
|
pAssetDefinition->mAssetRefreshEnable = false;
|
|
pAssetDefinition->mAssetType = StringTable->insert( pAssetBase->getClassName() );
|
|
pAssetDefinition->mAssetLoadedCount = 0;
|
|
pAssetDefinition->mAssetInternal = false;
|
|
pAssetDefinition->mAssetPrivate = true;
|
|
|
|
// Format asset name.
|
|
char assetNameBuffer[256];
|
|
dSprintf(assetNameBuffer, sizeof(assetNameBuffer), "%s_%d", pAssetDefinition->mAssetType, masterPrivateAssetId++ );
|
|
|
|
// Set asset identity.
|
|
pAssetDefinition->mAssetName = StringTable->insert( assetNameBuffer );
|
|
pAssetDefinition->mAssetId = pAssetDefinition->mAssetName;
|
|
|
|
// Ensure that the source asset is fully synchronized with the new asset definition.
|
|
pSourceAssetDefinition->mAssetName = pAssetDefinition->mAssetName;
|
|
pSourceAssetDefinition->mAssetAutoUnload = pAssetDefinition->mAssetAutoUnload;
|
|
pSourceAssetDefinition->mAssetInternal = pAssetDefinition->mAssetInternal;
|
|
|
|
// Set ownership by asset manager.
|
|
pAssetDefinition->mpAssetBase->setOwned( this, pAssetDefinition );
|
|
|
|
// Store in declared assets.
|
|
mDeclaredAssets.insert( pAssetDefinition->mAssetId, pAssetDefinition );
|
|
|
|
// Increase the private loaded asset count.
|
|
if ( ++mLoadedPrivateAssetsCount > mMaxLoadedPrivateAssetsCount )
|
|
mMaxLoadedPrivateAssetsCount = mLoadedPrivateAssetsCount;
|
|
|
|
return pAssetDefinition->mAssetId;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::removeDeclaredAssets( ModuleDefinition* pModuleDefinition )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RemoveDeclaredAssets);
|
|
|
|
// Sanity!
|
|
AssertFatal( pModuleDefinition != NULL, "Cannot remove declared assets using a NULL module definition" );
|
|
|
|
// Fetch module assets.
|
|
ModuleDefinition::typeModuleAssetsVector& moduleAssets = pModuleDefinition->getModuleAssets();
|
|
|
|
// Remove all module assets.
|
|
while ( moduleAssets.size() > 0 )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = *moduleAssets.begin();
|
|
|
|
// Remove this asset.
|
|
removeDeclaredAsset( pAssetDefinition->mAssetId );
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
Con::printSeparator();
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::removeDeclaredAsset( const char* pAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RemoveSingleDeclaredAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetId != NULL, "Cannot remove single declared asset using NULL asset Id." );
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Find declared asset.
|
|
typeDeclaredAssetsHash::iterator declaredAssetItr = mDeclaredAssets.find( assetId );
|
|
|
|
// Did we find the declared asset?
|
|
if ( declaredAssetItr == mDeclaredAssets.end() )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot remove single asset Id '%s' it could not be found.", assetId );
|
|
return false;
|
|
}
|
|
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = declaredAssetItr->value;
|
|
|
|
// Is the asset private?
|
|
if ( !pAssetDefinition->mAssetPrivate )
|
|
{
|
|
// No, so fetch module assets.
|
|
ModuleDefinition::typeModuleAssetsVector& moduleAssets = pAssetDefinition->mpModuleDefinition->getModuleAssets();
|
|
|
|
// Remove module asset.
|
|
for ( ModuleDefinition::typeModuleAssetsVector::iterator moduleAssetItr = moduleAssets.begin(); moduleAssetItr != moduleAssets.end(); ++moduleAssetItr )
|
|
{
|
|
if ( *moduleAssetItr == pAssetDefinition )
|
|
{
|
|
moduleAssets.erase( moduleAssetItr );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Remove asset dependencies.
|
|
removeAssetDependencies( pAssetId );
|
|
}
|
|
|
|
// Do we have an asset loaded?
|
|
if ( pAssetDefinition->mpAssetBase != NULL )
|
|
{
|
|
// Yes, so delete it.
|
|
// NOTE: If anything is using this then this'll cause a crash. Objects should always use safe reference methods however.
|
|
pAssetDefinition->mpAssetBase->deleteObject();
|
|
}
|
|
|
|
// Remove from declared assets.
|
|
mDeclaredAssets.erase( declaredAssetItr );
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: Removing Asset Id '%s' of type '%s' in asset file '%s'.",
|
|
pAssetDefinition->mAssetId,
|
|
pAssetDefinition->mAssetType,
|
|
pAssetDefinition->mAssetBaseFilePath );
|
|
}
|
|
|
|
// Destroy asset definition.
|
|
delete pAssetDefinition;
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
StringTableEntry AssetManager::getAssetName( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return NULL;
|
|
}
|
|
|
|
return pAssetDefinition->mAssetName;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
StringTableEntry AssetManager::getAssetDescription( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return NULL;
|
|
}
|
|
|
|
return pAssetDefinition->mAssetDescription;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
StringTableEntry AssetManager::getAssetCategory( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return NULL;
|
|
}
|
|
|
|
return pAssetDefinition->mAssetCategory;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
StringTableEntry AssetManager::getAssetType( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return NULL;
|
|
}
|
|
|
|
return pAssetDefinition->mAssetType;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
StringTableEntry AssetManager::getAssetFilePath( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return StringTable->EmptyString();
|
|
}
|
|
|
|
return pAssetDefinition->mAssetBaseFilePath;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
StringTableEntry AssetManager::getAssetPath( const char* pAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_GetAssetPath);
|
|
|
|
// Fetch asset file-path.
|
|
StringTableEntry assetFilePath = getAssetFilePath( pAssetId );
|
|
|
|
// Finish if no file-path.
|
|
if ( assetFilePath == StringTable->EmptyString() )
|
|
return assetFilePath;
|
|
|
|
// Find the final slash which should be just before the file.
|
|
const char* pFinalSlash = dStrrchr( assetFilePath, '/' );
|
|
|
|
// Sanity!
|
|
AssertFatal( pFinalSlash != NULL, "Should always be able to find final slash in the asset file-path." );
|
|
|
|
// Fetch asset path.
|
|
return StringTable->insertn( assetFilePath, (U32)(pFinalSlash - assetFilePath) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
ModuleDefinition* AssetManager::getAssetModuleDefinition( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return NULL;
|
|
}
|
|
|
|
return pAssetDefinition->mpModuleDefinition;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::isAssetInternal( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return false;
|
|
}
|
|
|
|
return pAssetDefinition->mAssetInternal;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::isAssetPrivate( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return false;
|
|
}
|
|
|
|
return pAssetDefinition->mAssetPrivate;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::isAssetAutoUnload( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return false;
|
|
}
|
|
|
|
return pAssetDefinition->mAssetAutoUnload;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::isAssetLoaded( const char* pAssetId )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId );
|
|
return false;
|
|
}
|
|
|
|
return pAssetDefinition->mpAssetBase != NULL;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::isDeclaredAsset( const char* pAssetId )
|
|
{
|
|
return findAsset( pAssetId ) != NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::doesAssetDependOn( const char* pAssetId, const char* pDependsOnAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_DoesAssetDependOn);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." );
|
|
AssertFatal( pDependsOnAssetId != NULL, "Cannot use NULL depends-on asset Id." );
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Fetch depends-on asset Id.
|
|
StringTableEntry dependsOnAssetId = StringTable->insert( pDependsOnAssetId );
|
|
|
|
// Find depends-on entry.
|
|
typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find( assetId );
|
|
|
|
// Iterate all dependencies.
|
|
while( dependsOnItr != mAssetDependsOn.end() && dependsOnItr->key == assetId )
|
|
{
|
|
// Finish if a depends on.
|
|
if ( dependsOnItr->value == dependsOnAssetId )
|
|
return true;
|
|
|
|
// Next dependency.
|
|
dependsOnItr++;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::isAssetDependedOn( const char* pAssetId, const char* pDependedOnByAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_IsAssetDependedOn);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." );
|
|
AssertFatal( pDependedOnByAssetId != NULL, "Cannot use NULL depended-on-by asset Id." );
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Fetch depended-on-by asset Id.
|
|
StringTableEntry dependedOnByAssetId = StringTable->insert( pDependedOnByAssetId );
|
|
|
|
// Find depended-on-by entry.
|
|
typeAssetDependsOnHash::Iterator dependedOnItr = mAssetIsDependedOn.find(assetId);
|
|
|
|
// Iterate all dependencies.
|
|
while( dependedOnItr != mAssetIsDependedOn.end() && dependedOnItr->key == assetId )
|
|
{
|
|
// Finish if depended-on.
|
|
if ( dependedOnItr->value == dependedOnByAssetId )
|
|
return true;
|
|
|
|
// Next dependency.
|
|
dependedOnItr++;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::isReferencedAsset( const char* pAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_IsReferencedAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetId != NULL, "Cannot check if NULL asset Id is referenced." );
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Is asset Id the correct format?
|
|
if ( StringUnit::getUnitCount( assetId, ASSET_SCOPE_TOKEN ) != 2 )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot check if asset Id '%s' is referenced as it is not the correct format.", assetId );
|
|
return false;
|
|
}
|
|
|
|
return mReferencedAssets.count( assetId ) > 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::renameDeclaredAsset( const char* pAssetIdFrom, const char* pAssetIdTo )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RenameDeclaredAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetIdFrom != NULL, "Cannot rename from NULL asset Id." );
|
|
AssertFatal( pAssetIdTo != NULL, "Cannot rename to NULL asset Id." );
|
|
|
|
// Fetch asset Ids.
|
|
StringTableEntry assetIdFrom = StringTable->insert( pAssetIdFrom );
|
|
StringTableEntry assetIdTo = StringTable->insert( pAssetIdTo );
|
|
|
|
// Is asset Id from the correct format?
|
|
if ( StringUnit::getUnitCount( assetIdFrom, ASSET_SCOPE_TOKEN ) != 2 )
|
|
{
|
|
// No, so warn.
|
|
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 );
|
|
return false;
|
|
}
|
|
|
|
// Is asset Id to the correct format?
|
|
if ( StringUnit::getUnitCount( assetIdTo, ASSET_SCOPE_TOKEN ) != 2 )
|
|
{
|
|
// No, so warn.
|
|
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 );
|
|
return false;
|
|
}
|
|
|
|
// Does the asset Id from exist?
|
|
if ( !mDeclaredAssets.contains( assetIdFrom ) )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as source asset Id is not declared.", assetIdFrom, assetIdTo );
|
|
return false;
|
|
}
|
|
|
|
// Does the asset Id to exist?
|
|
if ( mDeclaredAssets.contains( assetIdTo ) )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as target asset Id is already declared.", assetIdFrom, assetIdTo );
|
|
return false;
|
|
}
|
|
|
|
// Split module Ids from asset Ids.
|
|
StringTableEntry moduleIdFrom = StringTable->insert( StringUnit::getUnit( assetIdFrom, 0, ASSET_SCOPE_TOKEN ) );
|
|
StringTableEntry moduleIdTo = StringTable->insert( StringUnit::getUnit( assetIdTo, 0, ASSET_SCOPE_TOKEN ) );
|
|
|
|
// Are the module Ids the same?
|
|
if ( moduleIdFrom != moduleIdTo )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as the module Id cannot be changed.", assetIdFrom, assetIdTo );
|
|
return false;
|
|
}
|
|
|
|
// Find asset definition.
|
|
typeDeclaredAssetsHash::iterator assetDefinitionItr = mDeclaredAssets.find( assetIdFrom );
|
|
|
|
// Sanity!
|
|
AssertFatal( assetDefinitionItr != mDeclaredAssets.end(), "Asset Manager: Failed to find asset." );
|
|
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetDefinitionItr->value;
|
|
|
|
// Is this a private asset?
|
|
if ( pAssetDefinition->mAssetPrivate )
|
|
{
|
|
// Yes, so warn.
|
|
Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as the source asset is private.", assetIdFrom, assetIdTo );
|
|
return false;
|
|
}
|
|
|
|
// Setup declared update visitor.
|
|
TamlAssetDeclaredUpdateVisitor assetDeclaredUpdateVisitor;
|
|
assetDeclaredUpdateVisitor.setAssetIdFrom( assetIdFrom );
|
|
assetDeclaredUpdateVisitor.setAssetIdTo( assetIdTo );
|
|
|
|
// Update asset file declaration.
|
|
if ( !mTaml.parse( pAssetDefinition->mAssetBaseFilePath, assetDeclaredUpdateVisitor ) )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as the declared asset file could not be parsed: %s",
|
|
assetIdFrom, assetIdTo, pAssetDefinition->mAssetBaseFilePath );
|
|
return false;
|
|
}
|
|
|
|
// Update asset definition.
|
|
pAssetDefinition->mAssetId = assetIdTo;
|
|
pAssetDefinition->mAssetName = StringTable->insert( StringUnit::getUnit( assetIdTo, 1, ASSET_SCOPE_TOKEN ) );
|
|
|
|
// Reinsert declared asset.
|
|
mDeclaredAssets.erase( assetIdFrom );
|
|
mDeclaredAssets.insert( assetIdTo, pAssetDefinition );
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: Renaming declared Asset Id '%s' to Asset Id '%s'.", assetIdFrom, assetIdTo );
|
|
Con::printSeparator();
|
|
}
|
|
|
|
// Rename asset dependencies.
|
|
renameAssetDependencies( assetIdFrom, assetIdTo );
|
|
|
|
// Do we have an asset tags manifest?
|
|
if ( !mAssetTagsManifest.isNull() )
|
|
{
|
|
// Yes, so rename any assets.
|
|
mAssetTagsManifest->renameAssetId( pAssetIdFrom, pAssetIdTo );
|
|
|
|
// Save the asset tags.
|
|
saveAssetTags();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::renameReferencedAsset( const char* pAssetIdFrom, const char* pAssetIdTo )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RenameReferencedAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetIdFrom != NULL, "Cannot rename from NULL asset Id." );
|
|
AssertFatal( pAssetIdTo != NULL, "Cannot rename to NULL asset Id." );
|
|
|
|
// Fetch asset Ids.
|
|
StringTableEntry assetIdFrom = StringTable->insert( pAssetIdFrom );
|
|
StringTableEntry assetIdTo = StringTable->insert( pAssetIdTo );
|
|
|
|
// Is asset Id from the correct format?
|
|
if ( StringUnit::getUnitCount( assetIdFrom, ASSET_SCOPE_TOKEN ) != 2 )
|
|
{
|
|
// No, so warn.
|
|
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 );
|
|
return false;
|
|
}
|
|
|
|
// Is asset Id to the correct format?
|
|
if ( StringUnit::getUnitCount( assetIdTo, ASSET_SCOPE_TOKEN ) != 2 )
|
|
{
|
|
// No, so warn.
|
|
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 );
|
|
return false;
|
|
}
|
|
|
|
// Does the asset Id to exist?
|
|
if ( !mDeclaredAssets.contains( assetIdTo ) )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as target asset Id is not declared.", assetIdFrom, assetIdTo );
|
|
return false;
|
|
}
|
|
|
|
// Rename asset references.
|
|
renameAssetReferences( assetIdFrom, assetIdTo );
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
Con::printSeparator();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetManager::compileAllAssets(const bool compressed, const bool includeUnloaded)
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_CompileAllAssets);
|
|
|
|
// Info.
|
|
if (mEchoInfo)
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf("Asset Manager: Started compiling ALL assets.");
|
|
}
|
|
|
|
Vector<typeAssetId> assetsToRelease;
|
|
|
|
// Are we including unloaded assets?
|
|
if (includeUnloaded)
|
|
{
|
|
// Yes, so prepare a list of assets to release and load them.
|
|
for (typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr)
|
|
{
|
|
// Fetch asset Id.
|
|
typeAssetId assetId = assetItr->key;
|
|
|
|
// Skip if asset is loaded.
|
|
if (assetItr->value->mpAssetBase != NULL)
|
|
continue;
|
|
|
|
// Note asset as needing a release.
|
|
assetsToRelease.push_back(assetId);
|
|
|
|
// Acquire the asset.
|
|
acquireAsset<AssetBase>(assetId);
|
|
}
|
|
}
|
|
|
|
bool oldCompressed = mTaml.getBinaryCompression();
|
|
mTaml.setBinaryCompression(compressed);
|
|
bool success = false;
|
|
// Refresh the current loaded assets.
|
|
// NOTE: This will result in some assets being refreshed more than once due to asset dependencies.
|
|
for (typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr)
|
|
{
|
|
// Skip private assets.
|
|
if (assetItr->value->mAssetPrivate)
|
|
continue;
|
|
|
|
// Refresh asset if it's loaded.
|
|
success = compileAsset(assetItr->key);
|
|
if (!success)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
mTaml.setBinaryCompression(oldCompressed);
|
|
|
|
// Are we including unloaded assets?
|
|
if (includeUnloaded)
|
|
{
|
|
// Yes, so release the assets we loaded.
|
|
for (Vector<typeAssetId>::iterator assetItr = assetsToRelease.begin(); assetItr != assetsToRelease.end(); ++assetItr)
|
|
{
|
|
releaseAsset(*assetItr);
|
|
}
|
|
}
|
|
|
|
// Info.
|
|
if (mEchoInfo)
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf("Asset Manager: Finished compiling ALL assets.");
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
bool AssetManager::compileModuleAssets(ModuleDefinition* pModuleDefinition)
|
|
{
|
|
// Sanity!
|
|
AssertFatal(pModuleDefinition != NULL, "Cannot remove declared assets using a NULL module definition");
|
|
|
|
// Fetch module assets.
|
|
ModuleDefinition::typeModuleAssetsVector& moduleAssets = pModuleDefinition->getModuleAssets();
|
|
|
|
// Remove all module assets.
|
|
while (moduleAssets.size() > 0)
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = *moduleAssets.begin();
|
|
bool success = compileAsset(pAssetDefinition->mAssetId);
|
|
if (!success)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetManager::compileAsset(const char* pAssetId)
|
|
{
|
|
// Sanity!
|
|
AssertFatal(pAssetId != NULL, "Cannot compile NULL asset");
|
|
|
|
AssetDefinition* pAssetDefinition = findAsset(pAssetId);
|
|
|
|
// Does the asset exist?
|
|
if (pAssetDefinition == NULL)
|
|
{
|
|
Con::warnf("Asset Manager::compileAsset Failed to compile asset Id '%s' as it does not exist", pAssetId);
|
|
return false;
|
|
}
|
|
|
|
// Info.
|
|
if (mEchoInfo)
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf("Asset Manager::compileAsset Started compiling Asset Id '%s'...", pAssetId);
|
|
}
|
|
|
|
AssetBase* pAssetBase = pAssetDefinition->mpAssetBase;
|
|
if (pAssetBase != NULL)
|
|
{
|
|
Torque::Path binaryPath = pAssetDefinition->mAssetBaseFilePath;
|
|
binaryPath.setExtension(mTaml.getAutoFormatBinaryExtension());
|
|
// Save asset.
|
|
mTaml.write(pAssetBase, binaryPath.getFullPath().c_str());
|
|
}
|
|
else
|
|
{
|
|
Con::warnf("Asset Manager::compileAsset Failed to compile asset Id '%s' as it does not have an assetBase", pAssetId);
|
|
return false;
|
|
}
|
|
|
|
// Info.
|
|
if (mEchoInfo)
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf("Asset Manager: Finished compiling Asset Id '%s'.", pAssetId);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::releaseAsset( const char* pAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_ReleaseAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetId != NULL, "Cannot release NULL asset Id." );
|
|
|
|
// Find asset.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Failed to release asset Id '%s' as it does not exist.", pAssetId );
|
|
return false;
|
|
}
|
|
|
|
// Is the asset loaded?
|
|
if ( pAssetDefinition->mpAssetBase == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Failed to release asset Id '%s' as it is not acquired.", pAssetId );
|
|
return false;
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Started releasing Asset Id '%s'...", pAssetId );
|
|
}
|
|
|
|
// Release asset reference.
|
|
if ( pAssetDefinition->mpAssetBase->releaseAssetReference() )
|
|
{
|
|
// Are we ignoring auto-unloaded assets?
|
|
if ( mIgnoreAutoUnload )
|
|
{
|
|
// Yes, so info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: > Releasing to idle state." );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No, so info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: > Unload the asset from memory." );
|
|
}
|
|
|
|
// Unload the asset.
|
|
unloadAsset( pAssetDefinition );
|
|
}
|
|
}
|
|
// Info.
|
|
else if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: > Reference count now '%d'.", pAssetDefinition->mpAssetBase->getAcquiredReferenceCount() );
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: > Finished releasing Asset Id '%s'.", pAssetId );
|
|
Con::printSeparator();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::purgeAssets( void )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_PurgeAssets);
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: Started purging assets..." );
|
|
}
|
|
|
|
// Iterate asset definitions.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetItr->value;
|
|
|
|
// Skip asset if private, not loaded or referenced.
|
|
if ( pAssetDefinition->mAssetPrivate ||
|
|
pAssetDefinition->mpAssetBase == NULL ||
|
|
pAssetDefinition->mpAssetBase->getAcquiredReferenceCount() > 0 )
|
|
continue;
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: Purging asset Id '%s'...", pAssetDefinition->mAssetId );
|
|
}
|
|
|
|
// Unload the asset.
|
|
unloadAsset( pAssetDefinition );
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: ... Finished purging assets." );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::deleteAsset( const char* pAssetId, const bool deleteLooseFiles, const bool deleteDependencies )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_DeleteAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetId != NULL, "Cannot delete NULL asset Id." );
|
|
|
|
// Find asset.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Failed to delete asset Id '%s' as it does not exist.", pAssetId );
|
|
return false;
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Started deleting Asset Id '%s'...", pAssetId );
|
|
}
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Are we deleting dependencies?
|
|
if ( deleteDependencies )
|
|
{
|
|
Vector<typeAssetId> dependantAssets;
|
|
|
|
// Yes, so find depended-on-by entry.
|
|
typeAssetDependsOnHash::Iterator dependedOnItr = mAssetIsDependedOn.find( assetId );
|
|
|
|
// Iterate all dependencies.
|
|
while( dependedOnItr != mAssetIsDependedOn.end() && dependedOnItr->key == assetId )
|
|
{
|
|
// Store asset Id.
|
|
dependantAssets.push_back( dependedOnItr->value );
|
|
|
|
// Next dependency.
|
|
dependedOnItr++;
|
|
}
|
|
|
|
// Do we have any dependants?
|
|
if ( dependantAssets.size() > 0 )
|
|
{
|
|
// Yes, so iterate dependants.
|
|
for( Vector<typeAssetId>::const_iterator assetItr = dependantAssets.begin(); assetItr != dependantAssets.end(); ++assetItr )
|
|
{
|
|
StringTableEntry dependentAssetId = *assetItr;
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Deleting Asset Id '%s' dependant of '%s.'", pAssetId, dependentAssetId );
|
|
}
|
|
|
|
// Delete dependant.
|
|
deleteAsset( dependentAssetId, deleteLooseFiles, deleteDependencies );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove asset references.
|
|
removeAssetReferences( assetId );
|
|
|
|
// Are we deleting loose files?
|
|
if ( deleteLooseFiles )
|
|
{
|
|
// Yes, so remove loose files.
|
|
Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles;
|
|
for( Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr )
|
|
{
|
|
// Fetch loose file.
|
|
StringTableEntry looseFile = *looseFileItr;
|
|
|
|
// Delete the loose file.
|
|
if ( !dFileDelete( looseFile ) )
|
|
{
|
|
// Failed so warn.
|
|
Con::warnf( "Asset Manager: Failed to delete the loose file '%s' while deleting asset Id '%s'.", looseFile, pAssetId );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fetch asset definition file.
|
|
StringTableEntry assetDefinitionFile = pAssetDefinition->mAssetBaseFilePath;
|
|
|
|
// Remove reference here as we're about to remove the declared asset.
|
|
pAssetDefinition = NULL;
|
|
|
|
// Remove asset.
|
|
removeDeclaredAsset( pAssetId );
|
|
|
|
// Delete the asset definition file.
|
|
if ( !dFileDelete( assetDefinitionFile ) )
|
|
{
|
|
// Failed so warn.
|
|
Con::warnf( "Asset Manager: Failed to delete the asset definition file '%s' while deleting asset Id '%s'.", assetDefinitionFile, pAssetId );
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Finished deleting Asset Id '%s'.", pAssetId );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::refreshAsset( const char* pAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RefreshAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetId != NULL, "Cannot refresh NULL asset Id." );
|
|
|
|
// Find asset.
|
|
AssetDefinition* pAssetDefinition = findAsset( pAssetId );
|
|
|
|
// Did we find the asset?
|
|
if ( pAssetDefinition == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Failed to refresh asset Id '%s' as it does not exist.", pAssetId );
|
|
return false;
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Started refreshing Asset Id '%s'...", pAssetId );
|
|
}
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Is the asset private?
|
|
if ( pAssetDefinition->mAssetPrivate )
|
|
{
|
|
// Yes, so notify asset of asset refresh only.
|
|
pAssetDefinition->mpAssetBase->onAssetRefresh();
|
|
|
|
// Asset refresh notifications.
|
|
for( typeAssetPtrRefreshHash::iterator refreshNotifyItr = mAssetPtrRefreshNotifications.begin(); refreshNotifyItr != mAssetPtrRefreshNotifications.end(); ++refreshNotifyItr )
|
|
{
|
|
// Fetch pointed asset.
|
|
StringTableEntry pointedAsset = refreshNotifyItr->key->getAssetId();
|
|
|
|
// Ignore if the pointed asset is not the asset or a dependency.
|
|
if ( pointedAsset == StringTable->EmptyString() || ( pointedAsset != assetId && !doesAssetDependOn( pointedAsset, assetId ) ) )
|
|
continue;
|
|
|
|
// Perform refresh notification callback.
|
|
refreshNotifyItr->value->onAssetRefreshed( refreshNotifyItr->key );
|
|
}
|
|
}
|
|
// Is the asset definition allowed to refresh?
|
|
else if ( pAssetDefinition->mAssetRefreshEnable )
|
|
{
|
|
// Yes, so fetch the asset.
|
|
AssetBase* pAssetBase = pAssetDefinition->mpAssetBase;
|
|
|
|
// Is the asset loaded?
|
|
if ( pAssetBase != NULL )
|
|
{
|
|
// Yes, so notify asset of asset refresh.
|
|
pAssetBase->onAssetRefresh();
|
|
|
|
// Save asset.
|
|
mTaml.write( pAssetBase, pAssetDefinition->mAssetBaseFilePath );
|
|
|
|
// Remove asset dependencies.
|
|
removeAssetDependencies( pAssetId );
|
|
|
|
// Find any new dependencies.
|
|
TamlAssetDeclaredVisitor assetDeclaredVisitor;
|
|
|
|
// Parse the filename.
|
|
if ( !mTaml.parse( pAssetDefinition->mAssetBaseFilePath, assetDeclaredVisitor ) )
|
|
{
|
|
// Warn.
|
|
Con::warnf( "Asset Manager: Failed to parse file containing asset declaration: '%s'.\nDependencies are now incorrect!", pAssetDefinition->mAssetBaseFilePath );
|
|
return false;
|
|
}
|
|
|
|
// Fetch asset dependencies.
|
|
TamlAssetDeclaredVisitor::typeAssetIdVector& assetDependencies = assetDeclaredVisitor.getAssetDependencies();
|
|
|
|
// Are there any asset dependences?
|
|
if ( assetDependencies.size() > 0 )
|
|
{
|
|
// Yes, so iterate dependencies.
|
|
for( TamlAssetDeclaredVisitor::typeAssetIdVector::iterator assetDependencyItr = assetDependencies.begin(); assetDependencyItr != assetDependencies.end(); ++assetDependencyItr )
|
|
{
|
|
// Fetch dependency asset Id.
|
|
StringTableEntry dependencyAssetId = *assetDependencyItr;
|
|
|
|
// Insert depends-on.
|
|
mAssetDependsOn.insertEqual( assetId, dependencyAssetId );
|
|
|
|
// Insert is-depended-on.
|
|
mAssetIsDependedOn.insertEqual( dependencyAssetId, assetId );
|
|
}
|
|
}
|
|
|
|
// Fetch asset loose files.
|
|
TamlAssetDeclaredVisitor::typeLooseFileVector& assetLooseFiles = assetDeclaredVisitor.getAssetLooseFiles();
|
|
|
|
// Clear any existing loose files.
|
|
pAssetDefinition->mAssetLooseFiles.clear();
|
|
|
|
// Are there any loose files?
|
|
if ( assetLooseFiles.size() > 0 )
|
|
{
|
|
// Yes, so iterate loose files.
|
|
for( TamlAssetDeclaredVisitor::typeLooseFileVector::iterator assetLooseFileItr = assetLooseFiles.begin(); assetLooseFileItr != assetLooseFiles.end(); ++assetLooseFileItr )
|
|
{
|
|
// Store loose file.
|
|
pAssetDefinition->mAssetLooseFiles.push_back( *assetLooseFileItr );
|
|
}
|
|
}
|
|
|
|
// Asset refresh notifications.
|
|
for( typeAssetPtrRefreshHash::iterator refreshNotifyItr = mAssetPtrRefreshNotifications.begin(); refreshNotifyItr != mAssetPtrRefreshNotifications.end(); ++refreshNotifyItr )
|
|
{
|
|
// Fetch pointed asset.
|
|
StringTableEntry pointedAsset = refreshNotifyItr->key->getAssetId();
|
|
|
|
// Ignore if the pointed asset is not the asset or a dependency.
|
|
if ( pointedAsset == StringTable->EmptyString() || ( pointedAsset != assetId && !doesAssetDependOn( pointedAsset, assetId ) ) )
|
|
continue;
|
|
|
|
// Perform refresh notification callback.
|
|
refreshNotifyItr->value->onAssetRefreshed( refreshNotifyItr->key );
|
|
}
|
|
|
|
// Find is-depends-on entry.
|
|
typeAssetIsDependedOnHash::Iterator isDependedOnItr = mAssetIsDependedOn.find( assetId );
|
|
|
|
// Is asset depended on?
|
|
if ( isDependedOnItr != mAssetIsDependedOn.end() )
|
|
{
|
|
// Yes, so compiled them.
|
|
Vector<typeAssetId> dependedOn;
|
|
|
|
// Iterate all dependencies.
|
|
while( isDependedOnItr != mAssetIsDependedOn.end() && isDependedOnItr->key == assetId )
|
|
{
|
|
dependedOn.push_back( isDependedOnItr->value );
|
|
|
|
// Next dependency.
|
|
isDependedOnItr++;
|
|
}
|
|
|
|
// Refresh depended-on assets.
|
|
for ( Vector<typeAssetId>::iterator refreshItr = dependedOn.begin(); refreshItr != dependedOn.end(); ++refreshItr)
|
|
{
|
|
// Refresh dependency asset.
|
|
refreshAsset( *refreshItr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Finished refreshing Asset Id '%s'.", pAssetId );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::refreshAllAssets( const bool includeUnloaded )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RefreshAllAssets);
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Started refreshing ALL assets." );
|
|
}
|
|
|
|
Vector<typeAssetId> assetsToRelease;
|
|
|
|
// Are we including unloaded assets?
|
|
if ( includeUnloaded )
|
|
{
|
|
// Yes, so prepare a list of assets to release and load them.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset Id.
|
|
typeAssetId assetId = assetItr->key;
|
|
|
|
// Skip if asset is loaded.
|
|
if ( assetItr->value->mpAssetBase != NULL )
|
|
continue;
|
|
|
|
// Note asset as needing a release.
|
|
assetsToRelease.push_back( assetId );
|
|
|
|
// Acquire the asset.
|
|
acquireAsset<AssetBase>( assetId );
|
|
}
|
|
}
|
|
|
|
// Refresh the current loaded assets.
|
|
// NOTE: This will result in some assets being refreshed more than once due to asset dependencies.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Skip private assets.
|
|
if ( assetItr->value->mAssetPrivate )
|
|
continue;
|
|
|
|
// Refresh asset if it's loaded.
|
|
refreshAsset( assetItr->key );
|
|
}
|
|
|
|
// Are we including unloaded assets?
|
|
if ( includeUnloaded )
|
|
{
|
|
// Yes, so release the assets we loaded.
|
|
for( Vector<typeAssetId>::iterator assetItr = assetsToRelease.begin(); assetItr != assetsToRelease.end(); ++assetItr )
|
|
{
|
|
releaseAsset( *assetItr );
|
|
}
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Finished refreshing ALL assets." );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::registerAssetPtrRefreshNotify( AssetPtrBase* pAssetPtrBase, AssetPtrCallback* pCallback )
|
|
{
|
|
// Find an existing notification iterator.
|
|
typeAssetPtrRefreshHash::iterator notificationItr = mAssetPtrRefreshNotifications.find( pAssetPtrBase );
|
|
|
|
// Do we have one?
|
|
if ( notificationItr != mAssetPtrRefreshNotifications.end() )
|
|
{
|
|
// Yes, so update the callback.
|
|
notificationItr->value = pCallback;
|
|
return;
|
|
}
|
|
|
|
// No, so add one.
|
|
mAssetPtrRefreshNotifications.insert( pAssetPtrBase, pCallback );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::unregisterAssetPtrRefreshNotify( AssetPtrBase* pAssetPtrBase )
|
|
{
|
|
mAssetPtrRefreshNotifications.erase( pAssetPtrBase );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::loadAssetTags( ModuleDefinition* pModuleDefinition )
|
|
{
|
|
// Sanity!
|
|
AssertFatal( pModuleDefinition != NULL, "Cannot load asset tags manifest using a NULL module definition" );
|
|
|
|
// Expand manifest location.
|
|
char assetTagsManifestFilePathBuffer[1024];
|
|
Con::expandPath( assetTagsManifestFilePathBuffer, sizeof(assetTagsManifestFilePathBuffer), pModuleDefinition->getAssetTagsManifest() );
|
|
|
|
// Do we already have a manifest?
|
|
if ( !mAssetTagsManifest.isNull() )
|
|
{
|
|
// Yes, so warn.
|
|
Con::warnf( "Asset Manager: Cannot load asset tags manifest from module '%s' as one is already loaded.", pModuleDefinition->getSignature() );
|
|
return false;
|
|
}
|
|
|
|
// Is the specified file valid?
|
|
if (Torque::FS::IsFile( assetTagsManifestFilePathBuffer ) )
|
|
{
|
|
// Yes, so read asset tags manifest.
|
|
mAssetTagsManifest = mTaml.read<AssetTagsManifest>( assetTagsManifestFilePathBuffer );
|
|
|
|
// Did we read the manifest?
|
|
if ( mAssetTagsManifest.isNull() )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Failed to load asset tags manifest '%s' from module '%s'.", assetTagsManifestFilePathBuffer, pModuleDefinition->getSignature() );
|
|
return false;
|
|
}
|
|
|
|
// Set asset tags module definition.
|
|
mAssetTagsModuleDefinition = pModuleDefinition;
|
|
}
|
|
else
|
|
{
|
|
// No, so generate a new asset tags manifest.
|
|
mAssetTagsManifest = new AssetTagsManifest();
|
|
mAssetTagsManifest->registerObject();
|
|
|
|
// Set asset tags module definition.
|
|
mAssetTagsModuleDefinition = pModuleDefinition;
|
|
|
|
// Save the asset tags.
|
|
saveAssetTags();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::saveAssetTags( void )
|
|
{
|
|
// Do we have an asset tags manifest?
|
|
if ( mAssetTagsManifest.isNull() || mAssetTagsModuleDefinition.isNull() )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Failed to save asset tags manifest as one is not loaded." );
|
|
return false;
|
|
}
|
|
|
|
// Expand manifest location.
|
|
char assetTagsManifestFilePathBuffer[1024];
|
|
Con::expandPath( assetTagsManifestFilePathBuffer, sizeof(assetTagsManifestFilePathBuffer), mAssetTagsModuleDefinition->getAssetTagsManifest() );
|
|
|
|
// Save asset tags manifest.
|
|
if ( !mTaml.write( mAssetTagsManifest, assetTagsManifestFilePathBuffer ) )
|
|
{
|
|
// Failed so warn.
|
|
Con::warnf( "Asset Manager: Failed to save asset tags manifest '%s' from module '%s'.", assetTagsManifestFilePathBuffer, mAssetTagsModuleDefinition->getSignature() );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::restoreAssetTags( void )
|
|
{
|
|
// Do we already have a manifest?
|
|
if ( mAssetTagsManifest.isNull() )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot restore asset tags manifest as one is not already loaded." );
|
|
return false;
|
|
}
|
|
|
|
// Sanity!
|
|
AssertFatal( mAssetTagsModuleDefinition != NULL, "Cannot restore asset tags manifest as module definition is NULL." );
|
|
|
|
// Delete existing asset tags manifest.
|
|
mAssetTagsManifest->deleteObject();
|
|
|
|
// Reload asset tags manifest.
|
|
return loadAssetTags( mAssetTagsModuleDefinition );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const char* AssetManager::getAssetLooseFiles(const char* pAssetId)
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_getAssetLooseFIles);
|
|
|
|
// Sanity!
|
|
AssertFatal(pAssetId != NULL, "Cannot look up NULL asset Id.");
|
|
|
|
// Find asset.
|
|
AssetDefinition* pAssetDefinition = findAsset(pAssetId);
|
|
|
|
// Did we find the asset?
|
|
if (pAssetDefinition == NULL)
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Failed to find asset Id '%s' as it does not exist.", pAssetId);
|
|
return String::EmptyString;
|
|
}
|
|
|
|
// Info.
|
|
if (mEchoInfo)
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf("Asset Manager: Started getting loose files of Asset Id '%s'...", pAssetId);
|
|
}
|
|
|
|
String looseFileList = "";
|
|
Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles;
|
|
for (Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr)
|
|
{
|
|
// Fetch loose file.
|
|
StringTableEntry looseFile = *looseFileItr;
|
|
|
|
looseFileList += looseFile;
|
|
|
|
if (looseFileItr != assetLooseFiles.end())
|
|
looseFileList += "\t";
|
|
}
|
|
|
|
char* ret = Con::getReturnBuffer(1024);
|
|
dSprintf(ret, 1024, "%s", looseFileList.c_str());
|
|
|
|
return ret;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 QSORT_CALLBACK descendingAssetDefinitionLoadCount(const void* a, const void* b)
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_DescendingAssetDefinitionLoadCount);
|
|
|
|
// Fetch asset definitions.
|
|
const AssetDefinition* pAssetDefinitionA = *(AssetDefinition**)a;
|
|
const AssetDefinition* pAssetDefinitionB = *(AssetDefinition**)b;
|
|
|
|
// Sort.
|
|
return pAssetDefinitionB->mAssetLoadedCount - pAssetDefinitionA->mAssetLoadedCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::dumpDeclaredAssets( void ) const
|
|
{
|
|
Vector<const AssetDefinition*> assetDefinitions;
|
|
|
|
// Iterate asset definitions.
|
|
for( typeDeclaredAssetsHash::const_iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
assetDefinitions.push_back( assetItr->value );
|
|
}
|
|
|
|
// Sort asset definitions.
|
|
dQsort( assetDefinitions.address(), assetDefinitions.size(), sizeof(const AssetDefinition*), descendingAssetDefinitionLoadCount );
|
|
|
|
// Info.
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: %d declared asset(s) dump as follows:", mDeclaredAssets.size() );
|
|
Con::printBlankLine();
|
|
|
|
// Iterate sorted asset definitions.
|
|
for ( Vector<const AssetDefinition*>::iterator assetItr = assetDefinitions.begin(); assetItr != assetDefinitions.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
const AssetDefinition* pAssetDefinition = *assetItr;
|
|
|
|
// Info.
|
|
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'",
|
|
pAssetDefinition->mAssetId,
|
|
pAssetDefinition->mpAssetBase == NULL ? 0 : pAssetDefinition->mpAssetBase->getAcquiredReferenceCount(),
|
|
pAssetDefinition->mAssetLoadedCount,
|
|
pAssetDefinition->mAssetUnloadedCount,
|
|
pAssetDefinition->mAssetAutoUnload,
|
|
pAssetDefinition->mpAssetBase != NULL,
|
|
pAssetDefinition->mAssetInternal,
|
|
pAssetDefinition->mAssetPrivate,
|
|
pAssetDefinition->mAssetType,
|
|
pAssetDefinition->mAssetPrivate ? "Private" : pAssetDefinition->mpModuleDefinition->getModuleId(),
|
|
pAssetDefinition->mAssetPrivate ? 0 : pAssetDefinition->mpModuleDefinition->getVersionId(),
|
|
pAssetDefinition->mAssetBaseFilePath );
|
|
}
|
|
|
|
// Info.
|
|
Con::printSeparator();
|
|
Con::printBlankLine();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findAllAssets( AssetQuery* pAssetQuery, const bool ignoreInternal, const bool ignorePrivate )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAllAssets);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Iterate declared assets.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetItr->value;
|
|
|
|
// Skip if internal and we're ignoring them.
|
|
if ( ignoreInternal && pAssetDefinition->mAssetInternal )
|
|
continue;
|
|
|
|
// Skip if private and we're ignoring them.
|
|
if ( ignorePrivate && pAssetDefinition->mAssetPrivate )
|
|
continue;
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back( pAssetDefinition->mAssetId );
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findAssetName( AssetQuery* pAssetQuery, const char* pAssetName, const bool partialName )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAssetName);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
AssertFatal( pAssetName != NULL, "Cannot use NULL asset name." );
|
|
|
|
// Reset asset name.
|
|
StringTableEntry assetName = NULL;
|
|
S32 partialAssetNameLength = 0;
|
|
|
|
// Are we doing partial name search?
|
|
if ( partialName )
|
|
{
|
|
// Yes, so fetch length of partial name.
|
|
partialAssetNameLength = dStrlen( pAssetName );
|
|
}
|
|
else
|
|
{
|
|
// No, so fetch asset name.
|
|
assetName = StringTable->insert( pAssetName );
|
|
}
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Iterate declared assets.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetItr->value;
|
|
|
|
// Are we doing partial name search?
|
|
if ( partialName )
|
|
{
|
|
// Yes, so fetch the length of this asset name.
|
|
const S32 currentAssetNameLength = dStrlen( pAssetDefinition->mAssetName );
|
|
|
|
// Skip if the query asset name is longer than the current asset name.
|
|
if ( partialAssetNameLength > currentAssetNameLength )
|
|
continue;
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( dStrnicmp( pAssetDefinition->mAssetName, pAssetName, partialAssetNameLength ) != 0 )
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// No, so skip if this is not the asset we want.
|
|
if ( assetName != pAssetDefinition->mAssetName )
|
|
continue;
|
|
}
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findAssetCategory( AssetQuery* pAssetQuery, const char* pAssetCategory, const bool assetQueryAsSource )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAssetCategory);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
AssertFatal( pAssetCategory != NULL, "Cannot use NULL asset category." );
|
|
|
|
// Fetch asset category.
|
|
StringTableEntry assetCategory = StringTable->insert( pAssetCategory );
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Use asset-query as the source?
|
|
if ( assetQueryAsSource )
|
|
{
|
|
AssetQuery filteredAssets;
|
|
|
|
// Yes, so iterate asset query.
|
|
for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr)
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( *assetItr );
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( pAssetDefinition == NULL ||
|
|
pAssetDefinition->mAssetCategory != assetCategory )
|
|
continue;
|
|
|
|
// Store as result.
|
|
filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
// Set asset query.
|
|
pAssetQuery->set( filteredAssets );
|
|
}
|
|
else
|
|
{
|
|
// No, so iterate declared assets.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetItr->value;
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( assetCategory != pAssetDefinition->mAssetCategory )
|
|
continue;
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
S32 AssetManager::findAssetAutoUnload( AssetQuery* pAssetQuery, const bool assetAutoUnload, const bool assetQueryAsSource )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAssetAutoUnload);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Use asset-query as the source?
|
|
if ( assetQueryAsSource )
|
|
{
|
|
AssetQuery filteredAssets;
|
|
|
|
// Yes, so iterate asset query.
|
|
for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr)
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( *assetItr );
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( pAssetDefinition == NULL ||
|
|
pAssetDefinition->mAssetAutoUnload != assetAutoUnload )
|
|
continue;
|
|
|
|
// Store as result.
|
|
filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
// Set asset query.
|
|
pAssetQuery->set( filteredAssets );
|
|
}
|
|
else
|
|
{
|
|
// No, so iterate declared assets.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetItr->value;
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( assetAutoUnload != pAssetDefinition->mAssetAutoUnload )
|
|
continue;
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findAssetInternal( AssetQuery* pAssetQuery, const bool assetInternal, const bool assetQueryAsSource )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAssetInternal);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Use asset-query as the source?
|
|
if ( assetQueryAsSource )
|
|
{
|
|
AssetQuery filteredAssets;
|
|
|
|
// Yes, so iterate asset query.
|
|
for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr)
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( *assetItr );
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( pAssetDefinition == NULL ||
|
|
pAssetDefinition->mAssetInternal != assetInternal )
|
|
continue;
|
|
|
|
// Store as result.
|
|
filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
// Set asset query.
|
|
pAssetQuery->set( filteredAssets );
|
|
}
|
|
else
|
|
{
|
|
// No, so iterate declared assets.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetItr->value;
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( assetInternal != pAssetDefinition->mAssetInternal )
|
|
continue;
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findAssetPrivate( AssetQuery* pAssetQuery, const bool assetPrivate, const bool assetQueryAsSource )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAssetPrivate);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Use asset-query as the source?
|
|
if ( assetQueryAsSource )
|
|
{
|
|
AssetQuery filteredAssets;
|
|
|
|
// Yes, so iterate asset query.
|
|
for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr)
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( *assetItr );
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( pAssetDefinition == NULL ||
|
|
pAssetDefinition->mAssetPrivate != assetPrivate )
|
|
continue;
|
|
|
|
// Store as result.
|
|
filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
// Set asset query.
|
|
pAssetQuery->set( filteredAssets );
|
|
}
|
|
else
|
|
{
|
|
// No, so iterate declared assets.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetItr->value;
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( assetPrivate != pAssetDefinition->mAssetPrivate )
|
|
continue;
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findAssetType( AssetQuery* pAssetQuery, const char* pAssetType, const bool assetQueryAsSource )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAssetType);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
AssertFatal( pAssetType != NULL, "Cannot use NULL asset type." );
|
|
|
|
// Fetch asset type.
|
|
StringTableEntry assetType = StringTable->insert( pAssetType );
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Use asset-query as the source?
|
|
if ( assetQueryAsSource )
|
|
{
|
|
AssetQuery filteredAssets;
|
|
|
|
// Yes, so iterate asset query.
|
|
for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr)
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( *assetItr );
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( pAssetDefinition == NULL ||
|
|
pAssetDefinition->mAssetType != assetType )
|
|
continue;
|
|
|
|
// Store as result.
|
|
filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
// Set asset query.
|
|
pAssetQuery->set( filteredAssets );
|
|
}
|
|
else
|
|
{
|
|
// No, so iterate declared assets.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetItr->value;
|
|
|
|
// Skip if this is not the asset we want.
|
|
if ( assetType != pAssetDefinition->mAssetType )
|
|
continue;
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findAssetDependsOn( AssetQuery* pAssetQuery, const char* pAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAssetDependsOn);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." );
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Find depends-on entry.
|
|
typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find( assetId );
|
|
|
|
// Iterate all dependencies.
|
|
while( dependsOnItr != mAssetDependsOn.end() && dependsOnItr->key == assetId )
|
|
{
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(dependsOnItr->value);
|
|
|
|
// Next dependency.
|
|
dependsOnItr++;
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findAssetIsDependedOn( AssetQuery* pAssetQuery, const char* pAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAssetIsDependedOn);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." );
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Find depended-on entry.
|
|
typeAssetIsDependedOnHash::Iterator dependedOnItr = mAssetIsDependedOn.find( assetId );
|
|
|
|
// Iterate all dependencies.
|
|
while( dependedOnItr != mAssetIsDependedOn.end() && dependedOnItr->key == assetId )
|
|
{
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(dependedOnItr->value);
|
|
|
|
// Next dependency.
|
|
dependedOnItr++;
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findInvalidAssetReferences( AssetQuery* pAssetQuery )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindInvalidAssetReferences);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Iterate referenced assets.
|
|
for( typeReferencedAssetsHash::Iterator assetItr = mReferencedAssets.begin(); assetItr != mReferencedAssets.end(); ++assetItr )
|
|
{
|
|
// Find asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( assetItr->key );
|
|
|
|
// Skip if the asset definition was found.
|
|
if ( pAssetDefinition != NULL )
|
|
continue;
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(assetItr->key);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findTaggedAssets( AssetQuery* pAssetQuery, const char* pAssetTagNames, const bool assetQueryAsSource )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindTaggedAssets);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
AssertFatal( pAssetTagNames != NULL, "Cannot use NULL asset tag name(s)." );
|
|
|
|
// Do we have an asset tag manifest?
|
|
if ( mAssetTagsManifest.isNull() )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Cannot find tagged assets as no asset tag manifest is present." );
|
|
return 0;
|
|
}
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
const char* pTagSeparators = " ,\t\n";
|
|
|
|
// Fetch tag count.
|
|
U32 assetTagCount = StringUnit::getUnitCount( pAssetTagNames, pTagSeparators );
|
|
|
|
// Fetch asset tags.
|
|
Vector<AssetTagsManifest::AssetTag*> assetTags;
|
|
for( U32 tagIndex = 0; tagIndex < assetTagCount; ++tagIndex )
|
|
{
|
|
// Fetch asset tag name.
|
|
const char* pTagName = StringUnit::getUnit( pAssetTagNames, tagIndex, pTagSeparators );
|
|
|
|
// Fetch asset tag.
|
|
AssetTagsManifest::AssetTag* pAssetTag = mAssetTagsManifest->findAssetTag( pTagName );
|
|
|
|
// Did we find the asset tag?
|
|
if ( pAssetTag == NULL )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "AssetTagsManifest: Asset Manager: Cannot find tagged assets of '%s' as it does not exist. Ignoring tag.", pTagName );
|
|
continue;
|
|
}
|
|
|
|
assetTags.push_back( pAssetTag );
|
|
}
|
|
|
|
// Fetch found asset tag count.
|
|
assetTagCount = assetTags.size();
|
|
|
|
// Did we find any tags?
|
|
if ( assetTagCount == 0 )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "AssetTagsManifest: Asset Manager: No specified tagged assets found in '%s'.", pAssetTagNames );
|
|
return 0;
|
|
}
|
|
|
|
// Use asset-query as the source?
|
|
if ( assetQueryAsSource )
|
|
{
|
|
AssetQuery filteredAssets;
|
|
|
|
// Yes, so iterate asset query.
|
|
for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr)
|
|
{
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = *assetItr;
|
|
|
|
// Skip if asset is not valid.
|
|
if ( !isDeclaredAsset( assetId ) )
|
|
continue;
|
|
|
|
// Reset matched flag.
|
|
bool assetTagMatched = false;
|
|
|
|
// Iterate asset tags.
|
|
for ( Vector<AssetTagsManifest::AssetTag*>::iterator assetTagItr = assetTags.begin(); assetTagItr != assetTags.end(); ++assetTagItr )
|
|
{
|
|
// Fetch asset tag.
|
|
AssetTagsManifest::AssetTag* pAssetTag = *assetTagItr;
|
|
|
|
// Skip if asset is not tagged.
|
|
if ( !pAssetTag->containsAsset( assetId ) )
|
|
continue;
|
|
|
|
// Flag as matched.
|
|
assetTagMatched = true;
|
|
break;
|
|
}
|
|
|
|
// Did we find a match?
|
|
if ( assetTagMatched )
|
|
{
|
|
// Yes, so is asset already present?
|
|
if ( !filteredAssets.containsAsset( assetId ) )
|
|
{
|
|
// No, so store as result.
|
|
filteredAssets.mAssetList.push_back(assetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set asset query.
|
|
pAssetQuery->set( filteredAssets );
|
|
}
|
|
else
|
|
{
|
|
// Iterate asset tags.
|
|
for ( Vector<AssetTagsManifest::AssetTag*>::iterator assetTagItr = assetTags.begin(); assetTagItr != assetTags.end(); ++assetTagItr )
|
|
{
|
|
// Fetch asset tag.
|
|
AssetTagsManifest::AssetTag* pAssetTag = *assetTagItr;
|
|
|
|
// Iterate tagged assets.
|
|
for ( Vector<typeAssetId>::iterator assetItr = pAssetTag->mAssets.begin(); assetItr != pAssetTag->mAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = *assetItr;
|
|
|
|
// Skip if asset Id is already present.
|
|
if ( pAssetQuery->containsAsset( assetId ) )
|
|
continue;
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(assetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
S32 AssetManager::findAssetLooseFile( AssetQuery* pAssetQuery, const char* pLooseFile, const bool assetQueryAsSource )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAssetLooseFile);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." );
|
|
AssertFatal( pLooseFile != NULL, "Cannot use NULL loose file." );
|
|
|
|
// Make game relative path for loose file.
|
|
StringTableEntry looseFile = Platform::makeRelativePathName(pLooseFile, NULL);;
|
|
|
|
// Reset result count.
|
|
S32 resultCount = 0;
|
|
|
|
// Use asset-query as the source?
|
|
if ( assetQueryAsSource )
|
|
{
|
|
AssetQuery filteredAssets;
|
|
|
|
// Yes, so iterate asset query.
|
|
for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr)
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = findAsset( *assetItr );
|
|
|
|
// Fetch loose files.
|
|
Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles;
|
|
|
|
// Skip if this asset has no loose files.
|
|
if ( assetLooseFiles.size() == 0 )
|
|
continue;
|
|
|
|
// Search the assets loose files.
|
|
for( Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr )
|
|
{
|
|
// Is this the loose file we are searching for?
|
|
if ( *looseFileItr != looseFile )
|
|
continue;
|
|
|
|
// Store as result.
|
|
filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set asset query.
|
|
pAssetQuery->set( filteredAssets );
|
|
}
|
|
else
|
|
{
|
|
// No, so iterate declared assets.
|
|
for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr )
|
|
{
|
|
// Fetch asset definition.
|
|
AssetDefinition* pAssetDefinition = assetItr->value;
|
|
|
|
// Fetch loose files.
|
|
Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles;
|
|
|
|
// Skip if this asset has no loose files.
|
|
if ( assetLooseFiles.size() == 0 )
|
|
continue;
|
|
|
|
// Search the assets loose files.
|
|
for( Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr )
|
|
{
|
|
// Is this the loose file we are searching for?
|
|
if ( *looseFileItr != looseFile )
|
|
continue;
|
|
|
|
// Store as result.
|
|
pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId);
|
|
|
|
// Increase result count.
|
|
resultCount++;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return resultCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
AssetManager::typeAssetDependsOnHash* AssetManager::getDependedOnAssets()
|
|
{
|
|
// Find any asset dependencies.
|
|
return &mAssetDependsOn;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
S32 AssetManager::getAssetLooseFileCount(const char* pAssetId)
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_getAssetLooseFileCount);
|
|
|
|
// Sanity!
|
|
AssertFatal(pAssetId != NULL, "Cannot get loose files for NULL asset Id.");
|
|
|
|
// Find asset.
|
|
AssetDefinition* pAssetDefinition = findAsset(pAssetId);
|
|
|
|
// Did we find the asset?
|
|
if (pAssetDefinition == NULL)
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Failed to get loose files for asset Id '%s' as it does not exist.", pAssetId);
|
|
return false;
|
|
}
|
|
|
|
S32 looseFileCount = pAssetDefinition->mAssetLooseFiles.size();
|
|
|
|
// Cleanup our reference
|
|
pAssetDefinition = NULL;
|
|
|
|
return looseFileCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const char* AssetManager::getAssetLooseFile(const char* pAssetId, const S32& index)
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_getAssetLooseFile);
|
|
|
|
// Sanity!
|
|
AssertFatal(pAssetId != NULL, "Cannot get loose file for NULL asset Id.");
|
|
|
|
// Find asset.
|
|
AssetDefinition* pAssetDefinition = findAsset(pAssetId);
|
|
|
|
// Did we find the asset?
|
|
if (pAssetDefinition == NULL)
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Failed to get loose file for asset Id '%s' as it does not exist.", pAssetId);
|
|
return StringTable->EmptyString();
|
|
}
|
|
|
|
if(index < 0 || index >= pAssetDefinition->mAssetLooseFiles.size())
|
|
{
|
|
Con::warnf("Asset Manager : Failed to get loose file for asset Id '%s' as the index was out of range.", pAssetId);
|
|
}
|
|
|
|
StringTableEntry looseFile = pAssetDefinition->mAssetLooseFiles[index];
|
|
|
|
// Cleanup our reference
|
|
pAssetDefinition = NULL;
|
|
|
|
return looseFile;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::scanDeclaredAssets( const char* pPath, const char* pExtension, const bool recurse, ModuleDefinition* pModuleDefinition )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_ScanDeclaredAssets);
|
|
|
|
// Sanity!
|
|
AssertFatal( pPath != NULL, "Cannot scan declared assets with NULL path." );
|
|
AssertFatal( pExtension != NULL, "Cannot scan declared assets with NULL extension." );
|
|
|
|
// Expand path location.
|
|
String relativePath = Platform::makeRelativePathName(pPath, NULL);
|
|
// Strip any trailing slash off the path.
|
|
if (relativePath.endsWith("/"))
|
|
relativePath = relativePath.substr(0, relativePath.length() - 1);
|
|
|
|
Torque::Path scanPath = Torque::FS::GetCwd();
|
|
scanPath.setPath(relativePath);
|
|
|
|
// Find files.
|
|
Vector<String> files;
|
|
S32 numAssets = Torque::FS::FindByPattern(scanPath, pExtension, recurse, files, true);
|
|
if (numAssets <= 0)
|
|
{
|
|
// Failed so warn. or don't... Common error when scanning modules with no assets
|
|
//Con::warnf( "Asset Manager: No declared assets found in directory '%s'.", relativePath.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Is the asset file-path located within the specified module?
|
|
if ( !Con::isBasePath(relativePath.c_str(), pModuleDefinition->getModulePath()) )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Could not add declared asset file '%s' as file does not exist with module path '%s'",
|
|
pPath,
|
|
pModuleDefinition->getModulePath() );
|
|
return false;
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Scanning for declared assets in path '%s' for files with extension '%s'...", relativePath.c_str(), pExtension );
|
|
}
|
|
|
|
// Fetch module assets.
|
|
ModuleDefinition::typeModuleAssetsVector& moduleAssets = pModuleDefinition->getModuleAssets();
|
|
|
|
TamlAssetDeclaredVisitor assetDeclaredVisitor;
|
|
|
|
// Iterate files.
|
|
for (S32 i = 0; i < numAssets; ++i)
|
|
{
|
|
Torque::Path assetPath = files[i];
|
|
|
|
Torque::Path compiledPath = assetPath;
|
|
compiledPath.setExtension(mTaml.getAutoFormatBinaryExtension());
|
|
|
|
if (Torque::FS::IsFile(compiledPath))
|
|
{
|
|
Torque::FS::FileNodeRef assetFile = Torque::FS::GetFileNode(assetPath);
|
|
Torque::FS::FileNodeRef compiledFile = Torque::FS::GetFileNode(compiledPath);
|
|
|
|
if (assetFile != NULL && compiledFile != NULL)
|
|
{
|
|
if (compiledFile->getModifiedTime() >= assetFile->getModifiedTime())
|
|
assetPath = compiledPath;
|
|
}
|
|
}
|
|
|
|
// Clear declared assets.
|
|
assetDeclaredVisitor.clear();
|
|
|
|
// Format full file-path.
|
|
char assetFileBuffer[1024];
|
|
dSprintf( assetFileBuffer, sizeof(assetFileBuffer), "%s/%s", assetPath.getPath().c_str(), assetPath.getFullFileName().c_str());
|
|
|
|
// Parse the filename.
|
|
if ( !mTaml.parse( assetFileBuffer, assetDeclaredVisitor ) )
|
|
{
|
|
// Warn.
|
|
Con::warnf( "Asset Manager: Failed to parse file containing asset declaration: '%s'.", assetFileBuffer );
|
|
continue;
|
|
}
|
|
|
|
// Fetch asset definition.
|
|
AssetDefinition& foundAssetDefinition = assetDeclaredVisitor.getAssetDefinition();
|
|
|
|
// Did we get an asset name?
|
|
if ( foundAssetDefinition.mAssetName == StringTable->EmptyString() )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf( "Asset Manager: Parsed file '%s' but did not encounter an asset.", assetFileBuffer );
|
|
continue;
|
|
}
|
|
|
|
// Set module definition.
|
|
foundAssetDefinition.mpModuleDefinition = pModuleDefinition;
|
|
|
|
// Format asset Id.
|
|
char assetIdBuffer[1024];
|
|
dSprintf(assetIdBuffer, sizeof(assetIdBuffer), "%s%s%s",
|
|
pModuleDefinition->getModuleId(),
|
|
ASSET_SCOPE_TOKEN,
|
|
foundAssetDefinition.mAssetName );
|
|
|
|
// Set asset Id.
|
|
foundAssetDefinition.mAssetId = StringTable->insert( assetIdBuffer );
|
|
|
|
// Does this asset already exist?
|
|
if ( mDeclaredAssets.contains( foundAssetDefinition.mAssetId ) )
|
|
{
|
|
// Yes, so warn.
|
|
Con::warnf( "Asset Manager: Encountered asset Id '%s' in asset file '%s' but it conflicts with existing asset Id in asset file '%s'.",
|
|
foundAssetDefinition.mAssetId,
|
|
foundAssetDefinition.mAssetBaseFilePath,
|
|
mDeclaredAssets.find( foundAssetDefinition.mAssetId )->value->mAssetBaseFilePath );
|
|
|
|
continue;
|
|
}
|
|
|
|
// Create new asset definition.
|
|
AssetDefinition* pAssetDefinition = new AssetDefinition( foundAssetDefinition );
|
|
|
|
// Store in declared assets.
|
|
mDeclaredAssets.insert( pAssetDefinition->mAssetId, pAssetDefinition );
|
|
|
|
// Store in module assets.
|
|
moduleAssets.push_back( pAssetDefinition );
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Adding Asset Id '%s' of type '%s' in asset file '%s'.",
|
|
pAssetDefinition->mAssetId,
|
|
pAssetDefinition->mAssetType,
|
|
pAssetDefinition->mAssetBaseFilePath );
|
|
}
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = pAssetDefinition->mAssetId;
|
|
|
|
// Fetch asset dependencies.
|
|
TamlAssetDeclaredVisitor::typeAssetIdVector& assetDependencies = assetDeclaredVisitor.getAssetDependencies();
|
|
|
|
// Are there any asset dependencies?
|
|
if ( assetDependencies.size() > 0 )
|
|
{
|
|
// Yes, so iterate dependencies.
|
|
for( TamlAssetDeclaredVisitor::typeAssetIdVector::iterator assetDependencyItr = assetDependencies.begin(); assetDependencyItr != assetDependencies.end(); ++assetDependencyItr )
|
|
{
|
|
// Fetch asset Ids.
|
|
StringTableEntry dependencyAssetId = *assetDependencyItr;
|
|
|
|
// Insert depends-on.
|
|
mAssetDependsOn.insertEqual( assetId, dependencyAssetId );
|
|
|
|
// Insert is-depended-on.
|
|
mAssetIsDependedOn.insertEqual( dependencyAssetId, assetId );
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: Asset Id '%s' has dependency of Asset Id '%s'", assetId, dependencyAssetId );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fetch asset loose files.
|
|
TamlAssetDeclaredVisitor::typeLooseFileVector& assetLooseFiles = assetDeclaredVisitor.getAssetLooseFiles();
|
|
|
|
// Are there any loose files?
|
|
if ( assetLooseFiles.size() > 0 )
|
|
{
|
|
// Yes, so iterate loose files.
|
|
for( TamlAssetDeclaredVisitor::typeLooseFileVector::iterator assetLooseFileItr = assetLooseFiles.begin(); assetLooseFileItr != assetLooseFiles.end(); ++assetLooseFileItr )
|
|
{
|
|
// Fetch loose file.
|
|
StringTableEntry looseFile = *assetLooseFileItr;
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: Asset Id '%s' has loose file '%s'.", assetId, looseFile );
|
|
}
|
|
|
|
// Store loose file.
|
|
pAssetDefinition->mAssetLooseFiles.push_back( looseFile );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: ... Finished scanning for declared assets in path '%s' for files with extension '%s'.", relativePath.c_str(), pExtension );
|
|
Con::printSeparator();
|
|
Con::printBlankLine();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool AssetManager::scanReferencedAssets( const char* pPath, const char* pExtension, const bool recurse )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_ScanReferencedAssets);
|
|
|
|
// Sanity!
|
|
AssertFatal( pPath != NULL, "Cannot scan referenced assets with NULL path." );
|
|
AssertFatal( pExtension != NULL, "Cannot scan referenced assets with NULL extension." );
|
|
|
|
// Expand path location.
|
|
String relativePath = Platform::makeRelativePathName(pPath, NULL);
|
|
String pattern = "*.";
|
|
pattern += pExtension;
|
|
|
|
Torque::Path scanPath = Torque::FS::GetCwd();
|
|
scanPath.setPath(relativePath);
|
|
|
|
// Find files.
|
|
Vector<String> files;
|
|
S32 numAssets = Torque::FS::FindByPattern(scanPath, pattern, recurse, files, true);
|
|
if (numAssets <= 0)
|
|
{
|
|
// Failed so warn.
|
|
Con::warnf( "Asset Manager: Failed to scan referenced assets in directory '%s'.", pPath );
|
|
return false;
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
Con::printf( "Asset Manager: Scanning for referenced assets in path '%s' for files with extension '%s'...", pPath, pExtension );
|
|
}
|
|
|
|
TamlAssetReferencedVisitor assetReferencedVisitor;
|
|
|
|
// Iterate files.
|
|
for (S32 i = 0; i < numAssets; ++i)
|
|
{
|
|
Torque::Path assetPath = files[i];
|
|
|
|
// Clear referenced assets.
|
|
assetReferencedVisitor.clear();
|
|
|
|
// Format full file-path.
|
|
char assetFileBuffer[1024];
|
|
dSprintf( assetFileBuffer, sizeof(assetFileBuffer), "%s/%s", assetPath.getPath().c_str(), assetPath.getFullFileName().c_str());
|
|
|
|
// Format reference file-path.
|
|
typeReferenceFilePath referenceFilePath = StringTable->insert( assetFileBuffer );
|
|
|
|
// Parse the filename.
|
|
if ( !mTaml.parse( referenceFilePath, assetReferencedVisitor ) )
|
|
{
|
|
// Warn.
|
|
Con::warnf( "Asset Manager: Failed to parse file containing asset references: '%s'.", referenceFilePath );
|
|
continue;
|
|
}
|
|
|
|
// Fetch usage map.
|
|
const TamlAssetReferencedVisitor::typeAssetReferencedHash& assetReferencedMap = assetReferencedVisitor.getAssetReferencedMap();
|
|
|
|
// Do we have any asset references?
|
|
if ( assetReferencedMap.size() > 0 )
|
|
{
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printSeparator();
|
|
}
|
|
|
|
// Iterate usage.
|
|
for( TamlAssetReferencedVisitor::typeAssetReferencedHash::const_iterator usageItr = assetReferencedMap.begin(); usageItr != assetReferencedMap.end(); ++usageItr )
|
|
{
|
|
// Fetch asset name.
|
|
typeAssetId assetId = usageItr->key;
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: Found referenced Asset Id '%s' in file '%s'.", assetId, referenceFilePath );
|
|
}
|
|
|
|
// Add referenced asset.
|
|
addReferencedAsset( assetId, referenceFilePath );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: ... Finished scanning for referenced assets in path '%s' for files with extension '%s'.", relativePath.c_str(), pExtension );
|
|
Con::printSeparator();
|
|
Con::printBlankLine();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
AssetDefinition* AssetManager::findAsset( const char* pAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_FindAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetId != NULL, "Cannot find NULL asset Id." );
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Find declared asset.
|
|
typeDeclaredAssetsHash::iterator declaredAssetItr = mDeclaredAssets.find( assetId );
|
|
|
|
// Find if we didn't find a declared asset Id.
|
|
if ( declaredAssetItr == mDeclaredAssets.end() )
|
|
return NULL;
|
|
|
|
return declaredAssetItr->value;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::addReferencedAsset( StringTableEntry assetId, StringTableEntry referenceFilePath )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_AddReferencedAsset);
|
|
|
|
// Sanity!
|
|
AssertFatal( assetId != NULL, "Cannot add referenced asset with NULL asset Id." );
|
|
AssertFatal( referenceFilePath != NULL, "Cannot add referenced asset with NULL reference file-path." );
|
|
|
|
// Find referenced asset.
|
|
typeReferencedAssetsHash::Iterator referencedAssetItr = mReferencedAssets.find( assetId );
|
|
|
|
// Did we find the asset?
|
|
if ( referencedAssetItr == mReferencedAssets.end() )
|
|
{
|
|
// No, so add asset Id.
|
|
mReferencedAssets.insertEqual( assetId, referenceFilePath );
|
|
}
|
|
else
|
|
{
|
|
// Yes, so add asset Id with a unique file.
|
|
while( true )
|
|
{
|
|
// Finish if this file is already present.
|
|
if ( referencedAssetItr->value == referenceFilePath )
|
|
return;
|
|
|
|
// Move to next asset Id.
|
|
referencedAssetItr++;
|
|
|
|
// Is this the end of referenced assets or a different asset Id?
|
|
if ( referencedAssetItr == mReferencedAssets.end() ||
|
|
referencedAssetItr->key != assetId )
|
|
{
|
|
// Yes, so add asset reference.
|
|
mReferencedAssets.insertEqual( assetId, referenceFilePath );
|
|
return;
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::renameAssetReferences( StringTableEntry assetIdFrom, StringTableEntry assetIdTo )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RenameAssetReferences);
|
|
|
|
// Sanity!
|
|
AssertFatal( assetIdFrom != NULL, "Cannot rename asset references using NULL asset Id from." );
|
|
AssertFatal( assetIdTo != NULL, "Cannot rename asset references using NULL asset Id to." );
|
|
|
|
// Finish if the asset is not referenced.
|
|
if ( !mReferencedAssets.count( assetIdFrom ) )
|
|
return;
|
|
|
|
// Setup referenced update visitor.
|
|
TamlAssetReferencedUpdateVisitor assetReferencedUpdateVisitor;
|
|
assetReferencedUpdateVisitor.setAssetIdFrom( assetIdFrom );
|
|
assetReferencedUpdateVisitor.setAssetIdTo( assetIdTo );
|
|
|
|
// Find first referenced asset Id.
|
|
typeReferencedAssetsHash::Iterator referencedAssetItr = mReferencedAssets.find( assetIdFrom );
|
|
|
|
// Iterate references.
|
|
while( true )
|
|
{
|
|
// Finish if end of references.
|
|
if ( referencedAssetItr == mReferencedAssets.end() || referencedAssetItr->key != assetIdFrom )
|
|
return;
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: Renaming declared Asset Id '%s' to Asset Id '%s'. Updating referenced file '%s'",
|
|
assetIdFrom,
|
|
assetIdTo,
|
|
referencedAssetItr->value );
|
|
}
|
|
|
|
// Update asset file declaration.
|
|
if ( !mTaml.parse( referencedAssetItr->value, assetReferencedUpdateVisitor ) )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as the referenced asset file could not be parsed: %s",
|
|
assetIdFrom, assetIdTo, referencedAssetItr->value );
|
|
}
|
|
|
|
// Move to next reference.
|
|
referencedAssetItr++;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::removeAssetReferences( StringTableEntry assetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RemoveAssetReferences);
|
|
|
|
// Sanity!
|
|
AssertFatal( assetId != NULL, "Cannot rename asset references using NULL asset Id." );
|
|
|
|
// Finish if the asset is not referenced.
|
|
if ( !mReferencedAssets.count( assetId ) )
|
|
return;
|
|
|
|
// Setup referenced update visitor.
|
|
TamlAssetReferencedUpdateVisitor assetReferencedUpdateVisitor;
|
|
assetReferencedUpdateVisitor.setAssetIdFrom( assetId );
|
|
assetReferencedUpdateVisitor.setAssetIdTo( StringTable->EmptyString() );
|
|
|
|
// Find first referenced asset Id.
|
|
typeReferencedAssetsHash::Iterator referencedAssetItr = mReferencedAssets.find(assetId);
|
|
|
|
// Iterate references.
|
|
while( true )
|
|
{
|
|
// Finish if end of references.
|
|
if ( referencedAssetItr == mReferencedAssets.end() || referencedAssetItr->key != assetId )
|
|
break;
|
|
|
|
// Info.
|
|
if ( mEchoInfo )
|
|
{
|
|
Con::printf( "Asset Manager: Removing Asset Id '%s' references from file '%s'",
|
|
assetId,
|
|
referencedAssetItr->value );
|
|
}
|
|
|
|
// Update asset file declaration.
|
|
if ( !mTaml.parse( referencedAssetItr->value, assetReferencedUpdateVisitor ) )
|
|
{
|
|
// No, so warn.
|
|
Con::warnf("Asset Manager: Cannot remove referenced asset Id '%s' as the referenced asset file could not be parsed: %s",
|
|
assetId,
|
|
referencedAssetItr->value );
|
|
}
|
|
|
|
// Move to next reference.
|
|
referencedAssetItr++;
|
|
}
|
|
|
|
// Remove asset references.
|
|
mReferencedAssets.erase( assetId );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::renameAssetDependencies( StringTableEntry assetIdFrom, StringTableEntry assetIdTo )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RenameAssetDependencies);
|
|
|
|
// Sanity!
|
|
AssertFatal( assetIdFrom != NULL, "Cannot rename asset dependencies using NULL asset Id from." );
|
|
AssertFatal( assetIdTo != NULL, "Cannot rename asset dependencies using NULL asset Id to." );
|
|
|
|
// Rename via depends-on...
|
|
while( mAssetDependsOn.count( assetIdFrom ) > 0 )
|
|
{
|
|
// Find depends-on.
|
|
typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find(assetIdFrom);
|
|
|
|
// Fetch dependency asset Id.
|
|
StringTableEntry dependencyAssetId = dependsOnItr->value;
|
|
|
|
// Find is-depends-on entry.
|
|
typeAssetIsDependedOnHash::Iterator isDependedOnItr = mAssetIsDependedOn.find(dependencyAssetId);
|
|
|
|
// Sanity!
|
|
AssertFatal( isDependedOnItr != mAssetIsDependedOn.end(), "Asset dependencies are corrupt!" );
|
|
|
|
while( isDependedOnItr != mAssetIsDependedOn.end() && isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value != assetIdFrom )
|
|
{
|
|
isDependedOnItr++;
|
|
}
|
|
|
|
// Sanity!
|
|
AssertFatal( isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value == assetIdFrom, "Asset dependencies are corrupt!" );
|
|
|
|
// Remove is-depended-on.
|
|
mAssetIsDependedOn.erase( isDependedOnItr );
|
|
|
|
// Remove depends-on.
|
|
mAssetDependsOn.erase( dependsOnItr );
|
|
|
|
// Insert depends-on.
|
|
mAssetDependsOn.insertEqual( assetIdTo, dependencyAssetId );
|
|
|
|
// Insert is-depended-on.
|
|
mAssetIsDependedOn.insertEqual( dependencyAssetId, assetIdTo );
|
|
}
|
|
|
|
// Rename via is-depended-on...
|
|
while( mAssetIsDependedOn.count( assetIdFrom ) > 0 )
|
|
{
|
|
// Find is-depended-on.
|
|
typeAssetIsDependedOnHash::Iterator isdependedOnItr = mAssetIsDependedOn.find(assetIdFrom);
|
|
|
|
// Fetch dependency asset Id.
|
|
StringTableEntry dependencyAssetId = isdependedOnItr->value;
|
|
|
|
// Find depends-on entry.
|
|
typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find(dependencyAssetId);
|
|
|
|
// Sanity!
|
|
AssertFatal( dependsOnItr != mAssetDependsOn.end(), "Asset dependencies are corrupt!" );
|
|
|
|
while( dependsOnItr != mAssetDependsOn.end() && dependsOnItr->key == dependencyAssetId && dependsOnItr->value != assetIdFrom )
|
|
{
|
|
dependsOnItr++;
|
|
}
|
|
|
|
// Sanity!
|
|
AssertFatal( dependsOnItr->key == dependencyAssetId && dependsOnItr->value == assetIdFrom, "Asset dependencies are corrupt!" );
|
|
|
|
// Remove is-depended-on.
|
|
mAssetIsDependedOn.erase( isdependedOnItr );
|
|
|
|
// Remove depends-on.
|
|
mAssetDependsOn.erase( dependsOnItr );
|
|
|
|
// Insert depends-on.
|
|
mAssetDependsOn.insertEqual( dependencyAssetId, assetIdTo );
|
|
|
|
// Insert is-depended-on.
|
|
mAssetIsDependedOn.insertEqual( assetIdTo, dependencyAssetId );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::removeAssetDependencies( const char* pAssetId )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_RemvoeAsetDependencies);
|
|
|
|
// Sanity!
|
|
AssertFatal( pAssetId != NULL, "Cannot remove asset dependencies using NULL asset Id." );
|
|
|
|
// Fetch asset Id.
|
|
StringTableEntry assetId = StringTable->insert( pAssetId );
|
|
|
|
// Remove from depends-on assets.
|
|
while( mAssetDependsOn.count( assetId ) > 0 )
|
|
{
|
|
// Find depends-on.
|
|
typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find(assetId);
|
|
|
|
// Fetch dependency asset Id.
|
|
StringTableEntry dependencyAssetId = dependsOnItr->value;
|
|
|
|
// Find is-depends-on entry.
|
|
typeAssetIsDependedOnHash::Iterator isDependedOnItr = mAssetIsDependedOn.find(dependencyAssetId);
|
|
|
|
// Sanity!
|
|
AssertFatal( isDependedOnItr != mAssetIsDependedOn.end(), "Asset dependencies are corrupt!" );
|
|
|
|
while( isDependedOnItr != mAssetIsDependedOn.end() && isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value != assetId )
|
|
{
|
|
isDependedOnItr++;
|
|
}
|
|
|
|
// Sanity!
|
|
AssertFatal( isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value == assetId, "Asset dependencies are corrupt!" );
|
|
|
|
// Remove is-depended-on.
|
|
mAssetIsDependedOn.erase( isDependedOnItr );
|
|
|
|
// Remove depends-on.
|
|
mAssetDependsOn.erase( dependsOnItr );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::unloadAsset( AssetDefinition* pAssetDefinition )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_UnloadAsset);
|
|
|
|
pAssetDefinition->mpAssetBase->unloadAsset();
|
|
|
|
// Destroy the asset.
|
|
if(pAssetDefinition->mpAssetBase->isProperlyAdded())
|
|
pAssetDefinition->mpAssetBase->deleteObject();
|
|
|
|
// Increase unloaded count.
|
|
pAssetDefinition->mAssetUnloadedCount++;
|
|
|
|
// Is the asset internal?
|
|
if ( pAssetDefinition->mAssetInternal )
|
|
{
|
|
// Yes, so decrease internal loaded asset count.
|
|
mLoadedInternalAssetsCount--;
|
|
}
|
|
else
|
|
{
|
|
// No, so decrease external loaded assets count.
|
|
mLoadedExternalAssetsCount--;
|
|
}
|
|
|
|
// Is the asset private?
|
|
if ( pAssetDefinition->mAssetPrivate )
|
|
{
|
|
// Yes, so decrease private loaded asset count.
|
|
mLoadedPrivateAssetsCount--;
|
|
|
|
// Remove it completely.
|
|
removeDeclaredAsset( pAssetDefinition->mAssetId );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::onModulePreLoad( ModuleDefinition* pModuleDefinition )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_OnModulePreLoad);
|
|
|
|
// Add module declared assets.
|
|
addModuleDeclaredAssets( pModuleDefinition );
|
|
|
|
// Load any auto-loaded asset types
|
|
loadModuleAutoLoadAssets(pModuleDefinition);
|
|
|
|
// Is an asset tags manifest specified?
|
|
if ( pModuleDefinition->getAssetTagsManifest() != StringTable->EmptyString() )
|
|
{
|
|
// Yes, so load the asset tags manifest.
|
|
loadAssetTags( pModuleDefinition );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::onModulePreUnload( ModuleDefinition* pModuleDefinition )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_OnModulePreUnload);
|
|
|
|
// Is an asset tags manifest specified?
|
|
if ( pModuleDefinition->getAssetTagsManifest() != StringTable->EmptyString() )
|
|
{
|
|
// Yes, so save the asset tags manifest.
|
|
saveAssetTags();
|
|
|
|
// Do we have an asset tags manifest?
|
|
if ( !mAssetTagsManifest.isNull() )
|
|
{
|
|
// Yes, so remove it.
|
|
mAssetTagsManifest->deleteObject();
|
|
mAssetTagsModuleDefinition = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void AssetManager::onModulePostUnload( ModuleDefinition* pModuleDefinition )
|
|
{
|
|
// Debug Profiling.
|
|
PROFILE_SCOPE(AssetManager_OnModulePostUnload);
|
|
|
|
// Remove declared assets.
|
|
removeDeclaredAssets( pModuleDefinition );
|
|
}
|