Просмотр исходного кода

- Added JSON parser. You can now write module and assets using JSON because there's a parser available (it can even update so it works with renaming assets etc).

MelvMay-GG 12 лет назад
Родитель
Сommit
d39be86797

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

@@ -453,6 +453,7 @@
     <ClCompile Include="..\..\source\network\telnetConsole.cc" />
     <ClCompile Include="..\..\source\persistence\taml\binary\tamlBinaryReader.cc" />
     <ClCompile Include="..\..\source\persistence\taml\binary\tamlBinaryWriter.cc" />
+    <ClCompile Include="..\..\source\persistence\taml\json\tamlJSONParser.cc" />
     <ClCompile Include="..\..\source\persistence\taml\json\tamlJSONReader.cc" />
     <ClCompile Include="..\..\source\persistence\taml\json\tamlJSONWriter.cc" />
     <ClCompile Include="..\..\source\persistence\taml\taml.cc" />
@@ -915,6 +916,7 @@
     <ClInclude Include="..\..\source\persistence\rapidjson\include\rapidjson\writer.h" />
     <ClInclude Include="..\..\source\persistence\taml\binary\tamlBinaryReader.h" />
     <ClInclude Include="..\..\source\persistence\taml\binary\tamlBinaryWriter.h" />
+    <ClInclude Include="..\..\source\persistence\taml\json\tamlJSONParser.h" />
     <ClInclude Include="..\..\source\persistence\taml\json\tamlJSONReader.h" />
     <ClInclude Include="..\..\source\persistence\taml\json\tamlJSONWriter.h" />
     <ClInclude Include="..\..\source\persistence\taml\taml.h" />

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

@@ -1326,6 +1326,9 @@
     <ClCompile Include="..\..\source\persistence\taml\xml\tamlXmlWriter.cc">
       <Filter>persistence\taml\xml</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\persistence\taml\json\tamlJSONParser.cc">
+      <Filter>persistence\taml\json</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -2748,6 +2751,9 @@
     <ClInclude Include="..\..\source\persistence\taml\tamlVisitor.h">
       <Filter>persistence\taml</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\persistence\taml\json\tamlJSONParser.h">
+      <Filter>persistence\taml\json</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

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

@@ -460,6 +460,7 @@
     <ClCompile Include="..\..\source\network\telnetConsole.cc" />
     <ClCompile Include="..\..\source\persistence\taml\binary\tamlBinaryReader.cc" />
     <ClCompile Include="..\..\source\persistence\taml\binary\tamlBinaryWriter.cc" />
+    <ClCompile Include="..\..\source\persistence\taml\json\tamlJSONParser.cc" />
     <ClCompile Include="..\..\source\persistence\taml\json\tamlJSONReader.cc" />
     <ClCompile Include="..\..\source\persistence\taml\json\tamlJSONWriter.cc" />
     <ClCompile Include="..\..\source\persistence\taml\taml.cc" />
@@ -921,6 +922,7 @@
     <ClInclude Include="..\..\source\persistence\rapidjson\include\rapidjson\writer.h" />
     <ClInclude Include="..\..\source\persistence\taml\binary\tamlBinaryReader.h" />
     <ClInclude Include="..\..\source\persistence\taml\binary\tamlBinaryWriter.h" />
+    <ClInclude Include="..\..\source\persistence\taml\json\tamlJSONParser.h" />
     <ClInclude Include="..\..\source\persistence\taml\json\tamlJSONReader.h" />
     <ClInclude Include="..\..\source\persistence\taml\json\tamlJSONWriter.h" />
     <ClInclude Include="..\..\source\persistence\taml\taml.h" />

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

@@ -1326,6 +1326,9 @@
     <ClCompile Include="..\..\source\persistence\taml\xml\tamlXmlWriter.cc">
       <Filter>persistence\taml\xml</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\persistence\taml\json\tamlJSONParser.cc">
+      <Filter>persistence\taml\json</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -2745,6 +2748,9 @@
     <ClInclude Include="..\..\source\persistence\taml\tamlParser.h">
       <Filter>persistence\taml</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\persistence\taml\json\tamlJSONParser.h">
+      <Filter>persistence\taml\json</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 6 - 0
engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj

@@ -23,6 +23,7 @@
 		2ABF5C8F16569A0C00BBBF1D /* osxMutex.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2ABF5C8E16569A0C00BBBF1D /* osxMutex.mm */; };
 		2AC4404516B0142B00FC4091 /* ImageFont.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC4404316B0142B00FC4091 /* ImageFont.cc */; };
 		2AC5C7E81667C85700A0D046 /* platformStringTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC5C7E71667C85700A0D046 /* platformStringTests.cc */; };
+		2ACAFD4A1705CF4A0022601C /* tamlJSONParser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACAFD481705CF4A0022601C /* tamlJSONParser.cc */; };
 		2ACF5A2816E52D4B00F838D9 /* SpriteBatchQuery.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF5A2516E52D4B00F838D9 /* SpriteBatchQuery.cc */; };
 		2ACFC0A8166CE1AB00FE7370 /* platformMemoryTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACFC0A7166CE1AB00FE7370 /* platformMemoryTests.cc */; };
 		2AD42140170433FE005BB8AD /* tamlXmlParser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AD42139170433FE005BB8AD /* tamlXmlParser.cc */; };
@@ -492,6 +493,8 @@
 		2AC4404316B0142B00FC4091 /* ImageFont.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFont.cc; sourceTree = "<group>"; };
 		2AC4404416B0142B00FC4091 /* ImageFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFont.h; sourceTree = "<group>"; };
 		2AC5C7E71667C85700A0D046 /* platformStringTests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = platformStringTests.cc; path = ../../../source/testing/tests/platformStringTests.cc; sourceTree = "<group>"; };
+		2ACAFD481705CF4A0022601C /* tamlJSONParser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tamlJSONParser.cc; path = json/tamlJSONParser.cc; sourceTree = "<group>"; };
+		2ACAFD491705CF4A0022601C /* tamlJSONParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlJSONParser.h; path = json/tamlJSONParser.h; sourceTree = "<group>"; };
 		2ACF5A2516E52D4B00F838D9 /* SpriteBatchQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchQuery.cc; sourceTree = "<group>"; };
 		2ACF5A2616E52D4B00F838D9 /* SpriteBatchQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQuery.h; sourceTree = "<group>"; };
 		2ACF5A2716E52D4B00F838D9 /* SpriteBatchQueryResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQueryResult.h; sourceTree = "<group>"; };
@@ -1474,6 +1477,8 @@
 		2AD42137170433EA005BB8AD /* json */ = {
 			isa = PBXGroup;
 			children = (
+				2ACAFD481705CF4A0022601C /* tamlJSONParser.cc */,
+				2ACAFD491705CF4A0022601C /* tamlJSONParser.h */,
 				2AD4214317043408005BB8AD /* tamlJSONReader.cc */,
 				2AD4214417043408005BB8AD /* tamlJSONReader.h */,
 				2AD4214517043408005BB8AD /* tamlJSONWriter.cc */,
@@ -3380,6 +3385,7 @@
 				2AD4214817043408005BB8AD /* tamlJSONWriter.cc in Sources */,
 				2AD4214D17043413005BB8AD /* tamlBinaryReader.cc in Sources */,
 				2AD4214E17043413005BB8AD /* tamlBinaryWriter.cc in Sources */,
+				2ACAFD4A1705CF4A0022601C /* tamlJSONParser.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 6 - 0
engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj

@@ -17,6 +17,7 @@
 		2AB4C1B116DE9F6700B02479 /* PickingSceneController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB4C1AD16DE9F6700B02479 /* PickingSceneController.cc */; };
 		2AB97A2116B66BE50080F940 /* tamlCustom.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB97A1F16B66BE50080F940 /* tamlCustom.cc */; };
 		2AC4404E16B0144500FC4091 /* ImageFont.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC4404C16B0144500FC4091 /* ImageFont.cc */; };
+		2ACAFD471705CF340022601C /* tamlJSONParser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACAFD451705CF340022601C /* tamlJSONParser.cc */; };
 		2ACF5A2C16E52D6A00F838D9 /* SpriteBatchQuery.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF5A2916E52D6A00F838D9 /* SpriteBatchQuery.cc */; };
 		2AD42156170434C2005BB8AD /* tamlBinaryReader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AD42152170434C2005BB8AD /* tamlBinaryReader.cc */; };
 		2AD42157170434C2005BB8AD /* tamlBinaryWriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AD42154170434C2005BB8AD /* tamlBinaryWriter.cc */; };
@@ -512,6 +513,8 @@
 		2AC4404B16B0144500FC4091 /* ImageFont_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFont_ScriptBinding.h; sourceTree = "<group>"; };
 		2AC4404C16B0144500FC4091 /* ImageFont.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFont.cc; sourceTree = "<group>"; };
 		2AC4404D16B0144500FC4091 /* ImageFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFont.h; sourceTree = "<group>"; };
+		2ACAFD451705CF340022601C /* tamlJSONParser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tamlJSONParser.cc; path = json/tamlJSONParser.cc; sourceTree = "<group>"; };
+		2ACAFD461705CF340022601C /* tamlJSONParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tamlJSONParser.h; path = json/tamlJSONParser.h; sourceTree = "<group>"; };
 		2ACF5A2916E52D6A00F838D9 /* SpriteBatchQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchQuery.cc; sourceTree = "<group>"; };
 		2ACF5A2A16E52D6A00F838D9 /* SpriteBatchQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQuery.h; sourceTree = "<group>"; };
 		2ACF5A2B16E52D6A00F838D9 /* SpriteBatchQueryResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQueryResult.h; sourceTree = "<group>"; };
@@ -1514,6 +1517,8 @@
 		2AD42150170434AF005BB8AD /* json */ = {
 			isa = PBXGroup;
 			children = (
+				2ACAFD451705CF340022601C /* tamlJSONParser.cc */,
+				2ACAFD461705CF340022601C /* tamlJSONParser.h */,
 				2AD42162170434F0005BB8AD /* tamlJSONReader.cc */,
 				2AD42163170434F0005BB8AD /* tamlJSONReader.h */,
 				2AD42164170434F0005BB8AD /* tamlJSONWriter.cc */,
@@ -3516,6 +3521,7 @@
 				2AD42161170434E1005BB8AD /* tamlXmlWriter.cc in Sources */,
 				2AD42166170434F0005BB8AD /* tamlJSONReader.cc in Sources */,
 				2AD42167170434F0005BB8AD /* tamlJSONWriter.cc in Sources */,
+				2ACAFD471705CF340022601C /* tamlJSONParser.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 257 - 0
engine/source/persistence/taml/json/tamlJSONParser.cc

@@ -0,0 +1,257 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "persistence/taml/json/TamlJSONParser.h"
+#include "persistence/taml/tamlVisitor.h"
+#include "console/console.h"
+#include "io/fileStream.h"
+#include "memory/frameAllocator.h"
+
+// Debug Profiling.
+#include "debug/profiler.h"
+
+//-----------------------------------------------------------------------------
+
+bool TamlJSONParser::accept( const char* pFilename, TamlVisitor& visitor )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(TamlJSONParser_Accept);
+
+    // Sanity!
+    AssertFatal( pFilename != NULL, "Cannot parse a NULL filename." );
+
+    // Expand the file-path.
+    char filenameBuffer[1024];
+    Con::expandPath( filenameBuffer, sizeof(filenameBuffer), pFilename );
+
+    FileStream stream;
+
+    // File open for read?
+    if ( !stream.open( filenameBuffer, FileStream::Read ) )
+    {
+        // No, so warn.
+        Con::warnf("TamlJSONParser::parse() - Could not open filename '%s' for parse.", filenameBuffer );
+        return false;
+    }
+
+    // Read JSON file.
+    const U32 streamSize = stream.getStreamSize();
+    FrameTemp<char> jsonText( streamSize + 1 );
+    if ( !stream.read( streamSize, jsonText ) )
+    {
+        // Warn!
+        Con::warnf("TamlJSONParser::parse() - Could not load Taml JSON file from stream.");
+        return false;
+    }
+
+    // Create JSON document.
+    rapidjson::Document inputDocument;
+    inputDocument.Parse<0>( jsonText );
+
+    // Close the stream.
+    stream.close();
+
+    // Check the document is valid.
+    if ( inputDocument.GetType() != rapidjson::kObjectType )
+    {
+        // Warn!
+        Con::warnf("TamlJSONParser::parse() - Load Taml JSON file from stream but was invalid.");
+        return false;
+    }
+
+    // Set parsing filename.
+    setParsingFilename( filenameBuffer );
+
+    // Flag document as not dirty.
+    mDocumentDirty = false;
+
+    // Fetch the root.
+    rapidjson::Value::MemberIterator rootItr = inputDocument.MemberBegin();
+
+    // Parse root value.
+    parseType( rootItr, visitor, true );
+
+    // Reset parsing filename.
+    setParsingFilename( StringTable->EmptyString );
+
+    // Finish if the document is not dirty.
+    if ( !mDocumentDirty )
+        return true;
+
+    // Open for write?
+    if ( !stream.open( filenameBuffer, FileStream::Write ) )
+    {
+        // No, so warn.
+        Con::warnf("TamlJSONParser::parse() - Could not open filename '%s' for write.", filenameBuffer );
+        return false;
+    }
+
+    // Create output document.
+    rapidjson::Document outputDocument;
+    outputDocument.AddMember( rootItr->name, rootItr->value, outputDocument.GetAllocator() );
+
+    // Write document to stream.
+    rapidjson::PrettyWriter<FileStream> jsonStreamWriter( stream );
+    outputDocument.Accept( jsonStreamWriter );
+
+    // Close the stream.
+    stream.close();
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+inline bool TamlJSONParser::parseType( rapidjson::Value::MemberIterator& memberItr, TamlVisitor& visitor, const bool isRoot )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(TamlJSONParser_ParseType);
+
+    // Fetch name and value.
+    const rapidjson::Value& typeName = memberItr->name;
+    rapidjson::Value& typeValue = memberItr->value;
+
+    // Create a visitor property state.
+    TamlVisitor::PropertyState propertyState;
+    propertyState.setObjectName( typeName.GetString(), isRoot );
+
+    // Parse field members.
+    for( rapidjson::Value::MemberIterator fieldMemberItr = typeValue.MemberBegin(); fieldMemberItr != typeValue.MemberEnd(); ++fieldMemberItr )
+    {
+        // Fetch value.
+        const rapidjson::Value& fieldName = fieldMemberItr->name;
+        rapidjson::Value& fieldValue = fieldMemberItr->value;
+        
+        // Skip if not a field.
+        if ( fieldValue.IsObject() )
+            continue;
+
+        char valueBuffer[4096];
+        if ( !parseStringValue( valueBuffer, sizeof(valueBuffer), fieldValue, fieldName.GetString() ) )
+        {
+            // Warn.
+            Con::warnf( "TamlJSONParser::parseTyoe() - Could not interpret value for field '%s'", fieldName.GetString() );
+            continue;
+        }
+
+        // Configure property state.
+        propertyState.setProperty( fieldName.GetString(), valueBuffer );
+
+        // Visit this attribute.
+        const bool visitStatus = visitor.visit( *this, propertyState );
+
+        // Was the property value changed?
+        if ( propertyState.getPropertyValueDirty() )
+        {
+            // Yes, so update the attribute.
+            fieldValue.SetString( propertyState.getPropertyValue() );
+
+            // Flag the document as dirty.
+            mDocumentDirty = true;
+        }
+
+        // Finish if requested.
+        if ( !visitStatus )
+            return false;
+    }
+
+    // Finish if only the root is needed.
+    if ( visitor.wantsRootOnly() )
+        return false;
+
+    // Parse children and custom node members.
+    for( rapidjson::Value::MemberIterator objectMemberItr = typeValue.MemberBegin(); objectMemberItr != typeValue.MemberEnd(); ++objectMemberItr )
+    {
+        // Fetch name and value.
+        const rapidjson::Value& objectValue = objectMemberItr->value;
+        
+        // Skip if not an object.
+        if ( !objectValue.IsObject() )
+            continue;
+
+        // Parse the type.
+        if ( !parseType( objectMemberItr, visitor, false ) )
+            return false;
+    }
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+inline bool TamlJSONParser::parseStringValue( char* pBuffer, const S32 bufferSize, const rapidjson::Value& value, const char* pName )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(TamlJSONParser_ParseStringValue);
+
+    // Handle field value appropriately.
+
+    if ( value.IsString() )
+    {
+        dSprintf( pBuffer, bufferSize, "%s", value.GetString() );
+        return true;
+    }
+
+    if ( value.IsNumber() )
+    {
+        if ( value.IsInt() )
+        {
+            dSprintf( pBuffer, bufferSize, "%d", value.GetInt() );
+            return true;
+        }
+
+        if ( value.IsUint() )
+        {
+            dSprintf( pBuffer, bufferSize, "%d", value.GetUint() );
+            return true;
+        }
+
+        if ( value.IsInt64() )
+        {
+            dSprintf( pBuffer, bufferSize, "%d", value.GetInt64() );
+            return true;
+        }
+
+        if ( value.IsUint64() )
+        {
+            dSprintf( pBuffer, bufferSize, "%d", value.GetUint64() );
+            return true;
+        }
+
+        if ( value.IsDouble() )
+        {
+            dSprintf( pBuffer, bufferSize, "%f", value.GetDouble() );
+            return true;
+        }
+    }
+
+    if ( value.IsBool() )
+    {
+        dSprintf( pBuffer, bufferSize, "%d", value.GetBool() );
+        return true;
+    }
+
+    // Failed to get value type.
+    Con::warnf( "Taml: Encountered a field '%s' but its value is an unknown type.", pName );
+    return false;
+}
+

+ 55 - 0
engine/source/persistence/taml/json/tamlJSONParser.h

@@ -0,0 +1,55 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _TAML_JSONPARSER_H_
+#define _TAML_JSONPARSER_H_
+
+#ifndef _TAML_PARSER_H_
+#include "persistence/taml/tamlParser.h"
+#endif
+
+/// RapidJson.
+#include "rapidjson/document.h"
+#include "rapidjson/prettywriter.h"
+
+//-----------------------------------------------------------------------------
+
+class TamlJSONParser : public TamlParser
+{
+public:
+    TamlJSONParser() {}
+    virtual ~TamlJSONParser() {}
+
+    /// Whether the parser can change a property or not.
+    virtual bool canChangeProperty( void ) { return true; }
+
+    /// Accept visitor.
+    virtual bool accept( const char* pFilename, TamlVisitor& visitor );
+
+private:
+    inline bool parseType( rapidjson::Value::MemberIterator& memberItr, TamlVisitor& visitor, const bool isRoot );
+    inline bool parseStringValue( char* pBuffer, const S32 bufferSize, const rapidjson::Value& value, const char* pName );
+
+    bool mDocumentDirty;
+};
+
+#endif // _TAML_JSONPARSER_H_

+ 27 - 20
engine/source/persistence/taml/json/tamlJSONReader.cc

@@ -39,17 +39,24 @@ SimObject* TamlJSONReader::read( FileStream& stream )
     // Read JSON file.
     const U32 streamSize = stream.getStreamSize();
     FrameTemp<char> jsonText( streamSize + 1 );
-    jsonText.getObjectCount();
     if ( !stream.read( streamSize, jsonText ) )
     {
         // Warn!
-        Con::warnf("Taml: Could not load Taml JSON file from stream.");
+        Con::warnf("TamlJSONReader::read() -  Could not load Taml JSON file from stream.");
         return NULL;
     }
 
     // Create JSON document.
     rapidjson::Document document;
     document.Parse<0>( jsonText );
+
+    // Check the document is valid.
+    if ( document.GetType() != rapidjson::kObjectType )
+    {
+        // Warn!
+        Con::warnf("TamlJSONReader::read() -  Load Taml JSON file from stream but was invalid.");
+        return NULL;
+    }
     
     // Parse root value.
     SimObject* pSimObject = parseType( document.MemberBegin() );
@@ -86,7 +93,7 @@ SimObject* TamlJSONReader::parseType( const rapidjson::Value::ConstMemberIterato
     if ( !typeValue.IsObject() )
     {
         // No, so warn.
-        Con::warnf( "Taml: Cannot process type '%s' as it is not an object.", typeName.GetString() );
+        Con::warnf( "TamlJSONReader::parseType() -  Cannot process type '%s' as it is not an object.", typeName.GetString() );
         return NULL;
     }
 
@@ -106,7 +113,7 @@ SimObject* TamlJSONReader::parseType( const rapidjson::Value::ConstMemberIterato
         if ( referenceItr == mObjectReferenceMap.end() )
         {
             // No, so warn.
-            Con::warnf( "Taml: Could not find a reference Id of '%d'", tamlRefToId );
+            Con::warnf( "TamlJSONReader::parseType() -  Could not find a reference Id of '%d'", tamlRefToId );
             return NULL;
         }
 
@@ -242,7 +249,7 @@ inline void TamlJSONReader::parseField( rapidjson::Value::ConstMemberIterator& m
     if ( !parseStringValue( valueBuffer, sizeof(valueBuffer), value, fieldName ) )
     {
         // Warn.
-        Con::warnf( "Taml: Could not interpret value for field '%s'", fieldName );
+        Con::warnf( "Taml::parseField() Could not interpret value for field '%s'", fieldName );
         return;
     }
 
@@ -267,7 +274,7 @@ inline void TamlJSONReader::parseChild( rapidjson::Value::ConstMemberIterator& m
     if ( pChildren == NULL )
     {
         // No, so warn.
-        Con::warnf("Taml: Child member '%s' found under parent '%s' but object cannot have children.",
+        Con::warnf("Taml::parseChild() - Child member '%s' found under parent '%s' but object cannot have children.",
             name.GetString(),
             pSimObject->getClassName() );
 
@@ -291,7 +298,7 @@ inline void TamlJSONReader::parseChild( rapidjson::Value::ConstMemberIterator& m
         if ( !pChildSimObject->getClassRep()->isClass( pContainerChildClass ) )
         {
             // No, so warn.
-            Con::warnf("Taml: Child element '%s' found under parent '%s' but object is restricted to children of type '%s'.",
+            Con::warnf("Taml::parseChild() - Child element '%s' found under parent '%s' but object is restricted to children of type '%s'.",
                 pChildSimObject->getClassName(),
                 pSimObject->getClassName(),
                 pContainerChildClass->getClassName() );
@@ -340,7 +347,7 @@ inline void TamlJSONReader::parseCustom( rapidjson::Value::ConstMemberIterator&
         if ( !customValue.IsObject() && !customValue.IsArray() )
         {
             // No, so warn.
-            Con::warnf( "Taml: Cannot process custom node name '%s' member as child value is not an object or array.", pCustomNodeName );
+            Con::warnf( "Taml::parseCustom() - Cannot process custom node name '%s' member as child value is not an object or array.", pCustomNodeName );
             return;
         }
 
@@ -398,13 +405,13 @@ inline void TamlJSONReader::parseCustomNode( rapidjson::Value::ConstMemberIterat
             else
             {
                 // Warn.
-                Con::warnf( "Taml: Encountered text in the custom node '%s' but could not interpret the value.", nodeName );
+                Con::warnf( "Taml::parseCustomNode() - Encountered text in the custom node '%s' but could not interpret the value.", nodeName );
             }
         }
         else
         {
             // No, so warn.
-            Con::warnf( "Taml: Encountered text in the custom node '%s' but more than a single element was found in the array.", nodeName );
+            Con::warnf( "Taml::parseCustomNode() - Encountered text in the custom node '%s' but more than a single element was found in the array.", nodeName );
         }
 
         return;
@@ -438,12 +445,12 @@ inline void TamlJSONReader::parseCustomNode( rapidjson::Value::ConstMemberIterat
                 }
 
                 // Warn.
-                Con::warnf( "Taml: Encountered text in the custom node '%s' but could not interpret the value.", fieldName );
+                Con::warnf( "Taml::parseCustomNode() - Encountered text in the custom node '%s' but could not interpret the value.", fieldName );
                 return;
             }
 
             // No, so warn.
-            Con::warnf( "Taml: Encountered text in the custom node '%s' but more than a single element was found in the array.", fieldName );
+            Con::warnf( "Taml::parseCustomNode() - Encountered text in the custom node '%s' but more than a single element was found in the array.", fieldName );
             return;
         }
 
@@ -465,7 +472,7 @@ inline void TamlJSONReader::parseCustomNode( rapidjson::Value::ConstMemberIterat
         if ( !parseStringValue( valueBuffer, sizeof(valueBuffer), childValue, childName.GetString() ) )
         {
             // Warn.
-            Con::warnf( "Taml: Could not interpret value for field '%s'", fieldName );
+            Con::warnf( "Taml::parseCustomNode() - Could not interpret value for field '%s'", fieldName );
             continue;
         }
         
@@ -497,7 +504,7 @@ inline StringTableEntry TamlJSONReader::getDemangledName( const char* pMangledNa
 inline bool TamlJSONReader::parseStringValue( char* pBuffer, const S32 bufferSize, const rapidjson::Value& value, const char* pName )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(TTamlJSONReader_ParseStringValue);
+    PROFILE_SCOPE(TamlJSONReader_ParseStringValue);
 
     // Handle field value appropriately.
 
@@ -562,7 +569,7 @@ inline U32 TamlJSONReader::getTamlRefId( const rapidjson::Value& value )
     if ( !value.IsObject()  )
     {
         // No, so warn.
-        Con::warnf( "Taml: Cannot get '%s' member as value is not an object.", tamlRefIdName );
+        Con::warnf( "Taml::getTamlRefId() - Cannot get '%s' member as value is not an object.", tamlRefIdName );
         return 0;
     }
 
@@ -580,7 +587,7 @@ inline U32 TamlJSONReader::getTamlRefId( const rapidjson::Value& value )
         if ( !memberItr->value.IsInt() )
         {
             // No, so warn.
-            Con::warnf( "Taml: Found '%s' member but it is not an integer.", tamlRefIdName );
+            Con::warnf( "Taml::getTamlRefId() - Found '%s' member but it is not an integer.", tamlRefIdName );
             return 0;
         }
 
@@ -603,7 +610,7 @@ inline U32 TamlJSONReader::getTamlRefToId( const rapidjson::Value& value )
     if ( !value.IsObject()  )
     {
         // No, so warn.
-        Con::warnf( "Taml: Cannot get '%s' member as value is not an object.", tamlRefToIdName );
+        Con::warnf( "Taml::getTamlRefToId() - Cannot get '%s' member as value is not an object.", tamlRefToIdName );
         return 0;
     }
 
@@ -621,7 +628,7 @@ inline U32 TamlJSONReader::getTamlRefToId( const rapidjson::Value& value )
         if ( !memberItr->value.IsInt() )
         {
             // No, so warn.
-            Con::warnf( "Taml: Found '%s' member but it is not an integer.", tamlRefToIdName );
+            Con::warnf( "Taml::getTamlRefToId() - Found '%s' member but it is not an integer.", tamlRefToIdName );
             return 0;
         }
 
@@ -644,7 +651,7 @@ inline const char* TamlJSONReader::getTamlObjectName( const rapidjson::Value& va
     if ( !value.IsObject()  )
     {
         // No, so warn.
-        Con::warnf( "Taml: Cannot get '%s' member as value is not an object.", tamlNamedObjectName );
+        Con::warnf( "Taml::getTamlObjectName() - Cannot get '%s' member as value is not an object.", tamlNamedObjectName );
         return 0;
     }
 
@@ -662,7 +669,7 @@ inline const char* TamlJSONReader::getTamlObjectName( const rapidjson::Value& va
         if ( !memberItr->value.IsString() )
         {
             // No, so warn.
-            Con::warnf( "Taml: Found '%s' member but it is not a string.", tamlNamedObjectName );
+            Con::warnf( "Taml::getTamlObjectName() - Found '%s' member but it is not a string.", tamlNamedObjectName );
             return NULL;
         }
 

+ 30 - 2
engine/source/persistence/taml/taml.cc

@@ -50,6 +50,10 @@
 #include "persistence/taml/json/tamlJSONReader.h"
 #endif
 
+#ifndef _TAML_JSONPARSER_H_
+#include "persistence/taml/json/tamlJSONParser.h"
+#endif
+
 #ifndef _FRAMEALLOCATOR_H_
 #include "memory/frameAllocator.h"
 #endif
@@ -428,11 +432,35 @@ bool Taml::parse( const char* pFilename, TamlVisitor& visitor )
         case XmlFormat:
         {
             // Parse with the visitor.
-            TamlXmlParser xmlParser;
-            return xmlParser.accept( pFilename, visitor );            
+            TamlXmlParser 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;
+            }
+
+            return parser.accept( pFilename, visitor );            
         }
 
         case JSONFormat:
+        {
+            // Parse with the visitor.
+            TamlJSONParser 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;
+            }
+
+            return parser.accept( pFilename, visitor );            
+        }
+
         case BinaryFormat:
         default:
             break;

+ 3 - 0
engine/source/persistence/taml/tamlParser.h

@@ -39,6 +39,9 @@ public:
     {}
     virtual ~TamlParser() {}
 
+    /// Whether the parser can change a property or not.
+    virtual bool canChangeProperty( void ) = 0;
+
     /// Accept visitor.
     virtual bool accept( const char* pFilename, TamlVisitor& visitor ) = 0;
 

+ 2 - 2
engine/source/persistence/taml/xml/tamlXmlParser.cc

@@ -104,7 +104,7 @@ bool TamlXmlParser::accept( const char* pFilename, TamlVisitor& visitor )
 
 //-----------------------------------------------------------------------------
 
-bool TamlXmlParser::parseElement( TiXmlElement* pXmlElement, TamlVisitor& visitor )
+inline bool TamlXmlParser::parseElement( TiXmlElement* pXmlElement, TamlVisitor& visitor )
 {
     // Debug Profiling.
     PROFILE_SCOPE(TamlXmlParser_ParseElement);
@@ -137,7 +137,7 @@ bool TamlXmlParser::parseElement( TiXmlElement* pXmlElement, TamlVisitor& visito
 
 //-----------------------------------------------------------------------------
 
-bool TamlXmlParser::parseAttributes( TiXmlElement* pXmlElement, TamlVisitor& visitor )
+inline bool TamlXmlParser::parseAttributes( TiXmlElement* pXmlElement, TamlVisitor& visitor )
 {
     // Debug Profiling.
     PROFILE_SCOPE(TamlXmlParser_ParseAttribute);

+ 5 - 3
engine/source/persistence/taml/xml/tamlXmlParser.h

@@ -31,7 +31,6 @@
 #include "persistence/tinyXML/tinyxml.h"
 #endif
 
-
 //-----------------------------------------------------------------------------
 
 class TamlXmlParser : public TamlParser
@@ -40,12 +39,15 @@ public:
     TamlXmlParser() {}
     virtual ~TamlXmlParser() {}
 
+    /// Whether the parser can change a property or not.
+    virtual bool canChangeProperty( void ) { return true; }
+
     /// Accept visitor.
     virtual bool accept( const char* pFilename, TamlVisitor& visitor );
 
 private:
-    bool parseElement( TiXmlElement* pXmlElement, TamlVisitor& visitor );
-    bool parseAttributes( TiXmlElement* pXmlElement, TamlVisitor& visitor );
+    inline bool parseElement( TiXmlElement* pXmlElement, TamlVisitor& visitor );
+    inline bool parseAttributes( TiXmlElement* pXmlElement, TamlVisitor& visitor );
 
     bool mDocumentDirty;
 };

+ 4 - 0
modules/ToyAssets/1/module.taml

@@ -7,4 +7,8 @@
 			Path="assets"
 			Extension="asset.taml"
 			Recurse="true"/>
+		<DeclaredAssets
+			Path="assets"
+			Extension="asset.json"
+			Recurse="true"/>			
 </ModuleDefinition>