tamlAssetDeclaredVisitor.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _TAML_ASSET_DECLARED_VISITOR_H_
  23. #define _TAML_ASSET_DECLARED_VISITOR_H_
  24. #ifndef _TAML_XMLPARSER_H_
  25. #include "persistence//taml/tamlXmlParser.h"
  26. #endif
  27. #ifndef _ASSET_FIELD_TYPES_H_
  28. #include "assets/assetFieldTypes.h"
  29. #endif
  30. #ifndef _ASSET_DEFINITION_H_
  31. #include "assetDefinition.h"
  32. #endif
  33. #ifndef _ASSET_BASE_H_
  34. #include "assetBase.h"
  35. #endif
  36. // Debug Profiling.
  37. #include "debug/profiler.h"
  38. //-----------------------------------------------------------------------------
  39. class TamlAssetDeclaredVisitor : public TamlXmlVisitor
  40. {
  41. protected:
  42. virtual bool visit( TiXmlElement* pXmlElement, TamlXmlParser& xmlParser )
  43. {
  44. // Debug Profiling.
  45. PROFILE_SCOPE(TamlAssetDeclaredVisitor_VisitElement);
  46. // Finish if this is not the root element.
  47. if ( pXmlElement != pXmlElement->GetDocument()->RootElement() )
  48. return true;
  49. // Fetch asset field names.
  50. StringTableEntry assetNameField = StringTable->insert( ASSET_BASE_ASSETNAME_FIELD );
  51. StringTableEntry assetDescriptionField = StringTable->insert( ASSET_BASE_ASSETDESCRIPTION_FIELD );
  52. StringTableEntry assetCategoryField = StringTable->insert( ASSET_BASE_CATEGORY_FIELD );
  53. StringTableEntry assetAutoUnloadField = StringTable->insert( ASSET_BASE_AUTOUNLOAD_FIELD );
  54. StringTableEntry assetInternalField = StringTable->insert( ASSET_BASE_ASSETINTERNAL_FIELD );
  55. // Iterate attributes.
  56. for ( TiXmlAttribute* pAttribute = pXmlElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->Next() )
  57. {
  58. // Insert attribute name.
  59. StringTableEntry attributeName = StringTable->insert( pAttribute->Name() );
  60. // Asset name?
  61. if ( attributeName == assetNameField )
  62. {
  63. // Yes, so assign it.
  64. mAssetDefinition.mAssetName = StringTable->insert( pAttribute->Value() );
  65. continue;
  66. }
  67. // Asset description?
  68. else if ( attributeName == assetDescriptionField )
  69. {
  70. // Yes, so assign it.
  71. mAssetDefinition.mAssetDescription = StringTable->insert( pAttribute->Value() );
  72. continue;
  73. }
  74. // Asset description?
  75. else if ( attributeName == assetCategoryField )
  76. {
  77. // Yes, so assign it.
  78. mAssetDefinition.mAssetCategory = StringTable->insert( pAttribute->Value() );
  79. continue;
  80. }
  81. // Asset auto-unload?
  82. else if ( attributeName == assetAutoUnloadField )
  83. {
  84. // Yes, so assign it.
  85. mAssetDefinition.mAssetAutoUnload = dAtob( pAttribute->Value() );
  86. continue;
  87. }
  88. // Asset internal?
  89. else if ( attributeName == assetInternalField )
  90. {
  91. // Yes, so assign it.
  92. mAssetDefinition.mAssetInternal = dAtob( pAttribute->Value() );
  93. continue;
  94. }
  95. }
  96. // Did we get an asset name?
  97. if ( mAssetDefinition.mAssetName == StringTable->EmptyString )
  98. {
  99. // No, so reset everything.
  100. clear();
  101. // Stop processing!
  102. return false;
  103. }
  104. // Set asset file-path.
  105. mAssetDefinition.mAssetBaseFilePath = StringTable->insert( xmlParser.getParsingFilename() );
  106. // Set asset type.
  107. mAssetDefinition.mAssetType = StringTable->insert( pXmlElement->Value() );
  108. return true;
  109. }
  110. virtual bool visit( TiXmlAttribute* pAttribute, TamlXmlParser& xmlParser )
  111. {
  112. // Debug Profiling.
  113. PROFILE_SCOPE(TamlAssetDeclaredVisitor_VisitAttribute);
  114. // Sanity!
  115. AssertFatal( mAssetDefinition.mAssetName != StringTable->EmptyString, "Cannot generate asset dependencies without asset name." );
  116. // Fetch asset reference.
  117. const char* pAssetReference = pAttribute->Value();
  118. // Fetch field word count.
  119. const U32 fieldWordCount = StringUnit::getUnitCount( pAssetReference, ASSET_ASSIGNMENT_TOKEN );
  120. // Finish if there are not two words.
  121. if ( fieldWordCount != 2 )
  122. return true;
  123. // Fetch the asset signature.
  124. StringTableEntry assetSignature = StringTable->insert( StringUnit::getUnit( pAssetReference, 0, ASSET_ASSIGNMENT_TOKEN ) );
  125. // Is this an asset Id signature?
  126. if ( assetSignature == StringTable->insert(ASSET_ID_SIGNATURE) )
  127. {
  128. // Yes, so get asset Id.
  129. typeAssetId assetId = StringTable->insert( StringUnit::getUnit( pAssetReference, 1, ASSET_ASSIGNMENT_TOKEN ) );
  130. // Finish if the dependency is itself!
  131. if ( mAssetDefinition.mAssetId == assetId )
  132. return true;
  133. // Iterate existing dependencies.
  134. for( typeAssetIdVector::iterator dependencyItr = mAssetDependencies.begin(); dependencyItr != mAssetDependencies.end(); ++dependencyItr )
  135. {
  136. // Finish if asset Id is already a dependency.
  137. if ( *dependencyItr == assetId )
  138. return true;
  139. }
  140. // Insert asset reference.
  141. mAssetDependencies.push_back( assetId );
  142. }
  143. // Is this a loose-file signature?
  144. else if ( assetSignature == StringTable->insert(ASSET_LOOSEFILE_SIGNATURE) )
  145. {
  146. // Yes, so get loose-file reference.
  147. const char* pAssetLooseFile = StringUnit::getUnit( pAssetReference, 1, ASSET_ASSIGNMENT_TOKEN );
  148. char assetFilePathBuffer[1024];
  149. // Is the asset loose-file expando specified?
  150. if ( *pAssetLooseFile == '#' )
  151. {
  152. // Yes, so fetch relative path.
  153. char parsingFileBuffer[1024];
  154. dStrcpy( parsingFileBuffer, xmlParser.getParsingFilename() );
  155. // Find the final slash.
  156. char* pLastSlash = dStrrchr( parsingFileBuffer, '/' );
  157. // Is this the last slash?
  158. if ( pLastSlash == NULL )
  159. {
  160. // No, so warn.
  161. Con::warnf( "Failed to parse the loose-file path '%s' in asset file '%s'.", pAssetLooseFile, parsingFileBuffer );
  162. return true;
  163. }
  164. // Remove parsing file.
  165. *pLastSlash = 0;
  166. // Format expanded path taking into account any missing slash.
  167. dSprintf( assetFilePathBuffer, sizeof(assetFilePathBuffer), "%s/%s", parsingFileBuffer, pAssetLooseFile + (pAssetLooseFile[1] == '/' ? 2 : 1 ) );
  168. }
  169. else
  170. {
  171. // No, so expand the path in the usual way.
  172. Con::expandPath( assetFilePathBuffer, sizeof(assetFilePathBuffer), pAssetLooseFile );
  173. }
  174. // Insert asset loose-file.
  175. mAssetLooseFiles.push_back( StringTable->insert( assetFilePathBuffer ) );
  176. }
  177. return true;
  178. }
  179. public:
  180. TamlAssetDeclaredVisitor() { mAssetDefinition.reset(); }
  181. virtual ~TamlAssetDeclaredVisitor() {}
  182. bool parse( const char* pFilename )
  183. {
  184. TamlXmlParser parser;
  185. return parser.parse( pFilename, *this, false );
  186. }
  187. typedef StringTableEntry typeAssetId;
  188. typedef Vector<typeAssetId> typeAssetIdVector;
  189. typedef Vector<StringTableEntry> typeLooseFileVector;
  190. inline AssetDefinition& getAssetDefinition( void ) { return mAssetDefinition; }
  191. inline typeAssetIdVector& getAssetDependencies( void ) { return mAssetDependencies; }
  192. inline typeLooseFileVector& getAssetLooseFiles( void ) { return mAssetLooseFiles; }
  193. void clear( void ) { mAssetDefinition.reset(); mAssetDependencies.clear(); mAssetLooseFiles.clear(); }
  194. private:
  195. AssetDefinition mAssetDefinition;
  196. typeAssetIdVector mAssetDependencies;
  197. typeLooseFileVector mAssetLooseFiles;
  198. };
  199. #endif // _TAML_ASSET_DECLARED_VISITOR_H_