Browse Source

Added support for loading any object that can load from a Properties object using a url instead of just a file name.

Chris Culy 13 years ago
parent
commit
7dd0fc15ef

+ 4 - 4
gameplay/src/Animation.cpp

@@ -105,14 +105,14 @@ unsigned long Animation::getDuration() const
     return _duration;
 }
 
-void Animation::createClips(const char* animationFile)
+void Animation::createClips(const char* url)
 {
-    assert(animationFile);
+    assert(url);
 
-    Properties* properties = Properties::create(animationFile);
+    Properties* properties = Properties::create(url);
     assert(properties);
 
-    Properties* pAnimation = properties->getNextNamespace();
+    Properties* pAnimation = (strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace();
     assert(pAnimation);
     
     int frameCount = pAnimation->getInt("frameCount");

+ 6 - 2
gameplay/src/Animation.h

@@ -43,9 +43,13 @@ public:
     unsigned long getDuration() const;
 
     /**
-     * Creates an AnimationClip from an .animation file.
+     * Creates an AnimationClip from the Properties object defined at the specified URL, 
+     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional).
+     * 
+     * @param url The URL pointing to the Properties object containing the clip definitions.
      */
-    void createClips(const char* animationFile);
+    void createClips(const char* url);
     
     /**
      * Creates an AnimationClip from the Animation.

+ 4 - 4
gameplay/src/AnimationTarget.cpp

@@ -47,14 +47,14 @@ Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsi
     return animation;
 }
 
-Animation* AnimationTarget::createAnimation(const char* id, const char* animationFile)
+Animation* AnimationTarget::createAnimation(const char* id, const char* url)
 {
-    assert(animationFile);
+    assert(url);
     
-    Properties* p = Properties::create(animationFile);
+    Properties* p = Properties::create(url);
     assert(p);
 
-    Animation* animation = createAnimation(id, p->getNextNamespace());
+    Animation* animation = createAnimation(id, (strlen(p->getNamespace()) > 0) ? p : p->getNextNamespace());
 
     SAFE_DELETE(p);
 

+ 5 - 3
gameplay/src/AnimationTarget.h

@@ -55,14 +55,16 @@ public:
     Animation* createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type);
 
     /**
-     * Creates an animation on this target using the data from the given properties object. 
+     * Creates an animation on this target using the data from the Properties object defined at the specified URL, 
+     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
      * 
      * @param id The ID of the animation.
-     * @param animationFile The animation file defining the animation data.
+     * @param url The URL pointing to the Properties object defining the animation data.
      *
      * @return The newly created animation.
      */
-    Animation* createAnimation(const char* id, const char* animationFile);
+    Animation* createAnimation(const char* id, const char* url);
 
     /**
      * Creates an animation on this target using the data from the given properties object. 

+ 7 - 7
gameplay/src/AudioSource.cpp

@@ -104,28 +104,28 @@ AudioSource::~AudioSource()
     SAFE_RELEASE(_buffer);
 }
 
-AudioSource* AudioSource::create(const char* path)
+AudioSource* AudioSource::create(const char* url)
 {
-    assert(path);
+    assert(url);
 
     // Load from a .audio file.
-    std::string pathStr = path;
+    std::string pathStr = url;
     if (pathStr.find(".audio") != pathStr.npos)
     {
-        Properties* properties = Properties::create(path);
+        Properties* properties = Properties::create(url);
         assert(properties);
         if (properties == NULL)
         {
             return NULL;
         }
 
-        AudioSource* audioSource = create(properties->getNextNamespace());
+        AudioSource* audioSource = create((strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace());
         SAFE_DELETE(properties);
         return audioSource;
     }
 
-    // Create an audio buffer from this path.
-    AudioBuffer* buffer = AudioBuffer::create(path);
+    // Create an audio buffer from this URL.
+    AudioBuffer* buffer = AudioBuffer::create(url);
     if (buffer == NULL)
         return NULL;
 

+ 5 - 4
gameplay/src/AudioSource.h

@@ -34,13 +34,14 @@ public:
     };
 
     /**
-     * Create an audio source. This is used to instantiate an Audio Source. Currently only wav, au, raw and .audio files are supported.
-     *
-     * @param path The relative location on disk of the sound file or .audio file.
+     * Create an audio source. This is used to instantiate an Audio Source. Currently only wav, au, and raw files are supported.
+     * Alternately, a URL specifying a Properties object that defines an audio source can be used (where the URL is of the format
+     * "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>" and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional).
      * 
+     * @param url The relative location on disk of the sound file or a URL specifying a Properties object defining an audio source.
      * @return The newly created audio source, or NULL if an audio source cannot be created.
      */
-    static AudioSource* create(const char* path);
+    static AudioSource* create(const char* url);
 
     /**
      * Create an audio source from the given properties object.

+ 4 - 4
gameplay/src/Form.cpp

@@ -36,18 +36,18 @@ namespace gameplay
         }
     }
 
-    Form* Form::create(const char* path)
+    Form* Form::create(const char* url)
     {
         // Load Form from .form file.
-        assert(path);
+        assert(url);
 
-        Properties* properties = Properties::create(path);
+        Properties* properties = Properties::create(url);
         assert(properties);
         if (properties == NULL)
             return NULL;
 
         // Check if the Properties is valid and has a valid namespace.
-        Properties* formProperties = properties->getNextNamespace();
+        Properties* formProperties = (strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace();
         assert(formProperties);
         if (!formProperties || !(strcmp(formProperties->getNamespace(), "form") == 0))
         {

+ 6 - 4
gameplay/src/Form.h

@@ -50,11 +50,13 @@ class Form : public Container
 public:
 
     /**
-     * Create from properties file.
-     *
-     * @param path Path to the properties file to create a new form from.
+     * Creates a form using the data from the Properties object defined at the specified URL, 
+     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
+     * 
+     * @param url The URL pointing to the Properties object defining the animation data. 
      */
-    static Form* create(const char* path);
+    static Form* create(const char* url);
 
     /**
      * Get a form from its ID.

+ 4 - 4
gameplay/src/Material.cpp

@@ -32,19 +32,19 @@ Material::~Material()
     }
 }
 
-Material* Material::create(const char* materialPath)
+Material* Material::create(const char* url)
 {
-    assert(materialPath);
+    assert(url);
 
     // Load the material properties from file
-    Properties* properties = Properties::create(materialPath);
+    Properties* properties = Properties::create(url);
     assert(properties);
     if (properties == NULL)
     {
         return NULL;
     }
 
-    Material* material = create(properties->getNextNamespace());
+    Material* material = create((strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace());
     SAFE_DELETE(properties);
 
     return material;

+ 6 - 4
gameplay/src/Material.h

@@ -28,13 +28,15 @@ class Material : public RenderState
 public:
 
     /**
-     * Creates a material from a specified file path.
-     *
-     * @param materialPath Path path to the material file.
+     * Creates a material using the data from the Properties object defined at the specified URL, 
+     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
+     * 
+     * @param url The URL pointing to the Properties object defining the material.
      * 
      * @return A new Material.
      */
-    static Material* create(const char* materialPath);
+    static Material* create(const char* url);
 
     /**
      * Creates a material from the specified properties object.

+ 4 - 4
gameplay/src/Node.cpp

@@ -994,18 +994,18 @@ PhysicsCollisionObject* Node::setCollisionObject(PhysicsCollisionObject::Type ty
     return _collisionObject;
 }
 
-PhysicsCollisionObject* Node::setCollisionObject(const char* filePath)
+PhysicsCollisionObject* Node::setCollisionObject(const char* url)
 {
     // Load the collision object properties from file.
-    Properties* properties = Properties::create(filePath);
+    Properties* properties = Properties::create(url);
     assert(properties);
     if (properties == NULL)
     {
-        WARN_VARG("Failed to load collision object file: %s", filePath);
+        WARN_VARG("Failed to load collision object file: %s", url);
         return NULL;
     }
 
-    PhysicsCollisionObject* collisionObject = setCollisionObject(properties->getNextNamespace());
+    PhysicsCollisionObject* collisionObject = setCollisionObject((strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace());
     SAFE_DELETE(properties);
 
     return collisionObject;

+ 5 - 3
gameplay/src/Node.h

@@ -520,11 +520,13 @@ public:
     PhysicsCollisionObject* setCollisionObject(PhysicsCollisionObject::Type type, const PhysicsCollisionShape::Definition& shape, PhysicsRigidBody::Parameters* rigidBodyParameters = NULL);
 
     /**
-     * Sets the physics collision object for this node using the definition in the given file.
+     * Sets the physics collision object for this node using the data from the Properties object defined at the specified URL, 
+     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
      * 
-     * @param filePath The path to the file that set the collision object definition.
+     * @param url The URL pointing to the Properties object defining the physics collision object.
      */
-    PhysicsCollisionObject* setCollisionObject(const char* filePath);
+    PhysicsCollisionObject* setCollisionObject(const char* url);
 
     /**
      * Sets the physics collision object for this node from the given properties object.

+ 5 - 5
gameplay/src/ParticleEmitter.cpp

@@ -82,18 +82,18 @@ ParticleEmitter* ParticleEmitter::create(const char* textureFile, TextureBlendin
     return emitter;
 }
 
-ParticleEmitter* ParticleEmitter::create(const char* particleFile)
+ParticleEmitter* ParticleEmitter::create(const char* url)
 {
-    assert(particleFile);
+    assert(url);
 
-    Properties* properties = Properties::create(particleFile);
+    Properties* properties = Properties::create(url);
     if (!properties)
     {
-        LOG_ERROR_VARG("Error loading ParticleEmitter: Could not load file: %s", particleFile);
+        LOG_ERROR_VARG("Error loading ParticleEmitter: Could not load file: %s", url);
         return NULL;
     }
 
-    ParticleEmitter* particle = create(properties->getNextNamespace());
+    ParticleEmitter* particle = create((strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace());
     SAFE_DELETE(properties);
 
     return particle;

+ 6 - 4
gameplay/src/ParticleEmitter.h

@@ -154,13 +154,15 @@ public:
     };
 
     /**
-     * Creates a particle emitter from a .particle file.
-     *
-     * @param particleFile The .particle file to load.
+     * Creates a particle emitter using the data from the Properties object defined at the specified URL, 
+     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
+     * 
+     * @param url The URL pointing to the Properties object defining the particle emitter.
      * 
      * @return An initialized ParticleEmitter.
      */
-    static ParticleEmitter* create(const char* particleFile);
+    static ParticleEmitter* create(const char* url);
 
     /**
      * Creates a particle emitter from the specified properties object.

+ 92 - 4
gameplay/src/Properties.cpp

@@ -46,11 +46,40 @@ Properties::Properties(FILE* file, const char* name, const char* id, const char*
     rewind();
 }
 
-Properties* Properties::create(const char* filePath)
+Properties* Properties::create(const char* url)
 {
-    assert(filePath);
+    assert(url);
 
-    FILE* file = FileSystem::openFile(filePath, "rb");
+    if (!url || strlen(url) == 0)
+    {
+        WARN("Attempting to create a Properties object from an empty URL!");
+        return NULL;
+    }
+
+    std::string urlString = url;
+    std::string fileString;
+    std::vector<std::string> namespacePath;
+
+    // If the url references a specific namespace within the file,
+    // calculate the full namespace path to the final namespace.
+    unsigned int loc = urlString.rfind("#");
+    if (loc != urlString.npos)
+    {
+        fileString = urlString.substr(0, loc);
+        std::string namespacePathString = urlString.substr(loc + 1);
+        while ((loc = namespacePathString.find("/")) != namespacePathString.npos)
+        {
+            namespacePath.push_back(namespacePathString.substr(0, loc));
+            namespacePathString = namespacePathString.substr(loc + 1);
+        }
+        namespacePath.push_back(namespacePathString);
+    }
+    else
+    {
+        fileString = url;
+    }
+
+    FILE* file = FileSystem::openFile(fileString.c_str(), "rb");
     if (!file)
     {
         return NULL;
@@ -62,7 +91,46 @@ Properties* Properties::create(const char* filePath)
 
     fclose(file);
 
-    return properties;
+    // If the url references a specific namespace within the file,
+    // return the specified namespace or notify the user if it cannot be found.
+    Properties* originalProperties = properties;
+    if (namespacePath.size() > 0)
+    {
+        unsigned int size = namespacePath.size();
+        Properties* iter = properties->getNextNamespace();
+        for (unsigned int i = 0; i < size;)
+        {
+            while (true)
+            {
+                if (strcmp(iter->getId(), namespacePath[i].c_str()) == 0)
+                {
+                    if (i != size - 1)
+                    {
+                        properties = iter->getNextNamespace();
+                        iter = properties;
+                    }
+                    else
+                        properties = iter;
+
+                    i++;
+                    break;
+                }
+                
+                iter = properties->getNextNamespace();
+                if (iter == NULL)
+                {
+                    WARN_VARG("Failed to load Properties object from URL '%s'.", url);
+                    return NULL;
+                }
+            }
+        }
+
+        properties = properties->clone();
+        SAFE_DELETE(originalProperties);
+        return properties;
+    }
+    else
+        return properties;
 }
 
 void Properties::readProperties(FILE* file)
@@ -817,4 +885,24 @@ bool Properties::getColor(const char* name, Vector4* out) const
     return false;
 }
 
+Properties* Properties::clone()
+{
+    Properties* p = new Properties();
+    
+    p->_namespace = _namespace;
+    p->_id = _id;
+    p->_parentID = _parentID;
+    p->_properties = _properties;
+    p->_propertiesItr = p->_properties.end();
+
+    unsigned int count = _namespaces.size();
+    for (unsigned int i = 0; i < count; i++)
+    {
+        p->_namespaces.push_back(_namespaces[i]->clone());
+    }
+    p->_namespacesItr = p->_namespaces.end();
+
+    return p;
+}
+
 }

+ 9 - 4
gameplay/src/Properties.h

@@ -142,11 +142,13 @@ public:
     };
 
     /**
-     * Creates a Properties runtime settings from a specified file path.
-     *
-     * @param filePath The file to create the properties from.
+     * Creates a Properties runtime settings from the specified URL, where the URL is of
+     * the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional).
+     * 
+     * @param url The URL to create the properties from.
      */
-    static Properties* create(const char* filePath);
+    static Properties* create(const char* url);
 
     /**
      * Destructor.
@@ -391,6 +393,9 @@ private:
     // Called by resolveInheritance().
     void mergeWith(Properties* overrides);
 
+    // Clones the Properties object.
+    Properties* clone();
+
     std::string _namespace;
     std::string _id;
     std::string _parentID;

+ 9 - 8
gameplay/src/SceneLoader.cpp

@@ -11,21 +11,21 @@ std::vector<SceneLoader::SceneAnimation> SceneLoader::_animations;
 std::vector<SceneLoader::SceneNode> SceneLoader::_sceneNodes;
 std::string SceneLoader::_path;
 
-Scene* SceneLoader::load(const char* filePath)
+Scene* SceneLoader::load(const char* url)
 {
-    assert(filePath);
+    assert(url);
 
     // Load the scene properties from file.
-    Properties* properties = Properties::create(filePath);
+    Properties* properties = Properties::create(url);
     assert(properties);
     if (properties == NULL)
     {
-        WARN_VARG("Failed to load scene file: %s", filePath);
+        WARN_VARG("Failed to load scene file: %s", url);
         return NULL;
     }
 
     // Check if the properties object is valid and has a valid namespace.
-    Properties* sceneProperties = properties->getNextNamespace();
+    Properties* sceneProperties = (strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace();
     assert(sceneProperties);
     if (!sceneProperties || !(strcmp(sceneProperties->getNamespace(), "scene") == 0))
     {
@@ -36,6 +36,7 @@ Scene* SceneLoader::load(const char* filePath)
 
     // Get the path to the main GPB.
     _path = sceneProperties->getString("path");
+
     // Build the node URL/property and animation reference tables and load the referenced files.
     buildReferenceTables(sceneProperties);
     loadReferencedFiles();
@@ -641,7 +642,7 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
         }
         else
         {
-            // TODO: Should we ignore these items? They could be used for generic properties file inheritence.
+            // TODO: Should we ignore these items? They could be used for generic properties file inheritance.
             WARN_VARG("Unsupported child namespace (of 'scene'): %s", ns->getNamespace());
         }
     }
@@ -772,8 +773,8 @@ Scene* SceneLoader::loadMainSceneData(const Properties* sceneProperties)
         return NULL;
     }
 
-    const char* sceneID = strlen(sceneProperties->getId()) == 0 ? NULL : sceneProperties->getId();
-    Scene* scene = bundle->loadScene(sceneID);
+    // TODO: Support loading a specific scene from a GPB file using the URL syntax (i.e. "res/scene.gpb#myscene").
+    Scene* scene = bundle->loadScene(NULL);
     if (!scene)
     {
         WARN_VARG("Failed to load scene from '%s'.", _path.c_str());

+ 6 - 2
gameplay/src/SceneLoader.h

@@ -20,9 +20,13 @@ class SceneLoader
 private:
 
     /**
-     * Loads a scene file file.
+     * Loads a scene using the data from the Properties object defined at the specified URL, 
+     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
+     * 
+     * @param url The URL pointing to the Properties object defining the scene.
      */
-    static Scene* load(const char* filePath);
+    static Scene* load(const char* url);
     
     /**
      * Helper structures and functions for SceneLoader::load(const char*).

+ 6 - 6
gameplay/src/Theme.cpp

@@ -52,15 +52,15 @@ namespace gameplay
         }
     }
 
-    Theme* Theme::create(const char* path)
+    Theme* Theme::create(const char* url)
     {
-        assert(path);
+        assert(url);
 
         // Search theme cache first.
         for (unsigned int i = 0, count = __themeCache.size(); i < count; ++i)
         {
             Theme* t = __themeCache[i];
-            if (t->_path == path)
+            if (t->_url == url)
             {
                 // Found a match.
                 t->addRef();
@@ -70,7 +70,7 @@ namespace gameplay
         }
 
         // Load theme properties from file path.
-        Properties* properties = Properties::create(path);
+        Properties* properties = Properties::create(url);
         assert(properties);
         if (properties == NULL)
         {
@@ -78,7 +78,7 @@ namespace gameplay
         }
 
         // Check if the Properties is valid and has a valid namespace.
-        Properties* themeProperties = properties->getNextNamespace();
+        Properties* themeProperties = (strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace();
         assert(themeProperties);
         if (!themeProperties || !(strcmp(themeProperties->getNamespace(), "theme") == 0))
         {
@@ -88,7 +88,7 @@ namespace gameplay
 
         // Create a new theme.
         Theme* theme = new Theme();
-        theme->_path = path;
+        theme->_url = url;
         
         // Parse the Properties object and set up the theme.
         const char* textureFile = themeProperties->getString("texture");

+ 7 - 5
gameplay/src/Theme.h

@@ -407,13 +407,15 @@ private:
     ~Theme();
 
     /**
-     * Creates an instance of a Theme from a theme file.
-     *
-     * @param path Path to a theme file.
+     * Creates an instance of a Theme using the data from the Properties object defined at the specified URL, 
+     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
+     * 
+     * @param url The URL pointing to the Properties object defining the theme.
      *
      * @return A new Theme.
      */
-    static Theme* create(const char* path);
+    static Theme* create(const char* url);
 
     Theme::Style* getStyle(const char* id) const;
 
@@ -425,7 +427,7 @@ private:
 
     void lookUpSprites(const Properties* overlaySpace, ImageList** imageList, ThemeImage** mouseCursor, Skin** skin);
 
-    std::string _path;
+    std::string _url;
     Texture* _texture;
     SpriteBatch* _spriteBatch;
     std::vector<Style*> _styles;