assetTagsManifest.cpp
Engine/source/assets/assetTagsManifest.cpp
Public Functions
Detailed Description
Public Functions
IMPLEMENT_CONOBJECT(AssetTagsManifest )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2013 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#ifndef _ASSET_TAGS_MANIFEST_H_ 25#include "assetTagsManifest.h" 26#endif 27 28#ifndef _ASSET_MANAGER_H_ 29#include "assetManager.h" 30#endif 31 32#ifndef _CONSOLETYPES_H_ 33#include "console/consoleTypes.h" 34#endif 35 36// Script binding. 37#include "assetTagsManifest_ScriptBinding.h" 38 39//----------------------------------------------------------------------------- 40 41IMPLEMENT_CONOBJECT( AssetTagsManifest ); 42 43//----------------------------------------------------------------------------- 44 45AssetTagsManifest::AssetTagsManifest() 46{ 47} 48 49//----------------------------------------------------------------------------- 50 51AssetTagsManifest::~AssetTagsManifest() 52{ 53 // Iterate tags. 54 for( typeTagNameHash::iterator tagNameItr = mTagNameDatabase.begin(); tagNameItr != mTagNameDatabase.end(); ++tagNameItr ) 55 { 56 // Delete asset tag. 57 delete tagNameItr->value; 58 } 59 60 // Clear database. 61 mTagNameDatabase.clear(); 62 mAssetToTagDatabase.clear(); 63} 64 65//----------------------------------------------------------------------------- 66 67StringTableEntry AssetTagsManifest::fetchTagName( const char* pTagName ) 68{ 69 // Sanity! 70 AssertFatal( pTagName != NULL, "Cannot use a NULL tag name." ); 71 72 return StringTable->insert( pTagName, true ); 73} 74 75//----------------------------------------------------------------------------- 76 77AssetTagsManifest::AssetTag* AssetTagsManifest::findAssetTag( const char* pTagName ) 78{ 79 // Fetch tag name. 80 StringTableEntry tagName = fetchTagName( pTagName ); 81 82 // Finish if the tag already exists. 83 typeTagNameHash::iterator tagNameItr = mTagNameDatabase.find( tagName ); 84 85 return tagNameItr == mTagNameDatabase.end() ? NULL : tagNameItr->value; 86} 87 88//----------------------------------------------------------------------------- 89 90void AssetTagsManifest::renameAssetId( const char* pAssetIdFrom, const char* pAssetIdTo ) 91{ 92 // Sanity! 93 AssertFatal( pAssetIdFrom != NULL, "Cannot rename from NULL asset Id." ); 94 AssertFatal( pAssetIdTo != NULL, "Cannot rename to NULL asset Id." ); 95 96 // Fetch asset Ids. 97 StringTableEntry assetIdFrom = StringTable->insert( pAssetIdFrom ); 98 StringTableEntry assetIdTo = StringTable->insert( pAssetIdTo ); 99 100 while( true ) 101 { 102 // Find asset Id. 103 typeAssetToTagHash::Iterator assetIdItr = mAssetToTagDatabase.find( assetIdFrom ); 104 105 // Finish if no asset Id to rename. 106 if ( assetIdItr == mAssetToTagDatabase.end() ) 107 return; 108 109 // Fetch asset tag. 110 AssetTag* pAssetTag = assetIdItr->value; 111 112 // Untag old asset Id. 113 untag( assetIdFrom, pAssetTag->mTagName ); 114 115 // Tag new asset Id. 116 tag( assetIdTo, pAssetTag->mTagName ); 117 } 118} 119 120//----------------------------------------------------------------------------- 121 122void AssetTagsManifest::onTamlCustomWrite( TamlCustomNodes& customNodes ) 123{ 124 // Call parent. 125 Parent::onTamlCustomWrite( customNodes ); 126 127 // Finish if no tags. 128 if ( mTagNameDatabase.size() == 0 ) 129 return; 130 131 // Add node. 132 TamlCustomNode* pTagsNode = customNodes.addNode( ASSETTAGS_TAGS_NODE_NAME ); 133 134 // Iterate tags. 135 for( typeTagNameHash::iterator tagItr = mTagNameDatabase.begin(); tagItr != mTagNameDatabase.end(); ++tagItr ) 136 { 137 // Add tag node. 138 TamlCustomNode* pTagNode = pTagsNode->addNode( ASSETTAGS_TAGS_TYPE_NAME ); 139 140 // Add fields. 141 pTagNode->addField( ASSETTAGS_TAGS_NAME_FIELD, tagItr->key ); 142 } 143 144 // Add node. 145 TamlCustomNode* pAssetTagsNode = customNodes.addNode( ASSETTAGS_ASSETS_NODE_NAME ); 146 147 // Iterate asset locations. 148 for( typeAssetToTagHash::Iterator assetTagItr = mAssetToTagDatabase.begin(); assetTagItr != mAssetToTagDatabase.end(); ++assetTagItr ) 149 { 150 // Add asset tag node. 151 TamlCustomNode* pAssetNode = pAssetTagsNode->addNode( ASSETTAGS_ASSETS_TYPE_NAME ); 152 153 // Add fields. 154 pAssetNode->addField( ASSETTAGS_ASSETS_ASSETID_FIELD, assetTagItr->key ); 155 pAssetNode->addField( ASSETTAGS_ASSETS_TAG_FIELD, assetTagItr->value->mTagName ); 156 } 157} 158 159//----------------------------------------------------------------------------- 160 161void AssetTagsManifest::onTamlCustomRead( const TamlCustomNodes& customNodes ) 162{ 163 // Call parent. 164 Parent::onTamlCustomRead( customNodes ); 165 166 // Find tags nodes. 167 const TamlCustomNode* pTagProperty = customNodes.findNode( ASSETTAGS_TAGS_NODE_NAME ); 168 169 // Finish if we don't have a tags node name. 170 if ( pTagProperty == NULL ) 171 return; 172 173 // Fetch node name. 174 StringTableEntry tagNodeName = StringTable->insert( ASSETTAGS_TAGS_TYPE_NAME ); 175 176 // Fetch children asset nodes. 177 const TamlCustomNodeVector& tagNodes = pTagProperty->getChildren(); 178 179 // Iterate tag nodes. 180 for( TamlCustomNodeVector::const_iterator tagNodeItr = tagNodes.begin(); tagNodeItr != tagNodes.end(); ++tagNodeItr ) 181 { 182 // Fetch tag node. 183 const TamlCustomNode* pTagNode = *tagNodeItr; 184 185 // Skip if an unknown node name. 186 if ( pTagNode->getNodeName() != tagNodeName ) 187 continue; 188 189 // Fetch "Name" field. 190 const TamlCustomField* pTagNameField = pTagNode->findField( ASSETTAGS_TAGS_NAME_FIELD ); 191 192 // Do we find the field? 193 if ( pTagNameField == NULL ) 194 { 195 // No, so warn. 196 Con::warnf( "AssetTagsManifest::onTamlCustomRead() - Could not find '%s' field.", ASSETTAGS_TAGS_NAME_FIELD ); 197 continue; 198 } 199 200 // Create the tag. 201 createTag( pTagNameField->getFieldValue() ); 202 } 203 204 // Find asset tags node. 205 const TamlCustomNode* pAssetTagProperty = customNodes.findNode( ASSETTAGS_ASSETS_NODE_NAME ); 206 207 // Finish if we don't have an asset tags node name. 208 if ( pAssetTagProperty == NULL ) 209 return; 210 211 // Fetch node name. 212 StringTableEntry assetTagNodeName = StringTable->insert( ASSETTAGS_ASSETS_TYPE_NAME ); 213 214 // Fetch children asset tag nodes. 215 const TamlCustomNodeVector& assetTagNodes = pAssetTagProperty->getChildren(); 216 217 // Iterate property alias. 218 for( TamlCustomNodeVector::const_iterator assetTagNodeItr = assetTagNodes.begin(); assetTagNodeItr != assetTagNodes.end(); ++assetTagNodeItr ) 219 { 220 // Fetch asset node. 221 const TamlCustomNode* pAssetTagNode = *assetTagNodeItr; 222 223 // Skip if an unknown node name. 224 if ( pAssetTagNode->getNodeName() != assetTagNodeName ) 225 continue; 226 227 // Fetch "AssetId" field. 228 const TamlCustomField* pAssetIdField = pAssetTagNode->findField( ASSETTAGS_ASSETS_ASSETID_FIELD ); 229 230 // Do we find the field? 231 if ( pAssetIdField == NULL ) 232 { 233 // No, so warn. 234 Con::warnf( "AssetTagsManifest::onTamlCustomRead() - Could not find '%s' field.", ASSETTAGS_ASSETS_ASSETID_FIELD ); 235 continue; 236 } 237 238 // Fetch "Tag" field. 239 const TamlCustomField* pTagField = pAssetTagNode->findField( ASSETTAGS_ASSETS_TAG_FIELD ); 240 241 // Do we find the field? 242 if ( pTagField == NULL ) 243 { 244 // No, so warn. 245 Con::warnf( "AssetTagsManifest::onTamlCustomRead() - Could not find '%s' field.", ASSETTAGS_ASSETS_TAG_FIELD ); 246 continue; 247 } 248 249 // Tag the asset. 250 tag( pAssetIdField->getFieldValue(), pTagField->getFieldValue() ); 251 } 252} 253 254//----------------------------------------------------------------------------- 255 256const AssetTagsManifest::AssetTag* AssetTagsManifest::createTag( const char* pTagName ) 257{ 258 // Sanity! 259 AssertFatal( pTagName != NULL, "Cannot use a NULL tag name." ); 260 261 // Finish if the tag already exists. 262 AssetTag* pAssetTag = findAssetTag( pTagName ); 263 264 // Return asset tag if already created. 265 if ( pAssetTag != NULL ) 266 return pAssetTag; 267 268 // Fetch tag name. 269 StringTableEntry tagName = fetchTagName( pTagName ); 270 271 // Generate the asset tag. 272 pAssetTag = new AssetTag( tagName ); 273 274 // Add the tag. 275 mTagNameDatabase.insert( tagName, pAssetTag ); 276 277 return pAssetTag; 278} 279 280//----------------------------------------------------------------------------- 281 282bool AssetTagsManifest::renameTag( const char* pOldTagName, const char* pNewTagName ) 283{ 284 // Sanity! 285 AssertFatal( pOldTagName != NULL, "Cannot use a NULL tag name." ); 286 AssertFatal( pNewTagName != NULL, "Cannot use a NULL tag name." ); 287 288 // Find old asset tags. 289 AssetTag* pOldAssetTag = findAssetTag( pOldTagName ); 290 291 // Did we find the asset tag? 292 if ( pOldAssetTag == NULL ) 293 { 294 // No, so warn. 295 Con::warnf( "AssetTagsManifest: Cannot rename tag '%s' as it does not exist.", pOldTagName ); 296 return false; 297 } 298 299 // Are the old and new tags the same? 300 if ( pOldAssetTag->mTagName == fetchTagName( pNewTagName ) ) 301 { 302 // Yes, so warn. 303 Con::warnf( "AssetTagsManifest: Cannot rename tag '%s' to tag '%s' as they are the same.", pOldTagName, pNewTagName ); 304 return false; 305 } 306 307 // Create new tag. 308 AssetTag* pNewAssetTag = const_cast<AssetTag*>( createTag( pNewTagName ) ); 309 310 // Transfer asset tags. 311 for ( Vector<typeAssetId>::iterator assetIdItr = pOldAssetTag->mAssets.begin(); assetIdItr != pOldAssetTag->mAssets.end(); ++assetIdItr ) 312 { 313 pNewAssetTag->mAssets.push_back( *assetIdItr ); 314 } 315 316 // Delete old tag. 317 deleteTag( pOldTagName ); 318 319 return true; 320} 321 322//----------------------------------------------------------------------------- 323 324bool AssetTagsManifest::deleteTag( const char* pTagName ) 325{ 326 // Sanity! 327 AssertFatal( pTagName != NULL, "Cannot use a NULL tag name." ); 328 329 // Find asset tag. 330 AssetTag* pAssetTag = findAssetTag( pTagName ); 331 332 // Did we find the asset tag? 333 if ( pAssetTag == NULL ) 334 { 335 // No, so warn. 336 Con::warnf( "AssetTagsManifest: Cannot delete tag '%s' as it does not exist.", pTagName ); 337 return false; 338 } 339 340 // Remove the tag. 341 mTagNameDatabase.erase( pAssetTag->mTagName ); 342 343 // Remove the asset tags. 344 for ( Vector<typeAssetId>::iterator assetIdItr = pAssetTag->mAssets.begin(); assetIdItr != pAssetTag->mAssets.end(); ++assetIdItr ) 345 { 346 // Find asset Id tag. 347 typeAssetToTagHash::Iterator assetItr = mAssetToTagDatabase.find( *assetIdItr ); 348 349 // Iterate asset Id tags. 350 while( assetItr != mAssetToTagDatabase.end() && assetItr->key == *assetIdItr ) 351 { 352 // Is this the asset tag? 353 if ( assetItr->value == pAssetTag ) 354 { 355 // Yes, so erase it. 356 mAssetToTagDatabase.erase( assetItr ); 357 break; 358 } 359 360 // Next entry. 361 assetItr++; 362 } 363 } 364 365 // Delete the asset tag. 366 delete pAssetTag; 367 368 return true; 369} 370 371//----------------------------------------------------------------------------- 372 373bool AssetTagsManifest::isTag( const char* pTagName ) 374{ 375 // Sanity! 376 AssertFatal( pTagName != NULL, "Cannot use a NULL tag name." ); 377 378 // Check whether tag exists or not. 379 return findAssetTag( pTagName ) != NULL; 380} 381 382//----------------------------------------------------------------------------- 383 384StringTableEntry AssetTagsManifest::getTag( const U32 tagIndex ) 385{ 386 // Finish if invalid tag count. 387 AssertFatal( tagIndex < getTagCount(), "Tag index is out of bounds." ); 388 389 // Fetch tag iterator. 390 typeTagNameHash::iterator tagItr = mTagNameDatabase.begin(); 391 392 // Find asset tag by index. 393 // NOTE: Unfortunately this is slow as it's not the natural access method. 394 for( U32 index = 0; index < tagIndex; ++index, ++tagItr ) {}; 395 396 // Return tag name. 397 return tagItr->value->mTagName; 398} 399 400//----------------------------------------------------------------------------- 401 402U32 AssetTagsManifest::getAssetTagCount( const char* pAssetId ) 403{ 404 // Sanity! 405 AssertFatal( pAssetId != NULL, "Cannot use a NULL asset Id." ); 406 407 // Fetch asset Id. 408 StringTableEntry assetId = StringTable->insert( pAssetId ); 409 410 return (U32)mAssetToTagDatabase.count( assetId ); 411} 412 413//----------------------------------------------------------------------------- 414 415StringTableEntry AssetTagsManifest::getAssetTag( const char* pAssetId, const U32 tagIndex ) 416{ 417 // Sanity! 418 AssertFatal( pAssetId != NULL, "Cannot use a NULL asset Id." ); 419 420 // Fetch asset Id. 421 StringTableEntry assetId = StringTable->insert( pAssetId ); 422 423 // Sanity! 424 AssertFatal( tagIndex < (U32)mAssetToTagDatabase.count( assetId ), "Asset tag index is out of bounds." ); 425 426 // Find asset tag. 427 typeAssetToTagHash::Iterator assetItr = mAssetToTagDatabase.find( assetId ); 428 429 // Find asset tag by index. 430 // NOTE: Unfortunately this is slow as it's not the natural access method. 431 for( U32 index = 0; index < tagIndex; ++index, ++assetItr ) {}; 432 433 // Return tag name. 434 return assetItr->value->mTagName; 435} 436 437//----------------------------------------------------------------------------- 438 439bool AssetTagsManifest::tag( const char* pAssetId, const char* pTagName ) 440{ 441 // Sanity! 442 AssertFatal( pAssetId != NULL, "Cannot use a NULL asset Id." ); 443 AssertFatal( pTagName != NULL, "Cannot use a NULL tag name." ); 444 445 // Find asset tag. 446 AssetTag* pAssetTag = findAssetTag( pTagName ); 447 448 // Does the tag exist? 449 if ( pAssetTag == NULL ) 450 { 451 // No, so warn. 452 Con::warnf("AssetTagsManifest: Cannot tag asset Id '%s' with tag name '%s' as tag name does not exist.", pAssetId, pTagName ); 453 return false; 454 } 455 456 // Is the asset Id valid? 457 if ( !AssetDatabase.isDeclaredAsset( pAssetId ) ) 458 { 459 // No, so warn. 460 Con::warnf( "AssetTagsManifest::onTamlCustomRead() - Ignoring asset Id '%s' mapped to tag name '%s' as it is not a declared asset Id.", pAssetId, pTagName ); 461 return false; 462 } 463 464 // Fetch asset Id. 465 typeAssetId assetId = StringTable->insert( pAssetId ); 466 467 // Find asset Id tag. 468 typeAssetToTagHash::Iterator assetItr = mAssetToTagDatabase.find(assetId); 469 470 // Iterate asset Id tags. 471 while( assetItr != mAssetToTagDatabase.end() && assetItr->key == assetId ) 472 { 473 // Is the asset already tagged appropriately? 474 if ( assetItr->value == pAssetTag ) 475 return true; 476 477 // Next entry. 478 assetItr++; 479 } 480 481 // No, so add tag. 482 mAssetToTagDatabase.insertEqual( assetId, pAssetTag ); 483 484 // Add to asset tag. 485 pAssetTag->mAssets.push_back( assetId ); 486 487 return true; 488} 489 490//----------------------------------------------------------------------------- 491 492bool AssetTagsManifest::untag( const char* pAssetId, const char* pTagName ) 493{ 494 // Sanity! 495 AssertFatal( pAssetId != NULL, "Cannot use a NULL asset Id." ); 496 AssertFatal( pTagName != NULL, "Cannot use a NULL tag name." ); 497 498 // Find asset tag. 499 AssetTag* pAssetTag = findAssetTag( pTagName ); 500 501 // Does the tag exist? 502 if ( pAssetTag == NULL ) 503 { 504 // No, so warn. 505 Con::warnf("AssetTagsManifest: Cannot untag asset Id '%s' from tag name '%s' as tag name does not exist.", pAssetId, pTagName ); 506 return false; 507 } 508 509 // Fetch asset Id. 510 typeAssetId assetId = StringTable->insert( pAssetId ); 511 512 // Is the asset tagged? 513 if ( !pAssetTag->containsAsset( assetId ) ) 514 { 515 // No, so warn. 516 Con::warnf("AssetTagsManifest: Cannot untag asset Id '%s' from tag name '%s' as the asset is not tagged with the tag name.", pAssetId, pTagName ); 517 return false; 518 } 519 520 // Remove asset from assert tag. 521 pAssetTag->removeAsset( assetId ); 522 523 // Find asset Id tag. 524 typeAssetToTagHash::Iterator assetItr = mAssetToTagDatabase.find(assetId); 525 526 // Iterate asset Id tags. 527 while( assetItr != mAssetToTagDatabase.end() && assetItr->key == assetId ) 528 { 529 // Is this the asset tag? 530 if ( assetItr->value == pAssetTag ) 531 { 532 // Yes, so remove it. 533 mAssetToTagDatabase.erase( assetItr ); 534 break; 535 } 536 537 // Next entry. 538 assetItr++; 539 } 540 541 return true; 542} 543 544//----------------------------------------------------------------------------- 545 546bool AssetTagsManifest::hasTag( const char* pAssetId, const char* pTagName ) 547{ 548 // Sanity! 549 AssertFatal( pAssetId != NULL, "Cannot use a NULL asset Id." ); 550 AssertFatal( pTagName != NULL, "Cannot use a NULL tag name." ); 551 552 // Find asset tag. 553 AssetTag* pAssetTag = findAssetTag( pTagName ); 554 555 // Does the tag exist? 556 if ( pAssetTag == NULL ) 557 { 558 // No, so warn. 559 Con::warnf("AssetTagsManifest: Cannot check if asset Id '%s' has tag name '%s' as tag name does not exist.", pAssetId, pTagName ); 560 return false; 561 } 562 563 // Return whether asset Id is tagged. 564 return pAssetTag->containsAsset( StringTable->insert( pAssetId ) ); 565} 566