ソースを参照

Merge pull request #1355 from sgrenier/next

next-sgrenier
Steve Grenier 12 年 前
コミット
dba5091d77

+ 2 - 2
gameplay/gameplay.vcxproj

@@ -756,7 +756,7 @@
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\png\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>
       </RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <DisableSpecificWarnings>
       </DisableSpecificWarnings>
     </ClCompile>
@@ -797,7 +797,7 @@
       <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GP_USE_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\png\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <DisableSpecificWarnings>
       </DisableSpecificWarnings>
     </ClCompile>

+ 209 - 172
gameplay/src/Properties.cpp

@@ -44,7 +44,6 @@ Properties::Properties(const Properties& copy)
     rewind();
 }
 
-
 Properties::Properties(Stream* stream)
     : _dirPath(NULL), _parent(NULL)
 {
@@ -196,7 +195,7 @@ void Properties::readProperties(Stream* stream)
                 value = trimWhiteSpace(value);
 
                 // Store name/value pair.
-                _properties[name] = value;
+                _properties.push_back(Property(name, value));
 
                 if (rc != NULL)
                 {
@@ -349,11 +348,11 @@ void Properties::readProperties(Stream* stream)
                             // Store "name value" as a name/value pair, or even just "name".
                             if (value != NULL)
                             {
-                                _properties[name] = value;
+                                _properties.push_back(Property(name, value));
                             }
                             else
                             {
-                                _properties[name] = std::string();
+                                _properties.push_back(Property(name, ""));
                             }
                         }
                     }
@@ -495,15 +494,13 @@ void Properties::mergeWith(Properties* overrides)
     GP_ASSERT(overrides);
 
     // Overwrite or add each property found in child.
-    char* value = new char[255];
     overrides->rewind();
-    const char* name = overrides->getNextProperty(&value);
+    const char* name = overrides->getNextProperty();
     while (name)
     {
-        this->_properties[name] = value;
-        name = overrides->getNextProperty(&value);
+        this->setString(name, overrides->getString());
+        name = overrides->getNextProperty();
     }
-    SAFE_DELETE_ARRAY(value);
     this->_propertiesItr = this->_properties.end();
 
     // Merge all common nested namespaces, add new ones.
@@ -539,7 +536,7 @@ void Properties::mergeWith(Properties* overrides)
     }
 }
 
-const char* Properties::getNextProperty(char** value)
+const char* Properties::getNextProperty()
 {
     if (_propertiesItr == _properties.end())
     {
@@ -552,20 +549,7 @@ const char* Properties::getNextProperty(char** value)
         ++_propertiesItr;
     }
 
-    if (_propertiesItr != _properties.end())
-    {
-        const std::string& name = _propertiesItr->first;
-        if (!name.empty())
-        {
-            if (value)
-            {
-                strcpy(*value, _propertiesItr->second.c_str());
-            }
-            return name.c_str();
-        }
-    }
-
-    return NULL;
+    return _propertiesItr == _properties.end() ? NULL : _propertiesItr->name.c_str();
 }
 
 Properties* Properties::getNextNamespace()
@@ -629,8 +613,16 @@ const char* Properties::getId() const
 
 bool Properties::exists(const char* name) const
 {
-    GP_ASSERT(name);
-    return _properties.find(name) != _properties.end();
+    if (name == NULL)
+        return false;
+
+    for (std::list<Property>::const_iterator itr = _properties.begin(); itr != _properties.end(); ++itr)
+    {
+        if (itr->name == name)
+            return true;
+    }
+
+    return false;
 }
 
 static const bool isStringNumeric(const char* str)
@@ -705,23 +697,52 @@ const char* Properties::getString(const char* name, const char* defaultValue) co
 {
     if (name)
     {
-        std::map<std::string, std::string>::const_iterator itr = _properties.find(name);
-        if (itr != _properties.end())
+        for (std::list<Property>::const_iterator itr = _properties.begin(); itr != _properties.end(); ++itr)
         {
-            return itr->second.c_str();
+            if (itr->name == name)
+                return itr->value.c_str();
         }
     }
     else
     {
         if (_propertiesItr != _properties.end())
         {
-            return _propertiesItr->second.c_str();
+            return _propertiesItr->value.c_str();
         }
     }
 
     return defaultValue;
 }
 
+bool Properties::setString(const char* name, const char* value)
+{
+    if (name)
+    {
+        for (std::list<Property>::iterator itr = _properties.begin(); itr != _properties.end(); ++itr)
+        {
+            if (itr->name == name)
+            {
+                // Update the first property that matches this name
+                itr->value = value ? value : "";
+                return true;
+            }
+        }
+
+        // There is no property with this name, so add one
+        _properties.push_back(Property(name, value ? value : ""));
+    }
+    else
+    {
+        // If there's a current property, set its value
+        if (_propertiesItr == _properties.end())
+            return false;
+
+        _propertiesItr->value = value ? value : "";
+    }
+
+    return true;
+}
+
 bool Properties::getBool(const char* name, bool defaultValue) const
 {
     const char* valueString = getString(name);
@@ -820,168 +841,32 @@ bool Properties::getMatrix(const char* name, Matrix* out) const
 
 bool Properties::getVector2(const char* name, Vector2* out) const
 {
-    GP_ASSERT(out);
-
-    const char* valueString = getString(name);
-    if (valueString)
-    {
-        float x, y;
-        int scanned;
-        scanned = sscanf(valueString, "%f,%f", &x, &y);
-        if (scanned != 2)
-        {
-            GP_ERROR("Error attempting to parse property '%s' as a two-dimensional vector.", name);
-            out->set(0.0f, 0.0f);
-            return false;
-        }
-
-        out->set(x, y);
-        return true;
-    }
-    
-    out->set(0.0f, 0.0f);
-    return false;
+    return parseVector2(getString(name), out);
 }
 
 bool Properties::getVector3(const char* name, Vector3* out) const
 {
-    GP_ASSERT(out);
-
-    const char* valueString = getString(name);
-    if (valueString)
-    {
-        float x, y, z;
-        int scanned;
-        scanned = sscanf(valueString, "%f,%f,%f", &x, &y, &z);
-        if (scanned != 3)
-        {
-            GP_ERROR("Error attempting to parse property '%s' as a three-dimensional vector.", name);
-            out->set(0.0f, 0.0f, 0.0f);
-            return false;
-        }
-
-        out->set(x, y, z);
-        return true;
-    }
-    
-    out->set(0.0f, 0.0f, 0.0f);
-    return false;
+    return parseVector3(getString(name), out);
 }
 
 bool Properties::getVector4(const char* name, Vector4* out) const
 {
-    GP_ASSERT(out);
-
-    const char* valueString = getString(name);
-    if (valueString)
-    {
-        float x, y, z, w;
-        int scanned;
-        scanned = sscanf(valueString, "%f,%f,%f,%f", &x, &y, &z, &w);
-        if (scanned != 4)
-        {
-            GP_ERROR("Error attempting to parse property '%s' as a four-dimensional vector.", name);
-            out->set(0.0f, 0.0f, 0.0f, 0.0f);
-            return false;
-        }
-
-        out->set(x, y, z, w);
-        return true;
-    }
-    
-    out->set(0.0f, 0.0f, 0.0f, 0.0f);
-    return false;
+    return parseVector4(getString(name), out);
 }
 
 bool Properties::getQuaternionFromAxisAngle(const char* name, Quaternion* out) const
 {
-    GP_ASSERT(out);
-
-    const char* valueString = getString(name);
-    if (valueString)
-    {
-        float x, y, z, theta;
-        int scanned;
-        scanned = sscanf(valueString, "%f,%f,%f,%f", &x, &y, &z, &theta);
-        if (scanned != 4)
-        {
-            GP_ERROR("Error attempting to parse property '%s' as an axis-angle rotation.", name);
-            out->set(0.0f, 0.0f, 0.0f, 1.0f);
-            return false;
-        }
-
-        out->set(Vector3(x, y, z), MATH_DEG_TO_RAD(theta));
-        return true;
-    }
-    
-    out->set(0.0f, 0.0f, 0.0f, 1.0f);
-    return false;
+    return parseAxisAngle(getString(name), out);
 }
 
 bool Properties::getColor(const char* name, Vector3* out) const
 {
-    GP_ASSERT(out);
-
-    const char* valueString = getString(name);
-    if (valueString)
-    {
-        if (strlen(valueString) != 7 ||
-            valueString[0] != '#')
-        {
-            // Not a color string.
-            GP_ERROR("Error attempting to parse property '%s' as an RGB color (not specified as a color string).", name);
-            out->set(0.0f, 0.0f, 0.0f);
-            return false;
-        }
-
-        // Read the string into an int as hex.
-        unsigned int color;
-        if (sscanf(valueString+1, "%x", &color) != 1)
-        {
-            GP_ERROR("Error attempting to parse property '%s' as an RGB color.", name);
-            out->set(0.0f, 0.0f, 0.0f);
-            return false;
-        }
-
-        out->set(Vector3::fromColor(color));
-        return true;
-    }
-
-    out->set(0.0f, 0.0f, 0.0f);
-    return false;
+    return parseColor(getString(name), out);
 }
 
 bool Properties::getColor(const char* name, Vector4* out) const
 {
-    GP_ASSERT(out);
-
-    const char* valueString = getString(name);
-    if (valueString)
-    {
-        if (strlen(valueString) != 9 ||
-            valueString[0] != '#')
-        {
-            // Not a color string.
-            GP_WARN("Error attempting to parse property '%s' as an RGBA color (not specified as a color string).", name);
-            out->set(0.0f, 0.0f, 0.0f, 0.0f);
-            return false;
-        }
-
-        // Read the string into an int as hex.
-        unsigned int color;
-        if (sscanf(valueString+1, "%x", &color) != 1)
-        {
-            GP_WARN("Error attempting to parse property '%s' as an RGBA color.", name);
-            out->set(0.0f, 0.0f, 0.0f, 0.0f);
-            return false;
-        }
-
-        out->set(Vector4::fromColor(color));
-        return true;
-    }
-
-    out->set(0.0f, 0.0f, 0.0f, 0.0f);
-    return false;
+    return parseColor(getString(name), out);
 }
 
 bool Properties::getPath(const char* name, std::string* path) const
@@ -1131,4 +1016,156 @@ Properties* getPropertiesFromNamespacePath(Properties* properties, const std::ve
         return properties;
 }
 
+bool Properties::parseVector2(const char* str, Vector2* out)
+{
+    if (str)
+    {
+        float x, y;
+        if (sscanf(str, "%f,%f", &x, &y) == 2)
+        {
+            if (out)
+                out->set(x, y);
+            return true;
+        }
+        else
+        {
+            GP_WARN("Error attempting to parse property as a two-dimensional vector: %s", str);
+        }
+    }
+
+    if (out)
+        out->set(0.0f, 0.0f);
+    return false;
+}
+
+bool Properties::parseVector3(const char* str, Vector3* out)
+{
+    if (str)
+    {
+        float x, y, z;
+        if (sscanf(str, "%f,%f,%f", &x, &y, &z) == 3)
+        {
+            if (out)
+                out->set(x, y, z);
+            return true;
+        }
+        else
+        {
+            GP_WARN("Error attempting to parse property as a three-dimensional vector: %s", str);
+        }
+    }
+
+    if (out)
+        out->set(0.0f, 0.0f, 0.0f);
+    return false;
+}
+
+bool Properties::parseVector4(const char* str, Vector4* out)
+{
+    if (str)
+    {
+        float x, y, z, w;
+        if (sscanf(str, "%f,%f,%f,%f", &x, &y, &z, &w) == 4)
+        {
+            if (out)
+                out->set(x, y, z, w);
+            return true;
+        }
+        else
+        {
+            GP_WARN("Error attempting to parse property as a four-dimensional vector: %s", str);
+        }
+    }
+
+    if (out)
+        out->set(0.0f, 0.0f, 0.0f, 0.0f);
+    return false;
+}
+
+bool Properties::parseAxisAngle(const char* str, Quaternion* out)
+{
+    if (str)
+    {
+        float x, y, z, theta;
+        if (sscanf(str, "%f,%f,%f,%f", &x, &y, &z, &theta) == 4)
+        {
+            if (out)
+                out->set(Vector3(x, y, z), MATH_DEG_TO_RAD(theta));
+            return true;
+        }
+        else
+        {
+            GP_WARN("Error attempting to parse property as an axis-angle rotation: %s", str);
+        }
+    }
+
+    if (out)
+        out->set(0.0f, 0.0f, 0.0f, 1.0f);
+    return false;
+}
+
+bool Properties::parseColor(const char* str, Vector3* out)
+{
+    if (str)
+    {
+        if (strlen(str) == 7 && str[0] == '#')
+        {
+            // Read the string into an int as hex.
+            unsigned int color;
+            if (sscanf(str + 1, "%x", &color) == 1)
+            {
+                if (out)
+                    out->set(Vector3::fromColor(color));
+                return true;
+            }
+            else
+            {
+                // Invalid format
+                GP_WARN("Error attempting to parse property as an RGB color: %s", str);
+            }
+        }
+        else
+        {
+            // Not a color string.
+            GP_WARN("Error attempting to parse property as an RGB color (not specified as a color string): %s", str);
+        }
+    }
+
+    if (out)
+        out->set(0.0f, 0.0f, 0.0f);
+    return false;
+}
+
+bool Properties::parseColor(const char* str, Vector4* out)
+{
+    if (str)
+    {
+        if (strlen(str) == 9 && str[0] == '#')
+        {
+            // Read the string into an int as hex.
+            unsigned int color;
+            if (sscanf(str + 1, "%x", &color) == 1)
+            {
+                if (out)
+                    out->set(Vector4::fromColor(color));
+                return true;
+            }
+            else
+            {
+                // Invalid format
+                GP_WARN("Error attempting to parse property as an RGBA color: %s", str);
+            }
+        }
+        else
+        {
+            // Not a color string.
+            GP_WARN("Error attempting to parse property as an RGBA color (not specified as a color string): %s", str);
+        }
+    }
+
+    if (out)
+        out->set(0.0f, 0.0f, 0.0f, 0.0f);
+    return false;
+}
+
 }

+ 107 - 6
gameplay/src/Properties.h

@@ -163,12 +163,13 @@ public:
     /**
      * Get the name of the next property.
      *
-     * @param value Optional pointer to a const char* to store the value of the next property in.
-     * 
+     * If a valid next property is returned, the value of the property can be
+     * retrieved using any of the get methods in this class, passing NULL for
+     // the property name.
+     *
      * @return The name of the next property, or NULL if there are no properties remaining.
-     * @script{ignore}
      */
-    const char* getNextProperty(char** value = NULL);
+    const char* getNextProperty();
 
     /**
      * Get the next namespace.
@@ -241,6 +242,24 @@ public:
      */
     const char* getString(const char* name = NULL, const char* defaultValue = NULL) const;
 
+    /**
+     * Sets the value of the property with the specified name.
+     *
+     * If there is no property in this namespace with the current name,
+     * one is added. Otherwise, the value of the first property with the
+     * specified name is updated.
+     *
+     * If name is NULL, the value current property (see getNextProperty) is
+     * set, unless there is no current property, in which case false
+     * is returned.
+     *
+     * @param name The name of the property to set.
+     * @param value The property value.
+     *
+     * @return True if the property was set, false otherwise.
+     */
+    bool setString(const char* name, const char* value);
+
     /**
      * Interpret the value of the given property as a boolean.
      *
@@ -395,8 +414,90 @@ public:
      */
     bool getPath(const char* name, std::string* path) const;
 
+    /**
+     * Attempts to parse the specified string as a Vector2 value.
+     *
+     * On error, false is returned and the output is set to all zero values.
+     *
+     * @param str The string to parse.
+     * @param out The value to populate if successful.
+     *
+     * @return True if a valid Vector2 was parsed, false otherwise.
+     */
+    static bool parseVector2(const char* str, Vector2* out);
+
+    /**
+     * Attempts to parse the specified string as a Vector3 value.
+     *
+     * On error, false is returned and the output is set to all zero values.
+     *
+     * @param str The string to parse.
+     * @param out The value to populate if successful.
+     *
+     * @return True if a valid Vector3 was parsed, false otherwise.
+     */
+    static bool parseVector3(const char* str, Vector3* out);
+    
+    /**
+     * Attempts to parse the specified string as a Vector4 value.
+     *
+     * On error, false is returned and the output is set to all zero values.
+     *
+     * @param str The string to parse.
+     * @param out The value to populate if successful.
+     *
+     * @return True if a valid Vector4 was parsed, false otherwise.
+     */
+    static bool parseVector4(const char* str, Vector4* out);
+
+    /**
+     * Attempts to parse the specified string as an axis-angle value.
+     *
+     * The specified string is expected to contain four comma-separated
+     * values, where the first three values represents the axis and the
+     * fourth value represents the angle, in degrees.
+     *
+     * On error, false is returned and the output is set to all zero values.
+     *
+     * @param str The string to parse.
+     * @param out A Quaternion populated with the orientation of the axis-angle, if successful.
+     *
+     * @return True if a valid axis-angle was parsed, false otherwise.
+     */
+    static bool parseAxisAngle(const char* str, Quaternion* out);
+
+    /**
+     * Atempts to parse the specified string as an RGB color value.
+     *
+     * @param str The string to parse.
+     * @param out The value to populate if successful.
+     *
+     * @return True if a valid RGB color was parsed, false otherwise.
+     */
+    static bool parseColor(const char* str, Vector3* out);
+
+    /**
+     * Atempts to parse the specified string as an RGBA color value.
+     *
+     * @param str The string to parse.
+     * @param out The value to populate if successful.
+     *
+     * @return True if a valid RGBA color was parsed, false otherwise.
+     */
+    static bool parseColor(const char* str, Vector4* out);
+
 private:
     
+    /**
+     * Internal structure containing a single property.
+     */
+    struct Property
+    {
+        std::string name;
+        std::string value;
+        Property(const char* name, const char* value) : name(name), value(value) { }
+    };
+
     /**
      * Constructor.
      */
@@ -436,8 +537,8 @@ private:
     std::string _namespace;
     std::string _id;
     std::string _parentID;
-    std::map<std::string, std::string> _properties;
-    std::map<std::string, std::string>::const_iterator _propertiesItr;
+    std::list<Property> _properties;
+    std::list<Property>::iterator _propertiesItr;
     std::vector<Properties*> _namespaces;
     std::vector<Properties*>::const_iterator _namespacesItr;
     std::string* _dirPath;

+ 36 - 30
gameplay/src/SceneLoader.cpp

@@ -176,23 +176,31 @@ void SceneLoader::addSceneAnimation(const char* animationID, const char* targetI
     _animations.push_back(SceneAnimation(animationID, targetID, urlStr));
 }
 
-void SceneLoader::addSceneNodeProperty(SceneNode& sceneNode, SceneNodeProperty::Type type, const char* url, int index)
+void SceneLoader::addSceneNodeProperty(SceneNode& sceneNode, SceneNodeProperty::Type type, const char* value, bool supportsUrl, int index)
 {
-    std::string urlStr = url ? url : "";
+    bool isUrl = false;
 
-    // If there is a non-GPB file that needs to be loaded later, add an 
-    // empty entry to the properties table to signify it.
-    if (urlStr.length() > 0 && urlStr.find(".") != std::string::npos && urlStr.find(".gpb") == std::string::npos && _properties.count(urlStr) == 0)
-        _properties[urlStr] = NULL;
+    std::string str = value ? value : "";
 
-    SceneNodeProperty prop(type, urlStr, index);
+    if (supportsUrl)
+    {
+        // If there is a non-GPB file that needs to be loaded later, add an 
+        // empty entry to the properties table to signify it.
+        if (str.length() > 0 && str.find(".") != std::string::npos && str.find(".gpb") == std::string::npos && _properties.count(str) == 0)
+        {
+            isUrl = true;
+            _properties[str] = NULL;
+        }
+    }
+
+    SceneNodeProperty prop(type, str, index, isUrl);
 
     // Parse for wildcharacter character (only supported on the URL attribute)
     if (type == SceneNodeProperty::URL)
     {
-        if (urlStr.length() > 1 && urlStr.at(urlStr.length()-1) == '*')
+        if (str.length() > 1 && str.at(str.length() - 1) == '*')
         {
-            prop._url = urlStr.substr(0, urlStr.length()-1);
+            prop._value = str.substr(0, str.length() - 1);
             sceneNode._exactMatch = false;
         }
     }
@@ -240,10 +248,10 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
         snp._type == SceneNodeProperty::COLLISION_OBJECT)
     {
         // Check to make sure the referenced properties object was loaded properly.
-        Properties* p = _properties[snp._url];
+        Properties* p = _properties[snp._value];
         if (!p)
         {
-            GP_ERROR("The referenced node data at url '%s' failed to load.", snp._url.c_str());
+            GP_ERROR("The referenced node data at url '%s' failed to load.", snp._value.c_str());
             return;
         }
         p->rewind();
@@ -370,28 +378,26 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
     else
     {
         // Handle scale, rotate and translate.
-        Properties* np = sceneProperties->getNamespace(sceneNode._nodeID);
-
         switch (snp._type)
         {
         case SceneNodeProperty::TRANSLATE:
         {
             Vector3 t;
-            if (np && np->getVector3("translate", &t))
+            if (Properties::parseVector3(snp._value.c_str(), &t))
                 node->translate(t);
             break;
         }
         case SceneNodeProperty::ROTATE:
         {
             Quaternion r;
-            if (np && np->getQuaternionFromAxisAngle("rotate", &r))
+            if (Properties::parseAxisAngle(snp._value.c_str(), &r))
                 node->rotate(r);
             break;
         }
         case SceneNodeProperty::SCALE:
         {
             Vector3 s;
-            if (np && np->getVector3("scale", &s))
+            if (Properties::parseVector3(snp._value.c_str(), &s))
                 node->scale(s);
             break;
         }
@@ -427,7 +433,7 @@ void SceneLoader::applyNodeUrls(SceneNode& sceneNode, Node* parent)
 
         std::string file;
         std::string id;
-        splitURL(snp._url, &file, &id);
+        splitURL(snp._value, &file, &id);
 
         if (file.empty())
         {
@@ -716,11 +722,11 @@ void SceneLoader::parseNode(Properties* ns, SceneNode* parent, const std::string
     {
         if (strcmp(name, "url") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::URL, ns->getString());
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::URL, ns->getString(), true);
         }
         else if (strcmp(name, "audio") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::AUDIO, ns->getString());
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::AUDIO, ns->getString(), true);
         }
         else if (strncmp(name, "material", 8) == 0)
         {
@@ -732,27 +738,27 @@ void SceneLoader::parseNode(Properties* ns, SceneNode* parent, const std::string
                 indexString = indexString.substr(1, indexString.size()-2);
                 materialIndex = (unsigned int)atoi(indexString.c_str());
             }
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::MATERIAL, ns->getString(), materialIndex);
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::MATERIAL, ns->getString(), true, materialIndex);
         }
         else if (strcmp(name, "particle") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::PARTICLE, ns->getString());
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::PARTICLE, ns->getString(), true);
         }
         else if (strcmp(name, "terrain") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::TERRAIN, ns->getString());
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::TERRAIN, ns->getString(), true);
         }
         else if (strcmp(name, "light") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::LIGHT, ns->getString());
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::LIGHT, ns->getString(), true);
         }
         else if (strcmp(name, "camera") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::CAMERA, ns->getString());
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::CAMERA, ns->getString(), true);
         }
         else if (strcmp(name, "collisionObject") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::COLLISION_OBJECT, ns->getString());
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::COLLISION_OBJECT, ns->getString(), true);
         }
         else if (strcmp(name, "rigidBodyModel") == 0)
         {
@@ -764,15 +770,15 @@ void SceneLoader::parseNode(Properties* ns, SceneNode* parent, const std::string
         }
         else if (strcmp(name, "translate") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::TRANSLATE);
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::TRANSLATE, ns->getString());
         }
         else if (strcmp(name, "rotate") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::ROTATE);
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::ROTATE, ns->getString());
         }
         else if (strcmp(name, "scale") == 0)
         {
-            addSceneNodeProperty(sceneNode, SceneNodeProperty::SCALE);
+            addSceneNodeProperty(sceneNode, SceneNodeProperty::SCALE, ns->getString());
         }
         else
         {
@@ -1228,8 +1234,8 @@ SceneLoader::SceneNode::SceneNode()
 {
 }
 
-SceneLoader::SceneNodeProperty::SceneNodeProperty(Type type, const std::string& url, int index)
-    : _type(type), _url(url), _index(index)
+SceneLoader::SceneNodeProperty::SceneNodeProperty(Type type, const std::string& value, int index, bool isUrl)
+    : _type(type), _value(value), _isUrl(isUrl), _index(index)
 {
 }
 

+ 4 - 3
gameplay/src/SceneLoader.h

@@ -60,10 +60,11 @@ private:
             URL = 1024
         };
 
-        SceneNodeProperty(Type type, const std::string& url, int index);
+        SceneNodeProperty(Type type, const std::string& value, int index, bool isUrl);
 
         Type _type;
-        std::string _url;
+        std::string _value;
+        bool _isUrl;
         int _index;
     };
 
@@ -88,7 +89,7 @@ private:
 
     void addSceneAnimation(const char* animationID, const char* targetID, const char* url);
 
-    void addSceneNodeProperty(SceneNode& sceneNode, SceneNodeProperty::Type type, const char* url = NULL, int index = 0);
+    void addSceneNodeProperty(SceneNode& sceneNode, SceneNodeProperty::Type type, const char* value = NULL, bool supportsUrl = false, int index = 0);
 
     void applyNodeProperties(const Properties* sceneProperties, unsigned int typeFlags);
 

+ 2 - 2
samples/browser/sample-browser.vcxproj

@@ -143,7 +143,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>..\..\gameplay\src;..\..\external-deps\lua\include;..\..\external-deps\bullet\include;..\..\external-deps\openal\include\AL;..\..\external-deps\oggvorbis\include;..\..\external-deps\png\include;..\..\external-deps\zlib\include;..\..\external-deps\glew\include</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <DisableSpecificWarnings>
       </DisableSpecificWarnings>
     </ClCompile>
@@ -204,7 +204,7 @@ copy ..\..\gameplay\res\logo_powered_white.png res</Command>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <ShowIncludes>false</ShowIncludes>
       <PreprocessToFile>false</PreprocessToFile>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <DisableSpecificWarnings>
       </DisableSpecificWarnings>
     </ClCompile>

+ 5 - 5
samples/character/sample-character.vcxproj

@@ -138,7 +138,7 @@
       <AdditionalIncludeDirectories>..\..\gameplay\src;..\..\external-deps\bullet\include;..\..\external-deps\lua\include;..\..\external-deps\openal\include\AL;..\..\external-deps\oggvorbis\include;..\..\external-deps\png\include;..\..\external-deps\zlib\include;..\..\external-deps\glew\include</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>
       </RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -156,7 +156,7 @@
       <Outputs>game.config.dummy</Outputs>
     </CustomBuildStep>
     <PreBuildEvent>
-      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /d
+      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /d
 xcopy ..\..\gameplay\res\ui res\ui\* /s /y /d
 
 copy ..\..\gameplay\res\logo_powered_white.png res
@@ -201,7 +201,7 @@ copy .\game.dxt.config .\game.config</Command>
       <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_WINDOWS;GP_USE_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>..\..\gameplay\src;..\..\external-deps\bullet\include;..\..\external-deps\lua\include;..\..\external-deps\openal\include\AL;..\..\external-deps\oggvorbis\include;..\..\external-deps\png\include;..\..\external-deps\zlib\include;..\..\external-deps\glew\include</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -219,7 +219,7 @@ copy .\game.dxt.config .\game.config</Command>
       <Outputs>game.config.dummy</Outputs>
     </CustomBuildStep>
     <PreBuildEvent>
-      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /d
+      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /d
 xcopy ..\..\gameplay\res\ui res\ui\* /s /y /d
 
 copy ..\..\gameplay\res\logo_powered_white.png res
@@ -283,7 +283,7 @@ copy .\game.dxt.config .\game.config</Command>
       <Outputs>game.config.dummy</Outputs>
     </CustomBuildStep>
     <PreBuildEvent>
-      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /d
+      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /d
 xcopy ..\..\gameplay\res\ui res\ui\* /s /y /d
 
 copy ..\..\gameplay\res\logo_powered_white.png res

+ 2 - 2
samples/lua/sample-lua.vcxproj

@@ -143,7 +143,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>..\..\gameplay\src;..\..\external-deps\bullet\include;..\..\external-deps\lua\include;..\..\external-deps\openal\include\AL;..\..\external-deps\oggvorbis\include;..\..\external-deps\png\include;..\..\external-deps\zlib\include;..\..\external-deps\glew\include</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -203,7 +203,7 @@ copy ..\..\gameplay\res\logo_powered_white.png res</Command>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <ShowIncludes>false</ShowIncludes>
       <PreprocessToFile>false</PreprocessToFile>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>

+ 2 - 2
samples/mesh/sample-mesh.vcxproj

@@ -143,7 +143,7 @@
       <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>..\..\gameplay\src;..\..\external-deps\bullet\include;..\..\external-deps\lua\include;..\..\external-deps\openal\include\AL;..\..\external-deps\oggvorbis\include;..\..\external-deps\png\include;..\..\external-deps\zlib\include;..\..\external-deps\glew\include</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -203,7 +203,7 @@ copy ..\..\gameplay\res\logo_powered_white.png res</Command>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <ShowIncludes>false</ShowIncludes>
       <PreprocessToFile>false</PreprocessToFile>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>

+ 2 - 2
samples/particles/sample-particles.vcxproj

@@ -192,7 +192,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>..\..\gameplay\src;..\..\external-deps\bullet\include;..\..\external-deps\lua\include;..\..\external-deps\openal\include\AL;..\..\external-deps\oggvorbis\include;..\..\external-deps\png\include;..\..\external-deps\zlib\include;..\..\external-deps\glew\include</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -252,7 +252,7 @@ copy ..\..\gameplay\res\logo_powered_white.png res</Command>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <ShowIncludes>false</ShowIncludes>
       <PreprocessToFile>false</PreprocessToFile>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>

+ 2 - 2
samples/racer/sample-racer.vcxproj

@@ -149,7 +149,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>..\..\gameplay\src;..\..\external-deps\bullet\include;..\..\external-deps\lua\include;..\..\external-deps\openal\include\AL;..\..\external-deps\oggvorbis\include;..\..\external-deps\png\include;..\..\external-deps\zlib\include;..\..\external-deps\glew\include</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -206,7 +206,7 @@ copy .\game.dxt.config .\game.config</Command>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <ShowIncludes>false</ShowIncludes>
       <PreprocessToFile>false</PreprocessToFile>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>

+ 5 - 5
samples/spaceship/sample-spaceship.vcxproj

@@ -130,7 +130,7 @@
       <Optimization>Disabled</Optimization>
       <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>..\..\gameplay\src;..\..\external-deps\bullet\include;..\..\external-deps\lua\include;..\..\external-deps\openal\include\AL;..\..\external-deps\oggvorbis\include;..\..\external-deps\png\include;..\..\external-deps\zlib\include;..\..\external-deps\glew\include</AdditionalIncludeDirectories>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -151,7 +151,7 @@
       </Outputs>
     </CustomBuildStep>
     <PreBuildEvent>
-      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /u
+      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /u
 xcopy ..\..\gameplay\res\ui res\ui\* /s /y /d
 
 copy ..\..\gameplay\res\logo_powered_white.png res</Command>
@@ -195,7 +195,7 @@ copy ..\..\gameplay\res\logo_powered_white.png res</Command>
       <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_WINDOWS;GP_USE_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>..\..\gameplay\src;..\..\external-deps\bullet\include;..\..\external-deps\lua\include;..\..\external-deps\openal\include\AL;..\..\external-deps\oggvorbis\include;..\..\external-deps\png\include;..\..\external-deps\zlib\include;..\..\external-deps\glew\include</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -216,7 +216,7 @@ copy ..\..\gameplay\res\logo_powered_white.png res</Command>
       </Outputs>
     </CustomBuildStep>
     <PreBuildEvent>
-      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /u
+      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /u
 xcopy ..\..\gameplay\res\ui res\ui\* /s /y /d
 
 copy ..\..\gameplay\res\logo_powered_white.png res</Command>
@@ -284,7 +284,7 @@ copy ..\..\gameplay\res\logo_powered_white.png res</Command>
       </Outputs>
     </CustomBuildStep>
     <PreBuildEvent>
-      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /u
+      <Command>xcopy ..\..\gameplay\res\shaders res\shaders\* /s /y /u
 xcopy ..\..\gameplay\res\ui res\ui\* /s /y /d
 
 copy ..\..\gameplay\res\logo_powered_white.png res</Command>