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

Added support for inline properties within the scene file.
Removed support for wildcards in node urls in the scene file.
Adds support for namespaces to end on the same line they begin on in Properties.cpp.

Chris Culy 13 лет назад
Родитель
Сommit
5da5cd58f5
3 измененных файлов с 194 добавлено и 228 удалено
  1. 75 0
      gameplay/src/Properties.cpp
  2. 109 216
      gameplay/src/SceneLoader.cpp
  3. 10 12
      gameplay/src/SceneLoader.h

+ 75 - 0
gameplay/src/Properties.cpp

@@ -145,6 +145,7 @@ void Properties::readProperties(FILE* file)
     char* parentID;
     char* rc;
     char* rcc;
+    char* rccc;
 
     while (true)
     {
@@ -205,6 +206,9 @@ void Properties::readProperties(FILE* file)
             {
                 parentID = NULL;
 
+                // Get the last character on the line (ignoring whitespace).
+                const char* lineEnd = trimWhiteSpace(line) + (strlen(trimWhiteSpace(line)) - 1);
+
                 // This line might begin or end a namespace,
                 // or it might be a key/value pair without '='.
 
@@ -213,6 +217,9 @@ void Properties::readProperties(FILE* file)
 
                 // Check for inheritance: ':'
                 rcc = strchr(line, ':');
+
+                // Check for '}' on same line.
+                rccc = strchr(line, '}');
             
                 // Get the name of the namespace.
                 name = strtok(line, " \t\n{");
@@ -231,6 +238,8 @@ void Properties::readProperties(FILE* file)
                 // Get its ID if it has one.
                 value = strtok(NULL, ":{");
                 value = trimWhiteSpace(value);
+
+                // Get its parent ID if it has one.
                 if (rcc != NULL)
                 {
                     parentID = strtok(NULL, "{");
@@ -239,18 +248,84 @@ void Properties::readProperties(FILE* file)
 
                 if (value != NULL && value[0] == '{')
                 {
+                    // If the namespace ends on this line, seek back to right before the '}' character.
+                    if (rccc && rccc == lineEnd)
+                    {
+                        if (fseek(file, -1, SEEK_CUR) != 0)
+                        {
+                            GP_ERROR("Failed to seek back to before a '}' character in properties file.");
+                            return;
+                        }
+                        while (fgetc(file) != '}')
+                        {
+                            if (fseek(file, -2, SEEK_CUR) != 0)
+                            {
+                                GP_ERROR("Failed to seek back to before a '}' character in properties file.");
+                                return;
+                            }
+                        }
+                        if (fseek(file, -1, SEEK_CUR) != 0)
+                        {
+                            GP_ERROR("Failed to seek back to before a '}' character in properties file.");
+                            return;
+                        }
+                    }
+
                     // New namespace without an ID.
                     Properties* space = new Properties(file, name, NULL, parentID);
                     _namespaces.push_back(space);
+
+                    // If the namespace ends on this line, seek to right after the '}' character.
+                    if (rccc && rccc == lineEnd)
+                    {
+                        if (fseek(file, 1, SEEK_CUR) != 0)
+                        {
+                            GP_ERROR("Failed to seek to immediately after a '}' character in properties file.");
+                            return;
+                        }
+                    }
                 }
                 else
                 {
                     // If '{' appears on the same line.
                     if (rc != NULL)
                     {
+                        // If the namespace ends on this line, seek back to right before the '}' character.
+                        if (rccc && rccc == lineEnd)
+                        {
+                            if (fseek(file, -1, SEEK_CUR) != 0)
+                            {
+                                GP_ERROR("Failed to seek back to before a '}' character in properties file.");
+                                return;
+                            }
+                            while (fgetc(file) != '}')
+                            {
+                                if (fseek(file, -2, SEEK_CUR) != 0)
+                                {
+                                    GP_ERROR("Failed to seek back to before a '}' character in properties file.");
+                                    return;
+                                }
+                            }
+                            if (fseek(file, -1, SEEK_CUR) != 0)
+                            {
+                                GP_ERROR("Failed to seek back to before a '}' character in properties file.");
+                                return;
+                            }
+                        }
+
                         // Create new namespace.
                         Properties* space = new Properties(file, name, value, parentID);
                         _namespaces.push_back(space);
+
+                        // If the namespace ends on this line, seek to right after the '}' character.
+                        if (rccc && rccc == lineEnd)
+                        {
+                            if (fseek(file, 1, SEEK_CUR) != 0)
+                            {
+                                GP_ERROR("Failed to seek to immediately after a '}' character in properties file.");
+                                return;
+                            }
+                        }
                     }
                     else
                     {

+ 109 - 216
gameplay/src/SceneLoader.cpp

@@ -6,13 +6,19 @@
 namespace gameplay
 {
 
-std::map<std::string, Properties*> SceneLoader::_propertiesFromFile;
+std::map<std::string, Properties*> SceneLoader::_properties;
 std::vector<SceneLoader::SceneAnimation> SceneLoader::_animations;
 std::vector<SceneLoader::SceneNode> SceneLoader::_sceneNodes;
+std::string SceneLoader::_gpbPath;
 std::string SceneLoader::_path;
 
 Scene* SceneLoader::load(const char* url)
 {
+    // Get the file part of the url that we are loading the scene from.
+    std::string urlStr = url ? url : "";
+    std::string id;
+    splitURL(urlStr, &_path, &id);
+
     // Load the scene properties from file.
     Properties* properties = Properties::create(url);
     if (properties == NULL)
@@ -31,9 +37,9 @@ Scene* SceneLoader::load(const char* url)
     }
 
     // Get the path to the main GPB.
-    _path = sceneProperties->getString("path");
+    _gpbPath = sceneProperties->getString("path");
 
-    // Build the node URL/property and animation reference tables and load the referenced files.
+    // Build the node URL/property and animation reference tables and load the referenced files/store the inline properties objects.
     buildReferenceTables(sceneProperties);
     loadReferencedFiles();
 
@@ -83,17 +89,18 @@ Scene* SceneLoader::load(const char* url)
         loadPhysics(physics, scene);
 
     // Clean up all loaded properties objects.
-    std::map<std::string, Properties*>::iterator iter = _propertiesFromFile.begin();
-    for (; iter != _propertiesFromFile.end(); iter++)
+    std::map<std::string, Properties*>::iterator iter = _properties.begin();
+    for (; iter != _properties.end(); iter++)
     {
-        SAFE_DELETE(iter->second);
+        if (iter->first.find(_path) == iter->first.npos)
+            SAFE_DELETE(iter->second);
     }
 
     // Clean up the .scene file's properties object.
     SAFE_DELETE(properties);
 
     // Clear all temporary data stores.
-    _propertiesFromFile.clear();
+    _properties.clear();
     _animations.clear();
     _sceneNodes.clear();
 
@@ -102,46 +109,28 @@ Scene* SceneLoader::load(const char* url)
 
 void SceneLoader::addSceneAnimation(const char* animationID, const char* targetID, const char* url)
 {
-    // Calculate the file and id from the given url.
-    std::string file;
-    std::string id;
-    splitURL(url, &file, &id);
+    std::string urlStr = url ? url : "";
 
     // If there is a file that needs to be loaded later, add an 
     // empty entry to the properties table to signify it.
-    if (file.length() > 0 && _propertiesFromFile.count(file) == 0)
-        _propertiesFromFile[file] = NULL;
+    if (urlStr.length() > 0 && _properties.count(urlStr) == 0)
+        _properties[urlStr] = NULL;
 
     // Add the animation to the list of animations to be resolved later.
-    _animations.push_back(SceneAnimation(animationID, targetID, file, id));
+    _animations.push_back(SceneAnimation(animationID, targetID, urlStr));
 }
 
 void SceneLoader::addSceneNodeProperty(SceneNode& sceneNode, SceneNodeProperty::Type type, const char* url, int index)
 {
-    // Calculate the file and id from the given url.
-    std::string file;
-    std::string id;
-    splitURL(url, &file, &id);
+    std::string urlStr = url ? url : "";
 
     // 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 (file.length() > 0 && file.find(".gpb") == file.npos && _propertiesFromFile.count(file) == 0)
-        _propertiesFromFile[file] = NULL;
-
-    SceneNodeProperty prop(type, file, id, index);
-
-    // Parse for wildcharacter character (only supported on the URL attribute)
-    if (type == SceneNodeProperty::URL)
-    {
-        if (id.length() > 1 && id.at(id.length()-1) == '*')
-        {
-            prop._id = id.substr(0, id.length()-1);
-            sceneNode._exactMatch = false;
-        }
-    }
+    if (urlStr.length() > 0 && urlStr.find(".gpb") == urlStr.npos && _properties.count(urlStr) == 0)
+        _properties[urlStr] = NULL;
 
     // Add the node property to the list of node properties to be resolved later.
-    sceneNode._properties.push_back(prop);
+    sceneNode._properties.push_back(SceneNodeProperty(type, urlStr, index));
 }
 
 void SceneLoader::applyNodeProperties(const Scene* scene, const Properties* sceneProperties, unsigned int typeFlags)
@@ -151,43 +140,19 @@ void SceneLoader::applyNodeProperties(const Scene* scene, const Properties* scen
         SceneNode& sceneNode = _sceneNodes[i];
         GP_ASSERT(sceneNode._nodeID);
 
-        if (sceneNode._exactMatch)
+        // Find the node matching the specified ID.
+        Node* node = scene->findNode(sceneNode._nodeID);
+        if (!node)
         {
-            // Find the node matching the specified ID exactly.
-            Node* node = scene->findNode(sceneNode._nodeID);
-            if (!node)
-            {
-                GP_ERROR("Failed to set property for node '%s', which does not exist in the scene.", sceneNode._nodeID);
-                continue;
-            }
-
-            for (unsigned int j = 0, pcount = sceneNode._properties.size(); j < pcount; ++j)
-            {
-                SceneNodeProperty& snp = sceneNode._properties[j];
-                if (typeFlags & snp._type)
-                    applyNodeProperty(sceneNode, node, sceneProperties, snp, scene);
-            }
+            GP_ERROR("Failed to set property for node '%s', which does not exist in the scene.", sceneNode._nodeID);
+            continue;
         }
-        else
-        {
-            // Find all nodes matching the specified ID.
-            std::vector<Node*> nodes;
-            unsigned int nodeCount = scene->findNodes(sceneNode._nodeID, nodes, true, false);
-            if (nodeCount == 0)
-            {
-                GP_ERROR("Failed to set property for nodes with id matching '%s'; no such nodes exist in the scene.", sceneNode._nodeID);
-                continue;
-            }
-            
-            for (unsigned int j = 0, pcount = sceneNode._properties.size(); j < pcount; ++j)
-            {
-                SceneNodeProperty& snp = sceneNode._properties[j];
-                if ((typeFlags & snp._type) == 0)
-                    continue;
 
-                for (unsigned int k = 0; k < nodeCount; ++k)
-                    applyNodeProperty(sceneNode, nodes[k], sceneProperties, snp, scene);
-            }
+        for (unsigned int j = 0, pcount = sceneNode._properties.size(); j < pcount; ++j)
+        {
+            SceneNodeProperty& snp = sceneNode._properties[j];
+            if (typeFlags & snp._type)
+                applyNodeProperty(sceneNode, node, sceneProperties, snp, scene);
         }
     }
 }
@@ -200,30 +165,13 @@ 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 = _propertiesFromFile[snp._file];
+        Properties* p = _properties[snp._url];
         if (!p)
         {
-            GP_ERROR("The referenced node data in file '%s' failed to load.", snp._file.c_str());
+            GP_ERROR("The referenced node data at url '%s' failed to load.", snp._url.c_str());
             return;
         }
 
-        // If a specific namespace within the file was specified, load that namespace.
-        if (snp._id.size() > 0)
-        {
-            p = p->getNamespace(snp._id.c_str());
-            if (!p)
-            {
-                GP_ERROR("The referenced node data at '%s#%s' failed to load.", snp._file.c_str(), snp._id.c_str());
-                return;
-            }
-        }
-        else
-        {
-            // Otherwise, use the first namespace.
-            p->rewind();
-            p = p->getNextNamespace();
-        }
-
         switch (snp._type)
         {
         case SceneNodeProperty::AUDIO:
@@ -255,31 +203,6 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
         }
         case SceneNodeProperty::COLLISION_OBJECT:
         {
-            // Check to make sure the referenced properties object was loaded properly.
-            Properties* p = _propertiesFromFile[snp._file];
-            if (!p)
-            {
-                GP_ERROR("The referenced node data in file '%s' failed to load.", snp._file.c_str());
-                return;
-            }
-
-            // If a specific namespace within the file was specified, load that namespace.
-            if (snp._id.size() > 0)
-            {
-                p = p->getNamespace(snp._id.c_str());
-                if (!p)
-                {
-                    GP_ERROR("The referenced node data at '%s#%s' failed to load.", snp._file.c_str(), snp._id.c_str());
-                    return;
-                }
-            }
-            else
-            {
-                // Otherwise, use the first namespace.
-                p->rewind();
-                p = p->getNextNamespace();
-            }
-
             // Check to make sure the type of the namespace used to load the physics collision object is correct.
             if (snp._type == SceneNodeProperty::COLLISION_OBJECT && strcmp(p->getNamespace(), "collisionObject") != 0)
             {
@@ -402,48 +325,24 @@ void SceneLoader::applyNodeUrls(Scene* scene)
             if (snp._type != SceneNodeProperty::URL)
                 continue;
 
-            if (snp._file.empty())
+            std::string file;
+            std::string id;
+            splitURL(snp._url, &file, &id);
+
+            if (file.empty())
             {
                 // The node is from the main GPB and should just be renamed.
 
                 // TODO: Should we do all nodes with this case first to allow users to stitch in nodes with
                 // IDs equal to IDs that were in the original GPB file but were changed in the scene file?
-                if (sceneNode._exactMatch)
+                Node* node = scene->findNode(id.c_str());
+                if (node)
                 {
-                    Node* node = scene->findNode(snp._id.c_str());
-                    if (node)
-                    {
-                        node->setId(sceneNode._nodeID);
-                    }
-                    else
-                    {
-                        GP_ERROR("Could not find node '%s' in main scene GPB file.", snp._id.c_str());
-                    }
+                    node->setId(sceneNode._nodeID);
                 }
                 else
                 {
-                    // Search for nodes using a partial match
-                    std::string partialMatch = snp._id;
-                    std::vector<Node*> nodes;
-                    unsigned int nodeCount = scene->findNodes(snp._id.c_str(), nodes, true, false);
-                    if (nodeCount > 0)
-                    {
-                        GP_ASSERT(sceneNode._nodeID);
-
-                        for (unsigned int k = 0; k < nodeCount; ++k)
-                        {
-                            // Construct a new node ID using _nodeID plus the remainder of the partial match.
-                            Node* node = nodes[k];
-                            GP_ASSERT(node);
-                            std::string newID(sceneNode._nodeID);
-                            newID += (node->getId() + snp._id.length());
-                            node->setId(newID.c_str());
-                        }
-                    }
-                    else
-                    {
-                        GP_ERROR("Could not find any nodes matching '%s' in main scene GPB file.", snp._id.c_str());
-                    }
+                    GP_ERROR("Could not find node '%s' in main scene GPB file.", id.c_str());
                 }
             }
             else
@@ -453,60 +352,26 @@ void SceneLoader::applyNodeUrls(Scene* scene)
                 // TODO: Revisit this to determine if we should cache Bundle objects for the duration of the scene
                 // load to prevent constantly creating/destroying the same externally referenced bundles each time
                 // a url with a file is encountered.
-                Bundle* tmpBundle = Bundle::create(snp._file.c_str());
+                Bundle* tmpBundle = Bundle::create(file.c_str());
                 if (tmpBundle)
                 {
-                    if (sceneNode._exactMatch)
+                    Node* node = tmpBundle->loadNode(id.c_str(), scene);
+                    if (node)
                     {
-                        Node* node = tmpBundle->loadNode(snp._id.c_str(), scene);
-                        if (node)
-                        {
-                            node->setId(sceneNode._nodeID);
-                            scene->addNode(node);
-                            SAFE_RELEASE(node);
-                        }
-                        else
-                        {
-                            GP_ERROR("Could not load node '%s' from GPB file '%s'.", snp._id.c_str(), snp._file.c_str());
-                        }
+                        node->setId(sceneNode._nodeID);
+                        scene->addNode(node);
+                        SAFE_RELEASE(node);
                     }
                     else
                     {
-                        // Search for nodes in the bundle using a partial match
-                        std::string partialMatch = snp._id;
-                        unsigned int objectCount = tmpBundle->getObjectCount();
-                        unsigned int matchCount = 0;
-                        for (unsigned int k = 0; k < objectCount; ++k)
-                        {
-                            const char* objid = tmpBundle->getObjectID(k);
-                            if (strstr(objid, snp._id.c_str()) == objid)
-                            {
-                                // This object ID matches (starts with).
-                                // Try to load this object as a Node.
-                                Node* node = tmpBundle->loadNode(objid);
-                                if (node)
-                                {
-                                    // Construct a new node ID using _nodeID plus the remainder of the partial match.
-                                    std::string newID(sceneNode._nodeID);
-                                    newID += (node->getId() + snp._id.length());
-                                    node->setId(newID.c_str());
-                                    scene->addNode(node);
-                                    SAFE_RELEASE(node);
-                                    matchCount++;
-                                }
-                            }
-                        }
-                        if (matchCount == 0)
-                        {
-                            GP_ERROR("Could not find any nodes matching '%s' in GPB file '%s'.", snp._id.c_str(), snp._file.c_str());
-                        }
+                        GP_ERROR("Could not load node '%s' from GPB file '%s'.", id.c_str(), file.c_str());
                     }
 
                     SAFE_RELEASE(tmpBundle);
                 }
                 else
                 {
-                    GP_ERROR("Failed to load GPB file '%s' for node stitching.", snp._file.c_str());
+                    GP_ERROR("Failed to load GPB file '%s' for node stitching.", file.c_str());
                 }
             }
 
@@ -536,6 +401,42 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
             SceneNode& sceneNode = _sceneNodes[_sceneNodes.size()-1];
             sceneNode._nodeID = ns->getId();
 
+            // Parse the node's sub-namespaces.
+            Properties* subns;
+            std::string propertyUrl = _path + "#" + ns->getId() + "/";
+            while ((subns = ns->getNextNamespace()) != NULL)
+            {
+                if (strcmp(subns->getNamespace(), "audio") == 0)
+                {
+                    propertyUrl += "audio/" + std::string(subns->getId());
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::AUDIO, propertyUrl.c_str());
+                    _properties[propertyUrl] = subns;
+                }
+                else if (strcmp(subns->getNamespace(), "material") == 0)
+                {
+                    propertyUrl += "material/" + std::string(subns->getId());
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::MATERIAL, propertyUrl.c_str());
+                    _properties[propertyUrl] = subns;
+                }
+                else if (strcmp(subns->getNamespace(), "particle") == 0)
+                {
+                    propertyUrl += "particle/" + std::string(subns->getId());
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::PARTICLE, propertyUrl.c_str());
+                    _properties[propertyUrl] = subns;
+                }
+                else if (strcmp(subns->getNamespace(), "collisionObject") == 0)
+                {
+                    propertyUrl += "collisionObject/" + std::string(subns->getId());
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::COLLISION_OBJECT, propertyUrl.c_str());
+                    _properties[propertyUrl] = subns;
+                }
+                else
+                {
+                    GP_ERROR("Unsupported child namespace '%s' of 'node' namespace.", subns->getNamespace());
+                }
+            }
+
+            // Parse the node's attributes.
             while ((name = ns->getNextProperty()) != NULL)
             {
                 if (strcmp(name, "url") == 0)
@@ -660,21 +561,12 @@ void SceneLoader::createAnimations(const Scene* scene)
         }
 
         // Check to make sure the referenced properties object was loaded properly.
-        Properties* p = _propertiesFromFile[_animations[i]._file];
+        Properties* p = _properties[_animations[i]._url];
         if (!p)
         {
-            GP_ERROR("The referenced animation data in file '%s' failed to load.", _animations[i]._file.c_str());
+            GP_ERROR("The referenced animation data at url '%s' failed to load.", _animations[i]._url.c_str());
             continue;
         }
-        if (_animations[i]._id.size() > 0)
-        {
-            p = p->getNamespace(_animations[i]._id.c_str());
-            if (!p)
-            {
-                GP_ERROR("The referenced animation data at '%s#%s' failed to load.", _animations[i]._file.c_str(), _animations[i]._id.c_str());
-                continue;
-            }
-        }
 
         node->createAnimation(_animations[i]._animationID, p);
     }
@@ -789,10 +681,10 @@ Scene* SceneLoader::loadMainSceneData(const Properties* sceneProperties)
     GP_ASSERT(sceneProperties);
 
     // Load the main scene from the specified path.
-    Bundle* bundle = Bundle::create(_path.c_str());
+    Bundle* bundle = Bundle::create(_gpbPath.c_str());
     if (!bundle)
     {
-        GP_ERROR("Failed to load scene GPB file '%s'.", _path.c_str());
+        GP_ERROR("Failed to load scene GPB file '%s'.", _gpbPath.c_str());
         return NULL;
     }
 
@@ -800,7 +692,7 @@ Scene* SceneLoader::loadMainSceneData(const Properties* sceneProperties)
     Scene* scene = bundle->loadScene(NULL);
     if (!scene)
     {
-        GP_ERROR("Failed to load scene from '%s'.", _path.c_str());
+        GP_ERROR("Failed to load scene from '%s'.", _gpbPath.c_str());
         SAFE_RELEASE(bundle);
         return NULL;
     }
@@ -930,14 +822,17 @@ void SceneLoader::loadPhysics(Properties* physics, Scene* scene)
 void SceneLoader::loadReferencedFiles()
 {
     // Load all referenced properties files.
-    std::map<std::string, Properties*>::iterator iter = _propertiesFromFile.begin();
-    for (; iter != _propertiesFromFile.end(); iter++)
+    std::map<std::string, Properties*>::iterator iter = _properties.begin();
+    for (; iter != _properties.end(); iter++)
     {
-        Properties* p = Properties::create(iter->first.c_str());
-        if (p == NULL)
-            GP_ERROR("Failed to load referenced file '%s'.", iter->first.c_str());
+        if (iter->second == NULL)
+        {
+            Properties* p = Properties::create(iter->first.c_str());
+            if (p == NULL)
+                GP_ERROR("Failed to load referenced file '%s'.", iter->first.c_str());
 
-        iter->second = p;
+            iter->second = p;
+        }
     }
 }
 
@@ -1043,28 +938,26 @@ PhysicsConstraint* SceneLoader::loadSpringConstraint(const Properties* constrain
     return physicsConstraint;
 }
 
-void SceneLoader::splitURL(const char* url, std::string* file, std::string* id)
+void SceneLoader::splitURL(const std::string& url, std::string* file, std::string* id)
 {
-    if (!url)
+    if (url.empty())
     {
         // This is allowed since many scene node properties do not use the URL.
         return;
     }
 
-    std::string urlString = url;
-
     // Check if the url references a file (otherwise, it only references a node within the main GPB).
-    unsigned int loc = urlString.rfind(".");
-    if (loc != urlString.npos)
+    unsigned int loc = url.rfind(".");
+    if (loc != url.npos)
     {
         // If the url references a specific namespace within the file,
         // set the id out parameter appropriately. Otherwise, set the id out
         // parameter to the empty string so we know to load the first namespace.
-        loc = urlString.rfind("#");
-        if (loc != urlString.npos)
+        loc = url.rfind("#");
+        if (loc != url.npos)
         {
-            *file = urlString.substr(0, loc);
-            *id = urlString.substr(loc + 1);
+            *file = url.substr(0, loc);
+            *id = url.substr(loc + 1);
         }
         else
         {

+ 10 - 12
gameplay/src/SceneLoader.h

@@ -33,13 +33,12 @@ private:
      */
     struct SceneAnimation
     {
-        SceneAnimation(const char* animationID, const char* targetID, std::string file, std::string id)
-            : _animationID(animationID), _targetID(targetID), _file(file), _id(id) {}
+        SceneAnimation(const char* animationID, const char* targetID, std::string url)
+            : _animationID(animationID), _targetID(targetID), _url(url) {}
 
         const char* _animationID;
         const char* _targetID;
-        std::string _file;
-        std::string _id;
+        std::string _url;
     };
 
     struct SceneNodeProperty
@@ -58,20 +57,18 @@ private:
             DYNAMIC = 512
         };
 
-        SceneNodeProperty(Type type, std::string file, std::string id, int index) : _type(type), _file(file), _id(id), _index(index) { }
+        SceneNodeProperty(Type type, std::string url, int index) : _type(type), _url(url), _index(index) { }
 
         Type _type;
-        std::string _file;
-        std::string _id;
+        std::string _url;
         int _index;
     };
 
     struct SceneNode
     {
-        SceneNode() : _nodeID(""), _exactMatch(true) { }
+        SceneNode() : _nodeID("") { }
 
         const char* _nodeID;
-        bool _exactMatch;
         std::vector<SceneNodeProperty> _properties;
     };
 
@@ -105,13 +102,14 @@ private:
 
     static PhysicsConstraint* loadSpringConstraint(const Properties* constraint, PhysicsRigidBody* rbA, PhysicsRigidBody* rbB);
 
-    static void splitURL(const char* url, std::string* file, std::string* id);
+    static void splitURL(const std::string& url, std::string* file, std::string* id);
     
     
-    static std::map<std::string, Properties*> _propertiesFromFile;      // Holds the properties object for a given file path.
+    static std::map<std::string, Properties*> _properties;              // Holds the properties object for a given URL.
     static std::vector<SceneAnimation> _animations;                     // Holds the animations declared in the .scene file.
     static std::vector<SceneNode> _sceneNodes;                          // Holds all the nodes+properties declared in the .scene file.
-    static std::string _path;                                           // The path of the main GPB for the scene being loaded.
+    static std::string _gpbPath;                                        // The path of the main GPB for the scene being loaded.
+    static std::string _path;                                           // The path of the scene file being loaded.
 };
 
 }