Browse Source

- Completely rewritten the Taml visitor/parser set-up this morning. Now TAML can perform parsing requests for visitors for potentially any format i.e. you can write a visitor without having knowledge of the format being read. Only an XML parser is currently present but I'm now writing JSON and BINARY parsers. With a JSON and BINARY parser in place you will be able to define things like asset-definitions and module-definitions in any TAML format (any that has a parser).

MelvMay-GG 12 years ago
parent
commit
61544fec27

+ 2 - 1
engine/compilers/VisualStudio 2010/Torque 2D.vcxproj

@@ -921,11 +921,12 @@
     <ClInclude Include="..\..\source\persistence\taml\tamlCallbacks.h" />
     <ClInclude Include="..\..\source\persistence\taml\tamlChildren.h" />
     <ClInclude Include="..\..\source\persistence\taml\tamlCustom.h" />
+    <ClInclude Include="..\..\source\persistence\taml\tamlParser.h" />
+    <ClInclude Include="..\..\source\persistence\taml\tamlVisitor.h" />
     <ClInclude Include="..\..\source\persistence\taml\tamlWriteNode.h" />
     <ClInclude Include="..\..\source\persistence\taml\taml_ScriptBinding.h" />
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlParser.h" />
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlReader.h" />
-    <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlVisitor.h" />
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlWriter.h" />
     <ClInclude Include="..\..\source\persistence\tinyXML\tinystr.h" />
     <ClInclude Include="..\..\source\persistence\tinyXML\tinyxml.h" />

+ 6 - 3
engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters

@@ -2739,12 +2739,15 @@
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlReader.h">
       <Filter>persistence\taml\xml</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlVisitor.h">
-      <Filter>persistence\taml\xml</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlWriter.h">
       <Filter>persistence\taml\xml</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\persistence\taml\tamlParser.h">
+      <Filter>persistence\taml</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\persistence\taml\tamlVisitor.h">
+      <Filter>persistence\taml</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 2 - 1
engine/compilers/VisualStudio 2012/Torque 2D.vcxproj

@@ -927,11 +927,12 @@
     <ClInclude Include="..\..\source\persistence\taml\tamlCallbacks.h" />
     <ClInclude Include="..\..\source\persistence\taml\tamlChildren.h" />
     <ClInclude Include="..\..\source\persistence\taml\tamlCustom.h" />
+    <ClInclude Include="..\..\source\persistence\taml\tamlParser.h" />
+    <ClInclude Include="..\..\source\persistence\taml\tamlVisitor.h" />
     <ClInclude Include="..\..\source\persistence\taml\tamlWriteNode.h" />
     <ClInclude Include="..\..\source\persistence\taml\taml_ScriptBinding.h" />
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlParser.h" />
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlReader.h" />
-    <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlVisitor.h" />
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlWriter.h" />
     <ClInclude Include="..\..\source\persistence\tinyXML\tinystr.h" />
     <ClInclude Include="..\..\source\persistence\tinyXML\tinyxml.h" />

+ 6 - 3
engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters

@@ -2736,12 +2736,15 @@
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlReader.h">
       <Filter>persistence\taml\xml</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlVisitor.h">
-      <Filter>persistence\taml\xml</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\persistence\taml\xml\tamlXmlWriter.h">
       <Filter>persistence\taml\xml</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\persistence\taml\tamlVisitor.h">
+      <Filter>persistence\taml</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\persistence\taml\tamlParser.h">
+      <Filter>persistence\taml</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 4 - 2
engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj

@@ -473,6 +473,8 @@
 		2AB14A0216D7CDC200EABBF2 /* PointForceController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PointForceController_ScriptBinding.h; path = controllers/PointForceController_ScriptBinding.h; sourceTree = "<group>"; };
 		2AB14A0316D7CDC200EABBF2 /* PointForceController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PointForceController.cc; path = controllers/PointForceController.cc; sourceTree = "<group>"; };
 		2AB14A0416D7CDC300EABBF2 /* PointForceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PointForceController.h; path = controllers/PointForceController.h; sourceTree = "<group>"; };
+		2AB4A5221705A84D0043CBAA /* tamlParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tamlParser.h; sourceTree = "<group>"; };
+		2AB4A5231705A84D0043CBAA /* tamlVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tamlVisitor.h; sourceTree = "<group>"; };
 		2AB4C19716DE9F0600B02479 /* GroupedSceneController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupedSceneController_ScriptBinding.h; path = controllers/core/GroupedSceneController_ScriptBinding.h; sourceTree = "<group>"; };
 		2AB4C19816DE9F0600B02479 /* GroupedSceneController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GroupedSceneController.cc; path = controllers/core/GroupedSceneController.cc; sourceTree = "<group>"; };
 		2AB4C19916DE9F0600B02479 /* GroupedSceneController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupedSceneController.h; path = controllers/core/GroupedSceneController.h; sourceTree = "<group>"; };
@@ -515,7 +517,6 @@
 		2AD4213A170433FE005BB8AD /* tamlXmlParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlXmlParser.h; path = xml/tamlXmlParser.h; sourceTree = "<group>"; };
 		2AD4213B170433FE005BB8AD /* tamlXmlReader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tamlXmlReader.cc; path = xml/tamlXmlReader.cc; sourceTree = "<group>"; };
 		2AD4213C170433FE005BB8AD /* tamlXmlReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlXmlReader.h; path = xml/tamlXmlReader.h; sourceTree = "<group>"; };
-		2AD4213D170433FE005BB8AD /* tamlXmlVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlXmlVisitor.h; path = xml/tamlXmlVisitor.h; sourceTree = "<group>"; };
 		2AD4213E170433FE005BB8AD /* tamlXmlWriter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tamlXmlWriter.cc; path = xml/tamlXmlWriter.cc; sourceTree = "<group>"; };
 		2AD4213F170433FE005BB8AD /* tamlXmlWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlXmlWriter.h; path = xml/tamlXmlWriter.h; sourceTree = "<group>"; };
 		2AD4214317043408005BB8AD /* tamlJSONReader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tamlJSONReader.cc; path = json/tamlJSONReader.cc; sourceTree = "<group>"; };
@@ -1488,7 +1489,6 @@
 				2AD4213A170433FE005BB8AD /* tamlXmlParser.h */,
 				2AD4213B170433FE005BB8AD /* tamlXmlReader.cc */,
 				2AD4213C170433FE005BB8AD /* tamlXmlReader.h */,
-				2AD4213D170433FE005BB8AD /* tamlXmlVisitor.h */,
 				2AD4213E170433FE005BB8AD /* tamlXmlWriter.cc */,
 				2AD4213F170433FE005BB8AD /* tamlXmlWriter.h */,
 			);
@@ -2717,6 +2717,8 @@
 		86BC80F216518D4600D96ADF /* taml */ = {
 			isa = PBXGroup;
 			children = (
+				2AB4A5221705A84D0043CBAA /* tamlParser.h */,
+				2AB4A5231705A84D0043CBAA /* tamlVisitor.h */,
 				2AD42138170433F3005BB8AD /* xml */,
 				2AD42137170433EA005BB8AD /* json */,
 				2AD42136170433E4005BB8AD /* binary */,

+ 4 - 2
engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj

@@ -495,6 +495,8 @@
 		2AB14A0616D7CDCE00EABBF2 /* PointForceController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PointForceController_ScriptBinding.h; path = controllers/PointForceController_ScriptBinding.h; sourceTree = "<group>"; };
 		2AB14A0716D7CDCE00EABBF2 /* PointForceController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PointForceController.cc; path = controllers/PointForceController.cc; sourceTree = "<group>"; };
 		2AB14A0816D7CDCE00EABBF2 /* PointForceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PointForceController.h; path = controllers/PointForceController.h; sourceTree = "<group>"; };
+		2AB4A5241705A88F0043CBAA /* tamlParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tamlParser.h; sourceTree = "<group>"; };
+		2AB4A5251705A88F0043CBAA /* tamlVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tamlVisitor.h; sourceTree = "<group>"; };
 		2AB4C1A416DE9F4B00B02479 /* AmbientForceController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AmbientForceController_ScriptBinding.h; path = controllers/AmbientForceController_ScriptBinding.h; sourceTree = "<group>"; };
 		2AB4C1A516DE9F4B00B02479 /* AmbientForceController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AmbientForceController.cc; path = controllers/AmbientForceController.cc; sourceTree = "<group>"; };
 		2AB4C1A616DE9F4B00B02479 /* AmbientForceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AmbientForceController.h; path = controllers/AmbientForceController.h; sourceTree = "<group>"; };
@@ -522,7 +524,6 @@
 		2AD42159170434E1005BB8AD /* tamlXmlParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlXmlParser.h; path = xml/tamlXmlParser.h; sourceTree = "<group>"; };
 		2AD4215A170434E1005BB8AD /* tamlXmlReader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tamlXmlReader.cc; path = xml/tamlXmlReader.cc; sourceTree = "<group>"; };
 		2AD4215B170434E1005BB8AD /* tamlXmlReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlXmlReader.h; path = xml/tamlXmlReader.h; sourceTree = "<group>"; };
-		2AD4215C170434E1005BB8AD /* tamlXmlVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlXmlVisitor.h; path = xml/tamlXmlVisitor.h; sourceTree = "<group>"; };
 		2AD4215D170434E1005BB8AD /* tamlXmlWriter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tamlXmlWriter.cc; path = xml/tamlXmlWriter.cc; sourceTree = "<group>"; };
 		2AD4215E170434E1005BB8AD /* tamlXmlWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlXmlWriter.h; path = xml/tamlXmlWriter.h; sourceTree = "<group>"; };
 		2AD42162170434F0005BB8AD /* tamlJSONReader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tamlJSONReader.cc; path = json/tamlJSONReader.cc; sourceTree = "<group>"; };
@@ -1528,7 +1529,6 @@
 				2AD42159170434E1005BB8AD /* tamlXmlParser.h */,
 				2AD4215A170434E1005BB8AD /* tamlXmlReader.cc */,
 				2AD4215B170434E1005BB8AD /* tamlXmlReader.h */,
-				2AD4215C170434E1005BB8AD /* tamlXmlVisitor.h */,
 				2AD4215D170434E1005BB8AD /* tamlXmlWriter.cc */,
 				2AD4215E170434E1005BB8AD /* tamlXmlWriter.h */,
 			);
@@ -2468,6 +2468,8 @@
 		867BAF5616AEC9050033868F /* taml */ = {
 			isa = PBXGroup;
 			children = (
+				2AB4A5241705A88F0043CBAA /* tamlParser.h */,
+				2AB4A5251705A88F0043CBAA /* tamlVisitor.h */,
 				2AD42151170434B5005BB8AD /* xml */,
 				2AD42150170434AF005BB8AD /* json */,
 				2AD4214F170434A9005BB8AD /* binary */,

+ 15 - 6
engine/source/assets/assetBase.cc

@@ -44,6 +44,15 @@ IMPLEMENT_CONOBJECT( AssetBase );
 
 //-----------------------------------------------------------------------------
 
+StringTableEntry assetNameField = StringTable->insert( "AssetName" );
+StringTableEntry assetDescriptionField = StringTable->insert( "AssetDescription" );
+StringTableEntry assetCategoryField = StringTable->insert( "AssetCategory" );
+StringTableEntry assetInternalField = StringTable->insert( "AssetInternal" );
+StringTableEntry assetPrivateField = StringTable->insert( "AssetPrivate" );
+StringTableEntry assetAutoUnloadField = StringTable->insert( "AssetAutoUnload" );
+
+//-----------------------------------------------------------------------------
+
 AssetBase::AssetBase() :
     mAcquireReferenceCount( 0 ),
     mpOwningAssetManager( NULL ),
@@ -71,12 +80,12 @@ void AssetBase::initPersistFields()
     Parent::initPersistFields();
 
     // Asset configuration.
-    addProtectedField( ASSET_BASE_ASSETNAME_FIELD, TypeString, 0, &setAssetName, &getAssetName, &writeAssetName, "The name of the asset.  The is not a unique identification like an asset Id." );
-    addProtectedField( ASSET_BASE_ASSETDESCRIPTION_FIELD, TypeString, 0, &setAssetDescription, &getAssetDescription, &writeAssetDescription, "The simple description of the asset contents." );
-    addProtectedField( ASSET_BASE_CATEGORY_FIELD, TypeString, 0, &setAssetCategory, &getAssetCategory, &writeAssetCategory, "An arbitrary category that can be used to categorized assets." );
-    addProtectedField( ASSET_BASE_AUTOUNLOAD_FIELD, TypeBool, 0, &setAssetAutoUnload, &getAssetAutoUnload, &writeAssetAutoUnload, "Whether the asset is automatically unloaded when an asset is released and has no other acquisitions or not." );
-    addProtectedField( ASSET_BASE_ASSETINTERNAL_FIELD, TypeBool, 0, &setAssetInternal, &getAssetInternal, &writeAssetInternal, "Whether the asset is used internally only or not." );
-    addProtectedField( ASSET_BASE_ASSETPRIVATE_FIELD, TypeBool, 0, &defaultProtectedNotSetFn, &getAssetPrivate, &defaultProtectedNotWriteFn, "Whether the asset is private or not." );
+    addProtectedField( assetNameField, TypeString, 0, &setAssetName, &getAssetName, &writeAssetName, "The name of the asset.  The is not a unique identification like an asset Id." );
+    addProtectedField( assetDescriptionField, TypeString, 0, &setAssetDescription, &getAssetDescription, &writeAssetDescription, "The simple description of the asset contents." );
+    addProtectedField( assetCategoryField, TypeString, 0, &setAssetCategory, &getAssetCategory, &writeAssetCategory, "An arbitrary category that can be used to categorized assets." );
+    addProtectedField( assetInternalField, TypeBool, 0, &setAssetAutoUnload, &getAssetAutoUnload, &writeAssetAutoUnload, "Whether the asset is automatically unloaded when an asset is released and has no other acquisitions or not." );
+    addProtectedField( assetPrivateField, TypeBool, 0, &setAssetInternal, &getAssetInternal, &writeAssetInternal, "Whether the asset is used internally only or not." );
+    addProtectedField( assetAutoUnloadField, TypeBool, 0, &defaultProtectedNotSetFn, &getAssetPrivate, &defaultProtectedNotWriteFn, "Whether the asset is private or not." );
 }
 
 //------------------------------------------------------------------------------

+ 13 - 6
engine/source/assets/assetBase.h

@@ -41,12 +41,19 @@ class AssetManager;
 
 //-----------------------------------------------------------------------------
 
-#define ASSET_BASE_ASSETNAME_FIELD         "AssetName"
-#define ASSET_BASE_ASSETDESCRIPTION_FIELD  "AssetDescription"
-#define ASSET_BASE_CATEGORY_FIELD          "AssetCategory"
-#define ASSET_BASE_ASSETINTERNAL_FIELD     "AssetInternal"
-#define ASSET_BASE_ASSETPRIVATE_FIELD      "AssetPrivate"
-#define ASSET_BASE_AUTOUNLOAD_FIELD        "AssetAutoUnload"
+extern StringTableEntry assetNameField;
+extern StringTableEntry assetDescriptionField;
+extern StringTableEntry assetCategoryField;
+extern StringTableEntry assetInternalField;
+extern StringTableEntry assetPrivateField;
+extern StringTableEntry assetAutoUnloadField;
+
+//#define ASSET_BASE_ASSETNAME_FIELD         "AssetName"
+//#define ASSET_BASE_ASSETDESCRIPTION_FIELD  "AssetDescription"
+//#define ASSET_BASE_ASSETCATEGORY_FIELD     "AssetCategory"
+//#define ASSET_BASE_ASSETINTERNAL_FIELD     "AssetInternal"
+//#define ASSET_BASE_ASSETPRIVATE_FIELD      "AssetPrivate"
+//#define ASSET_BASE_AUTOUNLOAD_FIELD        "AssetAutoUnload"
 
 //-----------------------------------------------------------------------------
 

+ 5 - 0
engine/source/assets/assetFieldTypes.cc

@@ -50,6 +50,11 @@
 
 //-----------------------------------------------------------------------------
 
+StringTableEntry assetLooseIdSignature = StringTable->insert( ASSET_ID_SIGNATURE );
+StringTableEntry assetLooseFileSignature = StringTable->insert( ASSET_LOOSEFILE_SIGNATURE );
+
+//-----------------------------------------------------------------------------
+
 ConsoleType( assetLooseFilePath, TypeAssetLooseFilePath, sizeof(StringTableEntry), ASSET_LOOSE_FILE_FIELD_PREFIX )
 ConsoleType( assetIdString, TypeAssetId, sizeof(StringTableEntry), ASSET_ID_FIELD_PREFIX )
 

+ 5 - 0
engine/source/assets/assetFieldTypes.h

@@ -48,4 +48,9 @@ DefineConsoleType( TypeAssetLooseFilePath )
 #define ASSET_LOOSEFILE_SIGNATURE       "@assetFile"
 #define ASSET_LOOSE_FILE_FIELD_PREFIX   "@assetFile="
 
+//-----------------------------------------------------------------------------
+
+extern StringTableEntry assetLooseIdSignature;
+extern StringTableEntry assetLooseFileSignature;
+
 #endif // _ASSET_FIELD_TYPES_H_

+ 6 - 6
engine/source/assets/assetManager.cc

@@ -795,7 +795,7 @@ bool AssetManager::renameDeclaredAsset( const char* pAssetIdFrom, const char* pA
     assetDeclaredUpdateVisitor.setAssetIdTo( assetIdTo );
 
     // Update asset file declaration.
-    if ( !assetDeclaredUpdateVisitor.parse( pAssetDefinition->mAssetBaseFilePath ) )
+    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",
@@ -1192,7 +1192,7 @@ bool AssetManager::refreshAsset( const char* pAssetId )
             TamlAssetDeclaredVisitor assetDeclaredVisitor;
 
             // Parse the filename.
-            if ( !assetDeclaredVisitor.parse( pAssetDefinition->mAssetBaseFilePath ) )
+            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 );
@@ -2381,7 +2381,7 @@ bool AssetManager::scanDeclaredAssets( const char* pPath, const char* pExtension
         dSprintf( assetFileBuffer, sizeof(assetFileBuffer), "%s/%s", fileInfo.pFullPath, fileInfo.pFileName );
 
         // Parse the filename.
-        if ( !assetDeclaredVisitor.parse( assetFileBuffer ) )
+        if ( !mTaml.parse( assetFileBuffer, assetDeclaredVisitor ) )
         {
             // Warn.
             Con::warnf( "Asset Manager: Failed to parse file containing asset declaration: '%s'.", assetFileBuffer );
@@ -2575,7 +2575,7 @@ bool AssetManager::scanReferencedAssets( const char* pPath, const char* pExtensi
         typeReferenceFilePath referenceFilePath = StringTable->insert( assetFileBuffer );
 
         // Parse the filename.
-        if ( !assetReferencedVisitor.parse( referenceFilePath ) )
+        if ( !mTaml.parse( referenceFilePath, assetReferencedVisitor ) )
         {
             // Warn.
             Con::warnf( "Asset Manager: Failed to parse file containing asset references: '%s'.", referenceFilePath );
@@ -2730,7 +2730,7 @@ void AssetManager::renameAssetReferences( StringTableEntry assetIdFrom, StringTa
         }
 
         // Update asset file declaration.
-        if ( !assetReferencedUpdateVisitor.parse( referencedAssetItr->value ) )
+        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",
@@ -2780,7 +2780,7 @@ void AssetManager::removeAssetReferences( StringTableEntry assetId )
         }
 
         // Update asset file declaration.
-        if ( !assetReferencedUpdateVisitor.parse( referencedAssetItr->value ) )
+        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",

+ 39 - 65
engine/source/assets/tamlAssetDeclaredUpdateVisitor.h

@@ -23,16 +23,12 @@
 #ifndef _TAML_ASSET_DECLARED_UPDATE_VISITOR_H_
 #define _TAML_ASSET_DECLARED_UPDATE_VISITOR_H_
 
-#ifndef _TAML_XMLPARSER_H_
-#include "persistence//taml/tamlXmlParser.h"
+#ifndef _TAML_VISITOR_H_
+#include "persistence/taml/tamlVisitor.h"
 #endif
 
-#ifndef _STRINGUNIT_H_
-#include "string/stringUnit.h"
-#endif
-
-#ifndef _STRINGTABLE_H_
-#include "string/stringTable.h"
+#ifndef _TAML_PARSER_H_
+#include "persistence\/taml/tamlParser.h"
 #endif
 
 #ifndef _ASSET_FIELD_TYPES_H_
@@ -44,64 +40,18 @@
 
 //-----------------------------------------------------------------------------
 
-class TamlAssetDeclaredUpdateVisitor : public TamlXmlVisitor
+class TamlAssetDeclaredUpdateVisitor : public TamlVisitor
 {
-protected:
-    virtual bool visit( TiXmlElement* pXmlElement, TamlXmlParser& xmlParser )
-    {
-        // Debug Profiling.
-        PROFILE_SCOPE(TamlAssetDeclaredUpdateVisitor_VisitElement);
-
-        // Finish if this is not the root element.
-        if ( pXmlElement != pXmlElement->GetDocument()->RootElement() )
-            return true;
-
-        // Fetch asset field names.
-        StringTableEntry assetNameField = StringTable->insert( ASSET_BASE_ASSETNAME_FIELD );
-
-        // Iterate attributes.
-        for ( TiXmlAttribute* pAttribute = pXmlElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->Next() )
-        {
-            // Insert attribute name.
-            StringTableEntry attributeName = StringTable->insert( pAttribute->Name() );
-
-            // Asset name?
-            if ( attributeName != assetNameField )
-                continue;
-
-            // Is this the asset Id we're looking for?
-            if ( dStricmp( pAttribute->Value(), mAssetNameFrom ) != 0 )
-            {
-                // No, so warn.
-                Con::warnf("Cannot rename asset Name '%s' to asset Name '%s' as the declared asset Name was %s",
-                    mAssetNameFrom, mAssetNameTo, pAttribute->Value() );
-
-                // Stop processing!
-                return false;
-            }
-
-            // Assign new value.
-            pAttribute->SetValue( mAssetNameTo );
-
-            // Stop processing!
-            return false;
-        }
-
-        return true;
-    }
-
-    virtual bool visit( TiXmlAttribute* pAttribute, TamlXmlParser& xmlParser ) { return true; }
+private:    
+    StringTableEntry mAssetIdFrom;
+    StringTableEntry mAssetIdTo;
+    StringTableEntry mAssetNameFrom;
+    StringTableEntry mAssetNameTo;
 
 public:
     TamlAssetDeclaredUpdateVisitor() {}
     virtual ~TamlAssetDeclaredUpdateVisitor() {}
 
-    bool parse( const char* pFilename )
-    {
-        TamlXmlParser parser;
-        return parser.parse( pFilename, *this, true );
-    }
-
     void setAssetIdFrom( const char* pAssetIdFrom )
     {
         // Sanity!
@@ -148,11 +98,35 @@ public:
     }
     const char* getAssetIdTo( void ) const { return mAssetIdTo; }
 
-private:    
-    StringTableEntry mAssetIdFrom;
-    StringTableEntry mAssetIdTo;
-    StringTableEntry mAssetNameFrom;
-    StringTableEntry mAssetNameTo;
+    virtual bool wantsPropertyChanges( void ) { return true; }
+    virtual bool wantsRootOnly( void ) { return true; }
+
+    virtual bool visit( const TamlParser& parser, TamlVisitor::PropertyState& propertyState )
+    {
+        // Debug Profiling.
+        PROFILE_SCOPE(TamlAssetDeclaredUpdateVisitor_Visit);
+
+        // Finish if not the asset name field.
+        if ( propertyState.getPropertyName() != assetNameField )
+            return true;
+
+        // Is this the asset Id we're looking for?
+        if ( dStricmp( propertyState.getPropertyValue(), mAssetNameFrom ) != 0 )
+        {
+            // No, so warn.
+            Con::warnf("Cannot rename asset Name '%s' to asset Name '%s' as the declared asset Name was %s",
+                mAssetNameFrom, mAssetNameTo, propertyState.getPropertyValue() );
+
+            // Stop processing!
+            return false;
+        }
+
+        // Assign new value.
+        propertyState.updatePropertyValue( mAssetNameTo );
+
+        // Stop processing!
+        return false;
+    }
 };
 
 #endif // _TAML_ASSET_DECLARED_UPDATE_VISITOR_H_

+ 78 - 130
engine/source/assets/tamlAssetDeclaredVisitor.h

@@ -23,8 +23,12 @@
 #ifndef _TAML_ASSET_DECLARED_VISITOR_H_
 #define _TAML_ASSET_DECLARED_VISITOR_H_
 
-#ifndef _TAML_XMLPARSER_H_
-#include "persistence//taml/tamlXmlParser.h"
+#ifndef _TAML_VISITOR_H_
+#include "persistence/taml/tamlVisitor.h"
+#endif
+
+#ifndef _TAML_PARSER_H_
+#include "persistence\/taml/tamlParser.h"
 #endif
 
 #ifndef _ASSET_FIELD_TYPES_H_
@@ -44,113 +48,104 @@
 
 //-----------------------------------------------------------------------------
 
-class TamlAssetDeclaredVisitor : public TamlXmlVisitor
+class TamlAssetDeclaredVisitor : public TamlVisitor
 {
-protected:
-    virtual bool visit( TiXmlElement* pXmlElement, TamlXmlParser& xmlParser )
-    {
-        // Debug Profiling.
-        PROFILE_SCOPE(TamlAssetDeclaredVisitor_VisitElement);
+public:
+    typedef StringTableEntry typeAssetId;
+    typedef Vector<typeAssetId> typeAssetIdVector;
+    typedef Vector<StringTableEntry> typeLooseFileVector;
 
-        // Finish if this is not the root element.
-        if ( pXmlElement != pXmlElement->GetDocument()->RootElement() )
-            return true;
+private:
+    AssetDefinition         mAssetDefinition;
+    typeAssetIdVector       mAssetDependencies;
+    typeLooseFileVector     mAssetLooseFiles;
+
+public:
+    TamlAssetDeclaredVisitor() { mAssetDefinition.reset(); }
+    virtual ~TamlAssetDeclaredVisitor() {}
+
+
+    inline AssetDefinition& getAssetDefinition( void ) { return mAssetDefinition; }
+    inline typeAssetIdVector& getAssetDependencies( void ) { return mAssetDependencies; }
+    inline typeLooseFileVector& getAssetLooseFiles( void ) { return mAssetLooseFiles; }
+
+    void clear( void ) { mAssetDefinition.reset(); mAssetDependencies.clear(); mAssetLooseFiles.clear(); }
+
+    virtual bool wantsPropertyChanges( void ) { return false; }
+    virtual bool wantsRootOnly( void ) { return false; }
 
-        // Fetch asset field names.
-        StringTableEntry assetNameField = StringTable->insert( ASSET_BASE_ASSETNAME_FIELD );
-        StringTableEntry assetDescriptionField = StringTable->insert( ASSET_BASE_ASSETDESCRIPTION_FIELD );
-        StringTableEntry assetCategoryField = StringTable->insert( ASSET_BASE_CATEGORY_FIELD );
-        StringTableEntry assetAutoUnloadField = StringTable->insert( ASSET_BASE_AUTOUNLOAD_FIELD );
-        StringTableEntry assetInternalField = StringTable->insert( ASSET_BASE_ASSETINTERNAL_FIELD );
+    virtual bool visit( const TamlParser& parser, TamlVisitor::PropertyState& propertyState )
+    {    
+        // Debug Profiling.
+        PROFILE_SCOPE(TamlAssetDeclaredVisitor_Visit);
+
+        // Fetch property name and value.
+        StringTableEntry propertyName = propertyState.getPropertyName();
+        const char* pPropertyValue = propertyState.getPropertyValue();
 
-        // Iterate attributes.
-        for ( TiXmlAttribute* pAttribute = pXmlElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->Next() )
+        // Is this the root object?
+        if ( propertyState.isRootObject() )
         {
-            // Insert attribute name.
-            StringTableEntry attributeName = StringTable->insert( pAttribute->Name() );
+            // Yes, so is the asset type set yet?
+            if ( mAssetDefinition.mAssetType == StringTable->EmptyString )
+            {
+                // No, set set asset type and base file-path.
+                mAssetDefinition.mAssetType = propertyState.getObjectName();
+                mAssetDefinition.mAssetBaseFilePath = parser.getParsingFilename();
+            }
 
             // Asset name?
-            if ( attributeName == assetNameField )
+            if ( propertyName == assetNameField )
             {
                 // Yes, so assign it.
-                mAssetDefinition.mAssetName = StringTable->insert( pAttribute->Value() );
-                continue;
+                mAssetDefinition.mAssetName = StringTable->insert( pPropertyValue );
+                return true;
             }
             // Asset description?
-            else if ( attributeName == assetDescriptionField )
+            else if ( propertyName == assetDescriptionField )
             {
                 // Yes, so assign it.
-                mAssetDefinition.mAssetDescription = StringTable->insert( pAttribute->Value() );
-                continue;
+                mAssetDefinition.mAssetDescription = StringTable->insert( pPropertyValue );
+                return true;
             }
             // Asset description?
-            else if ( attributeName == assetCategoryField )
+            else if ( propertyName == assetCategoryField )
             {
                 // Yes, so assign it.
-                mAssetDefinition.mAssetCategory = StringTable->insert( pAttribute->Value() );
-                continue;
+                mAssetDefinition.mAssetCategory = StringTable->insert( pPropertyValue );
+                return true;
             }
             // Asset auto-unload?
-            else if ( attributeName == assetAutoUnloadField )
+            else if ( propertyName == assetAutoUnloadField )
             {
                 // Yes, so assign it.
-                mAssetDefinition.mAssetAutoUnload = dAtob( pAttribute->Value() );
-                continue;
+                mAssetDefinition.mAssetAutoUnload = dAtob( pPropertyValue );
+                return true;
             }
             // Asset internal?
-            else if ( attributeName == assetInternalField )
+            else if ( propertyName == assetInternalField )
             {
                 // Yes, so assign it.
-                mAssetDefinition.mAssetInternal = dAtob( pAttribute->Value() );
-                continue;
+                mAssetDefinition.mAssetInternal = dAtob( pPropertyValue );
+                return true;
             }
         }
 
-        // Did we get an asset name?
-        if ( mAssetDefinition.mAssetName == StringTable->EmptyString )
-        {
-            // No, so reset everything.
-            clear();
-
-            // Stop processing!
-            return false;
-        }
-
-        // Set asset file-path.
-        mAssetDefinition.mAssetBaseFilePath = StringTable->insert( xmlParser.getParsingFilename() );
-
-        // Set asset type.
-        mAssetDefinition.mAssetType = StringTable->insert( pXmlElement->Value() );
+        // Fetch property word count.
+        const U32 propertyWordCount = StringUnit::getUnitCount( pPropertyValue, ASSET_ASSIGNMENT_TOKEN );
 
-        return true;
-    }
-
-    virtual bool visit( TiXmlAttribute* pAttribute, TamlXmlParser& xmlParser )
-    {
-        // Debug Profiling.
-        PROFILE_SCOPE(TamlAssetDeclaredVisitor_VisitAttribute);
-
-        // Sanity!
-        AssertFatal( mAssetDefinition.mAssetName != StringTable->EmptyString, "Cannot generate asset dependencies without asset name." );
-
-        // Fetch asset reference.
-        const char* pAssetReference = pAttribute->Value();
-
-        // Fetch field word count.
-        const U32 fieldWordCount = StringUnit::getUnitCount( pAssetReference, ASSET_ASSIGNMENT_TOKEN );
-
-        // Finish if there are not two words.
-        if ( fieldWordCount != 2 )
+        // Finish if there's not two words.
+        if ( propertyWordCount != 2 )
             return true;
 
         // Fetch the asset signature.
-        StringTableEntry assetSignature = StringTable->insert( StringUnit::getUnit( pAssetReference, 0, ASSET_ASSIGNMENT_TOKEN ) );
+        StringTableEntry assetSignature = StringTable->insert( StringUnit::getUnit( pPropertyValue, 0, ASSET_ASSIGNMENT_TOKEN ) );
 
         // Is this an asset Id signature?
-        if ( assetSignature == StringTable->insert(ASSET_ID_SIGNATURE) )
+        if ( assetSignature == assetLooseIdSignature )
         {
             // Yes, so get asset Id.
-            typeAssetId assetId = StringTable->insert( StringUnit::getUnit( pAssetReference, 1, ASSET_ASSIGNMENT_TOKEN ) );
+            typeAssetId assetId = StringTable->insert( StringUnit::getUnit( pPropertyValue, 1, ASSET_ASSIGNMENT_TOKEN ) );
 
             // Finish if the dependency is itself!
             if ( mAssetDefinition.mAssetId == assetId )
@@ -168,42 +163,20 @@ protected:
             mAssetDependencies.push_back( assetId );
         }
         // Is this a loose-file signature?
-        else if ( assetSignature == StringTable->insert(ASSET_LOOSEFILE_SIGNATURE) )
+        else if ( assetSignature == assetLooseFileSignature )
         {
             // Yes, so get loose-file reference.
-            const char* pAssetLooseFile = StringUnit::getUnit( pAssetReference, 1, ASSET_ASSIGNMENT_TOKEN );
+            const char* pAssetLooseFile = StringUnit::getUnit( pPropertyValue, 1, ASSET_ASSIGNMENT_TOKEN );
 
-            char assetFilePathBuffer[1024];
+            // Fetch asset path only.
+            char assetBasePathBuffer[1024];
+            dSprintf( assetBasePathBuffer, sizeof(assetBasePathBuffer), "%s", mAssetDefinition.mAssetBaseFilePath );
+            char* pFinalSlash = dStrrchr( assetBasePathBuffer, '/' );
+            if ( pFinalSlash != NULL ) *pFinalSlash = 0;
 
-            // Is the asset loose-file expando specified?
-            if ( *pAssetLooseFile == '#' )
-            {
-                // Yes, so fetch relative path.
-                char parsingFileBuffer[1024];
-                dStrcpy( parsingFileBuffer, xmlParser.getParsingFilename() );
-                
-                // Find the final slash.
-                char* pLastSlash = dStrrchr( parsingFileBuffer, '/' );
-
-                // Is this the last slash?
-                if ( pLastSlash == NULL )
-                {
-                    // No, so warn.
-                    Con::warnf( "Failed to parse the loose-file path '%s' in asset file '%s'.", pAssetLooseFile, parsingFileBuffer );
-                    return true;
-                }
-
-                // Remove parsing file.
-                *pLastSlash = 0;
-
-                // Format expanded path taking into account any missing slash.
-                dSprintf( assetFilePathBuffer, sizeof(assetFilePathBuffer), "%s/%s", parsingFileBuffer, pAssetLooseFile + (pAssetLooseFile[1] == '/' ? 2 : 1 ) );               
-            }
-            else
-            {
-                // No, so expand the path in the usual way.
-                Con::expandPath( assetFilePathBuffer, sizeof(assetFilePathBuffer), pAssetLooseFile );
-            }
+            // Expand the path in the usual way.
+            char assetFilePathBuffer[1024];
+            Con::expandPath( assetFilePathBuffer, sizeof(assetFilePathBuffer), pAssetLooseFile, assetBasePathBuffer );
 
             // Insert asset loose-file.
             mAssetLooseFiles.push_back( StringTable->insert( assetFilePathBuffer ) );
@@ -211,31 +184,6 @@ protected:
 
         return true;
     }
-
-public:
-    TamlAssetDeclaredVisitor() { mAssetDefinition.reset(); }
-    virtual ~TamlAssetDeclaredVisitor() {}
-
-    bool parse( const char* pFilename )
-    {
-        TamlXmlParser parser;
-        return parser.parse( pFilename, *this, false );
-    }
-
-    typedef StringTableEntry typeAssetId;
-    typedef Vector<typeAssetId> typeAssetIdVector;
-    typedef Vector<StringTableEntry> typeLooseFileVector;
-
-    inline AssetDefinition& getAssetDefinition( void ) { return mAssetDefinition; }
-    inline typeAssetIdVector& getAssetDependencies( void ) { return mAssetDependencies; }
-    inline typeLooseFileVector& getAssetLooseFiles( void ) { return mAssetLooseFiles; }
-
-    void clear( void ) { mAssetDefinition.reset(); mAssetDependencies.clear(); mAssetLooseFiles.clear(); }
-
-private:
-    AssetDefinition         mAssetDefinition;
-    typeAssetIdVector       mAssetDependencies;
-    typeLooseFileVector     mAssetLooseFiles;
 };
 
 #endif // _TAML_ASSET_DECLARED_VISITOR_H_

+ 48 - 50
engine/source/assets/tamlAssetReferencedUpdateVisitor.h

@@ -23,8 +23,12 @@
 #ifndef _TAML_ASSET_REFERENCED_UPDATE_VISITOR_H_
 #define _TAML_ASSET_REFERENCED_UPDATE_VISITOR_H_
 
-#ifndef _TAML_XMLPARSER_H_
-#include "persistence//taml/xml/tamlXmlParser.h"
+#ifndef _TAML_VISITOR_H_
+#include "persistence/taml/tamlVisitor.h"
+#endif
+
+#ifndef _TAML_PARSER_H_
+#include "persistence\/taml/tamlParser.h"
 #endif
 
 #ifndef _STRINGUNIT_H_
@@ -44,32 +48,58 @@
 
 //-----------------------------------------------------------------------------
 
-class TamlAssetReferencedUpdateVisitor : public TamlXmlVisitor
+class TamlAssetReferencedUpdateVisitor : public TamlVisitor
 {
-protected:
-    virtual bool visit( TiXmlElement* pXmlElement, TamlXmlParser& xmlParser ) { return true; }
+private:    
+    StringTableEntry mAssetIdFrom;
+    StringTableEntry mAssetIdTo;
 
-    virtual bool visit( TiXmlAttribute* pAttribute, TamlXmlParser& xmlParser )
+public:
+    TamlAssetReferencedUpdateVisitor() {}
+    virtual ~TamlAssetReferencedUpdateVisitor() {}
+
+    void setAssetIdFrom( const char* pAssetIdFrom )
+    {
+        // Sanity!
+        AssertFatal( pAssetIdFrom != NULL, "Asset Id from cannot be NULL." );
+
+        mAssetIdFrom = StringTable->insert( pAssetIdFrom );
+    }
+    StringTableEntry getAssetIdFrom( void ) const { return mAssetIdFrom; }
+
+    void setAssetIdTo( const char* pAssetIdTo )
+    {
+        // Sanity!
+        AssertFatal( pAssetIdTo != NULL, "Asset Id to cannot be NULL." );
+
+        mAssetIdTo = StringTable->insert( pAssetIdTo );
+    }
+    const char* getAssetIdTo( void ) const { return mAssetIdTo; }
+
+    virtual bool wantsPropertyChanges( void ) { return true; }
+    virtual bool wantsRootOnly( void ) { return false; }
+
+    virtual bool visit( const TamlParser& parser, TamlVisitor::PropertyState& propertyState )
     {
         // Debug Profiling.
-        PROFILE_SCOPE(TamlAssetReferencedUpdateVisitor_VisitAttribute);
+        PROFILE_SCOPE(TamlAssetReferencedUpdateVisitor_Visit);
 
-        // Fetch attribute value.
-        const char* pAttributeValue = pAttribute->Value();
+        // Fetch the property value.
+        const char* pPropertyValue = propertyState.getPropertyValue();
 
-        // Fetch attribute value word count.
-        const U32 valueWordCount = StringUnit::getUnitCount( pAttributeValue, ASSET_ASSIGNMENT_TOKEN );
+        // Fetch property value word count.
+        const U32 valueWordCount = StringUnit::getUnitCount( pPropertyValue, ASSET_ASSIGNMENT_TOKEN );
 
         // Finish if not two words.
         if ( valueWordCount != 2 )
             return true;
 
-        // Skip if this is not an asset signature.
-        if ( dStricmp( StringUnit::getUnit( pAttributeValue, 0, ASSET_ASSIGNMENT_TOKEN), ASSET_ID_SIGNATURE ) != 0 )
+        // Finish if this is not an asset signature.
+        if ( dStricmp( StringUnit::getUnit( pPropertyValue, 0, ASSET_ASSIGNMENT_TOKEN), assetLooseIdSignature ) != 0 )
             return true;
 
         // Get the asset value.
-        const char* pAssetValue = StringUnit::getUnit( pAttributeValue, 1, ASSET_ASSIGNMENT_TOKEN );
+        const char* pAssetValue = StringUnit::getUnit( pPropertyValue, 1, ASSET_ASSIGNMENT_TOKEN );
 
         // Finish if not the asset Id we're looking for.
         if ( dStricmp( pAssetValue, mAssetIdFrom ) != 0 )
@@ -78,52 +108,20 @@ protected:
         // Is the target asset empty?
         if ( mAssetIdTo == StringTable->EmptyString )
         {
-            // Yes, so set the attribute as empty.
-            pAttribute->SetValue( StringTable->EmptyString );
+            // Yes, so update the property as empty.
+            propertyState.updatePropertyValue( StringTable->EmptyString );
             return true;
         }
 
         // Format asset.
         char assetBuffer[1024];
-        dSprintf( assetBuffer, sizeof(assetBuffer), "%s%s%s", ASSET_ID_SIGNATURE, ASSET_ASSIGNMENT_TOKEN, mAssetIdTo );
+        dSprintf( assetBuffer, sizeof(assetBuffer), "%s%s%s", assetLooseIdSignature, ASSET_ASSIGNMENT_TOKEN, mAssetIdTo );
 
         // Assign new value.
-        pAttribute->SetValue( assetBuffer );
+        propertyState.updatePropertyValue( assetBuffer );
 
         return true;
     }
-
-public:
-    TamlAssetReferencedUpdateVisitor() {}
-    virtual ~TamlAssetReferencedUpdateVisitor() {}
-
-    bool parse( const char* pFilename )
-    {
-        TamlXmlParser parser;
-        return parser.parse( pFilename, *this, true );
-    }
-
-    void setAssetIdFrom( const char* pAssetIdFrom )
-    {
-        // Sanity!
-        AssertFatal( pAssetIdFrom != NULL, "Asset Id from cannot be NULL." );
-
-        mAssetIdFrom = StringTable->insert( pAssetIdFrom );
-    }
-    StringTableEntry getAssetIdFrom( void ) const { return mAssetIdFrom; }
-
-    void setAssetIdTo( const char* pAssetIdTo )
-    {
-        // Sanity!
-        AssertFatal( pAssetIdTo != NULL, "Asset Id to cannot be NULL." );
-
-        mAssetIdTo = StringTable->insert( pAssetIdTo );
-    }
-    const char* getAssetIdTo( void ) const { return mAssetIdTo; }
-
-private:    
-    StringTableEntry mAssetIdFrom;
-    StringTableEntry mAssetIdTo;
 };
 
 #endif // _TAML_ASSET_REFERENCED_UPDATE_VISITOR_H_

+ 35 - 36
engine/source/assets/tamlAssetReferencedVisitor.h

@@ -23,8 +23,12 @@
 #ifndef _TAML_ASSET_REFERENCED_VISITOR_H_
 #define _TAML_ASSET_REFERENCED_VISITOR_H_
 
-#ifndef _TAML_XMLPARSER_H_
-#include "persistence//taml/xml/tamlXmlParser.h"
+#ifndef _TAML_VISITOR_H_
+#include "persistence/taml/tamlVisitor.h"
+#endif
+
+#ifndef _TAML_PARSER_H_
+#include "persistence/taml/tamlParser.h"
 #endif
 
 #ifndef _ASSET_FIELD_TYPES_H_
@@ -36,32 +40,47 @@
 
 //-----------------------------------------------------------------------------
 
-class TamlAssetReferencedVisitor : public TamlXmlVisitor
+class TamlAssetReferencedVisitor : public TamlVisitor
 {
-protected:
-    virtual bool visit( TiXmlElement* pXmlElement, TamlXmlParser& xmlParser ) { return true; }
+public:
+    typedef StringTableEntry typeAssetId;
+    typedef HashMap<typeAssetId, StringTableEntry> typeAssetReferencedHash;
+
+private:
+    typeAssetReferencedHash mAssetReferenced;
+
+public:
+    TamlAssetReferencedVisitor() {}
+    virtual ~TamlAssetReferencedVisitor() {}
+
+    const typeAssetReferencedHash& getAssetReferencedMap( void ) const { return mAssetReferenced; }
+
+    void clear( void ) { mAssetReferenced.clear(); }
+
+    virtual bool wantsPropertyChanges( void ) { return false; }
+    virtual bool wantsRootOnly( void ) { return false; }
 
-    virtual bool visit( TiXmlAttribute* pAttribute, TamlXmlParser& xmlParser )
-    {
+    virtual bool visit( const TamlParser& parser, TamlVisitor::PropertyState& propertyState )
+    {    
         // Debug Profiling.
-        PROFILE_SCOPE(TamlAssetReferencedVisitor_VisitAttribute);
+        PROFILE_SCOPE(TamlAssetReferencedVisitor_Visit);
 
-        // Fetch asset reference.
-        const char* pAssetReference = pAttribute->Value();
+        // Fetch property value.
+        const char* pPropertyValue = propertyState.getPropertyValue();
 
-        // Fetch field word count.
-        const U32 fieldWordCount = StringUnit::getUnitCount( pAssetReference, ASSET_ASSIGNMENT_TOKEN );
+        // Fetch property word count.
+        const U32 propertyWordCount = StringUnit::getUnitCount( pPropertyValue, ASSET_ASSIGNMENT_TOKEN );
 
-        // Finish if there are not two words.
-        if ( fieldWordCount != 2 )
+        // Finish if there's not two words.
+        if ( propertyWordCount != 2 )
             return true;
 
         // Finish if the first word is not an asset signature.
-        if ( StringTable->insert( StringUnit::getUnit( pAssetReference, 0, ASSET_ASSIGNMENT_TOKEN ) ) != StringTable->insert(ASSET_ID_SIGNATURE) )
+        if ( StringTable->insert( StringUnit::getUnit( pPropertyValue, 0, ASSET_ASSIGNMENT_TOKEN ) ) != assetLooseIdSignature )
             return true;
 
         // Get asset Id.
-        typeAssetId assetId = StringTable->insert( StringUnit::getUnit( pAssetReference, 1, ASSET_ASSIGNMENT_TOKEN ) );
+        typeAssetId assetId = StringTable->insert( StringUnit::getUnit( pPropertyValue, 1, ASSET_ASSIGNMENT_TOKEN ) );
 
         // Finish if we already have this asset Id.
         if ( mAssetReferenced.contains( assetId ) )
@@ -72,26 +91,6 @@ protected:
 
         return true;
     }
-
-public:
-    TamlAssetReferencedVisitor() {}
-    virtual ~TamlAssetReferencedVisitor() {}
-
-    bool parse( const char* pFilename )
-    {
-        TamlXmlParser parser;
-        return parser.parse( pFilename, *this, false );
-    }
-
-    typedef StringTableEntry typeAssetId;
-    typedef HashMap<typeAssetId, StringTableEntry> typeAssetReferencedHash;
-
-    const typeAssetReferencedHash& getAssetReferencedMap( void ) const { return mAssetReferenced; }
-
-    void clear( void ) { mAssetReferenced.clear(); }
-
-private:
-    typeAssetReferencedHash mAssetReferenced;
 };
 
 #endif // _TAML_ASSET_REFERENCED_VISITOR_H_

+ 2 - 2
engine/source/module/moduleManager.cc

@@ -1263,8 +1263,8 @@ StringTableEntry ModuleManager::copyModule( ModuleDefinition* pSourceModuleDefin
             char parseFileBuffer[1024];
             dSprintf( parseFileBuffer, sizeof(parseFileBuffer), "%s/%s", pFileInfo->pFullPath, pFilename );
 
-            // Parse file.
-            if ( !moduleIdUpdateVisitor.parse( parseFileBuffer ) )
+            // Parse file.            
+            if ( !mTaml.parse( parseFileBuffer, moduleIdUpdateVisitor ) )
             {
                 // Warn.
                 Con::warnf("Module Manager: Failed to parse file '%s' whilst copying module Id '%s' using target directory '%s'.",

+ 57 - 65
engine/source/module/tamlModuleIdUpdateVisitor.h

@@ -23,12 +23,12 @@
 #ifndef _TAML_MODULE_ID_UPDATE_VISITOR_H_
 #define _TAML_MODULE_ID_UPDATE_VISITOR_H_
 
-#ifndef _TAML_XMLPARSER_H_
-#include "persistence//taml/xml/tamlXmlParser.h"
+#ifndef _TAML_VISITOR_H_
+#include "persistence/taml/tamlVisitor.h"
 #endif
 
-#ifndef _STRINGTABLE_H_
-#include "string/stringTable.h"
+#ifndef _TAML_PARSER_H_
+#include "persistence/taml/tamlParser.h"
 #endif
 
 #ifndef _ASSET_FIELD_TYPES_H_
@@ -37,74 +37,72 @@
 
 //-----------------------------------------------------------------------------
 
-class TamlModuleIdUpdateVisitor : public TamlXmlVisitor
+class TamlModuleIdUpdateVisitor : public TamlVisitor
 {
-protected:
-    virtual bool visit( TiXmlElement* pXmlElement, TamlXmlParser& xmlParser )
+private:    
+    StringTableEntry mModuleIdFrom;
+    StringTableEntry mModuleIdTo;
+    U32 mModuleIdFromLength;
+    U32 mModuleIdToLength;
+
+public:
+    TamlModuleIdUpdateVisitor() :
+        mModuleIdFrom( StringTable->EmptyString ),
+        mModuleIdTo( StringTable->EmptyString ),
+        mModuleIdFromLength( 0 ),
+        mModuleIdToLength( 0 )      
+        {}
+    virtual ~TamlModuleIdUpdateVisitor() {}
+
+    virtual bool wantsPropertyChanges( void ) { return true; }
+    virtual bool wantsRootOnly( void ) { return true; }
+
+    virtual bool visit( const TamlParser& parser, TamlVisitor::PropertyState& propertyState )
     {
-        // Iterate attributes.
-        for ( TiXmlAttribute* pAttribute = pXmlElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->Next() )
-        {
-            // Fetch attribute value.
-            const char* pAttributeValue = pAttribute->Value();
+        // Debug Profiling.
+        PROFILE_SCOPE(TamlModuleIdUpdateVisitor_Visit);
 
-            // Fetch value length.
-            const U32 valueLenth = dStrlen(pAttributeValue);
+        // Fetch property value.
+        const char* pPropertyValue = propertyState.getPropertyValue();
 
-            char newAttributeValueBuffer[1024];
+        // Fetch value length.
+        const U32 valueLenth = dStrlen(pPropertyValue);
 
-            // Is this an expando?
-            if ( *pAttributeValue == '^' )
-            {
-                // Yes, so skip if it's not the correct length.
-                if ( valueLenth < mModuleIdLengthFrom+1 )
-                    continue;
-
-                // Is this the module Id?
-                if ( dStrnicmp( pAttributeValue+1, mModuleIdFrom, mModuleIdLengthFrom ) == 0 )
-                {
-                    // Yes, so format a new value.
-                    dSprintf( newAttributeValueBuffer, sizeof(newAttributeValueBuffer), "^%s%s",
-                        mModuleIdTo, pAttributeValue+1+mModuleIdLengthFrom );
-
-                    // Assign new value.
-                    pAttribute->SetValue( newAttributeValueBuffer );
-                }
-
-                // Skip to next attribute.
-                continue;
-            }
+        char newAttributeValueBuffer[1024];
+
+        // Is this an expando?
+        if ( *pPropertyValue == '^' )
+        {
+            // Yes, so finish if it's not the correct length.
+            if ( valueLenth < mModuleIdFromLength+1 )
+                return true;
 
-            // Does the field start with the module Id?
-            if ( dStrnicmp( pAttributeValue, mModuleIdFrom, mModuleIdLengthFrom ) == 0 )
+            // Is this the module Id?
+            if ( dStrnicmp( pPropertyValue+1, mModuleIdFrom, mModuleIdFromLength ) == 0 )
             {
                 // Yes, so format a new value.
-                dSprintf( newAttributeValueBuffer, sizeof(newAttributeValueBuffer), "%s%s",
-                    mModuleIdTo, pAttributeValue+mModuleIdLengthFrom );
+                dSprintf( newAttributeValueBuffer, sizeof(newAttributeValueBuffer), "^%s%s",
+                    mModuleIdTo, pPropertyValue+1+mModuleIdFromLength );
 
                 // Assign new value.
-                pAttribute->SetValue( newAttributeValueBuffer );
+                propertyState.updatePropertyValue( newAttributeValueBuffer );
             }
-        }
 
-        return true;
-    }
+            return true;
+        }
 
-    virtual bool visit( TiXmlAttribute* pAttribute, TamlXmlParser& xmlParser ) { return true; }
+        // Does the field start with the module Id?
+        if ( dStrnicmp( pPropertyValue, mModuleIdFrom, mModuleIdFromLength ) == 0 )
+        {
+            // Yes, so format a new value.
+            dSprintf( newAttributeValueBuffer, sizeof(newAttributeValueBuffer), "%s%s",
+                mModuleIdTo, pPropertyValue+mModuleIdFromLength );
 
-public:
-    TamlModuleIdUpdateVisitor() :
-        mModuleIdFrom( StringTable->EmptyString ),
-        mModuleIdTo( StringTable->EmptyString ),
-        mModuleIdLengthFrom( 0 ),
-        mModuleIdLengthTo( 0 )      
-        {}
-    virtual ~TamlModuleIdUpdateVisitor() {}
+            // Assign new value.
+            propertyState.updatePropertyValue( newAttributeValueBuffer );
+        }
 
-    bool parse( const char* pFilename )
-    {
-        TamlXmlParser parser;
-        return parser.parse( pFilename, *this, true );
+        return true;
     }
 
     void setModuleIdFrom( const char* pModuleIdFrom )
@@ -114,7 +112,7 @@ public:
 
         // Set module Id.
         mModuleIdFrom = StringTable->insert( pModuleIdFrom );
-        mModuleIdLengthFrom = dStrlen(mModuleIdFrom);
+        mModuleIdFromLength = dStrlen(mModuleIdFrom);
     }
     StringTableEntry getModuleIdFrom( void ) const { return mModuleIdFrom; }
 
@@ -125,15 +123,9 @@ public:
 
         // Set module Id.
         mModuleIdTo = StringTable->insert( pModuleIdTo );
-        mModuleIdLengthTo = dStrlen(mModuleIdTo);
+        mModuleIdToLength = dStrlen(mModuleIdTo);
     }
     const char* getModuleIdTo( void ) const { return mModuleIdTo; }
-
-private:    
-    StringTableEntry mModuleIdFrom;
-    StringTableEntry mModuleIdTo;
-    U32 mModuleIdLengthFrom;
-    U32 mModuleIdLengthTo;
 };
 
 #endif // _TAML_MODULE_ID_UPDATE_VISITOR_H_

+ 41 - 3
engine/source/persistence/taml/taml.cc

@@ -30,6 +30,10 @@
 #include "persistence/taml/xml/tamlXmlReader.h"
 #endif
 
+#ifndef _TAML_XMLPARSER_H_
+#include "persistence/taml/xml/tamlXmlParser.h"
+#endif
+
 #ifndef _TAML_BINARYWRITER_H_
 #include "persistence/taml/binary/tamlBinaryWriter.h"
 #endif
@@ -407,6 +411,40 @@ SimObject* Taml::read( FileStream& stream, const TamlFormatMode formatMode )
 
 //-----------------------------------------------------------------------------
 
+bool Taml::parse( const char* pFilename, TamlVisitor& visitor )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(Taml_Parse);
+
+    // Sanity!
+    AssertFatal( pFilename != NULL, "Taml::parse() - Cannot parse a NULL filename." );
+
+    // Fetch format mode.
+    const TamlFormatMode formatMode = getFileAutoFormatMode( pFilename );
+
+    // Handle format mode appropriately.
+    switch( formatMode )
+    {
+        case XmlFormat:
+        {
+            // Parse with the visitor.
+            TamlXmlParser xmlParser;
+            return xmlParser.accept( pFilename, visitor );            
+        }
+
+        case JSONFormat:
+        case BinaryFormat:
+        default:
+            break;
+    }
+
+    // Warn.
+    Con::warnf( "Taml::parse() - Cannot parse '%s' file-type for filename '%s' as a required parser is not available.", getFormatModeDescription(formatMode), pFilename );
+    return false;
+}
+
+//-----------------------------------------------------------------------------
+
 void Taml::resetCompilation( void )
 {
     // Debug Profiling.
@@ -438,7 +476,7 @@ void Taml::resetCompilation( void )
 Taml::TamlFormatMode Taml::getFileAutoFormatMode( const char* pFilename )
 {
     // Sanity!
-    AssertFatal( pFilename != NULL, "Cannot auto-format using a NULL filename." );
+    AssertFatal( pFilename != NULL, "Taml::getFileAutoFormatMode() - Cannot auto-format using a NULL filename." );
 
     // Is auto-format active?
     if ( mAutoFormat )
@@ -479,7 +517,7 @@ TamlWriteNode* Taml::compileObject( SimObject* pSimObject, const bool forceId )
     PROFILE_SCOPE(Taml_CompileObject);
 
     // Sanity!
-    AssertFatal( pSimObject != NULL, "Cannot compile a NULL object." );
+    AssertFatal( pSimObject != NULL, "Taml::compileObject() - Cannot compile a NULL object." );
 
     // Fetch object Id.
     const SimObjectId objectId = pSimObject->getId();
@@ -491,7 +529,7 @@ TamlWriteNode* Taml::compileObject( SimObject* pSimObject, const bool forceId )
     if ( compiledItr != mCompiledObjects.end() )
     {
         // Yes, so sanity!
-        AssertFatal( mCompiledNodes.size() != 0, "Found a compiled node at the root." );
+        AssertFatal( mCompiledNodes.size() != 0, "Taml::compileObject() - Found a compiled node at the root." );
 
         // Yes, so fetch node.
         TamlWriteNode* compiledNode = compiledItr->value;

+ 12 - 4
engine/source/persistence/taml/taml.h

@@ -36,7 +36,11 @@
 #endif
 
 #ifndef _TAML_WRITE_NODE_H_
-#include "persistence/taml/TamlWriteNode.h"
+#include "persistence/taml/tamlWriteNode.h"
+#endif
+
+#ifndef _TAML_VISITOR_H_
+#include "persistence/taml/tamlVisitor.h"
 #endif
 
 #ifndef _SIMBASE_H_
@@ -178,10 +182,10 @@ public:
     }
     SimObject* read( const char* pFilename );
 
-    static TamlFormatMode getFormatModeEnum( const char* label );
-    static const char* getFormatModeDescription( const TamlFormatMode formatMode );
+    /// Parse.
+    bool parse( const char* pFilename, TamlVisitor& visitor );
 
-    // Create type.
+    /// Create type.
     static SimObject* createType( StringTableEntry typeName, const Taml* pTaml, const char* pProgenitorSuffix = NULL );
 
     /// Schema generation.
@@ -190,6 +194,10 @@ public:
     /// Write a unrestricted custom Taml schema.
     static void WriteUnrestrictedCustomTamlSchema( const char* pCustomNodeName, const AbstractClassRep* pClassRep, TiXmlElement* pParentElement );
 
+    /// Get format mode info.
+    static TamlFormatMode getFormatModeEnum( const char* label );
+    static const char* getFormatModeDescription( const TamlFormatMode formatMode );
+
     /// Taml callbacks.
     inline void tamlPreWrite( TamlCallbacks* pCallbacks )                                           { pCallbacks->onTamlPreWrite(); }
     inline void tamlPostWrite( TamlCallbacks* pCallbacks )                                          { pCallbacks->onTamlPostWrite(); }

+ 18 - 18
engine/source/persistence/taml/xml/tamlXmlVisitor.h → engine/source/persistence/taml/tamlParser.h

@@ -20,34 +20,34 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
-#ifndef _TAML_XML_VISITOR_H_
-#define _TAML_XML_VISITOR_H_
+#ifndef _TAML_PARSER_H_
+#define _TAML_PARSER_H_
 
-#ifndef TINYXML_INCLUDED
-#include "persistence/tinyXML/tinyxml.h"
-#endif
+#include "string/stringTable.h"
 
 //-----------------------------------------------------------------------------
 
-class TamlXmlParser;
+class TamlVisitor;
 
 //-----------------------------------------------------------------------------
 
-class TamlXmlVisitor
+class TamlParser
 {
-private:
-    friend class TamlXmlParser;
-
 public:
-    TamlXmlVisitor() {}
-    virtual ~TamlXmlVisitor() {}
+    TamlParser() :
+        mParsingFilename(StringTable->EmptyString)
+    {}
+    virtual ~TamlParser() {}
 
-    /// Parsing.
-    virtual bool parse( const char* pFilename ) = 0;
+    /// Accept visitor.
+    virtual bool accept( const char* pFilename, TamlVisitor& visitor ) = 0;
 
-protected:
-    virtual bool visit( TiXmlElement* pXmlElement, TamlXmlParser& xmlParser ) = 0;
-    virtual bool visit( TiXmlAttribute* pAttribute, TamlXmlParser& xmlParser ) = 0;
+    /// Filename.
+    inline void setParsingFilename( const char* pFilename ) { mParsingFilename = StringTable->insert(pFilename); }
+    inline StringTableEntry getParsingFilename( void ) const { return mParsingFilename; }
+
+private:
+    StringTableEntry mParsingFilename;
 };
 
-#endif // _TAML_XML_VISITOR_H_
+#endif // _TAML_PARSER_H_

+ 108 - 0
engine/source/persistence/taml/tamlVisitor.h

@@ -0,0 +1,108 @@
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _TAML_VISITOR_H_
+#define _TAML_VISITOR_H_
+
+#include "string/stringTable.h"
+
+//-----------------------------------------------------------------------------
+
+class TamlParser;
+
+//-----------------------------------------------------------------------------
+
+class TamlVisitor
+{
+public:
+    /// Visitor property state.
+    struct PropertyState
+    {
+    private:
+        StringTableEntry    mObjectName;
+        StringTableEntry    mPropertyName;
+        char                mPropertyValue[4096];
+        bool                mPropertyValueDirty;
+        bool                mIsRootObject;
+
+    public:
+        PropertyState()
+        {
+            mObjectName = StringTable->EmptyString;
+            mPropertyName = StringTable->EmptyString;
+            *mPropertyValue = 0;
+            mPropertyValueDirty = false;
+            mIsRootObject = false;
+        }
+
+        inline void setObjectName( const char* pObjectName, const bool rootObject )
+        {
+            mObjectName = StringTable->insert( pObjectName );
+            mIsRootObject = rootObject;
+        }
+        inline StringTableEntry getObjectName( void ) const { return mObjectName; }
+        inline bool isRootObject( void ) const { return mIsRootObject; }
+
+        inline void setProperty( const char* pPropertyName, const char* pPropertyValue )
+        {
+            // Set property name.
+            mPropertyName = StringTable->insert( pPropertyName );
+
+            // Format property value.
+            dSprintf( mPropertyValue, sizeof(mPropertyValue), "%s", pPropertyValue );
+
+            // Flag as not dirty.
+            mPropertyValueDirty = false;
+        }
+
+        inline void updatePropertyValue( const char* pPropertyValue )
+        {
+            // Update property value.
+            dSprintf( mPropertyValue, sizeof(mPropertyValue), "%s", pPropertyValue );
+
+            // Flag as dirty.
+            mPropertyValueDirty = true;
+        }
+
+        inline StringTableEntry getPropertyName( void ) const { return mPropertyName; }
+        inline const char* getPropertyValue( void ) const { return mPropertyValue; }
+
+        inline void resetPropertyValueDirty( void ) { mPropertyValueDirty = false; }
+        inline bool getPropertyValueDirty( void ) const { return mPropertyValueDirty; }
+    };
+
+public:
+    TamlVisitor() {}
+    virtual ~TamlVisitor() {}
+
+    /// Whether the visitor wants to perform property changes.
+    /// This allows a check against the parser which may not allow changes.
+    virtual bool wantsPropertyChanges( void ) = 0;
+
+    /// Whether the visitor wants to visit the root node only.
+    virtual bool wantsRootOnly( void ) = 0;
+
+    /// The state of the visited property.
+    virtual bool visit( const TamlParser& parser, PropertyState& propertyState ) = 0;
+};
+
+#endif // _TAML_VISITOR_H_

+ 60 - 31
engine/source/persistence/taml/xml/tamlXmlParser.cc

@@ -21,20 +21,23 @@
 //-----------------------------------------------------------------------------
 
 #include "persistence/taml/xml/tamlXmlParser.h"
+#include "persistence/taml/tamlVisitor.h"
+#include "console/console.h"
 
 // Debug Profiling.
 #include "debug/profiler.h"
 
 //-----------------------------------------------------------------------------
 
-bool TamlXmlParser::parse( const char* pFilename, TamlXmlVisitor& visitor, const bool writeDocument )
+bool TamlXmlParser::accept( const char* pFilename, TamlVisitor& visitor )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(TamlXmlParser_Parse);
+    PROFILE_SCOPE(TamlXmlParser_Accept);
 
     // Sanity!
     AssertFatal( pFilename != NULL, "Cannot parse a NULL filename." );
 
+    // Expand the file-path.
     char filenameBuffer[1024];
     Con::expandPath( filenameBuffer, sizeof(filenameBuffer), pFilename );
 
@@ -62,55 +65,58 @@ bool TamlXmlParser::parse( const char* pFilename, TamlXmlVisitor& visitor, const
     stream.close();
 
     // Set parsing filename.
-    mpParsingFilename = filenameBuffer;
+    setParsingFilename( filenameBuffer );
+
+    // Flag document as not dirty.
+    mDocumentDirty = false;
 
     // Parse root element.
     parseElement( xmlDocument.RootElement(), visitor );
 
     // Reset parsing filename.
-    mpParsingFilename = NULL;
+    setParsingFilename( StringTable->EmptyString );
 
-    // Are we writing the document?
-    if ( writeDocument )
-    {
-        // Yes, so open for write?
-        if ( !stream.open( filenameBuffer, FileStream::Write ) )
-        {
-            // No, so warn.
-            Con::warnf("TamlXmlParser::parse() - Could not open filename '%s' for write.", filenameBuffer );
-            return false;
-        }
+    // Finish if the document is not dirty.
+    if ( !mDocumentDirty )
+        return true;
 
-        // Yes, so save the document.
-        if ( !xmlDocument.SaveFile( stream ) )
-        {
-            // Warn!
-            Con::warnf("TamlXmlParser: Could not save Taml XML document.");
-            return false;
-        }
+    // Open for write?
+    if ( !stream.open( filenameBuffer, FileStream::Write ) )
+    {
+        // No, so warn.
+        Con::warnf("TamlXmlParser::parse() - Could not open filename '%s' for write.", filenameBuffer );
+        return false;
+    }
 
-        // Close the stream.
-        stream.close();
+    // Yes, so save the document.
+    if ( !xmlDocument.SaveFile( stream ) )
+    {
+        // Warn!
+        Con::warnf("TamlXmlParser: Could not save Taml XML document.");
+        return false;
     }
 
+    // Close the stream.
+    stream.close();
+
     return true;
 }
 
 //-----------------------------------------------------------------------------
 
-bool TamlXmlParser::parseElement( TiXmlElement* pXmlElement, TamlXmlVisitor& visitor )
+bool TamlXmlParser::parseElement( TiXmlElement* pXmlElement, TamlVisitor& visitor )
 {
     // Debug Profiling.
     PROFILE_SCOPE(TamlXmlParser_ParseElement);
 
-    // Visit this element (stop processing if instructed).
-    if ( !visitor.visit( pXmlElement, *this ) )
-        return false;
-
     // Parse attributes (stop processing if instructed).
     if ( !parseAttributes( pXmlElement, visitor ) )
         return false;
 
+    // Finish if only the root is needed.
+    if ( visitor.wantsRootOnly() )
+        return false;
+
     // Fetch any children.
     TiXmlNode* pChildXmlNode = pXmlElement->FirstChild();
 
@@ -131,16 +137,39 @@ bool TamlXmlParser::parseElement( TiXmlElement* pXmlElement, TamlXmlVisitor& vis
 
 //-----------------------------------------------------------------------------
 
-bool TamlXmlParser::parseAttributes( TiXmlElement* pXmlElement, TamlXmlVisitor& visitor )
+bool TamlXmlParser::parseAttributes( TiXmlElement* pXmlElement, TamlVisitor& visitor )
 {
     // Debug Profiling.
     PROFILE_SCOPE(TamlXmlParser_ParseAttribute);
 
+    // Calculate if element is at the root or not.
+    const bool isRoot = pXmlElement->GetDocument()->RootElement() == pXmlElement;
+
+    // Create a visitor property state.
+    TamlVisitor::PropertyState propertyState;
+    propertyState.setObjectName( pXmlElement->Value(), isRoot );
+
     // Iterate attributes.
     for ( TiXmlAttribute* pAttribute = pXmlElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->Next() )
     {
-        // Visit this attribute (stop processing if instructed).
-        if ( !visitor.visit( pAttribute, *this ) )
+        // Configure property state.
+        propertyState.setProperty( pAttribute->Name(), pAttribute->Value() );
+
+        // Visit this attribute.
+        const bool visitStatus = visitor.visit( *this, propertyState );
+
+        // Was the property value changed?
+        if ( propertyState.getPropertyValueDirty() )
+        {
+            // Yes, so update the attribute.
+            pAttribute->SetValue( propertyState.getPropertyValue() );
+
+            // Flag the document as dirty.
+            mDocumentDirty = true;
+        }
+
+        // Finish if requested.
+        if ( !visitStatus )
             return false;
     }
 

+ 12 - 16
engine/source/persistence/taml/xml/tamlXmlParser.h

@@ -23,35 +23,31 @@
 #ifndef _TAML_XMLPARSER_H_
 #define _TAML_XMLPARSER_H_
 
-#ifndef _TAML_XML_VISITOR_H_
-#include "persistence/taml/xml/tamlXmlVisitor.h"
+#ifndef _TAML_PARSER_H_
+#include "persistence/taml/tamlParser.h"
 #endif
 
-#ifndef _TAML_H_
-#include "persistence/taml/taml.h"
+#ifndef TINYXML_INCLUDED
+#include "persistence/tinyXML/tinyxml.h"
 #endif
 
+
 //-----------------------------------------------------------------------------
 
-class TamlXmlParser
+class TamlXmlParser : public TamlParser
 {
 public:
-    TamlXmlParser() :
-        mpParsingFilename( NULL ) {}
+    TamlXmlParser() {}
     virtual ~TamlXmlParser() {}
 
-    /// Parse.
-    bool parse( const char* pFilename, TamlXmlVisitor& visitor, const bool writeDocument );
-
-    /// Filename.
-    inline const char* getParsingFilename( void ) const { return mpParsingFilename; }
+    /// Accept visitor.
+    virtual bool accept( const char* pFilename, TamlVisitor& visitor );
 
 private:
-    const char* mpParsingFilename;
+    bool parseElement( TiXmlElement* pXmlElement, TamlVisitor& visitor );
+    bool parseAttributes( TiXmlElement* pXmlElement, TamlVisitor& visitor );
 
-private:
-    bool parseElement( TiXmlElement* pXmlElement, TamlXmlVisitor& visitor );
-    bool parseAttributes( TiXmlElement* pXmlElement, TamlXmlVisitor& visitor );
+    bool mDocumentDirty;
 };
 
 #endif // _TAML_XMLPARSER_H_