Browse Source

Merge pull request #1573 from marauder2k9-torque/Taml-Json

Taml Binary compilation and JSON format
Brian Roberts 1 week ago
parent
commit
1277b1a347

+ 2 - 1
Engine/source/CMakeLists.txt

@@ -115,7 +115,8 @@ torqueAddSourceDirectories("scene" "scene/culling" "scene/zones" "scene/mixin")
 torqueAddSourceDirectories("math" "math/util")
 torqueAddSourceDirectories("math" "math/util")
 
 
 # Handle persistence
 # Handle persistence
-torqueAddSourceDirectories("persistence/taml" "persistence/taml/binary" "persistence/taml/xml")
+set(TORQUE_INCLUDE_DIRECTORIES ${TORQUE_INCLUDE_DIRECTORIES} "persistence/rapidjson")
+torqueAddSourceDirectories("persistence/taml" "persistence/taml/binary" "persistence/taml/xml" "persistence/taml/json")
 
 
 # Handle Cinterface
 # Handle Cinterface
 torqueAddSourceDirectories("cinterface")
 torqueAddSourceDirectories("cinterface")

+ 260 - 103
Engine/source/assets/assetManager.cpp

@@ -964,6 +964,148 @@ bool AssetManager::renameReferencedAsset( const char* pAssetIdFrom, const char*
     return true;
     return true;
 }
 }
 
 
+bool AssetManager::compileAllAssets(const bool compressed, const bool includeUnloaded)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(AssetManager_CompileAllAssets);
+
+   // Info.
+   if (mEchoInfo)
+   {
+      Con::printSeparator();
+      Con::printf("Asset Manager: Started compiling ALL assets.");
+   }
+
+   Vector<typeAssetId> assetsToRelease;
+
+   // Are we including unloaded assets?
+   if (includeUnloaded)
+   {
+      // Yes, so prepare a list of assets to release and load them.
+      for (typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr)
+      {
+         // Fetch asset Id.
+         typeAssetId assetId = assetItr->key;
+
+         // Skip if asset is loaded.
+         if (assetItr->value->mpAssetBase != NULL)
+            continue;
+
+         // Note asset as needing a release.
+         assetsToRelease.push_back(assetId);
+
+         // Acquire the asset.
+         acquireAsset<AssetBase>(assetId);
+      }
+   }
+
+   bool oldCompressed = mTaml.getBinaryCompression();
+   mTaml.setBinaryCompression(compressed);
+   bool success = false;
+   // Refresh the current loaded assets.
+   // NOTE: This will result in some assets being refreshed more than once due to asset dependencies.
+   for (typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr)
+   {
+      // Skip private assets.
+      if (assetItr->value->mAssetPrivate)
+         continue;
+
+      // Refresh asset if it's loaded.
+      success = compileAsset(assetItr->key);
+      if (!success)
+      {
+         break;
+      }
+   }
+
+   mTaml.setBinaryCompression(oldCompressed);
+
+   // Are we including unloaded assets?
+   if (includeUnloaded)
+   {
+      // Yes, so release the assets we loaded.
+      for (Vector<typeAssetId>::iterator assetItr = assetsToRelease.begin(); assetItr != assetsToRelease.end(); ++assetItr)
+      {
+         releaseAsset(*assetItr);
+      }
+   }
+
+   // Info.
+   if (mEchoInfo)
+   {
+      Con::printSeparator();
+      Con::printf("Asset Manager: Finished compiling ALL assets.");
+   }
+
+   return success;
+}
+
+bool AssetManager::compileModuleAssets(ModuleDefinition* pModuleDefinition)
+{
+   // Sanity!
+   AssertFatal(pModuleDefinition != NULL, "Cannot remove declared assets using a NULL module definition");
+
+   // Fetch module assets.
+   ModuleDefinition::typeModuleAssetsVector& moduleAssets = pModuleDefinition->getModuleAssets();
+
+   // Remove all module assets.
+   while (moduleAssets.size() > 0)
+   {
+      // Fetch asset definition.
+      AssetDefinition* pAssetDefinition = *moduleAssets.begin();
+      bool success = compileAsset(pAssetDefinition->mAssetId);
+      if (!success)
+         return false;
+   }
+
+   return true;
+}
+
+bool AssetManager::compileAsset(const char* pAssetId)
+{
+   // Sanity!
+   AssertFatal(pAssetId != NULL, "Cannot compile NULL asset");
+
+   AssetDefinition* pAssetDefinition = findAsset(pAssetId);
+
+   // Does the asset exist?
+   if (pAssetDefinition == NULL)
+   {
+      Con::warnf("Asset Manager::compileAsset Failed to compile asset Id '%s' as it does not exist", pAssetId);
+      return false;
+   }
+
+   // Info.
+   if (mEchoInfo)
+   {
+      Con::printSeparator();
+      Con::printf("Asset Manager::compileAsset Started compiling Asset Id '%s'...", pAssetId);
+   }
+
+   AssetBase* pAssetBase = pAssetDefinition->mpAssetBase;
+   if (pAssetBase != NULL)
+   {
+      Torque::Path binaryPath = pAssetDefinition->mAssetBaseFilePath;
+      binaryPath.setExtension(mTaml.getAutoFormatBinaryExtension());
+      // Save asset.
+      mTaml.write(pAssetBase, binaryPath.getFullPath().c_str());
+   }
+   else
+   {
+      Con::warnf("Asset Manager::compileAsset Failed to compile asset Id '%s' as it does not have an assetBase", pAssetId);
+      return false;
+   }
+
+   // Info.
+   if (mEchoInfo)
+   {
+      Con::printSeparator();
+      Con::printf("Asset Manager: Finished compiling Asset Id '%s'.", pAssetId);
+   }
+
+   return true;
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 bool AssetManager::releaseAsset( const char* pAssetId )
 bool AssetManager::releaseAsset( const char* pAssetId )
@@ -2550,133 +2692,148 @@ bool AssetManager::scanDeclaredAssets( const char* pPath, const char* pExtension
 
 
     TamlAssetDeclaredVisitor assetDeclaredVisitor;
     TamlAssetDeclaredVisitor assetDeclaredVisitor;
 
 
-    // Iterate files.
-    for (S32 i = 0; i < numAssets; ++i)
-    {
-        Torque::Path assetPath = files[i];
+   // Iterate files.
+   for (S32 i = 0; i < numAssets; ++i)
+   {
+      Torque::Path assetPath = files[i];
+      
+      Torque::Path compiledPath = assetPath;
+      compiledPath.setExtension(mTaml.getAutoFormatBinaryExtension());
 
 
-        // Clear declared assets.
-        assetDeclaredVisitor.clear();
+      if (Torque::FS::IsFile(compiledPath))
+      {
+         Torque::FS::FileNodeRef assetFile = Torque::FS::GetFileNode(assetPath);
+         Torque::FS::FileNodeRef compiledFile = Torque::FS::GetFileNode(compiledPath);
 
 
-        // Format full file-path.
-        char assetFileBuffer[1024];
-        dSprintf( assetFileBuffer, sizeof(assetFileBuffer), "%s/%s", assetPath.getPath().c_str(), assetPath.getFullFileName().c_str());
+         if (assetFile != NULL && compiledFile != NULL)
+         {
+            if (compiledFile->getModifiedTime() >= assetFile->getModifiedTime())
+               assetPath = compiledPath;
+         }
+      }
 
 
-        // Parse the filename.
-        if ( !mTaml.parse( assetFileBuffer, assetDeclaredVisitor ) )
-        {
-            // Warn.
-            Con::warnf( "Asset Manager: Failed to parse file containing asset declaration: '%s'.", assetFileBuffer );
-            continue;
-        }
+      // Clear declared assets.
+      assetDeclaredVisitor.clear();
 
 
-        // Fetch asset definition.
-        AssetDefinition& foundAssetDefinition = assetDeclaredVisitor.getAssetDefinition();
+      // Format full file-path.
+      char assetFileBuffer[1024];
+      dSprintf( assetFileBuffer, sizeof(assetFileBuffer), "%s/%s", assetPath.getPath().c_str(), assetPath.getFullFileName().c_str());
 
 
-        // Did we get an asset name?
-        if ( foundAssetDefinition.mAssetName == StringTable->EmptyString() )
-        {
-            // No, so warn.
-            Con::warnf( "Asset Manager: Parsed file '%s' but did not encounter an asset.", assetFileBuffer );
-            continue;
-        }
+      // Parse the filename.
+      if ( !mTaml.parse( assetFileBuffer, assetDeclaredVisitor ) )
+      {
+         // Warn.
+         Con::warnf( "Asset Manager: Failed to parse file containing asset declaration: '%s'.", assetFileBuffer );
+         continue;
+      }
 
 
-        // Set module definition.
-        foundAssetDefinition.mpModuleDefinition = pModuleDefinition;
+      // Fetch asset definition.
+      AssetDefinition& foundAssetDefinition = assetDeclaredVisitor.getAssetDefinition();
 
 
-        // Format asset Id.
-        char assetIdBuffer[1024];
-        dSprintf(assetIdBuffer, sizeof(assetIdBuffer), "%s%s%s",
-            pModuleDefinition->getModuleId(),
-            ASSET_SCOPE_TOKEN,
-            foundAssetDefinition.mAssetName );
+      // Did we get an asset name?
+      if ( foundAssetDefinition.mAssetName == StringTable->EmptyString() )
+      {
+         // No, so warn.
+         Con::warnf( "Asset Manager: Parsed file '%s' but did not encounter an asset.", assetFileBuffer );
+         continue;
+      }
 
 
-        // Set asset Id.
-        foundAssetDefinition.mAssetId = StringTable->insert( assetIdBuffer );
+      // Set module definition.
+      foundAssetDefinition.mpModuleDefinition = pModuleDefinition;
 
 
-        // Does this asset already exist?
-        if ( mDeclaredAssets.contains( foundAssetDefinition.mAssetId ) )
-        {
-            // Yes, so warn.
-            Con::warnf( "Asset Manager: Encountered asset Id '%s' in asset file '%s' but it conflicts with existing asset Id in asset file '%s'.",
-                foundAssetDefinition.mAssetId,
-                foundAssetDefinition.mAssetBaseFilePath,
-                mDeclaredAssets.find( foundAssetDefinition.mAssetId )->value->mAssetBaseFilePath );
+      // Format asset Id.
+      char assetIdBuffer[1024];
+      dSprintf(assetIdBuffer, sizeof(assetIdBuffer), "%s%s%s",
+         pModuleDefinition->getModuleId(),
+         ASSET_SCOPE_TOKEN,
+         foundAssetDefinition.mAssetName );
 
 
-            continue;
-        }
+      // Set asset Id.
+      foundAssetDefinition.mAssetId = StringTable->insert( assetIdBuffer );
+
+      // Does this asset already exist?
+      if ( mDeclaredAssets.contains( foundAssetDefinition.mAssetId ) )
+      {
+         // Yes, so warn.
+         Con::warnf( "Asset Manager: Encountered asset Id '%s' in asset file '%s' but it conflicts with existing asset Id in asset file '%s'.",
+               foundAssetDefinition.mAssetId,
+               foundAssetDefinition.mAssetBaseFilePath,
+               mDeclaredAssets.find( foundAssetDefinition.mAssetId )->value->mAssetBaseFilePath );
+
+         continue;
+      }
 
 
-        // Create new asset definition.
-        AssetDefinition* pAssetDefinition = new AssetDefinition( foundAssetDefinition );
+      // Create new asset definition.
+      AssetDefinition* pAssetDefinition = new AssetDefinition( foundAssetDefinition );
 
 
-        // Store in declared assets.
-        mDeclaredAssets.insert( pAssetDefinition->mAssetId, pAssetDefinition );
+      // Store in declared assets.
+      mDeclaredAssets.insert( pAssetDefinition->mAssetId, pAssetDefinition );
 
 
-        // Store in module assets.
-        moduleAssets.push_back( pAssetDefinition );
+      // Store in module assets.
+      moduleAssets.push_back( pAssetDefinition );
         
         
-        // Info.
-        if ( mEchoInfo )
-        {
-            Con::printSeparator();
-            Con::printf( "Asset Manager: Adding Asset Id '%s' of type '%s' in asset file '%s'.",
-                pAssetDefinition->mAssetId,
-                pAssetDefinition->mAssetType,
-                pAssetDefinition->mAssetBaseFilePath );
-        }
+      // Info.
+      if ( mEchoInfo )
+      {
+         Con::printSeparator();
+         Con::printf( "Asset Manager: Adding Asset Id '%s' of type '%s' in asset file '%s'.",
+               pAssetDefinition->mAssetId,
+               pAssetDefinition->mAssetType,
+               pAssetDefinition->mAssetBaseFilePath );
+      }
 
 
-        // Fetch asset Id.
-        StringTableEntry assetId = pAssetDefinition->mAssetId;
+      // Fetch asset Id.
+      StringTableEntry assetId = pAssetDefinition->mAssetId;
 
 
-        // Fetch asset dependencies.
-        TamlAssetDeclaredVisitor::typeAssetIdVector& assetDependencies = assetDeclaredVisitor.getAssetDependencies();
+      // Fetch asset dependencies.
+      TamlAssetDeclaredVisitor::typeAssetIdVector& assetDependencies = assetDeclaredVisitor.getAssetDependencies();
 
 
-        // Are there any asset dependencies?
-        if ( assetDependencies.size() > 0 )
-        {
-            // Yes, so iterate dependencies.
-            for( TamlAssetDeclaredVisitor::typeAssetIdVector::iterator assetDependencyItr = assetDependencies.begin(); assetDependencyItr != assetDependencies.end(); ++assetDependencyItr )
-            {
-                // Fetch asset Ids.
-                StringTableEntry dependencyAssetId = *assetDependencyItr;
+      // Are there any asset dependencies?
+      if ( assetDependencies.size() > 0 )
+      {
+         // Yes, so iterate dependencies.
+         for( TamlAssetDeclaredVisitor::typeAssetIdVector::iterator assetDependencyItr = assetDependencies.begin(); assetDependencyItr != assetDependencies.end(); ++assetDependencyItr )
+         {
+               // Fetch asset Ids.
+               StringTableEntry dependencyAssetId = *assetDependencyItr;
 
 
-                // Insert depends-on.
-                mAssetDependsOn.insertEqual( assetId, dependencyAssetId );
+               // Insert depends-on.
+               mAssetDependsOn.insertEqual( assetId, dependencyAssetId );
 
 
-                // Insert is-depended-on.
-                mAssetIsDependedOn.insertEqual( dependencyAssetId, assetId );
+               // Insert is-depended-on.
+               mAssetIsDependedOn.insertEqual( dependencyAssetId, assetId );
 
 
-                // Info.
-                if ( mEchoInfo )
-                {
-                    Con::printf( "Asset Manager: Asset Id '%s' has dependency of Asset Id '%s'", assetId, dependencyAssetId );
-                }
-            }
-        }
+               // Info.
+               if ( mEchoInfo )
+               {
+                  Con::printf( "Asset Manager: Asset Id '%s' has dependency of Asset Id '%s'", assetId, dependencyAssetId );
+               }
+         }
+      }
 
 
-        // Fetch asset loose files.
-        TamlAssetDeclaredVisitor::typeLooseFileVector& assetLooseFiles = assetDeclaredVisitor.getAssetLooseFiles();
+      // Fetch asset loose files.
+      TamlAssetDeclaredVisitor::typeLooseFileVector& assetLooseFiles = assetDeclaredVisitor.getAssetLooseFiles();
 
 
-        // Are there any loose files?
-        if ( assetLooseFiles.size() > 0 )
-        {
-            // Yes, so iterate loose files.
-            for( TamlAssetDeclaredVisitor::typeLooseFileVector::iterator assetLooseFileItr = assetLooseFiles.begin(); assetLooseFileItr != assetLooseFiles.end(); ++assetLooseFileItr )
-            {
-                // Fetch loose file.
-                StringTableEntry looseFile = *assetLooseFileItr;
+      // Are there any loose files?
+      if ( assetLooseFiles.size() > 0 )
+      {
+         // Yes, so iterate loose files.
+         for( TamlAssetDeclaredVisitor::typeLooseFileVector::iterator assetLooseFileItr = assetLooseFiles.begin(); assetLooseFileItr != assetLooseFiles.end(); ++assetLooseFileItr )
+         {
+               // Fetch loose file.
+               StringTableEntry looseFile = *assetLooseFileItr;
 
 
-                // Info.
-                if ( mEchoInfo )
-                {
-                    Con::printf( "Asset Manager: Asset Id '%s' has loose file '%s'.", assetId, looseFile );
-                }
+               // Info.
+               if ( mEchoInfo )
+               {
+                  Con::printf( "Asset Manager: Asset Id '%s' has loose file '%s'.", assetId, looseFile );
+               }
 
 
-                // Store loose file.
-                pAssetDefinition->mAssetLooseFiles.push_back( looseFile );
-            }
-        }
-    }
+               // Store loose file.
+               pAssetDefinition->mAssetLooseFiles.push_back( looseFile );
+         }
+      }
+   }
 
 
     // Info.
     // Info.
     if ( mEchoInfo )
     if ( mEchoInfo )

+ 23 - 1
Engine/source/assets/assetManager.h

@@ -151,6 +151,28 @@ public:
     bool isReferencedAsset( const char* pAssetId );
     bool isReferencedAsset( const char* pAssetId );
     bool renameReferencedAsset( const char* pAssetIdFrom, const char* pAssetIdTo );
     bool renameReferencedAsset( const char* pAssetIdFrom, const char* pAssetIdTo );
 
 
+    /// <summary>
+    /// Compile all assets.
+    /// </summary>
+    /// <param name="compressed">Do we want binary compression?</param>
+    /// <param name="includeUnloaded">Do we want to include unloaded assets?</param>
+    /// <returns>True if successful, otherwise false.</returns>
+    bool compileAllAssets(const bool compressed = false, const bool includeUnloaded = false);
+
+    /// <summary>
+    /// Compile all assets for a module.
+    /// </summary>
+    /// <param name="pModuleDefinition">The module definition to compile.</param>
+    /// <returns></returns>
+    bool compileModuleAssets(ModuleDefinition* pModuleDefinition);
+
+    /// <summary>
+    /// Compile a single asset to binary.
+    /// </summary>
+    /// <param name="pAssetId">The asset id to be compiled.</param>
+    /// <returns>True if successful, otherwise false.</returns>
+    bool compileAsset(const char* pAssetId);
+
     /// Public asset acquisition.
     /// Public asset acquisition.
     template<typename T> T* acquireAsset( const char* pAssetId )
     template<typename T> T* acquireAsset( const char* pAssetId )
     {
     {
@@ -404,4 +426,4 @@ private:
 
 
 extern AssetManager AssetDatabase;
 extern AssetManager AssetDatabase;
 
 
-#endif // _ASSET_MANAGER_H_
+#endif // _ASSET_MANAGER_H_

+ 41 - 3
Engine/source/assets/assetManager_ScriptBinding.h

@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // Copyright (c) 2013 GarageGames, LLC
 // Copyright (c) 2013 GarageGames, LLC
 //
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -20,11 +20,12 @@
 // IN THE SOFTWARE.
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
-#include "assetBase.h"
-#include "assetManager.h"
+#include "assets/assetBase.h"
+#include "assets/assetManager.h"
 #include "module/moduleDefinition.h"
 #include "module/moduleDefinition.h"
 #include "console/sim.h"
 #include "console/sim.h"
 
 
+
 DefineEngineMethod(AssetManager, compileReferencedAssets, bool, (const char* moduleDefinition), (""),
 DefineEngineMethod(AssetManager, compileReferencedAssets, bool, (const char* moduleDefinition), (""),
    "Compile the referenced assets determined by the specified module definition.\n"
    "Compile the referenced assets determined by the specified module definition.\n"
    "@param moduleDefinition The module definition specifies the asset manifest.\n"
    "@param moduleDefinition The module definition specifies the asset manifest.\n"
@@ -853,3 +854,40 @@ DefineEngineMethod(AssetManager, dumpDeclaredAssets, void, (), ,
 {
 {
     return object->dumpDeclaredAssets();
     return object->dumpDeclaredAssets();
 }
 }
+
+//-----------------------------------------------------------------------------
+
+DefineEngineMethod(AssetManager, compileAllAssets, bool, (bool compressed, bool includeUnloaded),(false, true),
+   "Compile all assets.\n"
+   "@return true on success.\n")
+{
+   return object->compileAllAssets(compressed, includeUnloaded);
+}
+
+DefineEngineMethod(AssetManager, compileModuleAssets, bool, (const char* moduleDefinition), (""),
+   "Compile all assets for a module.\n"
+   "@return true on success.\n")
+{
+   // Fetch module definition.
+   ModuleDefinition* pModuleDefinition;
+   Sim::findObject(moduleDefinition, pModuleDefinition);
+
+   // Did we find the module definition?
+   if (pModuleDefinition == NULL)
+   {
+      // No, so warn.
+      Con::warnf("AssetManager::compileModuleAssets() - Could not find the module definition '%s'.", moduleDefinition);
+      return false;
+   }
+
+   // Remove declared assets.
+   return object->compileModuleAssets(pModuleDefinition);
+}
+
+DefineEngineMethod(AssetManager, compileAsset, bool, (const char* assetId), (""),
+   "Compile a single asset.\n"
+   "@return true on success.\n")
+{
+   return object->compileAsset(assetId);
+}
+

+ 213 - 0
Engine/source/persistence/taml/binary/tamlBinaryParser.cpp

@@ -0,0 +1,213 @@
+#include "persistence/taml/binary/tamlBinaryParser.h"
+#include "console/console.h"
+#include "core/util/zip/zipSubStream.h"
+#include "platform/profiler.h"
+#include "persistence/taml/taml.h"
+
+bool TamlBinaryParser::accept(const char* pFilename, TamlVisitor& visitor)
+{
+   isRoot = true;
+   PROFILE_SCOPE(TamlBinaryParser_Accept);
+   AssertFatal(pFilename != NULL, "TamlBinaryParser::accept - NULL filename.");
+
+   char filenameBuffer[1024];
+   Con::expandScriptFilename(filenameBuffer, sizeof(filenameBuffer), pFilename);
+
+   FileStream stream;
+   if (!stream.open(filenameBuffer, Torque::FS::File::Read))
+   {
+      Con::warnf("TamlBinaryParser::accept - Could not open file '%s'.", filenameBuffer);
+      return false;
+   }
+
+   // Read TAML signature.
+   StringTableEntry signature = stream.readSTString();
+   if (signature != StringTable->insert(TAML_SIGNATURE))
+   {
+      Con::warnf("TamlBinaryParser::accept - Invalid signature in '%s'.", filenameBuffer);
+      stream.close();
+      return false;
+   }
+
+   setParsingFilename(pFilename);
+
+   U32 versionId;
+   stream.read(&versionId);
+
+   bool compressed;
+   stream.read(&compressed);
+
+   if (compressed)
+   {
+      ZipSubRStream zipStream;
+      zipStream.attachStream(&stream);
+      parseElement(zipStream, visitor, versionId);
+      zipStream.detachStream();
+   }
+   else
+   {
+      parseElement(stream, visitor, versionId);
+   }
+
+   stream.close();
+
+   setParsingFilename(StringTable->EmptyString());
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+
+bool TamlBinaryParser::parseElement(Stream& stream, TamlVisitor& visitor, const U32 versionId)
+{
+   PROFILE_SCOPE(TamlBinaryParser_ParseElement);
+
+   // --- Read element header ---
+   StringTableEntry pElementName = stream.readSTString();
+   StringTableEntry pObjectName = stream.readSTString();
+
+   // Read references.
+   U32 refId, refToId;
+   stream.read(&refId);
+   stream.read(&refToId);
+
+   // If this is a reference to another object, skip it.
+   if (refToId != 0)
+      return true;
+
+   // Create a property visitor state.
+   TamlVisitor::PropertyState propertyState;
+
+   propertyState.setObjectName(pElementName, isRoot);
+   if (pObjectName != StringTable->EmptyString())
+      propertyState.setProperty("Name", pObjectName);
+
+   if(isRoot)
+      isRoot = false;
+
+   // --- Attributes ---
+   parseAttributes(stream, visitor, versionId, propertyState);
+   // --- Children ---
+   parseChildren(stream, visitor, versionId);
+   // --- Custom elements ---
+   parseCustomElements(stream, visitor, versionId);
+
+
+   return true;
+}
+
+void TamlBinaryParser::parseAttributes(Stream& stream, TamlVisitor& visitor, const U32 versionId, TamlVisitor::PropertyState& state)
+{
+   PROFILE_SCOPE(TamlBinaryParser_ParseAttributes);
+
+   U32 attributeCount;
+   stream.read(&attributeCount);
+   if (attributeCount == 0)
+      return;
+
+   char valueBuffer[4096];
+   for (U32 i = 0; i < attributeCount; ++i)
+   {
+      StringTableEntry attrName = stream.readSTString();
+      stream.readLongString(4096, valueBuffer);
+      state.setProperty(attrName, valueBuffer);
+      const bool visitStatus = visitor.visit(*this, state);
+      if (!visitStatus)
+         return;
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+void TamlBinaryParser::parseChildren(Stream& stream, TamlVisitor& visitor, const U32 versionId)
+{
+   PROFILE_SCOPE(TamlBinaryParser_ParseChildren);
+
+   U32 childCount = 0;
+   stream.read(&childCount);
+   if (childCount == 0)
+      return;
+
+   for (U32 i = 0; i < childCount; ++i)
+   {
+      parseElement(stream, visitor, versionId);
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+void TamlBinaryParser::parseCustomElements(Stream& stream, TamlVisitor& visitor, const U32 versionId)
+{
+   PROFILE_SCOPE(TamlBinaryParser_ParseCustomElements);
+
+   U32 customNodeCount = 0;
+   stream.read(&customNodeCount);
+   if (customNodeCount == 0)
+      return;
+
+   TamlVisitor::PropertyState state;
+
+   for (U32 nodeIndex = 0; nodeIndex < customNodeCount; ++nodeIndex)
+   {
+      StringTableEntry nodeName = stream.readSTString();
+      state.setObjectName(nodeName, false);
+
+      U32 nodeChildrenCount = 0;
+      stream.read(&nodeChildrenCount);
+      if (nodeChildrenCount == 0)
+         return;
+
+      for(U32 nodeChild = 0; nodeChild < nodeChildrenCount; ++nodeChild)
+         parseCustomNode(stream, visitor, versionId, state);
+   }
+
+}
+
+
+//-----------------------------------------------------------------------------
+
+bool TamlBinaryParser::parseCustomNode(Stream& stream, TamlVisitor& visitor, const U32 versionId, TamlVisitor::PropertyState& state)
+{
+   PROFILE_SCOPE(TamlBinaryParser_ParseCustomNode);
+
+   bool isProxyObject;
+   stream.read(&isProxyObject);
+   if (isProxyObject)
+   {
+      // Parse nested proxy element.
+      return parseElement(stream, visitor, versionId);
+   }
+
+   StringTableEntry nodeName = stream.readSTString();
+
+   char nodeValue[MAX_TAML_NODE_FIELDVALUE_LENGTH];
+
+   stream.readLongString(MAX_TAML_NODE_FIELDVALUE_LENGTH, nodeValue);
+
+   U32 childCount;
+   stream.read(&childCount);
+   for (U32 i = 0; i < childCount; ++i)
+   {
+      if (!parseCustomNode(stream, visitor, versionId, state))
+         return false;
+   }
+
+   U32 fieldCount;
+   stream.read(&fieldCount);
+
+   if (fieldCount > 0)
+   {
+      char valueBuffer[MAX_TAML_NODE_FIELDVALUE_LENGTH];
+      for (U32 f = 0; f < fieldCount; ++f)
+      {
+         StringTableEntry fieldName = stream.readSTString();
+         stream.readLongString(MAX_TAML_NODE_FIELDVALUE_LENGTH, valueBuffer);
+         state.setProperty(fieldName, valueBuffer);
+         const bool visitStatus = visitor.visit(*this, state);
+         if (!visitStatus)
+            return false;
+      }
+   }
+
+   return true;
+}

+ 42 - 0
Engine/source/persistence/taml/binary/tamlBinaryParser.h

@@ -0,0 +1,42 @@
+#pragma once
+#ifndef _TAML_BINARYPARSER_H_
+
+#ifndef _TAML_PARSER_H_
+#include "persistence/taml/tamlParser.h"
+#endif
+
+#ifndef _TAML_VISITOR_H_
+#include "persistence/taml/tamlVisitor.h"
+#endif
+
+#ifndef _STREAM_H_
+#include "core/stream/stream.h"
+#endif
+
+#ifndef _FILESTREAM_H_
+#include "core/stream/fileStream.h"
+#endif
+
+class TamlBinaryParser : public TamlParser
+{
+public:
+   TamlBinaryParser() {}
+   virtual ~TamlBinaryParser() {}
+
+   /// Whether the parser can change a property or not.
+   bool canChangeProperty(void) override { return false; }
+
+   /// Accept visitor.
+   bool accept(const char* pFilename, TamlVisitor& visitor) override;
+
+private:
+   bool parseElement(Stream& stream, TamlVisitor& visitor, const U32 versionId);
+   void parseAttributes(Stream& stream, TamlVisitor& visitor, const U32 versionId, TamlVisitor::PropertyState& state);
+   void parseChildren(Stream& stream, TamlVisitor& visitor, const U32 versionId);
+   void parseCustomElements(Stream& stream, TamlVisitor& visitor, const U32 versionId);
+   bool parseCustomNode(Stream& stream, TamlVisitor& visitor, const U32 versionId, TamlVisitor::PropertyState& state);
+
+   bool isRoot;
+};
+
+#endif // !_TAML_BINARYPARSER_H_

+ 8 - 2
Engine/source/persistence/taml/binary/tamlBinaryReader.cpp

@@ -345,8 +345,14 @@ void TamlBinaryReader::parseCustomElements( Stream& stream, TamlCallbacks* pCall
         // Add custom node.
         // Add custom node.
         TamlCustomNode* pCustomNode = customNodes.addNode( nodeName );
         TamlCustomNode* pCustomNode = customNodes.addNode( nodeName );
 
 
+        U32 nodeChildrenCount = 0;
+        stream.read(&nodeChildrenCount);
+        if (nodeChildrenCount == 0)
+           return;
+
         // Parse the custom node.
         // Parse the custom node.
-        parseCustomNode( stream, pCustomNode, versionId );
+        for (U32 nodeChild = 0; nodeChild < nodeChildrenCount; ++nodeChild)
+         parseCustomNode( stream, pCustomNode, versionId );
     }
     }
 
 
     // Do we have callbacks?
     // Do we have callbacks?
@@ -428,4 +434,4 @@ void TamlBinaryReader::parseCustomNode( Stream& stream, TamlCustomNode* pCustomN
             pChildNode->addField( fieldName, valueBuffer );
             pChildNode->addField( fieldName, valueBuffer );
         }
         }
     }
     }
-}
+}

+ 3 - 1
Engine/source/persistence/taml/binary/tamlBinaryWriter.cpp

@@ -212,6 +212,8 @@ void TamlBinaryWriter::writeCustomElements( Stream& stream, const TamlWriteNode*
         // Fetch node children.
         // Fetch node children.
         const TamlCustomNodeVector& nodeChildren = pCustomNode->getChildren();
         const TamlCustomNodeVector& nodeChildren = pCustomNode->getChildren();
 
 
+        stream.write((U32)nodeChildren.size());
+
         // Iterate children nodes.
         // Iterate children nodes.
         for( TamlCustomNodeVector::const_iterator childNodeItr = nodeChildren.begin(); childNodeItr != nodeChildren.end(); ++childNodeItr )
         for( TamlCustomNodeVector::const_iterator childNodeItr = nodeChildren.begin(); childNodeItr != nodeChildren.end(); ++childNodeItr )
         {
         {
@@ -294,4 +296,4 @@ void TamlBinaryWriter::writeCustomNode( Stream& stream, const TamlCustomNode* pC
             stream.writeLongString( MAX_TAML_NODE_FIELDVALUE_LENGTH, pField->getFieldValue() );
             stream.writeLongString( MAX_TAML_NODE_FIELDVALUE_LENGTH, pField->getFieldValue() );
         }
         }
     }
     }
-}
+}

+ 1297 - 1285
Engine/source/persistence/taml/taml.cpp

@@ -42,17 +42,21 @@
 #include "persistence/taml/binary/tamlBinaryReader.h"
 #include "persistence/taml/binary/tamlBinaryReader.h"
 #endif
 #endif
 
 
-/*#ifndef _TAML_JSONWRITER_H_
-#include "taml/json/tamlJSONWriter.h"
+#ifndef _TAML_BINARYPARSER_H_
+#include "persistence/taml/binary/tamlBinaryParser.h"
+#endif
+
+#ifndef _TAML_JSONWRITER_H_
+#include "persistence/taml/json/tamlJSONWriter.h"
 #endif
 #endif
 
 
 #ifndef _TAML_JSONREADER_H_
 #ifndef _TAML_JSONREADER_H_
-#include "taml/json/tamlJSONReader.h"
+#include "persistence/taml/json/tamlJSONReader.h"
 #endif
 #endif
 
 
 #ifndef _TAML_JSONPARSER_H_
 #ifndef _TAML_JSONPARSER_H_
-#include "taml/json/tamlJSONParser.h"
-#endif*/
+#include "persistence/taml/json/tamlJSONParser.h"
+#endif
 
 
 #ifndef _FRAMEALLOCATOR_H_
 #ifndef _FRAMEALLOCATOR_H_
 #include "core/frameAllocator.h"
 #include "core/frameAllocator.h"
@@ -94,1587 +98,1595 @@ StringTableEntry tamlNamedObjectName = StringTable->insert("Name");
 
 
 typedef Taml::TamlFormatMode _TamlFormatMode;
 typedef Taml::TamlFormatMode _TamlFormatMode;
 ImplementEnumType(_TamlFormatMode,
 ImplementEnumType(_TamlFormatMode,
-   "")
-{
-   Taml::XmlFormat, "xml"
-},
-{ Taml::BinaryFormat, "binary" }//,
-                                //{ Taml::JSONFormat, "json" }
-   EndImplementEnumType;
+"")
+   { Taml::XmlFormat, "xml"         },
+   { Taml::BinaryFormat, "binary"   },
+   { Taml::JSONFormat, "json"       }
+EndImplementEnumType;
 
 
-   //-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 
 
-   Taml::TamlFormatMode Taml::getFormatModeEnum(const char* label)
+Taml::TamlFormatMode Taml::getFormatModeEnum(const char* label)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(__TamlFormatMode::_sEnums) / sizeof(EnumTable::Value)); i++)
    {
    {
-      // Search for Mnemonic.
-      for (U32 i = 0; i < (sizeof(__TamlFormatMode::_sEnums) / sizeof(EnumTable::Value)); i++)
-      {
-         if (dStricmp(__TamlFormatMode::_sEnumTable[i].getName(), label) == 0)
-            return (TamlFormatMode)__TamlFormatMode::_sEnumTable[i].getInt();
-      }
+      if (dStricmp(__TamlFormatMode::_sEnumTable[i].getName(), label) == 0)
+         return (TamlFormatMode)__TamlFormatMode::_sEnumTable[i].getInt();
+   }
 
 
-      // Warn.
-      Con::warnf("Taml::getFormatModeEnum() - Invalid format of '%s'.", label);
+   // Warn.
+   Con::warnf("Taml::getFormatModeEnum() - Invalid format of '%s'.", label);
 
 
-      return Taml::InvalidFormat;
-   }
+   return Taml::InvalidFormat;
+}
 
 
-   //-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 
 
-   const char* Taml::getFormatModeDescription(const Taml::TamlFormatMode formatMode)
+const char* Taml::getFormatModeDescription(const Taml::TamlFormatMode formatMode)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(__TamlFormatMode::_sEnums) / sizeof(EnumTable::Value)); i++)
    {
    {
-      // Search for Mnemonic.
-      for (U32 i = 0; i < (sizeof(__TamlFormatMode::_sEnums) / sizeof(EnumTable::Value)); i++)
-      {
-         if (__TamlFormatMode::_sEnumTable[i].getInt() == (S32)formatMode)
-            return __TamlFormatMode::_sEnumTable[i].getName();
-      }
+      if (__TamlFormatMode::_sEnumTable[i].getInt() == (S32)formatMode)
+         return __TamlFormatMode::_sEnumTable[i].getName();
+   }
 
 
-      // Warn.
-      Con::warnf("Taml::getFormatModeDescription() - Invalid format mode.");
+   // Warn.
+   Con::warnf("Taml::getFormatModeDescription() - Invalid format mode.");
 
 
-      return StringTable->EmptyString();
-   }
+   return StringTable->EmptyString();
+}
 
 
-   //-----------------------------------------------------------------------------
-
-   // The string-table-entries are set to string literals below because Taml is used in a static scope and the string-table cannot currently be used like that.
-   Taml::Taml() :
-      mMasterNodeId(0),
-      mFormatMode(XmlFormat),
-      mJSONStrict(true),
-      mBinaryCompression(true),
-      mWriteDefaults(false),
-      mAutoFormatXmlExtension("taml"),
-      mAutoFormat(true),
-      mProgenitorUpdate(true),
-      mAutoFormatBinaryExtension("baml"),
-      mAutoFormatJSONExtension("json")
-   {
-      // Reset the file-path buffer.
-      mFilePathBuffer[0] = 0;
-   }
+//-----------------------------------------------------------------------------
 
 
-   //-----------------------------------------------------------------------------
+// The string-table-entries are set to string literals below because Taml is used in a static scope and the string-table cannot currently be used like that.
+Taml::Taml() :
+   mMasterNodeId(0),
+   mFormatMode(XmlFormat),
+   mJSONStrict(true),
+   mBinaryCompression(true),
+   mWriteDefaults(false),
+   mAutoFormatXmlExtension("taml"),
+   mAutoFormat(true),
+   mProgenitorUpdate(true),
+   mAutoFormatBinaryExtension("baml"),
+   mAutoFormatJSONExtension("json")
+{
+   // Reset the file-path buffer.
+   mFilePathBuffer[0] = 0;
+}
 
 
-   void Taml::initPersistFields()
-   {
-      docsURL;
-      // Call parent.
-      Parent::initPersistFields();
-
-      addField("Format", TYPEID<_TamlFormatMode>(), Offset(mFormatMode, Taml), "The read/write format that should be used.");
-      addField("JSONStrict", TypeBool, Offset(mBinaryCompression, Taml), "Whether to write JSON that is strictly compatible with RFC4627 or not.\n");
-      addField("BinaryCompression", TypeBool, Offset(mBinaryCompression, Taml), "Whether ZIP compression is used on binary formatting or not.\n");
-      addField("WriteDefaults", TypeBool, Offset(mWriteDefaults, Taml), "Whether to write static fields that are at their default or not.\n");
-      addField("ProgenitorUpdate", TypeBool, Offset(mProgenitorUpdate, Taml), "Whether to update each type instances file-progenitor or not.\n");
-      addField("AutoFormat", TypeBool, Offset(mAutoFormat, Taml), "Whether the format type is automatically determined by the filename extension or not.\n");
-      addField("AutoFormatXmlExtension", TypeString, Offset(mAutoFormatXmlExtension, Taml), "When using auto-format, this is the extension (end of filename) used to detect the XML format.\n");
-      addField("AutoFormatBinaryExtension", TypeString, Offset(mAutoFormatBinaryExtension, Taml), "When using auto-format, this is the extension (end of filename) used to detect the BINARY format.\n");
-      addField("AutoFormatJSONExtension", TypeString, Offset(mAutoFormatJSONExtension, Taml), "When using auto-format, this is the extension (end of filename) used to detect the JSON format.\n");
-   }
+//-----------------------------------------------------------------------------
 
 
-   //-----------------------------------------------------------------------------
+void Taml::initPersistFields()
+{
+   docsURL;
+   // Call parent.
+   Parent::initPersistFields();
+
+   addField("Format", TYPEID<_TamlFormatMode>(), Offset(mFormatMode, Taml), "The read/write format that should be used.");
+   addField("JSONStrict", TypeBool, Offset(mBinaryCompression, Taml), "Whether to write JSON that is strictly compatible with RFC4627 or not.\n");
+   addField("BinaryCompression", TypeBool, Offset(mBinaryCompression, Taml), "Whether ZIP compression is used on binary formatting or not.\n");
+   addField("WriteDefaults", TypeBool, Offset(mWriteDefaults, Taml), "Whether to write static fields that are at their default or not.\n");
+   addField("ProgenitorUpdate", TypeBool, Offset(mProgenitorUpdate, Taml), "Whether to update each type instances file-progenitor or not.\n");
+   addField("AutoFormat", TypeBool, Offset(mAutoFormat, Taml), "Whether the format type is automatically determined by the filename extension or not.\n");
+   addField("AutoFormatXmlExtension", TypeString, Offset(mAutoFormatXmlExtension, Taml), "When using auto-format, this is the extension (end of filename) used to detect the XML format.\n");
+   addField("AutoFormatBinaryExtension", TypeString, Offset(mAutoFormatBinaryExtension, Taml), "When using auto-format, this is the extension (end of filename) used to detect the BINARY format.\n");
+   addField("AutoFormatJSONExtension", TypeString, Offset(mAutoFormatJSONExtension, Taml), "When using auto-format, this is the extension (end of filename) used to detect the JSON format.\n");
+}
 
 
-   bool Taml::onAdd()
-   {
-      // Call parent.
-      if (!Parent::onAdd())
-         return false;
+//-----------------------------------------------------------------------------
 
 
-      // Set JSON strict mode.
-      mJSONStrict = Con::getBoolVariable(TAML_JSON_STRICT_VARIBLE, true);
+bool Taml::onAdd()
+{
+   // Call parent.
+   if (!Parent::onAdd())
+      return false;
 
 
-      // Reset the compilation.
-      resetCompilation();
+   // Set JSON strict mode.
+   mJSONStrict = Con::getBoolVariable(TAML_JSON_STRICT_VARIBLE, true);
 
 
-      return true;
-   }
+   // Reset the compilation.
+   resetCompilation();
 
 
-   //-----------------------------------------------------------------------------
+   return true;
+}
 
 
-   void Taml::onRemove()
-   {
-      // Reset the compilation.
-      resetCompilation();
+//-----------------------------------------------------------------------------
 
 
-      // Call parent.
-      Parent::onRemove();
-   }
+void Taml::onRemove()
+{
+   // Reset the compilation.
+   resetCompilation();
 
 
-   //-----------------------------------------------------------------------------
+   // Call parent.
+   Parent::onRemove();
+}
 
 
-   bool Taml::write(SimObject* pSimObject, const char* pFilename)
-   {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_Write);
+//-----------------------------------------------------------------------------
+
+bool Taml::write(SimObject* pSimObject, const char* pFilename)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_Write);
 
 
-      // Sanity!
-      AssertFatal(pSimObject != NULL, "Cannot write a NULL object.");
-      AssertFatal(pFilename != NULL, "Cannot write to a NULL filename.");
+   // Sanity!
+   AssertFatal(pSimObject != NULL, "Cannot write a NULL object.");
+   AssertFatal(pFilename != NULL, "Cannot write to a NULL filename.");
 
 
-      // Expand the file-name into the file-path buffer unless we're a secure VFS
+   // Expand the file-name into the file-path buffer unless we're a secure VFS
 #ifndef TORQUE_SECURE_VFS
 #ifndef TORQUE_SECURE_VFS
-      Con::expandToolScriptFilename(mFilePathBuffer, sizeof(mFilePathBuffer), pFilename);
+   Con::expandToolScriptFilename(mFilePathBuffer, sizeof(mFilePathBuffer), pFilename);
 #else
 #else
-      dMemset(mFilePathBuffer, 0x00, sizeof(mFilePathBuffer));
-      dMemcpy(mFilePathBuffer, pFilename, dStrlen(pFilename));
+   dMemset(mFilePathBuffer, 0x00, sizeof(mFilePathBuffer));
+   dMemcpy(mFilePathBuffer, pFilename, dStrlen(pFilename));
 #endif
 #endif
 
 
-      FileStream stream;
-
-      // File opened?
-      if (!stream.open(mFilePathBuffer, Torque::FS::File::Write))
-      {
-         // No, so warn.
-         Con::warnf("Taml::writeFile() - Could not open filename '%s' for write.", mFilePathBuffer);
-         return false;
-      }
+   FileStream stream;
 
 
-      // Get the file auto-format mode.
-      const TamlFormatMode formatMode = getFileAutoFormatMode(mFilePathBuffer);
+   // File opened?
+   if (!stream.open(mFilePathBuffer, Torque::FS::File::Write))
+   {
+      // No, so warn.
+      Con::warnf("Taml::writeFile() - Could not open filename '%s' for write.", mFilePathBuffer);
+      return false;
+   }
 
 
-      // Reset the compilation.
-      resetCompilation();
+   // Get the file auto-format mode.
+   const TamlFormatMode formatMode = getFileAutoFormatMode(mFilePathBuffer);
 
 
-      // Write object.
-      const bool status = write(stream, pSimObject, formatMode);
+   // Reset the compilation.
+   resetCompilation();
 
 
-      // Close file.
-      stream.close();
+   // Write object.
+   const bool status = write(stream, pSimObject, formatMode);
 
 
-      // Reset the compilation.
-      resetCompilation();
+   // Close file.
+   stream.close();
 
 
-      return status;
-   }
+   // Reset the compilation.
+   resetCompilation();
 
 
-   //-----------------------------------------------------------------------------
+   return status;
+}
 
 
-   SimObject* Taml::read(const char* pFilename)
-   {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_Read);
+//-----------------------------------------------------------------------------
 
 
-      // Sanity!
-      AssertFatal(pFilename != NULL, "Cannot read from a NULL filename.");
+SimObject* Taml::read(const char* pFilename)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_Read);
 
 
-      // Expand the file-name into the file-path buffer.
-      Con::expandScriptFilename(mFilePathBuffer, sizeof(mFilePathBuffer), pFilename);
+   // Sanity!
+   AssertFatal(pFilename != NULL, "Cannot read from a NULL filename.");
 
 
-      FileStream stream;
+   // Expand the file-name into the file-path buffer.
+   Con::expandScriptFilename(mFilePathBuffer, sizeof(mFilePathBuffer), pFilename);
 
 
-      // File opened?
-      if (!stream.open(mFilePathBuffer, Torque::FS::File::Read))
-      {
-         // No, so warn.
-         Con::warnf("Taml::read() - Could not open filename '%s' for read.", mFilePathBuffer);
-         return NULL;
-      }
+   FileStream stream;
 
 
-      // Get the file auto-format mode.
-      const TamlFormatMode formatMode = getFileAutoFormatMode(mFilePathBuffer);
+   // File opened?
+   if (!stream.open(mFilePathBuffer, Torque::FS::File::Read))
+   {
+      // No, so warn.
+      Con::warnf("Taml::read() - Could not open filename '%s' for read.", mFilePathBuffer);
+      return NULL;
+   }
 
 
-      // Reset the compilation.
-      resetCompilation();
+   // Get the file auto-format mode.
+   const TamlFormatMode formatMode = getFileAutoFormatMode(mFilePathBuffer);
 
 
-      // Write object.
-      SimObject* pSimObject = read(stream, formatMode);
+   // Reset the compilation.
+   resetCompilation();
 
 
-      // Close file.
-      stream.close();
+   // Write object.
+   SimObject* pSimObject = read(stream, formatMode);
 
 
-      // Reset the compilation.
-      resetCompilation();
+   // Close file.
+   stream.close();
 
 
-      // Did we generate an object?
-      if (pSimObject == NULL)
-      {
-         // No, so warn.
-         Con::warnf("Taml::read() - Failed to load an object from the file '%s'.", mFilePathBuffer);
-      }
-      else
-      {
-         pSimObject->onPostAdd();
-      }
+   // Reset the compilation.
+   resetCompilation();
 
 
-      return pSimObject;
+   // Did we generate an object?
+   if (pSimObject == NULL)
+   {
+      // No, so warn.
+      Con::warnf("Taml::read() - Failed to load an object from the file '%s'.", mFilePathBuffer);
+   }
+   else
+   {
+      pSimObject->onPostAdd();
    }
    }
 
 
-   //-----------------------------------------------------------------------------
+   return pSimObject;
+}
 
 
-   bool Taml::write(FileStream& stream, SimObject* pSimObject, const TamlFormatMode formatMode)
-   {
-      // Sanity!
-      AssertFatal(pSimObject != NULL, "Cannot write a NULL object.");
+//-----------------------------------------------------------------------------
 
 
-      // Compile nodes.
-      TamlWriteNode* pRootNode = compileObject(pSimObject);
+bool Taml::write(FileStream& stream, SimObject* pSimObject, const TamlFormatMode formatMode)
+{
+   // Sanity!
+   AssertFatal(pSimObject != NULL, "Cannot write a NULL object.");
 
 
-      // Format appropriately.
-      switch (formatMode)
-      {
-         /// Xml.
-      case XmlFormat:
-      {
-         // Create writer.
-         TamlXmlWriter writer(this);
-         // Write.
-         return writer.write(stream, pRootNode);
-      }
+   // Compile nodes.
+   TamlWriteNode* pRootNode = compileObject(pSimObject);
 
 
-      /// Binary.
-      case BinaryFormat:
-      {
-         // Create writer.
-         TamlBinaryWriter writer(this);
+   // Format appropriately.
+   switch (formatMode)
+   {
+      /// Xml.
+   case XmlFormat:
+   {
+      // Create writer.
+      TamlXmlWriter writer(this);
+      // Write.
+      return writer.write(stream, pRootNode);
+   }
 
 
-         // Write.
-         return writer.write(stream, pRootNode, mBinaryCompression);
-      }
+   /// Binary.
+   case BinaryFormat:
+   {
+      // Create writer.
+      TamlBinaryWriter writer(this);
 
 
-      /// JSON.
-      case JSONFormat:
-      {
-         // Create writer.
-         //TamlJSONWriter writer( this );
+      // Write.
+      return writer.write(stream, pRootNode, mBinaryCompression);
+   }
 
 
-         // Write.
-         //return writer.write( stream, pRootNode );
-         return false;
-      }
+   /// JSON.
+   case JSONFormat:
+   {
+      // Create writer.
+      TamlJSONWriter writer( this );
 
 
-      /// Invalid.
-      case InvalidFormat:
-      {
-         // Warn.
-         Con::warnf("Taml::write() - Cannot write, invalid format.");
-         return false;
-      }
-      }
+      // Write.
+      return writer.write( stream, pRootNode );
+   }
 
 
+   /// Invalid.
+   case InvalidFormat:
+   {
       // Warn.
       // Warn.
-      Con::warnf("Taml::write() - Unknown format.");
+      Con::warnf("Taml::write() - Cannot write, invalid format.");
       return false;
       return false;
    }
    }
+   }
 
 
-   //-----------------------------------------------------------------------------
+   // Warn.
+   Con::warnf("Taml::write() - Unknown format.");
+   return false;
+}
 
 
-   SimObject* Taml::read(FileStream& stream, const TamlFormatMode formatMode)
-   {
-      // Format appropriately.
-      switch (formatMode)
-      {
-         /// Xml.
-      case XmlFormat:
-      {
-         // Create reader.
-         TamlXmlReader reader(this);
+//-----------------------------------------------------------------------------
 
 
-         // Read.
-         return reader.read(stream);
-      }
+SimObject* Taml::read(FileStream& stream, const TamlFormatMode formatMode)
+{
+   // Format appropriately.
+   switch (formatMode)
+   {
+      /// Xml.
+   case XmlFormat:
+   {
+      // Create reader.
+      TamlXmlReader reader(this);
 
 
-      /// Binary.
-      case BinaryFormat:
-      {
-         // Create reader.
-         TamlBinaryReader reader(this);
+      // Read.
+      return reader.read(stream);
+   }
 
 
-         // Read.
-         return reader.read(stream);
-      }
+   /// Binary.
+   case BinaryFormat:
+   {
+      // Create reader.
+      TamlBinaryReader reader(this);
 
 
-      /// JSON.
-      case JSONFormat:
-      {
-         // Create reader.
-         //TamlJSONReader reader( this );
+      // Read.
+      return reader.read(stream);
+   }
 
 
-         // Read.
-         //return reader.read( stream );
-         return NULL;
-      }
+   /// JSON.
+   case JSONFormat:
+   {
+      // Create reader.
+      TamlJSONReader reader( this );
 
 
-      /// Invalid.
-      case InvalidFormat:
-      {
-         // Warn.
-         Con::warnf("Taml::read() - Cannot read, invalid format.");
-         return NULL;
-      }
-      }
+      // Read.
+      return reader.read( stream );
+   }
 
 
+   /// Invalid.
+   case InvalidFormat:
+   {
       // Warn.
       // Warn.
-      Con::warnf("Taml::read() - Unknown format.");
+      Con::warnf("Taml::read() - Cannot read, invalid format.");
       return NULL;
       return NULL;
    }
    }
+   }
 
 
-   //-----------------------------------------------------------------------------
-
-   bool Taml::parse(const char* pFilename, TamlVisitor& visitor)
-   {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_Parse);
+   // Warn.
+   Con::warnf("Taml::read() - Unknown format.");
+   return NULL;
+}
 
 
-      // Sanity!
-      AssertFatal(pFilename != NULL, "Taml::parse() - Cannot parse a NULL filename.");
+//-----------------------------------------------------------------------------
 
 
-      // Fetch format mode.
-      const TamlFormatMode formatMode = getFileAutoFormatMode(pFilename);
+bool Taml::parse(const char* pFilename, TamlVisitor& visitor)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_Parse);
 
 
-      // Handle format mode appropriately.
-      switch (formatMode)
-      {
-      case XmlFormat:
-      {
-         // Parse with the visitor.
-         TamlXmlParser parser;
+   // Sanity!
+   AssertFatal(pFilename != NULL, "Taml::parse() - Cannot parse a NULL filename.");
 
 
-         // Are property changes needed but not supported?
-         if (visitor.wantsPropertyChanges() && !parser.canChangeProperty())
-         {
-            // Yes, so warn.
-            Con::warnf("Taml::parse() - Cannot parse '%s' file-type for filename '%s' as a specified visitor requires property changes which are not supported by the parser.", getFormatModeDescription(formatMode), pFilename);
-            return false;
-         }
+   // Fetch format mode.
+   const TamlFormatMode formatMode = getFileAutoFormatMode(pFilename);
 
 
-         return parser.accept(pFilename, visitor);
-      }
+   // Handle format mode appropriately.
+   switch (formatMode)
+   {
+   case XmlFormat:
+   {
+      // Parse with the visitor.
+      TamlXmlParser parser;
 
 
-      case JSONFormat:
+      // Are property changes needed but not supported?
+      if (visitor.wantsPropertyChanges() && !parser.canChangeProperty())
       {
       {
-         // Parse with the visitor.
-         /*TamlJSONParser parser;
-
-         // Are property changes needed but not supported?
-         if ( visitor.wantsPropertyChanges() && !parser.canChangeProperty() )
-         {
          // Yes, so warn.
          // Yes, so warn.
-         Con::warnf( "Taml::parse() - Cannot parse '%s' file-type for filename '%s' as a specified visitor requires property changes which are not supported by the parser.", getFormatModeDescription(formatMode), pFilename );
+         Con::warnf("Taml::parse() - Cannot parse '%s' file-type for filename '%s' as a specified visitor requires property changes which are not supported by the parser.", getFormatModeDescription(formatMode), pFilename);
          return false;
          return false;
-         }
-
-         return parser.accept( pFilename, visitor );       */
-         return false;
-      }
-
-      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;
+      return parser.accept(pFilename, visitor);
    }
    }
 
 
-   //-----------------------------------------------------------------------------
-
-   void Taml::resetCompilation(void)
+   case JSONFormat:
    {
    {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_ResetCompilation);
+      // Parse with the visitor.
+      TamlJSONParser parser;
 
 
-      // Clear compiled nodes.
-      for (typeNodeVector::iterator itr = mCompiledNodes.begin(); itr != mCompiledNodes.end(); ++itr)
+      // Are property changes needed but not supported?
+      if ( visitor.wantsPropertyChanges() && !parser.canChangeProperty() )
       {
       {
-         // Fetch node.
-         TamlWriteNode* pNode = (*itr);
+      // Yes, so warn.
+      Con::warnf( "Taml::parse() - Cannot parse '%s' file-type for filename '%s' as a specified visitor requires property changes which are not supported by the parser.", getFormatModeDescription(formatMode), pFilename );
+      return false;
+      }
 
 
-         // Reset node.
-         pNode->resetNode();
+      return parser.accept( pFilename, visitor );
+   }
 
 
-         // Delete node.
-         delete pNode;
+   case BinaryFormat:
+   {
+      // Parse with the visitor.
+      TamlBinaryParser parser;
+      // Are property changes needed but not supported?
+      if (visitor.wantsPropertyChanges() && !parser.canChangeProperty())
+      {
+         // Yes, so warn.
+         Con::warnf("Taml::parse() - Cannot parse '%s' file-type for filename '%s' as a specified visitor requires property changes which are not supported by the parser.", getFormatModeDescription(formatMode), pFilename);
+         return false;
       }
       }
-      mCompiledNodes.clear();
-
-      // Clear compiled objects.
-      mCompiledObjects.clear();
 
 
-      // Reset master node Id.
-      mMasterNodeId = 0;
+      return parser.accept(pFilename, visitor);
+   }
+   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;
+}
 
 
-   Taml::TamlFormatMode Taml::getFileAutoFormatMode(const char* pFilename)
-   {
-      // Sanity!
-      AssertFatal(pFilename != NULL, "Taml::getFileAutoFormatMode() - Cannot auto-format using a NULL filename.");
+//-----------------------------------------------------------------------------
 
 
-      // Is auto-format active?
-      if (mAutoFormat)
-      {
-         // Yes, so fetch the extension lengths.
-         const U32 xmlExtensionLength = dStrlen(mAutoFormatXmlExtension);
-         const U32 binaryExtensionLength = dStrlen(mAutoFormatBinaryExtension);
-         const U32 jsonExtensionLength = dStrlen(mAutoFormatJSONExtension);
+void Taml::resetCompilation(void)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_ResetCompilation);
 
 
-         // Fetch filename length.
-         const U32 filenameLength = dStrlen(pFilename);
+   // Clear compiled nodes.
+   for (typeNodeVector::iterator itr = mCompiledNodes.begin(); itr != mCompiledNodes.end(); ++itr)
+   {
+      // Fetch node.
+      TamlWriteNode* pNode = (*itr);
 
 
-         // Fetch end of filename,
-         const char* pEndOfFilename = pFilename + filenameLength;
+      // Reset node.
+      pNode->resetNode();
 
 
-         // Check for the XML format.
-         if (xmlExtensionLength <= filenameLength && dStricmp(pEndOfFilename - xmlExtensionLength, mAutoFormatXmlExtension) == 0)
-            return Taml::XmlFormat;
+      // Delete node.
+      delete pNode;
+   }
+   mCompiledNodes.clear();
 
 
-         // Check for the Binary format.
-         if (binaryExtensionLength <= filenameLength && dStricmp(pEndOfFilename - xmlExtensionLength, mAutoFormatBinaryExtension) == 0)
-            return Taml::BinaryFormat;
+   // Clear compiled objects.
+   mCompiledObjects.clear();
 
 
-         // Check for the XML format.
-         if (jsonExtensionLength <= filenameLength && dStricmp(pEndOfFilename - jsonExtensionLength, mAutoFormatJSONExtension) == 0)
-            return Taml::JSONFormat;
-      }
+   // Reset master node Id.
+   mMasterNodeId = 0;
+}
 
 
-      // Use the explicitly specified format mode.
-      return mFormatMode;
-   }
+//-----------------------------------------------------------------------------
 
 
-   //-----------------------------------------------------------------------------
+Taml::TamlFormatMode Taml::getFileAutoFormatMode(const char* pFilename)
+{
+   // Sanity!
+   AssertFatal(pFilename != NULL, "Taml::getFileAutoFormatMode() - Cannot auto-format using a NULL filename.");
 
 
-   TamlWriteNode* Taml::compileObject(SimObject* pSimObject, const bool forceId)
+   // Is auto-format active?
+   if (mAutoFormat)
    {
    {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_CompileObject);
+      // Yes, so fetch the extension lengths.
+      const U32 xmlExtensionLength = dStrlen(mAutoFormatXmlExtension);
+      const U32 binaryExtensionLength = dStrlen(mAutoFormatBinaryExtension);
+      const U32 jsonExtensionLength = dStrlen(mAutoFormatJSONExtension);
 
 
-      // Sanity!
-      AssertFatal(pSimObject != NULL, "Taml::compileObject() - Cannot compile a NULL object.");
+      // Fetch filename length.
+      const U32 filenameLength = dStrlen(pFilename);
 
 
-      // Fetch object Id.
-      const SimObjectId objectId = pSimObject->getId();
+      // Fetch end of filename,
+      const char* pEndOfFilename = pFilename + filenameLength;
 
 
-      // Find a previously compiled node.
-      typeCompiledHash::Iterator compiledItr = mCompiledObjects.find(objectId);
+      // Check for the XML format.
+      if (xmlExtensionLength <= filenameLength && dStricmp(pEndOfFilename - xmlExtensionLength, mAutoFormatXmlExtension) == 0)
+         return Taml::XmlFormat;
 
 
-      // Have we already compiled this?
-      if (compiledItr != mCompiledObjects.end())
-      {
-         // Yes, so sanity!
-         AssertFatal(mCompiledNodes.size() != 0, "Taml::compileObject() - Found a compiled node at the root.");
+      // Check for the Binary format.
+      if (binaryExtensionLength <= filenameLength && dStricmp(pEndOfFilename - xmlExtensionLength, mAutoFormatBinaryExtension) == 0)
+         return Taml::BinaryFormat;
 
 
-         // Yes, so fetch node.
-         TamlWriteNode* compiledNode = compiledItr->value;
+      // Check for the XML format.
+      if (jsonExtensionLength <= filenameLength && dStricmp(pEndOfFilename - jsonExtensionLength, mAutoFormatJSONExtension) == 0)
+         return Taml::JSONFormat;
+   }
 
 
-         // Is a reference Id already present?
-         if (compiledNode->mRefId == 0)
-         {
-            // No, so allocate one.
-            compiledNode->mRefId = ++mMasterNodeId;
-         }
+   // Use the explicitly specified format mode.
+   return mFormatMode;
+}
 
 
-         // Create write node.
-         TamlWriteNode* pNewNode = new TamlWriteNode();
-         pNewNode->set(pSimObject);
+//-----------------------------------------------------------------------------
+
+TamlWriteNode* Taml::compileObject(SimObject* pSimObject, const bool forceId)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_CompileObject);
+
+   // Sanity!
+   AssertFatal(pSimObject != NULL, "Taml::compileObject() - Cannot compile a NULL object.");
 
 
-         // Set reference node.
-         pNewNode->mRefToNode = compiledNode;
+   // Fetch object Id.
+   const SimObjectId objectId = pSimObject->getId();
+
+   // Find a previously compiled node.
+   typeCompiledHash::Iterator compiledItr = mCompiledObjects.find(objectId);
+
+   // Have we already compiled this?
+   if (compiledItr != mCompiledObjects.end())
+   {
+      // Yes, so sanity!
+      AssertFatal(mCompiledNodes.size() != 0, "Taml::compileObject() - Found a compiled node at the root.");
 
 
-         // Push new node.
-         mCompiledNodes.push_back(pNewNode);
+      // Yes, so fetch node.
+      TamlWriteNode* compiledNode = compiledItr->value;
 
 
-         return pNewNode;
+      // Is a reference Id already present?
+      if (compiledNode->mRefId == 0)
+      {
+         // No, so allocate one.
+         compiledNode->mRefId = ++mMasterNodeId;
       }
       }
 
 
-      // No, so create write node.
+      // Create write node.
       TamlWriteNode* pNewNode = new TamlWriteNode();
       TamlWriteNode* pNewNode = new TamlWriteNode();
       pNewNode->set(pSimObject);
       pNewNode->set(pSimObject);
 
 
-      // Is an Id being forced for this object?
-      if (forceId)
-      {
-         // Yes, so allocate one.
-         pNewNode->mRefId = ++mMasterNodeId;
-      }
+      // Set reference node.
+      pNewNode->mRefToNode = compiledNode;
 
 
       // Push new node.
       // Push new node.
       mCompiledNodes.push_back(pNewNode);
       mCompiledNodes.push_back(pNewNode);
 
 
-      // Insert compiled object.
-      mCompiledObjects.insertUnique(objectId, pNewNode);
-
-      // Are there any Taml callbacks?
-      if (pNewNode->mpTamlCallbacks != NULL)
-      {
-         // Yes, so call it.
-         tamlPreWrite(pNewNode->mpTamlCallbacks);
-      }
+      return pNewNode;
+   }
 
 
-      // Compile static and dynamic fields.
-      compileStaticFields(pNewNode);
-      compileDynamicFields(pNewNode);
+   // No, so create write node.
+   TamlWriteNode* pNewNode = new TamlWriteNode();
+   pNewNode->set(pSimObject);
 
 
-      // Compile children.
-      compileChildren(pNewNode);
+   // Is an Id being forced for this object?
+   if (forceId)
+   {
+      // Yes, so allocate one.
+      pNewNode->mRefId = ++mMasterNodeId;
+   }
 
 
-      // Compile custom state.
-      compileCustomState(pNewNode);
+   // Push new node.
+   mCompiledNodes.push_back(pNewNode);
 
 
-      // Are there any Taml callbacks?
-      if (pNewNode->mpTamlCallbacks != NULL)
-      {
-         // Yes, so call it.
-         tamlPostWrite(pNewNode->mpTamlCallbacks);
-      }
+   // Insert compiled object.
+   mCompiledObjects.insertUnique(objectId, pNewNode);
 
 
-      return pNewNode;
+   // Are there any Taml callbacks?
+   if (pNewNode->mpTamlCallbacks != NULL)
+   {
+      // Yes, so call it.
+      tamlPreWrite(pNewNode->mpTamlCallbacks);
    }
    }
 
 
-   //-----------------------------------------------------------------------------
+   // Compile static and dynamic fields.
+   compileStaticFields(pNewNode);
+   compileDynamicFields(pNewNode);
+
+   // Compile children.
+   compileChildren(pNewNode);
 
 
-   void Taml::compileStaticFields(TamlWriteNode* pTamlWriteNode)
+   // Compile custom state.
+   compileCustomState(pNewNode);
+
+   // Are there any Taml callbacks?
+   if (pNewNode->mpTamlCallbacks != NULL)
    {
    {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_CompileStaticFields);
+      // Yes, so call it.
+      tamlPostWrite(pNewNode->mpTamlCallbacks);
+   }
 
 
-      // Sanity!
-      AssertFatal(pTamlWriteNode != NULL, "Cannot compile static fields on a NULL node.");
-      AssertFatal(pTamlWriteNode->mpSimObject != NULL, "Cannot compile static fields on a node with no object.");
+   return pNewNode;
+}
 
 
-      // Fetch object.
-      SimObject* pSimObject = pTamlWriteNode->mpSimObject;
+//-----------------------------------------------------------------------------
 
 
-      // Fetch field list.
-      const AbstractClassRep::FieldList& fieldList = pSimObject->getFieldList();
+void Taml::compileStaticFields(TamlWriteNode* pTamlWriteNode)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_CompileStaticFields);
 
 
-      // Fetch field count.
-      const U32 fieldCount = fieldList.size();
+   // Sanity!
+   AssertFatal(pTamlWriteNode != NULL, "Cannot compile static fields on a NULL node.");
+   AssertFatal(pTamlWriteNode->mpSimObject != NULL, "Cannot compile static fields on a node with no object.");
 
 
-      ConsoleObject* defaultConObject = NULL;
-      SimObject* defaultObject = NULL;
-      if (!getWriteDefaults())
-      {
-         // Create a default object of the same type
-         defaultConObject = ConsoleObject::create(pSimObject->getClassName());
-         if (!defaultConObject)
-            return;
-         defaultObject = dynamic_cast<SimObject*>(defaultConObject);
-      
-      }
-      // ***Really*** shouldn't happen
-      if (!defaultConObject || !defaultObject)
-         return;
+   // Fetch object.
+   SimObject* pSimObject = pTamlWriteNode->mpSimObject;
 
 
-      // Iterate fields.
-      U8 arrayDepth = 0;
-      TamlCustomNode* currentArrayNode = NULL;
-      for (U32 index = 0; index < fieldCount; ++index)
-      {
-         // Fetch field.
-         const AbstractClassRep::Field* pField = &fieldList[index];
+   // Fetch field list.
+   const AbstractClassRep::FieldList& fieldList = pSimObject->getFieldList();
 
 
-         // Ignore if field not appropriate.
-         if (pField->type == AbstractClassRep::DeprecatedFieldType ||
-            pField->type == AbstractClassRep::StartGroupFieldType ||
-            pField->type == AbstractClassRep::EndGroupFieldType)
-            continue;
+   // Fetch field count.
+   const U32 fieldCount = fieldList.size();
 
 
-         if (pField->type == AbstractClassRep::StartArrayFieldType)
-         {
-            TamlCustomNodes& pCustomNodes = pTamlWriteNode->mCustomNodes;
-            currentArrayNode = pCustomNodes.addNode(pField->pGroupname);
-            for (U16 idx = 0; idx < pField->elementCount; idx++)
-               currentArrayNode->addNode(pField->pFieldname);
-            arrayDepth++;
-            continue;
-         }
+   ConsoleObject* defaultConObject = NULL;
+   SimObject* defaultObject = NULL;
+   if (!getWriteDefaults())
+   {
+      // Create a default object of the same type
+      defaultConObject = ConsoleObject::create(pSimObject->getClassName());
+      if (!defaultConObject)
+         return;
+      defaultObject = dynamic_cast<SimObject*>(defaultConObject);
+      
+   }
+   // ***Really*** shouldn't happen
+   if (!defaultConObject || !defaultObject)
+      return;
+
+   // Iterate fields.
+   U8 arrayDepth = 0;
+   TamlCustomNode* currentArrayNode = NULL;
+   for (U32 index = 0; index < fieldCount; ++index)
+   {
+      // Fetch field.
+      const AbstractClassRep::Field* pField = &fieldList[index];
 
 
-         if (pField->type == AbstractClassRep::EndArrayFieldType)
-         {
-            arrayDepth--;
-            continue;
-         }
+      // Ignore if field not appropriate.
+      if (pField->type == AbstractClassRep::DeprecatedFieldType ||
+         pField->type == AbstractClassRep::StartGroupFieldType ||
+         pField->type == AbstractClassRep::EndGroupFieldType)
+         continue;
 
 
-         if (arrayDepth == 0 && pField->elementCount > 1)
-         {
-            TamlCustomNodes& pCustomNodes = pTamlWriteNode->mCustomNodes;
-            char* niceFieldName = const_cast<char *>(pField->pFieldname);
-            niceFieldName[0] = dToupper(niceFieldName[0]);
-            String str_niceFieldName = String(niceFieldName);
-            currentArrayNode = pCustomNodes.addNode(str_niceFieldName + "s");
-            for (U16 idx = 0; idx < pField->elementCount; idx++)
-               currentArrayNode->addNode(str_niceFieldName);
-         }
+      if (pField->type == AbstractClassRep::StartArrayFieldType)
+      {
+         TamlCustomNodes& pCustomNodes = pTamlWriteNode->mCustomNodes;
+         currentArrayNode = pCustomNodes.addNode(pField->pGroupname);
+         for (U16 idx = 0; idx < pField->elementCount; idx++)
+            currentArrayNode->addNode(pField->pFieldname);
+         arrayDepth++;
+         continue;
+      }
 
 
-         // Fetch fieldname.
-         StringTableEntry fieldName = StringTable->insert(pField->pFieldname);
+      if (pField->type == AbstractClassRep::EndArrayFieldType)
+      {
+         arrayDepth--;
+         continue;
+      }
 
 
-         // Fetch element count.
-         const U32 elementCount = pField->elementCount;
+      if (arrayDepth == 0 && pField->elementCount > 1)
+      {
+         TamlCustomNodes& pCustomNodes = pTamlWriteNode->mCustomNodes;
+         char* niceFieldName = const_cast<char *>(pField->pFieldname);
+         niceFieldName[0] = dToupper(niceFieldName[0]);
+         String str_niceFieldName = String(niceFieldName);
+         currentArrayNode = pCustomNodes.addNode(str_niceFieldName + "s");
+         for (U16 idx = 0; idx < pField->elementCount; idx++)
+            currentArrayNode->addNode(str_niceFieldName);
+      }
 
 
-         // Skip if the field should not be written.
-         // For now, we only deal with non-array fields.
-         if (elementCount == 1 &&
-            pField->setDataFn != NULL &&
-            (!getWriteDefaults() && pField->writeDataFn(pSimObject, fieldName) == false))
-            continue;
+      // Fetch fieldname.
+      StringTableEntry fieldName = StringTable->insert(pField->pFieldname);
 
 
-         // Iterate elements.
-         for (U32 elementIndex = 0; elementIndex < elementCount; ++elementIndex)
-         {
-            char indexBuffer[8];
-            dSprintf(indexBuffer, 8, "%d", elementIndex);
+      // Fetch element count.
+      const U32 elementCount = pField->elementCount;
+
+      // Skip if the field should not be written.
+      // For now, we only deal with non-array fields.
+      if (elementCount == 1 &&
+         pField->setDataFn != NULL &&
+         (!getWriteDefaults() && pField->writeDataFn(pSimObject, fieldName) == false))
+         continue;
 
 
-            // Fetch object field value.
-            const char* pFieldValue = pSimObject->getPrefixedDataField(fieldName, indexBuffer);
+      // Iterate elements.
+      for (U32 elementIndex = 0; elementIndex < elementCount; ++elementIndex)
+      {
+         char indexBuffer[8];
+         dSprintf(indexBuffer, 8, "%d", elementIndex);
 
 
-            if (!pFieldValue)
-               pFieldValue = StringTable->EmptyString();
+         // Fetch object field value.
+         const char* pFieldValue = pSimObject->getPrefixedDataField(fieldName, indexBuffer);
 
 
-            U32 nBufferSize = dStrlen(pFieldValue) + 1;
-            FrameTemp<char> valueCopy(nBufferSize);
-            dStrcpy((char *)valueCopy, pFieldValue, nBufferSize);
+         if (!pFieldValue)
+            pFieldValue = StringTable->EmptyString();
 
 
-            // Skip if field should not be written.
-            if (!pSimObject->writeField(fieldName, valueCopy))
-               continue;
+         U32 nBufferSize = dStrlen(pFieldValue) + 1;
+         FrameTemp<char> valueCopy(nBufferSize);
+         dStrcpy((char *)valueCopy, pFieldValue, nBufferSize);
 
 
-            if (!getWriteDefaults())
-            {
-               //If the field hasn't been changed from the default value, then don't bother writing it out
-               const char* fieldData = defaultObject->getDataField(fieldName, indexBuffer);
-               if (fieldData && fieldData[0] != '\0' && dStricmp(fieldData, pFieldValue) == 0)
-                  continue;
-            }
+         // Skip if field should not be written.
+         if (!pSimObject->writeField(fieldName, valueCopy))
+            continue;
 
 
-            // Reassign field value.
-            pFieldValue = valueCopy;
+         if (!getWriteDefaults())
+         {
+            //If the field hasn't been changed from the default value, then don't bother writing it out
+            const char* fieldData = defaultObject->getDataField(fieldName, indexBuffer);
+            if (fieldData && fieldData[0] != '\0' && dStricmp(fieldData, pFieldValue) == 0)
+               continue;
+         }
 
 
-            if (pField->type == TypeBool)
-               pFieldValue = dAtob(pFieldValue) ? "true" : "false";
+         // Reassign field value.
+         pFieldValue = valueCopy;
 
 
-            // Detect and collapse relative path information
-            char fnBuf[1024];
-            if ((S32)pField->type == TypeFilename)
-            {
-               Con::collapseScriptFilename(fnBuf, 1024, pFieldValue);
-               pFieldValue = fnBuf;
-            }
+         if (pField->type == TypeBool)
+            pFieldValue = dAtob(pFieldValue) ? "true" : "false";
 
 
-            // Save field/value.
-            if (currentArrayNode && (arrayDepth > 0 || pField->elementCount > 1))
-               currentArrayNode->getChildren()[elementIndex]->addField(fieldName, pFieldValue);
-            else
-            {
-               TamlWriteNode::FieldValuePair* pFieldValuePair = new TamlWriteNode::FieldValuePair(fieldName, pFieldValue);
-               pTamlWriteNode->mFields.push_back(pFieldValuePair);
-            }
+         // Detect and collapse relative path information
+         char fnBuf[1024];
+         if ((S32)pField->type == TypeFilename)
+         {
+            Con::collapseScriptFilename(fnBuf, 1024, pFieldValue);
+            pFieldValue = fnBuf;
          }
          }
-      }
 
 
-      if (!getWriteDefaults())
-      {
-         // Cleanup our created default object
-         delete defaultConObject;
+         // Save field/value.
+         if (currentArrayNode && (arrayDepth > 0 || pField->elementCount > 1))
+            currentArrayNode->getChildren()[elementIndex]->addField(fieldName, pFieldValue);
+         else
+         {
+            TamlWriteNode::FieldValuePair* pFieldValuePair = new TamlWriteNode::FieldValuePair(fieldName, pFieldValue);
+            pTamlWriteNode->mFields.push_back(pFieldValuePair);
+         }
       }
       }
    }
    }
 
 
-   //-----------------------------------------------------------------------------
-
-   static S32 QSORT_CALLBACK compareFieldEntries(const void* a, const void* b)
+   if (!getWriteDefaults())
    {
    {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_CompareFieldEntries);
-
-      SimFieldDictionary::Entry *fa = *((SimFieldDictionary::Entry **)a);
-      SimFieldDictionary::Entry *fb = *((SimFieldDictionary::Entry **)b);
-      return dStricmp(fa->slotName, fb->slotName);
+      // Cleanup our created default object
+      delete defaultConObject;
    }
    }
+}
 
 
-   //-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 
 
-   void Taml::compileDynamicFields(TamlWriteNode* pTamlWriteNode)
-   {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_CompileDynamicFields);
+static S32 QSORT_CALLBACK compareFieldEntries(const void* a, const void* b)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_CompareFieldEntries);
 
 
-      // Sanity!
-      AssertFatal(pTamlWriteNode != NULL, "Cannot compile dynamic fields on a NULL node.");
-      AssertFatal(pTamlWriteNode->mpSimObject != NULL, "Cannot compile dynamic fields on a node with no object.");
+   SimFieldDictionary::Entry *fa = *((SimFieldDictionary::Entry **)a);
+   SimFieldDictionary::Entry *fb = *((SimFieldDictionary::Entry **)b);
+   return dStricmp(fa->slotName, fb->slotName);
+}
 
 
-      // Fetch object.
-      SimObject* pSimObject = pTamlWriteNode->mpSimObject;
+//-----------------------------------------------------------------------------
 
 
-      // Fetch field dictionary.
-      SimFieldDictionary* pFieldDictionary = pSimObject->getFieldDictionary();
+void Taml::compileDynamicFields(TamlWriteNode* pTamlWriteNode)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_CompileDynamicFields);
 
 
-      // Ignore if not writing dynamic fields.
-      if (!pFieldDictionary || !pSimObject->getCanSaveDynamicFields())
-         return;
+   // Sanity!
+   AssertFatal(pTamlWriteNode != NULL, "Cannot compile dynamic fields on a NULL node.");
+   AssertFatal(pTamlWriteNode->mpSimObject != NULL, "Cannot compile dynamic fields on a node with no object.");
 
 
-      // Fetch field list.
-      const AbstractClassRep::FieldList& fieldList = pSimObject->getFieldList();
+   // Fetch object.
+   SimObject* pSimObject = pTamlWriteNode->mpSimObject;
 
 
-      // Fetch field count.
-      const U32 fieldCount = fieldList.size();
+   // Fetch field dictionary.
+   SimFieldDictionary* pFieldDictionary = pSimObject->getFieldDictionary();
 
 
-      Vector<SimFieldDictionary::Entry*> dynamicFieldList(__FILE__, __LINE__);
+   // Ignore if not writing dynamic fields.
+   if (!pFieldDictionary || !pSimObject->getCanSaveDynamicFields())
+      return;
 
 
-      // Ensure the dynamic field doesn't conflict with static field.
-      for (U32 hashIndex = 0; hashIndex < SimFieldDictionary::HashTableSize; ++hashIndex)
-      {
-         for (SimFieldDictionary::Entry* pEntry = pFieldDictionary->mHashTable[hashIndex]; pEntry; pEntry = pEntry->next)
-         {
-            // Iterate static fields.
-            U32 fieldIndex;
-            for (fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
-            {
-               if (fieldList[fieldIndex].pFieldname == pEntry->slotName)
-                  break;
-            }
+   // Fetch field list.
+   const AbstractClassRep::FieldList& fieldList = pSimObject->getFieldList();
 
 
-            // Skip if found.
-            if (fieldIndex != (U32)fieldList.size())
-               continue;
+   // Fetch field count.
+   const U32 fieldCount = fieldList.size();
 
 
-            // Skip if not writing field.
-            if (!pSimObject->writeField(pEntry->slotName, pEntry->value))
-               continue;
+   Vector<SimFieldDictionary::Entry*> dynamicFieldList(__FILE__, __LINE__);
 
 
-            dynamicFieldList.push_back(pEntry);
+   // Ensure the dynamic field doesn't conflict with static field.
+   for (U32 hashIndex = 0; hashIndex < SimFieldDictionary::HashTableSize; ++hashIndex)
+   {
+      for (SimFieldDictionary::Entry* pEntry = pFieldDictionary->mHashTable[hashIndex]; pEntry; pEntry = pEntry->next)
+      {
+         // Iterate static fields.
+         U32 fieldIndex;
+         for (fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
+         {
+            if (fieldList[fieldIndex].pFieldname == pEntry->slotName)
+               break;
          }
          }
-      }
 
 
-      // Sort Entries to prevent version control conflicts
-      if (dynamicFieldList.size() > 1)
-         dQsort(dynamicFieldList.address(), dynamicFieldList.size(), sizeof(SimFieldDictionary::Entry*), compareFieldEntries);
+         // Skip if found.
+         if (fieldIndex != (U32)fieldList.size())
+            continue;
 
 
-      // Save the fields.
-      for (Vector<SimFieldDictionary::Entry*>::iterator entryItr = dynamicFieldList.begin(); entryItr != dynamicFieldList.end(); ++entryItr)
-      {
-         // Fetch entry.
-         SimFieldDictionary::Entry* pEntry = *entryItr;
+         // Skip if not writing field.
+         if (!pSimObject->writeField(pEntry->slotName, pEntry->value))
+            continue;
 
 
-         // Save field/value.
-         TamlWriteNode::FieldValuePair*  pFieldValuePair = new TamlWriteNode::FieldValuePair(pEntry->slotName, pEntry->value);
-         pTamlWriteNode->mFields.push_back(pFieldValuePair);
+         dynamicFieldList.push_back(pEntry);
       }
       }
    }
    }
 
 
-   //-----------------------------------------------------------------------------
+   // Sort Entries to prevent version control conflicts
+   if (dynamicFieldList.size() > 1)
+      dQsort(dynamicFieldList.address(), dynamicFieldList.size(), sizeof(SimFieldDictionary::Entry*), compareFieldEntries);
 
 
-   void Taml::compileChildren(TamlWriteNode* pTamlWriteNode)
+   // Save the fields.
+   for (Vector<SimFieldDictionary::Entry*>::iterator entryItr = dynamicFieldList.begin(); entryItr != dynamicFieldList.end(); ++entryItr)
    {
    {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_CompileChildren);
+      // Fetch entry.
+      SimFieldDictionary::Entry* pEntry = *entryItr;
 
 
-      // Sanity!
-      AssertFatal(pTamlWriteNode != NULL, "Cannot compile children on a NULL node.");
-      AssertFatal(pTamlWriteNode->mpSimObject != NULL, "Cannot compile children on a node with no object.");
+      // Save field/value.
+      TamlWriteNode::FieldValuePair*  pFieldValuePair = new TamlWriteNode::FieldValuePair(pEntry->slotName, pEntry->value);
+      pTamlWriteNode->mFields.push_back(pFieldValuePair);
+   }
+}
 
 
-      // Fetch object.
-      SimObject* pSimObject = pTamlWriteNode->mpSimObject;
+//-----------------------------------------------------------------------------
 
 
-      // Fetch the Taml children.
-      TamlChildren* pChildren = dynamic_cast<TamlChildren*>(pSimObject);
+void Taml::compileChildren(TamlWriteNode* pTamlWriteNode)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_CompileChildren);
 
 
-      // Finish if object does not contain Taml children.
-      if (pChildren == NULL || pChildren->getTamlChildCount() == 0)
-         return;
+   // Sanity!
+   AssertFatal(pTamlWriteNode != NULL, "Cannot compile children on a NULL node.");
+   AssertFatal(pTamlWriteNode->mpSimObject != NULL, "Cannot compile children on a node with no object.");
 
 
-      // Create children vector.
-      pTamlWriteNode->mChildren = new typeNodeVector();
+   // Fetch object.
+   SimObject* pSimObject = pTamlWriteNode->mpSimObject;
 
 
-      // Fetch the child count.
-      const U32 childCount = pChildren->getTamlChildCount();
+   // Fetch the Taml children.
+   TamlChildren* pChildren = dynamic_cast<TamlChildren*>(pSimObject);
 
 
-      // Iterate children.
-      for (U32 childIndex = 0; childIndex < childCount; childIndex++)
-      {
-         // Compile object.
-         TamlWriteNode* pChildTamlWriteNode = compileObject(pChildren->getTamlChild(childIndex));
+   // Finish if object does not contain Taml children.
+   if (pChildren == NULL || pChildren->getTamlChildCount() == 0)
+      return;
 
 
-         // Save node.
-         pTamlWriteNode->mChildren->push_back(pChildTamlWriteNode);
-      }
-   }
+   // Create children vector.
+   pTamlWriteNode->mChildren = new typeNodeVector();
 
 
-   //-----------------------------------------------------------------------------
+   // Fetch the child count.
+   const U32 childCount = pChildren->getTamlChildCount();
 
 
-   void Taml::compileCustomState(TamlWriteNode* pTamlWriteNode)
+   // Iterate children.
+   for (U32 childIndex = 0; childIndex < childCount; childIndex++)
    {
    {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_CompileCustomProperties);
+      // Compile object.
+      TamlWriteNode* pChildTamlWriteNode = compileObject(pChildren->getTamlChild(childIndex));
 
 
-      // Sanity!
-      AssertFatal(pTamlWriteNode != NULL, "Cannot compile custom state on a NULL node.");
-      AssertFatal(pTamlWriteNode->mpSimObject != NULL, "Cannot compile custom state on a node with no object.");
-
-      // Fetch the custom node on the write node.
-      TamlCustomNodes& customNodes = pTamlWriteNode->mCustomNodes;
+      // Save node.
+      pTamlWriteNode->mChildren->push_back(pChildTamlWriteNode);
+   }
+}
 
 
-      // Are there any Taml callbacks?
-      if (pTamlWriteNode->mpTamlCallbacks != NULL)
-      {
-         // Yes, so call it.
-         tamlCustomWrite(pTamlWriteNode->mpTamlCallbacks, customNodes);
-      }
+//-----------------------------------------------------------------------------
 
 
-      // Fetch custom nodes.
-      const TamlCustomNodeVector& nodes = customNodes.getNodes();
+void Taml::compileCustomState(TamlWriteNode* pTamlWriteNode)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_CompileCustomProperties);
 
 
-      // Finish if no custom nodes to process.
-      if (nodes.size() == 0)
-         return;
+   // Sanity!
+   AssertFatal(pTamlWriteNode != NULL, "Cannot compile custom state on a NULL node.");
+   AssertFatal(pTamlWriteNode->mpSimObject != NULL, "Cannot compile custom state on a node with no object.");
 
 
-      // Iterate custom properties.
-      for (TamlCustomNodeVector::const_iterator customNodesItr = nodes.begin(); customNodesItr != nodes.end(); ++customNodesItr)
-      {
-         // Fetch the custom node.
-         TamlCustomNode* pCustomNode = *customNodesItr;
+   // Fetch the custom node on the write node.
+   TamlCustomNodes& customNodes = pTamlWriteNode->mCustomNodes;
 
 
-         // Compile custom node state.
-         compileCustomNodeState(pCustomNode);
-      }
+   // Are there any Taml callbacks?
+   if (pTamlWriteNode->mpTamlCallbacks != NULL)
+   {
+      // Yes, so call it.
+      tamlCustomWrite(pTamlWriteNode->mpTamlCallbacks, customNodes);
    }
    }
 
 
-   //-----------------------------------------------------------------------------
+   // Fetch custom nodes.
+   const TamlCustomNodeVector& nodes = customNodes.getNodes();
+
+   // Finish if no custom nodes to process.
+   if (nodes.size() == 0)
+      return;
 
 
-   void Taml::compileCustomNodeState(TamlCustomNode* pCustomNode)
+   // Iterate custom properties.
+   for (TamlCustomNodeVector::const_iterator customNodesItr = nodes.begin(); customNodesItr != nodes.end(); ++customNodesItr)
    {
    {
-      // Sanity!
-      AssertFatal(pCustomNode != NULL, "Taml: Cannot compile NULL custom node state.");
+      // Fetch the custom node.
+      TamlCustomNode* pCustomNode = *customNodesItr;
 
 
-      // Fetch children.
-      const TamlCustomNodeVector& children = pCustomNode->getChildren();
+      // Compile custom node state.
+      compileCustomNodeState(pCustomNode);
+   }
+}
 
 
-      // Fetch proxy object.
-      SimObject* pProxyObject = pCustomNode->getProxyObject<SimObject>(false);
+//-----------------------------------------------------------------------------
 
 
-      // Do we have a proxy object?
-      if (pProxyObject != NULL)
-      {
-         // Yes, so sanity!
-         AssertFatal(children.size() == 0, "Taml: Cannot compile a proxy object on a custom node that has children.");
-
-         // Yes, so compile it.
-         // NOTE: We force an Id for custom compiled objects so we guarantee an Id.  The reason for this is fairly
-         // weak in that the XML parser currently has no way of distinguishing between a compiled object node
-         // and a custom node.  If the node has an Id or an Id-Ref then it's obviously an object and should be parsed as such.
-         pCustomNode->setWriteNode(compileObject(pProxyObject, true));
-         return;
-      }
+void Taml::compileCustomNodeState(TamlCustomNode* pCustomNode)
+{
+   // Sanity!
+   AssertFatal(pCustomNode != NULL, "Taml: Cannot compile NULL custom node state.");
 
 
-      // Finish if no children.
-      if (children.size() == 0)
-         return;
+   // Fetch children.
+   const TamlCustomNodeVector& children = pCustomNode->getChildren();
 
 
-      // Iterate children.
-      for (TamlCustomNodeVector::const_iterator childItr = children.begin(); childItr != children.end(); ++childItr)
-      {
-         // Fetch shape node.
-         TamlCustomNode* pChildNode = *childItr;
+   // Fetch proxy object.
+   SimObject* pProxyObject = pCustomNode->getProxyObject<SimObject>(false);
 
 
-         // Compile the child.
-         compileCustomNodeState(pChildNode);
-      }
+   // Do we have a proxy object?
+   if (pProxyObject != NULL)
+   {
+      // Yes, so sanity!
+      AssertFatal(children.size() == 0, "Taml: Cannot compile a proxy object on a custom node that has children.");
+
+      // Yes, so compile it.
+      // NOTE: We force an Id for custom compiled objects so we guarantee an Id.  The reason for this is fairly
+      // weak in that the XML parser currently has no way of distinguishing between a compiled object node
+      // and a custom node.  If the node has an Id or an Id-Ref then it's obviously an object and should be parsed as such.
+      pCustomNode->setWriteNode(compileObject(pProxyObject, true));
+      return;
    }
    }
 
 
-   //-----------------------------------------------------------------------------
+   // Finish if no children.
+   if (children.size() == 0)
+      return;
 
 
-   SimObject* Taml::createType(StringTableEntry typeName, const Taml* pTaml, const char* pProgenitorSuffix)
+   // Iterate children.
+   for (TamlCustomNodeVector::const_iterator childItr = children.begin(); childItr != children.end(); ++childItr)
    {
    {
-      // Debug Profiling.
-      PROFILE_SCOPE(Taml_CreateType);
+      // Fetch shape node.
+      TamlCustomNode* pChildNode = *childItr;
 
 
-      typedef HashTable<StringTableEntry, AbstractClassRep*> typeClassHash;
-      static typeClassHash mClassMap;
+      // Compile the child.
+      compileCustomNodeState(pChildNode);
+   }
+}
 
 
-      // Sanity!
-      AssertFatal(typeName != NULL, "Taml: Type cannot be NULL");
+//-----------------------------------------------------------------------------
 
 
-      // Find type.
-      typeClassHash::Iterator typeItr = mClassMap.find(typeName);
+SimObject* Taml::createType(StringTableEntry typeName, const Taml* pTaml, const char* pProgenitorSuffix)
+{
+   // Debug Profiling.
+   PROFILE_SCOPE(Taml_CreateType);
 
 
-      // Found type?
-      if (typeItr == mClassMap.end())
-      {
-         // No, so find type.
-         AbstractClassRep* pClassRep = AbstractClassRep::getClassList();
-         while (pClassRep)
-         {
-            // Is this the type?
-            if (dStricmp(pClassRep->getClassName(), typeName) == 0)
-            {
-               // Yes, so insert it.
-               typeItr = mClassMap.insertUnique(typeName, pClassRep);
-               break;
-            }
+   typedef HashTable<StringTableEntry, AbstractClassRep*> typeClassHash;
+   static typeClassHash mClassMap;
 
 
-            // Next type.
-            pClassRep = pClassRep->getNextClass();
-         }
+   // Sanity!
+   AssertFatal(typeName != NULL, "Taml: Type cannot be NULL");
 
 
-         // Did we find the type?
-         if (typeItr == mClassMap.end())
+   // Find type.
+   typeClassHash::Iterator typeItr = mClassMap.find(typeName);
+
+   // Found type?
+   if (typeItr == mClassMap.end())
+   {
+      // No, so find type.
+      AbstractClassRep* pClassRep = AbstractClassRep::getClassList();
+      while (pClassRep)
+      {
+         // Is this the type?
+         if (dStricmp(pClassRep->getClassName(), typeName) == 0)
          {
          {
-            // No, so warn and fail.
-            Con::warnf("Taml: Failed to create type '%s' as such a registered type could not be found.", typeName);
-            return NULL;
+            // Yes, so insert it.
+            typeItr = mClassMap.insertUnique(typeName, pClassRep);
+            break;
          }
          }
-      }
-
-      // Create the object.
-      ConsoleObject* pConsoleObject = typeItr->value->create();
 
 
-      // NOTE: It is important that we don't register the object here as many objects rely on the fact that
-      // fields are set prior to the object being registered.  Registering here will invalid those assumptions.
-
-      // Fetch the SimObject.
-      SimObject* pSimObject = dynamic_cast<SimObject*>(pConsoleObject);
+         // Next type.
+         pClassRep = pClassRep->getNextClass();
+      }
 
 
-      // Was it a SimObject?
-      if (pSimObject == NULL)
+      // Did we find the type?
+      if (typeItr == mClassMap.end())
       {
       {
-         // No, so warn.
-         Con::warnf("Taml: Failed to create type '%s' as it is not a SimObject.", typeName);
-
-         // Destroy object and fail.
-         delete pConsoleObject;
+         // No, so warn and fail.
+         Con::warnf("Taml: Failed to create type '%s' as such a registered type could not be found.", typeName);
          return NULL;
          return NULL;
       }
       }
+   }
 
 
-      // Are we updating the file-progenitor?
-      if (pTaml->getProgenitorUpdate())
-      {
-         // Yes, so do we have a progenitor suffix?
-         if (pProgenitorSuffix == NULL)
-         {
-            // No, so just set it to the progenitor file.
-            pSimObject->setProgenitorFile(pTaml->getFilePathBuffer());
-         }
-         else
-         {
-            // Yes, so format the progenitor buffer.
-            char progenitorBuffer[2048];
-            dSprintf(progenitorBuffer, sizeof(progenitorBuffer), "%s,%s", pTaml->getFilePathBuffer(), pProgenitorSuffix);
+   // Create the object.
+   ConsoleObject* pConsoleObject = typeItr->value->create();
 
 
-            // Set the progenitor file.
-            pSimObject->setProgenitorFile(progenitorBuffer);
-         }
-      }
+   // NOTE: It is important that we don't register the object here as many objects rely on the fact that
+   // fields are set prior to the object being registered.  Registering here will invalid those assumptions.
 
 
-      return pSimObject;
-   }
+   // Fetch the SimObject.
+   SimObject* pSimObject = dynamic_cast<SimObject*>(pConsoleObject);
+
+   // Was it a SimObject?
+   if (pSimObject == NULL)
+   {
+      // No, so warn.
+      Con::warnf("Taml: Failed to create type '%s' as it is not a SimObject.", typeName);
 
 
-   //-----------------------------------------------------------------------------
+      // Destroy object and fail.
+      delete pConsoleObject;
+      return NULL;
+   }
 
 
-   tinyxml2::XMLElement* g__write_schema_attribute_element(const AbstractClassRep::Field& field, AbstractClassRep* pType,
-                                                          tinyxml2::XMLDocument& schemaDocument)
+   // Are we updating the file-progenitor?
+   if (pTaml->getProgenitorUpdate())
    {
    {
-      // Skip if not a data field.
-      if (field.type == AbstractClassRep::DeprecatedFieldType ||
-         field.type == AbstractClassRep::StartGroupFieldType ||
-         field.type == AbstractClassRep::EndGroupFieldType)
-         return NULL;
+      // Yes, so do we have a progenitor suffix?
+      if (pProgenitorSuffix == NULL)
+      {
+         // No, so just set it to the progenitor file.
+         pSimObject->setProgenitorFile(pTaml->getFilePathBuffer());
+      }
+      else
+      {
+         // Yes, so format the progenitor buffer.
+         char progenitorBuffer[2048];
+         dSprintf(progenitorBuffer, sizeof(progenitorBuffer), "%s,%s", pTaml->getFilePathBuffer(), pProgenitorSuffix);
 
 
-      // Skip if the field root is not this type.
-      if (pType->findFieldRoot(field.pFieldname) != pType)
-         return NULL;
+         // Set the progenitor file.
+         pSimObject->setProgenitorFile(progenitorBuffer);
+      }
+   }
 
 
-      // Add attribute element.
-      tinyxml2::XMLElement* pAttributeElement = schemaDocument.NewElement("xs:attribute");
-      pAttributeElement->SetAttribute("name", field.pFieldname);
+   return pSimObject;
+}
 
 
-      // Handle the console type appropriately.
-      const S32 fieldType = (S32)field.type;
+//-----------------------------------------------------------------------------
 
 
-      /*
-      // Is the field an enumeration?
-      if ( fieldType == TypeEnum )
-      {
-      // Yes, so add attribute type.
-      tinyxml2::XMLElement* pAttributeSimpleTypeElement = schemaDocument.NewElement( "xs:simpleType" );
-      pAttributeElement->LinkEndChild( pAttributeSimpleTypeElement );
+tinyxml2::XMLElement* g__write_schema_attribute_element(const AbstractClassRep::Field& field, AbstractClassRep* pType,
+                                                         tinyxml2::XMLDocument& schemaDocument)
+{
+   // Skip if not a data field.
+   if (field.type == AbstractClassRep::DeprecatedFieldType ||
+      field.type == AbstractClassRep::StartGroupFieldType ||
+      field.type == AbstractClassRep::EndGroupFieldType)
+      return NULL;
 
 
-      // Add restriction element.
-      tinyxml2::XMLElement* pAttributeRestrictionElement = schemaDocument.NewElement( "xs:restriction" );
-      pAttributeRestrictionElement->SetAttribute( "base", "xs:string" );
-      pAttributeSimpleTypeElement->LinkEndChild( pAttributeRestrictionElement );
+   // Skip if the field root is not this type.
+   if (pType->findFieldRoot(field.pFieldname) != pType)
+      return NULL;
 
 
-      // Yes, so fetch enumeration count.
-      const S32 enumCount = field.table->size;
+   // Add attribute element.
+   tinyxml2::XMLElement* pAttributeElement = schemaDocument.NewElement("xs:attribute");
+   pAttributeElement->SetAttribute("name", field.pFieldname);
 
 
-      // Iterate enumeration.
-      for( S32 index = 0; index < enumCount; ++index )
-      {
-      // Add enumeration element.
-      tinyxml2::XMLElement* pAttributeEnumerationElement = schemaDocument.NewElement( "xs:enumeration" );
-      pAttributeEnumerationElement->SetAttribute( "value", field.table->table[index].label );
-      pAttributeRestrictionElement->LinkEndChild( pAttributeEnumerationElement );
-      }
-      }
-      else
-      {*/
-      // No, so assume it's a string type initially.
-      const char* pFieldTypeDescription = "xs:string";
+   // Handle the console type appropriately.
+   const S32 fieldType = (S32)field.type;
 
 
-      // Handle known types.
-      if (fieldType == TypeF32)
-      {
-         pFieldTypeDescription = "xs:float";
-      }
-      else if (fieldType == TypeS8 || fieldType == TypeS16 || fieldType == TypeS32)
-      {
-         pFieldTypeDescription = "xs:int";
-      }
-      else if (fieldType == TypeBool || fieldType == TypeFlag)
-      {
-         pFieldTypeDescription = "xs:boolean";
-      }
-      else if (fieldType == TypePoint2F)
-      {
-         pFieldTypeDescription = "Point2F_ConsoleType";
-      }
-      else if (fieldType == TypePoint2I)
-      {
-         pFieldTypeDescription = "Point2I_ConsoleType";
-      }
-      else if (fieldType == TypeRectI)
-      {
-         pFieldTypeDescription = "RectI_ConsoleType";
-      }
-      else if (fieldType == TypeRectF)
-      {
-         pFieldTypeDescription = "RectF_ConsoleType";
-      }
-      else if (fieldType == TypeColorF)
-      {
-         pFieldTypeDescription = "ColorF_ConsoleType";
-      }
-      else if (fieldType == TypeColorI)
-      {
-         pFieldTypeDescription = "ColorI_ConsoleType";
-      }
-      else if (fieldType == TypeAssetId/* ||
-                                       fieldType == TypeImageAssetPtr ||
-                                       fieldType == TypeAnimationAssetPtr ||
-                                       fieldType == TypeAudioAssetPtr*/)
-      {
-         pFieldTypeDescription = "AssetId_ConsoleType";
-      }
+   /*
+   // Is the field an enumeration?
+   if ( fieldType == TypeEnum )
+   {
+   // Yes, so add attribute type.
+   tinyxml2::XMLElement* pAttributeSimpleTypeElement = schemaDocument.NewElement( "xs:simpleType" );
+   pAttributeElement->LinkEndChild( pAttributeSimpleTypeElement );
 
 
-      // Set attribute type.
-      pAttributeElement->SetAttribute("type", pFieldTypeDescription);
-      //}
+   // Add restriction element.
+   tinyxml2::XMLElement* pAttributeRestrictionElement = schemaDocument.NewElement( "xs:restriction" );
+   pAttributeRestrictionElement->SetAttribute( "base", "xs:string" );
+   pAttributeSimpleTypeElement->LinkEndChild( pAttributeRestrictionElement );
 
 
-      pAttributeElement->SetAttribute("use", "optional");
-      return pAttributeElement;
-   }
+   // Yes, so fetch enumeration count.
+   const S32 enumCount = field.table->size;
 
 
-   String g_sanitize_schema_element_name(String buffer)
+   // Iterate enumeration.
+   for( S32 index = 0; index < enumCount; ++index )
    {
    {
-      return buffer.replace("(", "")
-         .replace(")", "");
+   // Add enumeration element.
+   tinyxml2::XMLElement* pAttributeEnumerationElement = schemaDocument.NewElement( "xs:enumeration" );
+   pAttributeEnumerationElement->SetAttribute( "value", field.table->table[index].label );
+   pAttributeRestrictionElement->LinkEndChild( pAttributeEnumerationElement );
    }
    }
+   }
+   else
+   {*/
+   // No, so assume it's a string type initially.
+   const char* pFieldTypeDescription = "xs:string";
 
 
-   bool Taml::generateTamlSchema()
+   // Handle known types.
+   if (fieldType == TypeF32)
+   {
+      pFieldTypeDescription = "xs:float";
+   }
+   else if (fieldType == TypeS8 || fieldType == TypeS16 || fieldType == TypeS32)
+   {
+      pFieldTypeDescription = "xs:int";
+   }
+   else if (fieldType == TypeBool || fieldType == TypeFlag)
+   {
+      pFieldTypeDescription = "xs:boolean";
+   }
+   else if (fieldType == TypePoint2F)
+   {
+      pFieldTypeDescription = "Point2F_ConsoleType";
+   }
+   else if (fieldType == TypePoint2I)
+   {
+      pFieldTypeDescription = "Point2I_ConsoleType";
+   }
+   else if (fieldType == TypeRectI)
+   {
+      pFieldTypeDescription = "RectI_ConsoleType";
+   }
+   else if (fieldType == TypeRectF)
+   {
+      pFieldTypeDescription = "RectF_ConsoleType";
+   }
+   else if (fieldType == TypeColorF)
+   {
+      pFieldTypeDescription = "ColorF_ConsoleType";
+   }
+   else if (fieldType == TypeColorI)
+   {
+      pFieldTypeDescription = "ColorI_ConsoleType";
+   }
+   else if (fieldType == TypeAssetId/* ||
+                                    fieldType == TypeImageAssetPtr ||
+                                    fieldType == TypeAnimationAssetPtr ||
+                                    fieldType == TypeAudioAssetPtr*/)
    {
    {
-      // Fetch any TAML Schema file reference.
-      const char* pTamlSchemaFile = Con::getVariable(TAML_SCHEMA_VARIABLE);
+      pFieldTypeDescription = "AssetId_ConsoleType";
+   }
 
 
-      // Do we have a schema file reference?
-      if (pTamlSchemaFile == NULL || *pTamlSchemaFile == 0)
-      {
-         // No, so warn.
-         Con::warnf("Taml::generateTamlSchema() - Cannot write a TAML schema as no schema variable is set ('%s').", TAML_SCHEMA_VARIABLE);
-         return false;
-      }
+   // Set attribute type.
+   pAttributeElement->SetAttribute("type", pFieldTypeDescription);
+   //}
 
 
-      // Expand the file-name into the file-path buffer.
-      char filePathBuffer[1024];
-      Con::expandToolScriptFilename(filePathBuffer, sizeof(filePathBuffer), pTamlSchemaFile);
+   pAttributeElement->SetAttribute("use", "optional");
+   return pAttributeElement;
+}
 
 
-      FileStream stream;
+String g_sanitize_schema_element_name(String buffer)
+{
+   return buffer.replace("(", "")
+      .replace(")", "");
+}
 
 
-      // File opened?
-      /*if ( !stream.open( filePathBuffer, Torque::FS::File::Write ) )
-      {
+bool Taml::generateTamlSchema()
+{
+   // Fetch any TAML Schema file reference.
+   const char* pTamlSchemaFile = Con::getVariable(TAML_SCHEMA_VARIABLE);
+
+   // Do we have a schema file reference?
+   if (pTamlSchemaFile == NULL || *pTamlSchemaFile == 0)
+   {
       // No, so warn.
       // No, so warn.
-      Con::warnf("Taml::GenerateTamlSchema() - Could not open filename '%s' for write.", filePathBuffer );
+      Con::warnf("Taml::generateTamlSchema() - Cannot write a TAML schema as no schema variable is set ('%s').", TAML_SCHEMA_VARIABLE);
       return false;
       return false;
-      }*/
-
-      // Create document.
-      tinyxml2::XMLDocument schemaDocument;
-
-      // Add declaration.
-      tinyxml2::XMLDeclaration* schemaDeclaration = schemaDocument.NewDeclaration("xml version=\"1.0\" encoding=\"iso-8859-1\" standalone =\"no\"");
-      schemaDocument.InsertEndChild(schemaDeclaration);
-
-      // Add schema element.
-      tinyxml2::XMLElement* pSchemaElement = schemaDocument.NewElement("xs:schema");
-      pSchemaElement->SetAttribute("xmlns:xs", "http://www.w3.org/2001/XMLSchema");
-      schemaDocument.LinkEndChild(pSchemaElement);
-
-      // Fetch class-rep root.
-      AbstractClassRep* pRootType = AbstractClassRep::getClassList();
-
-      // Fetch SimObject class rep.
-      AbstractClassRep* pSimObjectType = AbstractClassRep::findClassRep("SimObject");
-      // Sanity!
-      AssertFatal(pSimObjectType != NULL, "Taml::GenerateTamlSchema() - Could not find SimObject class rep.");
-
-      // Reset scratch state.
-      char buffer[1024];
-      HashTable<AbstractClassRep*, StringTableEntry> childGroups;
-
-      // *************************************************************
-      // Generate console type elements.
-      // *************************************************************
-
-      // Vector2.
-      tinyxml2::XMLComment* pVector2Comment = schemaDocument.NewComment("Vector2 Console Type");
-      pSchemaElement->LinkEndChild(pVector2Comment);
-      tinyxml2::XMLElement* pVector2TypeElement = schemaDocument.NewElement("xs:simpleType");
-      pVector2TypeElement->SetAttribute("name", "Vector2_ConsoleType");
-      pSchemaElement->LinkEndChild(pVector2TypeElement);
-      tinyxml2::XMLElement* pVector2ElementA = schemaDocument.NewElement("xs:restriction");
-      pVector2ElementA->SetAttribute("base", "xs:string");
-      pVector2TypeElement->LinkEndChild(pVector2ElementA);
-      tinyxml2::XMLElement* pVector2ElementB = schemaDocument.NewElement("xs:pattern");
-      pVector2ElementB->SetAttribute("value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b");
-      pVector2ElementA->LinkEndChild(pVector2ElementB);
-
-      // Point2F.
-      tinyxml2::XMLComment* pPoint2FComment = schemaDocument.NewComment("Point2F Console Type");
-      pSchemaElement->LinkEndChild(pPoint2FComment);
-      tinyxml2::XMLElement* pPoint2FTypeElement = schemaDocument.NewElement("xs:simpleType");
-      pPoint2FTypeElement->SetAttribute("name", "Point2F_ConsoleType");
-      pSchemaElement->LinkEndChild(pPoint2FTypeElement);
-      tinyxml2::XMLElement* pPoint2FElementA = schemaDocument.NewElement("xs:restriction");
-      pPoint2FElementA->SetAttribute("base", "xs:string");
-      pPoint2FTypeElement->LinkEndChild(pPoint2FElementA);
-      tinyxml2::XMLElement* pPoint2FElementB = schemaDocument.NewElement("xs:pattern");
-      pPoint2FElementB->SetAttribute("value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b");
-      pPoint2FElementA->LinkEndChild(pPoint2FElementB);
-
-      // Point2I.
-      tinyxml2::XMLComment* pPoint2IComment = schemaDocument.NewComment("Point2I Console Type");
-      pSchemaElement->LinkEndChild(pPoint2IComment);
-      tinyxml2::XMLElement* pPoint2ITypeElement = schemaDocument.NewElement("xs:simpleType");
-      pPoint2ITypeElement->SetAttribute("name", "Point2I_ConsoleType");
-      pSchemaElement->LinkEndChild(pPoint2ITypeElement);
-      tinyxml2::XMLElement* pPoint2IElementA = schemaDocument.NewElement("xs:restriction");
-      pPoint2IElementA->SetAttribute("base", "xs:string");
-      pPoint2ITypeElement->LinkEndChild(pPoint2IElementA);
-      tinyxml2::XMLElement* pPoint2IElementB = schemaDocument.NewElement("xs:pattern");
-      pPoint2IElementB->SetAttribute("value", "[-]?[0-9]* [-]?[0-9]*");
-      pPoint2IElementA->LinkEndChild(pPoint2IElementB);
-
-      // b2AABB.
-      tinyxml2::XMLComment* pb2AABBComment = schemaDocument.NewComment("b2AABB Console Type");
-      pSchemaElement->LinkEndChild(pb2AABBComment);
-      tinyxml2::XMLElement* pb2AABBTypeElement = schemaDocument.NewElement("xs:simpleType");
-      pb2AABBTypeElement->SetAttribute("name", "b2AABB_ConsoleType");
-      pSchemaElement->LinkEndChild(pb2AABBTypeElement);
-      tinyxml2::XMLElement* pb2AABBElementA = schemaDocument.NewElement("xs:restriction");
-      pb2AABBElementA->SetAttribute("base", "xs:string");
-      pb2AABBTypeElement->LinkEndChild(pb2AABBElementA);
-      tinyxml2::XMLElement* pb2AABBElementB = schemaDocument.NewElement("xs:pattern");
-      pb2AABBElementB->SetAttribute("value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b");
-      pb2AABBElementA->LinkEndChild(pb2AABBElementB);
-
-      // RectI.
-      tinyxml2::XMLComment* pRectIComment = schemaDocument.NewComment("RectI Console Type");
-      pSchemaElement->LinkEndChild(pRectIComment);
-      tinyxml2::XMLElement* pRectITypeElement = schemaDocument.NewElement("xs:simpleType");
-      pRectITypeElement->SetAttribute("name", "RectI_ConsoleType");
-      pSchemaElement->LinkEndChild(pRectITypeElement);
-      tinyxml2::XMLElement* pRectIElementA = schemaDocument.NewElement("xs:restriction");
-      pRectIElementA->SetAttribute("base", "xs:string");
-      pRectITypeElement->LinkEndChild(pRectIElementA);
-      tinyxml2::XMLElement* pRectIElementB = schemaDocument.NewElement("xs:pattern");
-      pRectIElementB->SetAttribute("value", "[-]?[0-9]* [-]?[0-9]* [-]?[0-9]* [-]?[0-9]*");
-      pRectIElementA->LinkEndChild(pRectIElementB);
-
-      // RectF.
-      tinyxml2::XMLComment* pRectFComment = schemaDocument.NewComment("RectF Console Type");
-      pSchemaElement->LinkEndChild(pRectFComment);
-      tinyxml2::XMLElement* pRectFTypeElement = schemaDocument.NewElement("xs:simpleType");
-      pRectFTypeElement->SetAttribute("name", "RectF_ConsoleType");
-      pSchemaElement->LinkEndChild(pRectFTypeElement);
-      tinyxml2::XMLElement* pRectFElementA = schemaDocument.NewElement("xs:restriction");
-      pRectFElementA->SetAttribute("base", "xs:string");
-      pRectFTypeElement->LinkEndChild(pRectFElementA);
-      tinyxml2::XMLElement* pRectFElementB = schemaDocument.NewElement("xs:pattern");
-      pRectFElementB->SetAttribute("value", "(\\b[-]?(b[0-9]+)?\\.)?[0-9]+\\b");
-      pRectFElementA->LinkEndChild(pRectFElementB);
-
-      // AssetId.
-      tinyxml2::XMLComment* pAssetIdComment = schemaDocument.NewComment("AssetId Console Type");
-      pSchemaElement->LinkEndChild(pAssetIdComment);
-      tinyxml2::XMLElement* pAssetIdTypeElement = schemaDocument.NewElement("xs:simpleType");
-      pAssetIdTypeElement->SetAttribute("name", "AssetId_ConsoleType");
-      pSchemaElement->LinkEndChild(pAssetIdTypeElement);
-      tinyxml2::XMLElement* pAssetIdElementA = schemaDocument.NewElement("xs:restriction");
-      pAssetIdElementA->SetAttribute("base", "xs:string");
-      pAssetIdTypeElement->LinkEndChild(pAssetIdElementA);
-      tinyxml2::XMLElement* pAssetIdElementB = schemaDocument.NewElement("xs:pattern");
-      dSprintf(buffer, sizeof(buffer), "(%s)?\\b[a-zA-Z0-9]+\\b%s\\b[a-zA-Z0-9]+\\b", ASSET_ID_FIELD_PREFIX, ASSET_SCOPE_TOKEN);
-      pAssetIdElementB->SetAttribute("value", buffer);
-      pAssetIdElementA->LinkEndChild(pAssetIdElementB);
-
-      // Color Enums.
-      tinyxml2::XMLComment* pColorEnumsComment = schemaDocument.NewComment("Color Enums");
-      pSchemaElement->LinkEndChild(pColorEnumsComment);
-      tinyxml2::XMLElement* pColorEnumsTypeElement = schemaDocument.NewElement("xs:simpleType");
-      pColorEnumsTypeElement->SetAttribute("name", "Color_Enums");
-      pSchemaElement->LinkEndChild(pColorEnumsTypeElement);
-      tinyxml2::XMLElement* pColorEnumsRestrictionElement = schemaDocument.NewElement("xs:restriction");
-      pColorEnumsRestrictionElement->SetAttribute("base", "xs:string");
-      pColorEnumsTypeElement->LinkEndChild(pColorEnumsRestrictionElement);
-      const S32 ColorEnumsCount = StockColor::getCount();
-      for (S32 index = 0; index < ColorEnumsCount; ++index)
-      {
-         // Add enumeration element.
-         tinyxml2::XMLElement* pColorEnumsAttributeEnumerationElement = schemaDocument.NewElement("xs:enumeration");
-         pColorEnumsAttributeEnumerationElement->SetAttribute("value", StockColor::getColorItem(index)->getColorName());
-         pColorEnumsRestrictionElement->LinkEndChild(pColorEnumsAttributeEnumerationElement);
-      }
+   }
 
 
-      // LinearColorF.
-      tinyxml2::XMLComment* pColorFValuesComment = schemaDocument.NewComment("LinearColorF Values");
-      pSchemaElement->LinkEndChild(pColorFValuesComment);
-      tinyxml2::XMLElement* pColorFValuesTypeElement = schemaDocument.NewElement("xs:simpleType");
-      pColorFValuesTypeElement->SetAttribute("name", "ColorF_Values");
-      pSchemaElement->LinkEndChild(pColorFValuesTypeElement);
-      tinyxml2::XMLElement* pColorFValuesElementA = schemaDocument.NewElement("xs:restriction");
-      pColorFValuesElementA->SetAttribute("base", "xs:string");
-      pColorFValuesTypeElement->LinkEndChild(pColorFValuesElementA);
-      tinyxml2::XMLElement* pColorFValuesElementB = schemaDocument.NewElement("xs:pattern");
-      pColorFValuesElementB->SetAttribute("value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b");
-      pColorFValuesElementA->LinkEndChild(pColorFValuesElementB);
-
-      tinyxml2::XMLComment* pColorFComment = schemaDocument.NewComment("LinearColorF Console Type");
-      pSchemaElement->LinkEndChild(pColorFComment);
-      tinyxml2::XMLElement* pColorFTypeElement = schemaDocument.NewElement("xs:simpleType");
-      pColorFTypeElement->SetAttribute("name", "ColorF_ConsoleType");
-      pSchemaElement->LinkEndChild(pColorFTypeElement);
-      tinyxml2::XMLElement* pColorFUnionElement = schemaDocument.NewElement("xs:union");
-      pColorFUnionElement->SetAttribute("memberTypes", "ColorF_Values Color_Enums");
-      pColorFTypeElement->LinkEndChild(pColorFUnionElement);
-
-      // ColorI.
-      tinyxml2::XMLComment* pColorIValuesComment = schemaDocument.NewComment("ColorI Values");
-      pSchemaElement->LinkEndChild(pColorIValuesComment);
-      tinyxml2::XMLElement* pColorIValuesTypeElement = schemaDocument.NewElement("xs:simpleType");
-      pColorIValuesTypeElement->SetAttribute("name", "ColorI_Values");
-      pSchemaElement->LinkEndChild(pColorIValuesTypeElement);
-      tinyxml2::XMLElement* pColorIValuesElementA = schemaDocument.NewElement("xs:restriction");
-      pColorIValuesElementA->SetAttribute("base", "xs:string");
-      pColorIValuesTypeElement->LinkEndChild(pColorIValuesElementA);
-      tinyxml2::XMLElement* pColorIValuesElementB = schemaDocument.NewElement("xs:pattern");
-      pColorIValuesElementB->SetAttribute("value", "[-]?[0-9]* [-]?[0-9]* [-]?[0-9]* [-]?[0-9]*");
-      pColorIValuesElementA->LinkEndChild(pColorIValuesElementB);
-
-      tinyxml2::XMLComment* pColorIComment = schemaDocument.NewComment("ColorI Console Type");
-      pSchemaElement->LinkEndChild(pColorIComment);
-      tinyxml2::XMLElement* pColorITypeElement = schemaDocument.NewElement("xs:simpleType");
-      pColorITypeElement->SetAttribute("name", "ColorI_ConsoleType");
-      pSchemaElement->LinkEndChild(pColorITypeElement);
-      tinyxml2::XMLElement* pColorIUnionElement = schemaDocument.NewElement("xs:union");
-      pColorIUnionElement->SetAttribute("memberTypes", "ColorI_Values Color_Enums");
-      pColorITypeElement->LinkEndChild(pColorIUnionElement);
-
-      // *************************************************************
-      // Generate engine type elements.
-      // *************************************************************
-
-      // Generate the engine type elements.
-      tinyxml2::XMLComment* tComment = schemaDocument.NewComment("Type Elements");
-      pSchemaElement->LinkEndChild(tComment);
-      for (AbstractClassRep* pType = pRootType; pType != NULL; pType = pType->getNextClass())
-      {
-         // Add type.
-         tinyxml2::XMLElement* pTypeElement = schemaDocument.NewElement("xs:element");
-         pTypeElement->SetAttribute("name", pType->getClassName());
-         dSprintf(buffer, sizeof(buffer), "%s_Type", pType->getClassName());
-         pTypeElement->SetAttribute("type", buffer);
-         pSchemaElement->LinkEndChild(pTypeElement);
-      }
+   // Expand the file-name into the file-path buffer.
+   char filePathBuffer[1024];
+   Con::expandToolScriptFilename(filePathBuffer, sizeof(filePathBuffer), pTamlSchemaFile);
+
+   FileStream stream;
 
 
-      // *************************************************************
-      // Generate the engine complex types.
-      // *************************************************************
-      for (AbstractClassRep* pType = pRootType; pType != NULL; pType = pType->getNextClass())
+   // File opened?
+   /*if ( !stream.open( filePathBuffer, Torque::FS::File::Write ) )
+   {
+   // No, so warn.
+   Con::warnf("Taml::GenerateTamlSchema() - Could not open filename '%s' for write.", filePathBuffer );
+   return false;
+   }*/
+
+   // Create document.
+   tinyxml2::XMLDocument schemaDocument;
+
+   // Add declaration.
+   tinyxml2::XMLDeclaration* schemaDeclaration = schemaDocument.NewDeclaration("xml version=\"1.0\" encoding=\"iso-8859-1\" standalone =\"no\"");
+   schemaDocument.InsertEndChild(schemaDeclaration);
+
+   // Add schema element.
+   tinyxml2::XMLElement* pSchemaElement = schemaDocument.NewElement("xs:schema");
+   pSchemaElement->SetAttribute("xmlns:xs", "http://www.w3.org/2001/XMLSchema");
+   schemaDocument.LinkEndChild(pSchemaElement);
+
+   // Fetch class-rep root.
+   AbstractClassRep* pRootType = AbstractClassRep::getClassList();
+
+   // Fetch SimObject class rep.
+   AbstractClassRep* pSimObjectType = AbstractClassRep::findClassRep("SimObject");
+   // Sanity!
+   AssertFatal(pSimObjectType != NULL, "Taml::GenerateTamlSchema() - Could not find SimObject class rep.");
+
+   // Reset scratch state.
+   char buffer[1024];
+   HashTable<AbstractClassRep*, StringTableEntry> childGroups;
+
+   // *************************************************************
+   // Generate console type elements.
+   // *************************************************************
+
+   // Vector2.
+   tinyxml2::XMLComment* pVector2Comment = schemaDocument.NewComment("Vector2 Console Type");
+   pSchemaElement->LinkEndChild(pVector2Comment);
+   tinyxml2::XMLElement* pVector2TypeElement = schemaDocument.NewElement("xs:simpleType");
+   pVector2TypeElement->SetAttribute("name", "Vector2_ConsoleType");
+   pSchemaElement->LinkEndChild(pVector2TypeElement);
+   tinyxml2::XMLElement* pVector2ElementA = schemaDocument.NewElement("xs:restriction");
+   pVector2ElementA->SetAttribute("base", "xs:string");
+   pVector2TypeElement->LinkEndChild(pVector2ElementA);
+   tinyxml2::XMLElement* pVector2ElementB = schemaDocument.NewElement("xs:pattern");
+   pVector2ElementB->SetAttribute("value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b");
+   pVector2ElementA->LinkEndChild(pVector2ElementB);
+
+   // Point2F.
+   tinyxml2::XMLComment* pPoint2FComment = schemaDocument.NewComment("Point2F Console Type");
+   pSchemaElement->LinkEndChild(pPoint2FComment);
+   tinyxml2::XMLElement* pPoint2FTypeElement = schemaDocument.NewElement("xs:simpleType");
+   pPoint2FTypeElement->SetAttribute("name", "Point2F_ConsoleType");
+   pSchemaElement->LinkEndChild(pPoint2FTypeElement);
+   tinyxml2::XMLElement* pPoint2FElementA = schemaDocument.NewElement("xs:restriction");
+   pPoint2FElementA->SetAttribute("base", "xs:string");
+   pPoint2FTypeElement->LinkEndChild(pPoint2FElementA);
+   tinyxml2::XMLElement* pPoint2FElementB = schemaDocument.NewElement("xs:pattern");
+   pPoint2FElementB->SetAttribute("value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b");
+   pPoint2FElementA->LinkEndChild(pPoint2FElementB);
+
+   // Point2I.
+   tinyxml2::XMLComment* pPoint2IComment = schemaDocument.NewComment("Point2I Console Type");
+   pSchemaElement->LinkEndChild(pPoint2IComment);
+   tinyxml2::XMLElement* pPoint2ITypeElement = schemaDocument.NewElement("xs:simpleType");
+   pPoint2ITypeElement->SetAttribute("name", "Point2I_ConsoleType");
+   pSchemaElement->LinkEndChild(pPoint2ITypeElement);
+   tinyxml2::XMLElement* pPoint2IElementA = schemaDocument.NewElement("xs:restriction");
+   pPoint2IElementA->SetAttribute("base", "xs:string");
+   pPoint2ITypeElement->LinkEndChild(pPoint2IElementA);
+   tinyxml2::XMLElement* pPoint2IElementB = schemaDocument.NewElement("xs:pattern");
+   pPoint2IElementB->SetAttribute("value", "[-]?[0-9]* [-]?[0-9]*");
+   pPoint2IElementA->LinkEndChild(pPoint2IElementB);
+
+   // b2AABB.
+   tinyxml2::XMLComment* pb2AABBComment = schemaDocument.NewComment("b2AABB Console Type");
+   pSchemaElement->LinkEndChild(pb2AABBComment);
+   tinyxml2::XMLElement* pb2AABBTypeElement = schemaDocument.NewElement("xs:simpleType");
+   pb2AABBTypeElement->SetAttribute("name", "b2AABB_ConsoleType");
+   pSchemaElement->LinkEndChild(pb2AABBTypeElement);
+   tinyxml2::XMLElement* pb2AABBElementA = schemaDocument.NewElement("xs:restriction");
+   pb2AABBElementA->SetAttribute("base", "xs:string");
+   pb2AABBTypeElement->LinkEndChild(pb2AABBElementA);
+   tinyxml2::XMLElement* pb2AABBElementB = schemaDocument.NewElement("xs:pattern");
+   pb2AABBElementB->SetAttribute("value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b");
+   pb2AABBElementA->LinkEndChild(pb2AABBElementB);
+
+   // RectI.
+   tinyxml2::XMLComment* pRectIComment = schemaDocument.NewComment("RectI Console Type");
+   pSchemaElement->LinkEndChild(pRectIComment);
+   tinyxml2::XMLElement* pRectITypeElement = schemaDocument.NewElement("xs:simpleType");
+   pRectITypeElement->SetAttribute("name", "RectI_ConsoleType");
+   pSchemaElement->LinkEndChild(pRectITypeElement);
+   tinyxml2::XMLElement* pRectIElementA = schemaDocument.NewElement("xs:restriction");
+   pRectIElementA->SetAttribute("base", "xs:string");
+   pRectITypeElement->LinkEndChild(pRectIElementA);
+   tinyxml2::XMLElement* pRectIElementB = schemaDocument.NewElement("xs:pattern");
+   pRectIElementB->SetAttribute("value", "[-]?[0-9]* [-]?[0-9]* [-]?[0-9]* [-]?[0-9]*");
+   pRectIElementA->LinkEndChild(pRectIElementB);
+
+   // RectF.
+   tinyxml2::XMLComment* pRectFComment = schemaDocument.NewComment("RectF Console Type");
+   pSchemaElement->LinkEndChild(pRectFComment);
+   tinyxml2::XMLElement* pRectFTypeElement = schemaDocument.NewElement("xs:simpleType");
+   pRectFTypeElement->SetAttribute("name", "RectF_ConsoleType");
+   pSchemaElement->LinkEndChild(pRectFTypeElement);
+   tinyxml2::XMLElement* pRectFElementA = schemaDocument.NewElement("xs:restriction");
+   pRectFElementA->SetAttribute("base", "xs:string");
+   pRectFTypeElement->LinkEndChild(pRectFElementA);
+   tinyxml2::XMLElement* pRectFElementB = schemaDocument.NewElement("xs:pattern");
+   pRectFElementB->SetAttribute("value", "(\\b[-]?(b[0-9]+)?\\.)?[0-9]+\\b");
+   pRectFElementA->LinkEndChild(pRectFElementB);
+
+   // AssetId.
+   tinyxml2::XMLComment* pAssetIdComment = schemaDocument.NewComment("AssetId Console Type");
+   pSchemaElement->LinkEndChild(pAssetIdComment);
+   tinyxml2::XMLElement* pAssetIdTypeElement = schemaDocument.NewElement("xs:simpleType");
+   pAssetIdTypeElement->SetAttribute("name", "AssetId_ConsoleType");
+   pSchemaElement->LinkEndChild(pAssetIdTypeElement);
+   tinyxml2::XMLElement* pAssetIdElementA = schemaDocument.NewElement("xs:restriction");
+   pAssetIdElementA->SetAttribute("base", "xs:string");
+   pAssetIdTypeElement->LinkEndChild(pAssetIdElementA);
+   tinyxml2::XMLElement* pAssetIdElementB = schemaDocument.NewElement("xs:pattern");
+   dSprintf(buffer, sizeof(buffer), "(%s)?\\b[a-zA-Z0-9]+\\b%s\\b[a-zA-Z0-9]+\\b", ASSET_ID_FIELD_PREFIX, ASSET_SCOPE_TOKEN);
+   pAssetIdElementB->SetAttribute("value", buffer);
+   pAssetIdElementA->LinkEndChild(pAssetIdElementB);
+
+   // Color Enums.
+   tinyxml2::XMLComment* pColorEnumsComment = schemaDocument.NewComment("Color Enums");
+   pSchemaElement->LinkEndChild(pColorEnumsComment);
+   tinyxml2::XMLElement* pColorEnumsTypeElement = schemaDocument.NewElement("xs:simpleType");
+   pColorEnumsTypeElement->SetAttribute("name", "Color_Enums");
+   pSchemaElement->LinkEndChild(pColorEnumsTypeElement);
+   tinyxml2::XMLElement* pColorEnumsRestrictionElement = schemaDocument.NewElement("xs:restriction");
+   pColorEnumsRestrictionElement->SetAttribute("base", "xs:string");
+   pColorEnumsTypeElement->LinkEndChild(pColorEnumsRestrictionElement);
+   const S32 ColorEnumsCount = StockColor::getCount();
+   for (S32 index = 0; index < ColorEnumsCount; ++index)
+   {
+      // Add enumeration element.
+      tinyxml2::XMLElement* pColorEnumsAttributeEnumerationElement = schemaDocument.NewElement("xs:enumeration");
+      pColorEnumsAttributeEnumerationElement->SetAttribute("value", StockColor::getColorItem(index)->getColorName());
+      pColorEnumsRestrictionElement->LinkEndChild(pColorEnumsAttributeEnumerationElement);
+   }
+
+   // LinearColorF.
+   tinyxml2::XMLComment* pColorFValuesComment = schemaDocument.NewComment("LinearColorF Values");
+   pSchemaElement->LinkEndChild(pColorFValuesComment);
+   tinyxml2::XMLElement* pColorFValuesTypeElement = schemaDocument.NewElement("xs:simpleType");
+   pColorFValuesTypeElement->SetAttribute("name", "ColorF_Values");
+   pSchemaElement->LinkEndChild(pColorFValuesTypeElement);
+   tinyxml2::XMLElement* pColorFValuesElementA = schemaDocument.NewElement("xs:restriction");
+   pColorFValuesElementA->SetAttribute("base", "xs:string");
+   pColorFValuesTypeElement->LinkEndChild(pColorFValuesElementA);
+   tinyxml2::XMLElement* pColorFValuesElementB = schemaDocument.NewElement("xs:pattern");
+   pColorFValuesElementB->SetAttribute("value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b");
+   pColorFValuesElementA->LinkEndChild(pColorFValuesElementB);
+
+   tinyxml2::XMLComment* pColorFComment = schemaDocument.NewComment("LinearColorF Console Type");
+   pSchemaElement->LinkEndChild(pColorFComment);
+   tinyxml2::XMLElement* pColorFTypeElement = schemaDocument.NewElement("xs:simpleType");
+   pColorFTypeElement->SetAttribute("name", "ColorF_ConsoleType");
+   pSchemaElement->LinkEndChild(pColorFTypeElement);
+   tinyxml2::XMLElement* pColorFUnionElement = schemaDocument.NewElement("xs:union");
+   pColorFUnionElement->SetAttribute("memberTypes", "ColorF_Values Color_Enums");
+   pColorFTypeElement->LinkEndChild(pColorFUnionElement);
+
+   // ColorI.
+   tinyxml2::XMLComment* pColorIValuesComment = schemaDocument.NewComment("ColorI Values");
+   pSchemaElement->LinkEndChild(pColorIValuesComment);
+   tinyxml2::XMLElement* pColorIValuesTypeElement = schemaDocument.NewElement("xs:simpleType");
+   pColorIValuesTypeElement->SetAttribute("name", "ColorI_Values");
+   pSchemaElement->LinkEndChild(pColorIValuesTypeElement);
+   tinyxml2::XMLElement* pColorIValuesElementA = schemaDocument.NewElement("xs:restriction");
+   pColorIValuesElementA->SetAttribute("base", "xs:string");
+   pColorIValuesTypeElement->LinkEndChild(pColorIValuesElementA);
+   tinyxml2::XMLElement* pColorIValuesElementB = schemaDocument.NewElement("xs:pattern");
+   pColorIValuesElementB->SetAttribute("value", "[-]?[0-9]* [-]?[0-9]* [-]?[0-9]* [-]?[0-9]*");
+   pColorIValuesElementA->LinkEndChild(pColorIValuesElementB);
+
+   tinyxml2::XMLComment* pColorIComment = schemaDocument.NewComment("ColorI Console Type");
+   pSchemaElement->LinkEndChild(pColorIComment);
+   tinyxml2::XMLElement* pColorITypeElement = schemaDocument.NewElement("xs:simpleType");
+   pColorITypeElement->SetAttribute("name", "ColorI_ConsoleType");
+   pSchemaElement->LinkEndChild(pColorITypeElement);
+   tinyxml2::XMLElement* pColorIUnionElement = schemaDocument.NewElement("xs:union");
+   pColorIUnionElement->SetAttribute("memberTypes", "ColorI_Values Color_Enums");
+   pColorITypeElement->LinkEndChild(pColorIUnionElement);
+
+   // *************************************************************
+   // Generate engine type elements.
+   // *************************************************************
+
+   // Generate the engine type elements.
+   tinyxml2::XMLComment* tComment = schemaDocument.NewComment("Type Elements");
+   pSchemaElement->LinkEndChild(tComment);
+   for (AbstractClassRep* pType = pRootType; pType != NULL; pType = pType->getNextClass())
+   {
+      // Add type.
+      tinyxml2::XMLElement* pTypeElement = schemaDocument.NewElement("xs:element");
+      pTypeElement->SetAttribute("name", pType->getClassName());
+      dSprintf(buffer, sizeof(buffer), "%s_Type", pType->getClassName());
+      pTypeElement->SetAttribute("type", buffer);
+      pSchemaElement->LinkEndChild(pTypeElement);
+   }
+
+   // *************************************************************
+   // Generate the engine complex types.
+   // *************************************************************
+   for (AbstractClassRep* pType = pRootType; pType != NULL; pType = pType->getNextClass())
+   {
+      // Add complex type comment.
+      dSprintf(buffer, sizeof(buffer), " %s Type ", pType->getClassName());
+      tinyxml2::XMLComment* ctComment = schemaDocument.NewComment(buffer);
+      pSchemaElement->LinkEndChild(ctComment);
+
+      // Add complex type.
+      tinyxml2::XMLElement* pComplexTypeElement = schemaDocument.NewElement("xs:complexType");
+      dSprintf(buffer, sizeof(buffer), "%s_Type", pType->getClassName());
+      pComplexTypeElement->SetAttribute("name", buffer);
+      pSchemaElement->LinkEndChild(pComplexTypeElement);
+
+      // Add sequence.
+      tinyxml2::XMLElement* pAllElement = schemaDocument.NewElement("xs:all");
+      pComplexTypeElement->LinkEndChild(pAllElement);
+
+      // Fetch container child class.
+      AbstractClassRep* pContainerChildClass = pType->getContainerChildClass(true);
+
+      // Is the type allowed children?
+      if (pContainerChildClass != NULL)
       {
       {
-         // Add complex type comment.
-         dSprintf(buffer, sizeof(buffer), " %s Type ", pType->getClassName());
-         tinyxml2::XMLComment* ctComment = schemaDocument.NewComment(buffer);
-         pSchemaElement->LinkEndChild(ctComment);
-
-         // Add complex type.
-         tinyxml2::XMLElement* pComplexTypeElement = schemaDocument.NewElement("xs:complexType");
-         dSprintf(buffer, sizeof(buffer), "%s_Type", pType->getClassName());
-         pComplexTypeElement->SetAttribute("name", buffer);
-         pSchemaElement->LinkEndChild(pComplexTypeElement);
-
-         // Add sequence.
-         tinyxml2::XMLElement* pAllElement = schemaDocument.NewElement("xs:all");
-         pComplexTypeElement->LinkEndChild(pAllElement);
-
-         // Fetch container child class.
-         AbstractClassRep* pContainerChildClass = pType->getContainerChildClass(true);
-
-         // Is the type allowed children?
-         if (pContainerChildClass != NULL)
-         {
-            // Yes, so add choice element.
-            tinyxml2::XMLElement* pChoiceElement = schemaDocument.NewElement("xs:choice");
-            pChoiceElement->SetAttribute("minOccurs", 0);
-            pChoiceElement->SetAttribute("maxOccurs", "unbounded");
-            pAllElement->LinkEndChild(pChoiceElement);
+         // Yes, so add choice element.
+         tinyxml2::XMLElement* pChoiceElement = schemaDocument.NewElement("xs:choice");
+         pChoiceElement->SetAttribute("minOccurs", 0);
+         pChoiceElement->SetAttribute("maxOccurs", "unbounded");
+         pAllElement->LinkEndChild(pChoiceElement);
 
 
-            // Find child group.
-            HashTable<AbstractClassRep*, StringTableEntry>::Iterator childGroupItr = childGroups.find(pContainerChildClass);
+         // Find child group.
+         HashTable<AbstractClassRep*, StringTableEntry>::Iterator childGroupItr = childGroups.find(pContainerChildClass);
 
 
-            // Does the group exist?
-            if (childGroupItr == childGroups.end())
-            {
-               // No, so format group name.
-               dSprintf(buffer, sizeof(buffer), "%s_ChildrenTypes", pContainerChildClass->getClassName());
+         // Does the group exist?
+         if (childGroupItr == childGroups.end())
+         {
+            // No, so format group name.
+            dSprintf(buffer, sizeof(buffer), "%s_ChildrenTypes", pContainerChildClass->getClassName());
 
 
-               // Insert into child group hash.
-               childGroupItr = childGroups.insertUnique(pContainerChildClass, StringTable->insert(buffer));
+            // Insert into child group hash.
+            childGroupItr = childGroups.insertUnique(pContainerChildClass, StringTable->insert(buffer));
 
 
-               // Add the group.
-               tinyxml2::XMLElement* pChildrenGroupElement = schemaDocument.NewElement("xs:group");
-               pChildrenGroupElement->SetAttribute("name", buffer);
-               pSchemaElement->LinkEndChild(pChildrenGroupElement);
+            // Add the group.
+            tinyxml2::XMLElement* pChildrenGroupElement = schemaDocument.NewElement("xs:group");
+            pChildrenGroupElement->SetAttribute("name", buffer);
+            pSchemaElement->LinkEndChild(pChildrenGroupElement);
 
 
-               // Add choice element.
-               tinyxml2::XMLElement* pChildreGroupChoiceElement = schemaDocument.NewElement("xs:choice");
-               pChildrenGroupElement->LinkEndChild(pChildreGroupChoiceElement);
+            // Add choice element.
+            tinyxml2::XMLElement* pChildreGroupChoiceElement = schemaDocument.NewElement("xs:choice");
+            pChildrenGroupElement->LinkEndChild(pChildreGroupChoiceElement);
 
 
-               // Add choice members.
-               for (AbstractClassRep* pChoiceType = pRootType; pChoiceType != NULL; pChoiceType = pChoiceType->getNextClass())
-               {
-                  // Skip if not derived from the container child class.
-                  if (!pChoiceType->isClass(pContainerChildClass))
-                     continue;
-
-                  // Add choice member.
-                  tinyxml2::XMLElement* pChildrenMemberElement = schemaDocument.NewElement("xs:element");
-                  pChildrenMemberElement->SetAttribute("name", pChoiceType->getClassName());
-                  dSprintf(buffer, sizeof(buffer), "%s_Type", pChoiceType->getClassName());
-                  pChildrenMemberElement->SetAttribute("type", buffer);
-                  pChildreGroupChoiceElement->LinkEndChild(pChildrenMemberElement);
-               }
+            // Add choice members.
+            for (AbstractClassRep* pChoiceType = pRootType; pChoiceType != NULL; pChoiceType = pChoiceType->getNextClass())
+            {
+               // Skip if not derived from the container child class.
+               if (!pChoiceType->isClass(pContainerChildClass))
+                  continue;
 
 
+               // Add choice member.
+               tinyxml2::XMLElement* pChildrenMemberElement = schemaDocument.NewElement("xs:element");
+               pChildrenMemberElement->SetAttribute("name", pChoiceType->getClassName());
+               dSprintf(buffer, sizeof(buffer), "%s_Type", pChoiceType->getClassName());
+               pChildrenMemberElement->SetAttribute("type", buffer);
+               pChildreGroupChoiceElement->LinkEndChild(pChildrenMemberElement);
             }
             }
 
 
-            // Reference the child group.
-            tinyxml2::XMLElement* pChoiceGroupReferenceElement = schemaDocument.NewElement("xs:group");
-            pChoiceGroupReferenceElement->SetAttribute("ref", childGroupItr->value);
-            pChoiceGroupReferenceElement->SetAttribute("minOccurs", 0);
-            pChoiceElement->LinkEndChild(pChoiceGroupReferenceElement);
          }
          }
 
 
-         // Generate the custom Taml schema.
-         for (AbstractClassRep* pCustomSchemaType = pType; pCustomSchemaType != NULL; pCustomSchemaType = pCustomSchemaType->getParentClass())
-         {
-            // Fetch the types custom TAML schema function.
-            AbstractClassRep::WriteCustomTamlSchema customSchemaFn = pCustomSchemaType->getCustomTamlSchema();
+         // Reference the child group.
+         tinyxml2::XMLElement* pChoiceGroupReferenceElement = schemaDocument.NewElement("xs:group");
+         pChoiceGroupReferenceElement->SetAttribute("ref", childGroupItr->value);
+         pChoiceGroupReferenceElement->SetAttribute("minOccurs", 0);
+         pChoiceElement->LinkEndChild(pChoiceGroupReferenceElement);
+      }
 
 
-            // Skip if no function avilable.
-            if (customSchemaFn == NULL)
-               continue;
+      // Generate the custom Taml schema.
+      for (AbstractClassRep* pCustomSchemaType = pType; pCustomSchemaType != NULL; pCustomSchemaType = pCustomSchemaType->getParentClass())
+      {
+         // Fetch the types custom TAML schema function.
+         AbstractClassRep::WriteCustomTamlSchema customSchemaFn = pCustomSchemaType->getCustomTamlSchema();
 
 
-            // Call schema generation function.
-            customSchemaFn(pType, pAllElement);
-         }
+         // Skip if no function avilable.
+         if (customSchemaFn == NULL)
+            continue;
 
 
-         // Fetch field list.
-         const AbstractClassRep::FieldList& fields = pType->mFieldList;
+         // Call schema generation function.
+         customSchemaFn(pType, pAllElement);
+      }
 
 
-         // Fetch field count.
-         const S32 fieldCount = fields.size();
+      // Fetch field list.
+      const AbstractClassRep::FieldList& fields = pType->mFieldList;
 
 
-         // Generate array attribute groups
-         for (S32 index = 0; index < fieldCount; ++index)
-         {
-            // Fetch field.
-            const AbstractClassRep::Field& field = fields[index];
+      // Fetch field count.
+      const S32 fieldCount = fields.size();
+
+      // Generate array attribute groups
+      for (S32 index = 0; index < fieldCount; ++index)
+      {
+         // Fetch field.
+         const AbstractClassRep::Field& field = fields[index];
 
 
-            if (field.type == AbstractClassRep::StartArrayFieldType)
+         if (field.type == AbstractClassRep::StartArrayFieldType)
+         {
+            // Add the top-level array identifier
+            tinyxml2::XMLElement* pArrayElement = schemaDocument.NewElement("xs:element");
+            dSprintf(buffer, sizeof(buffer), "%s.%s", pType->getClassName(), g_sanitize_schema_element_name(field.pGroupname).c_str());
+            pArrayElement->SetAttribute("name", buffer);
+            pArrayElement->SetAttribute("minOccurs", 0);
+            pAllElement->LinkEndChild(pArrayElement);
+
+            // Inline type specification
+            tinyxml2::XMLElement* pArrayComplexTypeElement = schemaDocument.NewElement("xs:complexType");
+            pArrayElement->LinkEndChild(pArrayComplexTypeElement);
+
+            // Add the actual (repeating) array elements
+            tinyxml2::XMLElement* pInnerArrayElement = schemaDocument.NewElement("xs:element");
+            pInnerArrayElement->SetAttribute("name", g_sanitize_schema_element_name(field.pFieldname).c_str());
+            pInnerArrayElement->SetAttribute("minOccurs", 0);
+            pInnerArrayElement->SetAttribute("maxOccurs", field.elementCount);
+            pArrayComplexTypeElement->LinkEndChild(pInnerArrayElement);
+
+            // Inline type specification
+            tinyxml2::XMLElement* pInnerComplexTypeElement = schemaDocument.NewElement("xs:complexType");
+            pInnerArrayElement->LinkEndChild(pInnerComplexTypeElement);
+
+            // Add a reference to the attribute group for the array
+            tinyxml2::XMLElement* pInnerAttributeGroupElement = schemaDocument.NewElement("xs:attributeGroup");
+            dSprintf(buffer, sizeof(buffer), "%s_%s_Array_Fields", pType->getClassName(), g_sanitize_schema_element_name(field.pFieldname).c_str());
+            pInnerAttributeGroupElement->SetAttribute("ref", buffer);
+            pInnerComplexTypeElement->LinkEndChild(pInnerAttributeGroupElement);
+
+            // Add the attribute group itself
+            tinyxml2::XMLElement* pFieldAttributeGroupElement = schemaDocument.NewElement("xs:attributeGroup");
+            pFieldAttributeGroupElement->SetAttribute("name", buffer);
+            pSchemaElement->LinkEndChild(pFieldAttributeGroupElement);
+
+            // Keep adding fields to attribute group until we hit the end of the array
+            for (; index < fieldCount; ++index)
             {
             {
-               // Add the top-level array identifier
-               tinyxml2::XMLElement* pArrayElement = schemaDocument.NewElement("xs:element");
-               dSprintf(buffer, sizeof(buffer), "%s.%s", pType->getClassName(), g_sanitize_schema_element_name(field.pGroupname).c_str());
-               pArrayElement->SetAttribute("name", buffer);
-               pArrayElement->SetAttribute("minOccurs", 0);
-               pAllElement->LinkEndChild(pArrayElement);
-
-               // Inline type specification
-               tinyxml2::XMLElement* pArrayComplexTypeElement = schemaDocument.NewElement("xs:complexType");
-               pArrayElement->LinkEndChild(pArrayComplexTypeElement);
-
-               // Add the actual (repeating) array elements
-               tinyxml2::XMLElement* pInnerArrayElement = schemaDocument.NewElement("xs:element");
-               pInnerArrayElement->SetAttribute("name", g_sanitize_schema_element_name(field.pFieldname).c_str());
-               pInnerArrayElement->SetAttribute("minOccurs", 0);
-               pInnerArrayElement->SetAttribute("maxOccurs", field.elementCount);
-               pArrayComplexTypeElement->LinkEndChild(pInnerArrayElement);
-
-               // Inline type specification
-               tinyxml2::XMLElement* pInnerComplexTypeElement = schemaDocument.NewElement("xs:complexType");
-               pInnerArrayElement->LinkEndChild(pInnerComplexTypeElement);
-
-               // Add a reference to the attribute group for the array
-               tinyxml2::XMLElement* pInnerAttributeGroupElement = schemaDocument.NewElement("xs:attributeGroup");
-               dSprintf(buffer, sizeof(buffer), "%s_%s_Array_Fields", pType->getClassName(), g_sanitize_schema_element_name(field.pFieldname).c_str());
-               pInnerAttributeGroupElement->SetAttribute("ref", buffer);
-               pInnerComplexTypeElement->LinkEndChild(pInnerAttributeGroupElement);
-
-               // Add the attribute group itself
-               tinyxml2::XMLElement* pFieldAttributeGroupElement = schemaDocument.NewElement("xs:attributeGroup");
-               pFieldAttributeGroupElement->SetAttribute("name", buffer);
-               pSchemaElement->LinkEndChild(pFieldAttributeGroupElement);
-
-               // Keep adding fields to attribute group until we hit the end of the array
-               for (; index < fieldCount; ++index)
+               const AbstractClassRep::Field& array_field = fields[index];
+               if (array_field.type == AbstractClassRep::EndArrayFieldType)
                {
                {
-                  const AbstractClassRep::Field& array_field = fields[index];
-                  if (array_field.type == AbstractClassRep::EndArrayFieldType)
-                  {
-                     break;
-                  }
+                  break;
+               }
                   
                   
-                  tinyxml2::XMLElement* pAttributeElement = g__write_schema_attribute_element(array_field, pType, schemaDocument);
-                  if (pAttributeElement == NULL)
-                  {
-                     continue;
-                  }
-
-                  pFieldAttributeGroupElement->LinkEndChild(pAttributeElement);
+               tinyxml2::XMLElement* pAttributeElement = g__write_schema_attribute_element(array_field, pType, schemaDocument);
+               if (pAttributeElement == NULL)
+               {
+                  continue;
                }
                }
+
+               pFieldAttributeGroupElement->LinkEndChild(pAttributeElement);
             }
             }
          }
          }
+      }
 
 
-         // Generate field attribute group.
-         tinyxml2::XMLElement* pFieldAttributeGroupElement = schemaDocument.NewElement("xs:attributeGroup");
-         dSprintf(buffer, sizeof(buffer), "%s_Fields", pType->getClassName());
-         pFieldAttributeGroupElement->SetAttribute("name", buffer);
-         pSchemaElement->LinkEndChild(pFieldAttributeGroupElement);
+      // Generate field attribute group.
+      tinyxml2::XMLElement* pFieldAttributeGroupElement = schemaDocument.NewElement("xs:attributeGroup");
+      dSprintf(buffer, sizeof(buffer), "%s_Fields", pType->getClassName());
+      pFieldAttributeGroupElement->SetAttribute("name", buffer);
+      pSchemaElement->LinkEndChild(pFieldAttributeGroupElement);
 
 
-         // Iterate static fields (in reverse as most types are organized from the root-fields up).
-         for (S32 index = fieldCount - 1; index > 0; --index)
-         {
-            // Fetch field.
-            const AbstractClassRep::Field& field = fields[index];
+      // Iterate static fields (in reverse as most types are organized from the root-fields up).
+      for (S32 index = fieldCount - 1; index > 0; --index)
+      {
+         // Fetch field.
+         const AbstractClassRep::Field& field = fields[index];
 
 
-            // Skip fields inside arrays
-            if (field.type == AbstractClassRep::EndArrayFieldType)
+         // Skip fields inside arrays
+         if (field.type == AbstractClassRep::EndArrayFieldType)
+         {
+            for (; index > 0; --index)
             {
             {
-               for (; index > 0; --index)
+               if (field.type == AbstractClassRep::StartArrayFieldType)
                {
                {
-                  if (field.type == AbstractClassRep::StartArrayFieldType)
-                  {
-                     break;
-                  }
+                  break;
                }
                }
-               continue;
             }
             }
-
-            tinyxml2::XMLElement* pAttributeElement = g__write_schema_attribute_element(field, pType, schemaDocument);
-            if (pAttributeElement == NULL)
-            {
-               continue;
-            }
-
-            pFieldAttributeGroupElement->LinkEndChild(pAttributeElement);
-         }
-
-         // Is this the SimObject Type?
-         if (pType == pSimObjectType)
-         {
-            // Yes, so add reserved Taml field attributes here...
-
-            // Add Taml "Name" attribute element.
-            tinyxml2::XMLElement* pNameAttributeElement = schemaDocument.NewElement("xs:attribute");
-            pNameAttributeElement->SetAttribute("name", tamlNamedObjectName);
-            pNameAttributeElement->SetAttribute("type", "xs:normalizedString");
-            pFieldAttributeGroupElement->LinkEndChild(pNameAttributeElement);
-
-            // Add Taml "TamlId" attribute element.
-            tinyxml2::XMLElement* pTamlIdAttributeElement = schemaDocument.NewElement("xs:attribute");
-            pTamlIdAttributeElement->SetAttribute("name", tamlRefIdName);
-            pTamlIdAttributeElement->SetAttribute("type", "xs:nonNegativeInteger");
-            pFieldAttributeGroupElement->LinkEndChild(pTamlIdAttributeElement);
-
-            // Add Taml "TamlRefId" attribute element.
-            tinyxml2::XMLElement* pTamlRefIdAttributeElement = schemaDocument.NewElement("xs:attribute");
-            pTamlRefIdAttributeElement->SetAttribute("name", tamlRefToIdName);
-            pTamlRefIdAttributeElement->SetAttribute("type", "xs:nonNegativeInteger");
-            pFieldAttributeGroupElement->LinkEndChild(pTamlRefIdAttributeElement);
+            continue;
          }
          }
 
 
-         // Add attribute group types.
-         for (AbstractClassRep* pAttributeGroupsType = pType; pAttributeGroupsType != NULL; pAttributeGroupsType = pAttributeGroupsType->getParentClass())
+         tinyxml2::XMLElement* pAttributeElement = g__write_schema_attribute_element(field, pType, schemaDocument);
+         if (pAttributeElement == NULL)
          {
          {
-            tinyxml2::XMLElement* pFieldAttributeGroupRefElement = schemaDocument.NewElement("xs:attributeGroup");
-            dSprintf(buffer, sizeof(buffer), "%s_Fields", pAttributeGroupsType->getClassName());
-            pFieldAttributeGroupRefElement->SetAttribute("ref", buffer);
-            pComplexTypeElement->LinkEndChild(pFieldAttributeGroupRefElement);
+            continue;
          }
          }
 
 
-         // Add "any" attribute element (dynamic fields).
-         tinyxml2::XMLElement* pAnyAttributeElement = schemaDocument.NewElement("xs:anyAttribute");
-         pAnyAttributeElement->SetAttribute("processContents", "skip");
-         pComplexTypeElement->LinkEndChild(pAnyAttributeElement);
+         pFieldAttributeGroupElement->LinkEndChild(pAttributeElement);
       }
       }
 
 
-      // Write the schema document.
-      schemaDocument.SaveFile(filePathBuffer);
+      // Is this the SimObject Type?
+      if (pType == pSimObjectType)
+      {
+         // Yes, so add reserved Taml field attributes here...
+
+         // Add Taml "Name" attribute element.
+         tinyxml2::XMLElement* pNameAttributeElement = schemaDocument.NewElement("xs:attribute");
+         pNameAttributeElement->SetAttribute("name", tamlNamedObjectName);
+         pNameAttributeElement->SetAttribute("type", "xs:normalizedString");
+         pFieldAttributeGroupElement->LinkEndChild(pNameAttributeElement);
+
+         // Add Taml "TamlId" attribute element.
+         tinyxml2::XMLElement* pTamlIdAttributeElement = schemaDocument.NewElement("xs:attribute");
+         pTamlIdAttributeElement->SetAttribute("name", tamlRefIdName);
+         pTamlIdAttributeElement->SetAttribute("type", "xs:nonNegativeInteger");
+         pFieldAttributeGroupElement->LinkEndChild(pTamlIdAttributeElement);
+
+         // Add Taml "TamlRefId" attribute element.
+         tinyxml2::XMLElement* pTamlRefIdAttributeElement = schemaDocument.NewElement("xs:attribute");
+         pTamlRefIdAttributeElement->SetAttribute("name", tamlRefToIdName);
+         pTamlRefIdAttributeElement->SetAttribute("type", "xs:nonNegativeInteger");
+         pFieldAttributeGroupElement->LinkEndChild(pTamlRefIdAttributeElement);
+      }
 
 
-      // Close file.
-      stream.close();
+      // Add attribute group types.
+      for (AbstractClassRep* pAttributeGroupsType = pType; pAttributeGroupsType != NULL; pAttributeGroupsType = pAttributeGroupsType->getParentClass())
+      {
+         tinyxml2::XMLElement* pFieldAttributeGroupRefElement = schemaDocument.NewElement("xs:attributeGroup");
+         dSprintf(buffer, sizeof(buffer), "%s_Fields", pAttributeGroupsType->getClassName());
+         pFieldAttributeGroupRefElement->SetAttribute("ref", buffer);
+         pComplexTypeElement->LinkEndChild(pFieldAttributeGroupRefElement);
+      }
 
 
-      return true;
+      // Add "any" attribute element (dynamic fields).
+      tinyxml2::XMLElement* pAnyAttributeElement = schemaDocument.NewElement("xs:anyAttribute");
+      pAnyAttributeElement->SetAttribute("processContents", "skip");
+      pComplexTypeElement->LinkEndChild(pAnyAttributeElement);
    }
    }
 
 
-   //-----------------------------------------------------------------------------
+   // Write the schema document.
+   schemaDocument.SaveFile(filePathBuffer);
 
 
-   void Taml::WriteUnrestrictedCustomTamlSchema(const char* pCustomNodeName, const AbstractClassRep* pClassRep, tinyxml2::XMLElement* pParentElement)
-   {
-      // Sanity!
-      AssertFatal(pCustomNodeName != NULL, "Taml::WriteDefaultCustomTamlSchema() - Node name cannot be NULL.");
-      AssertFatal(pClassRep != NULL, "Taml::WriteDefaultCustomTamlSchema() - ClassRep cannot be NULL.");
-      AssertFatal(pParentElement != NULL, "Taml::WriteDefaultCustomTamlSchema() - Parent Element cannot be NULL.");
-
-      tinyxml2::XMLDocument* doc = pParentElement->GetDocument();
-
-      char buffer[1024];
-
-      // Add custom type element.
-      tinyxml2::XMLElement* pCustomElement = doc->NewElement("xs:element");
-      dSprintf(buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), pCustomNodeName);
-      pCustomElement->SetAttribute("name", buffer);
-      pCustomElement->SetAttribute("minOccurs", 0);
-      pCustomElement->SetAttribute("maxOccurs", 1);
-      pParentElement->LinkEndChild(pCustomElement);
-
-      // Add complex type element.
-      tinyxml2::XMLElement* pComplexTypeElement = doc->NewElement("xs:complexType");
-      pCustomElement->LinkEndChild(pComplexTypeElement);
-
-      // Add choice element.
-      tinyxml2::XMLElement* pChoiceElement = doc->NewElement("xs:choice");
-      pChoiceElement->SetAttribute("minOccurs", 0);
-      pChoiceElement->SetAttribute("maxOccurs", "unbounded");
-      pComplexTypeElement->LinkEndChild(pChoiceElement);
-
-      // Add sequence element.
-      tinyxml2::XMLElement* pSequenceElement = doc->NewElement("xs:sequence");
-      pChoiceElement->LinkEndChild(pSequenceElement);
-
-      // Add "any" element.
-      tinyxml2::XMLElement* pAnyElement = doc->NewElement("xs:any");
-      pAnyElement->SetAttribute("processContents", "skip");
-      pSequenceElement->LinkEndChild(pAnyElement);
-   }
+   // Close file.
+   stream.close();
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+
+void Taml::WriteUnrestrictedCustomTamlSchema(const char* pCustomNodeName, const AbstractClassRep* pClassRep, tinyxml2::XMLElement* pParentElement)
+{
+   // Sanity!
+   AssertFatal(pCustomNodeName != NULL, "Taml::WriteDefaultCustomTamlSchema() - Node name cannot be NULL.");
+   AssertFatal(pClassRep != NULL, "Taml::WriteDefaultCustomTamlSchema() - ClassRep cannot be NULL.");
+   AssertFatal(pParentElement != NULL, "Taml::WriteDefaultCustomTamlSchema() - Parent Element cannot be NULL.");
+
+   tinyxml2::XMLDocument* doc = pParentElement->GetDocument();
+
+   char buffer[1024];
+
+   // Add custom type element.
+   tinyxml2::XMLElement* pCustomElement = doc->NewElement("xs:element");
+   dSprintf(buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), pCustomNodeName);
+   pCustomElement->SetAttribute("name", buffer);
+   pCustomElement->SetAttribute("minOccurs", 0);
+   pCustomElement->SetAttribute("maxOccurs", 1);
+   pParentElement->LinkEndChild(pCustomElement);
+
+   // Add complex type element.
+   tinyxml2::XMLElement* pComplexTypeElement = doc->NewElement("xs:complexType");
+   pCustomElement->LinkEndChild(pComplexTypeElement);
+
+   // Add choice element.
+   tinyxml2::XMLElement* pChoiceElement = doc->NewElement("xs:choice");
+   pChoiceElement->SetAttribute("minOccurs", 0);
+   pChoiceElement->SetAttribute("maxOccurs", "unbounded");
+   pComplexTypeElement->LinkEndChild(pChoiceElement);
+
+   // Add sequence element.
+   tinyxml2::XMLElement* pSequenceElement = doc->NewElement("xs:sequence");
+   pChoiceElement->LinkEndChild(pSequenceElement);
+
+   // Add "any" element.
+   tinyxml2::XMLElement* pAnyElement = doc->NewElement("xs:any");
+   pAnyElement->SetAttribute("processContents", "skip");
+   pSequenceElement->LinkEndChild(pAnyElement);
+}

+ 35 - 42
Engine/source/persistence/taml/taml_ScriptBinding.h

@@ -226,7 +226,7 @@ DefineEngineMethod(Taml, read, SimObject*, (const char* filename), ,    "(filena
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 DefineEngineFunction(TamlWrite, bool, (SimObject* simObject, const char* filename, const char* format, bool compressed), 
 DefineEngineFunction(TamlWrite, bool, (SimObject* simObject, const char* filename, const char* format, bool compressed), 
-                                       ("xml", true),  
+                                       ("xml", false),  
                                         "(object, filename, [format], [compressed]) - Writes an object to a file using Taml.\n"
                                         "(object, filename, [format], [compressed]) - Writes an object to a file using Taml.\n"
                                         "@param object The object to write.\n"
                                         "@param object The object to write.\n"
                                         "@param filename The filename to write to.\n"
                                         "@param filename The filename to write to.\n"
@@ -235,37 +235,30 @@ DefineEngineFunction(TamlWrite, bool, (SimObject* simObject, const char* filenam
                                         "@return Whether the write was successful or not.")
                                         "@return Whether the write was successful or not.")
 {
 {
 
 
-    // Did we find the object?
-    if ( simObject == NULL )
-    {
-        // No, so warn.
-       //Con::warnf( "TamlWrite() - Could not find object '%s' to write to file '%s'.", simObject->getIdString(), filename );
-       Con::warnf( "TamlWrite() - Could not find object to write to file '%s'.", filename );
-        return false;
-    }
-
-    Taml taml;
+   // Did we find the object?
+   if ( simObject == NULL )
+   {
+      // No, so warn.
+      Con::warnf( "TamlWrite() - Could not find object to write to file '%s'.", filename );
+      return false;
+   }
 
 
-    taml.setFormatMode( Taml::getFormatModeEnum(format) );  
+   Taml taml;
 
 
-   // Yes, so is the format mode binary?
-   if ( taml.getFormatMode() == Taml::BinaryFormat )
+   if (filename != NULL && filename[0] != '\0')
    {
    {
-         // Yes, so set binary compression.
-      taml.setBinaryCompression( compressed );
+      taml.setFormatMode(Taml::getFormatModeEnum(format));
+      // Turn-off auto-formatting.
+      taml.setAutoFormat(false);
    }
    }
-   else
+
+   if (taml.getFormatMode() == Taml::BinaryFormat)
    {
    {
-#ifdef TORQUE_DEBUG
-      // No, so warn.
-      Con::warnf( "TamlWrite() - Setting binary compression is only valid for XML formatting." );
-#endif
+      // Yes, so set binary compression.
+      taml.setBinaryCompression(compressed);
    }
    }
 
 
-   // Turn-off auto-formatting.
-   taml.setAutoFormat( false );
-
-    // Write.
+   // Write.
    return taml.write( simObject, filename );
    return taml.write( simObject, filename );
 }
 }
 
 
@@ -277,27 +270,27 @@ DefineEngineFunction(TamlRead, const char*, (const char* filename, const char* f
                                                 "@return (Object) The object read from the file or an empty string if read failed.")
                                                 "@return (Object) The object read from the file or an empty string if read failed.")
 {
 {
 
 
-    // Set the format mode.
-    Taml taml;
+   // Set the format mode.
+   Taml taml;
 
 
-	// Yes, so set it.
-    taml.setFormatMode( Taml::getFormatModeEnum(format) );  
+   // Yes, so set it.
+   taml.setFormatMode( Taml::getFormatModeEnum(format) );  
 
 
-	// Turn-off auto-formatting.
-	taml.setAutoFormat( false );
+   // Turn-off auto-formatting.
+   taml.setAutoFormat( false );
 
 
-    // Read object.
+   // Read object.
    SimObject* pSimObject = taml.read( filename );
    SimObject* pSimObject = taml.read( filename );
 
 
-    // Did we find the object?
-    if ( pSimObject == NULL )
-    {
-        // No, so warn.
-        Con::warnf( "TamlRead() - Could not read object from file '%s'.", filename );
-        return StringTable->EmptyString();
-    }
+   // Did we find the object?
+   if ( pSimObject == NULL )
+   {
+      // No, so warn.
+      Con::warnf( "TamlRead() - Could not read object from file '%s'.", filename );
+      return StringTable->EmptyString();
+   }
 
 
-    return pSimObject->getIdString();
+   return pSimObject->getIdString();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -306,8 +299,8 @@ DefineEngineFunction(GenerateTamlSchema, bool, (), , "() - Generate a TAML schem
                                                 "The schema file is specified using the console variable '" TAML_SCHEMA_VARIABLE "'.\n"
                                                 "The schema file is specified using the console variable '" TAML_SCHEMA_VARIABLE "'.\n"
                                                 "@return Whether the schema file was writtent or not." )
                                                 "@return Whether the schema file was writtent or not." )
 {
 {
-    // Generate the schema.
-    return Taml::generateTamlSchema();
+   // Generate the schema.
+   return Taml::generateTamlSchema();
 }
 }
 
 
 #endif //_TAML_SCRIPTBINDING_H
 #endif //_TAML_SCRIPTBINDING_H