Kaynağa Gözat

Updates SceneLoader to support wildcards on node URLs for matching multiple nodes in a scene (via asterisk at end of URL).

Added support for arbitrary custom tags on Nodes. This feature deprecates/replaces the previous transparent, dynamic and visible properties of nodes. Scene files now support a 'tags' section inside nodes (see character sample .scene file for an example).

Minor optimizations for loading large scene files.

Fixes #261
Steve Grenier 13 yıl önce
ebeveyn
işleme
981dd30ee4

+ 31 - 32
gameplay/src/Node.cpp

@@ -13,17 +13,12 @@
 #define NODE_DIRTY_BOUNDS 2
 #define NODE_DIRTY_ALL (NODE_DIRTY_WORLD | NODE_DIRTY_BOUNDS)
 
-// Node property flags
-#define NODE_FLAG_VISIBLE 1
-#define NODE_FLAG_TRANSPARENT 2
-#define NODE_FLAG_DYNAMIC 4
-
 namespace gameplay
 {
 
 Node::Node(const char* id)
     : _scene(NULL), _firstChild(NULL), _nextSibling(NULL), _prevSibling(NULL), _parent(NULL), _childCount(0),
-    _nodeFlags(NODE_FLAG_VISIBLE), _camera(NULL), _light(NULL), _model(NULL), _form(NULL), _audioSource(NULL), _particleEmitter(NULL),
+    _tags(NULL), _camera(NULL), _light(NULL), _model(NULL), _form(NULL), _audioSource(NULL), _particleEmitter(NULL),
     _collisionObject(NULL), _agent(NULL), _dirtyBits(NODE_DIRTY_ALL), _notifyHierarchyChanged(true), _userData(NULL)
 {
     if (id)
@@ -52,6 +47,7 @@ Node::~Node()
     SAFE_RELEASE(_particleEmitter);
     SAFE_RELEASE(_form);
     SAFE_DELETE(_collisionObject);
+    SAFE_DELETE(_tags);
 
     setAgent(NULL);
 
@@ -213,43 +209,46 @@ Node* Node::getParent() const
     return _parent;
 }
 
-bool Node::isVisible() const
+bool Node::hasTag(const char* name) const
 {
-    return ((_nodeFlags & NODE_FLAG_VISIBLE) == NODE_FLAG_VISIBLE);
-}
+    GP_ASSERT(name);
 
-void Node::setVisible(bool visible)
-{
-    if (visible)
-        _nodeFlags |= NODE_FLAG_VISIBLE;
-    else
-        _nodeFlags &= ~NODE_FLAG_VISIBLE;
+    return (_tags ? _tags->find(name) != _tags->end() : false);
 }
 
-bool Node::isTransparent() const
+const char* Node::getTag(const char* name) const
 {
-    return ((_nodeFlags & NODE_FLAG_TRANSPARENT) == NODE_FLAG_TRANSPARENT);
-}
+    GP_ASSERT(name);
 
-void Node::setTransparent(bool transparent)
-{
-    if (transparent)
-        _nodeFlags |= NODE_FLAG_TRANSPARENT;
-    else
-        _nodeFlags &= ~NODE_FLAG_TRANSPARENT;
-}
+    if (!_tags)
+        return NULL;
 
-bool Node::isDynamic() const
-{
-    return ((_nodeFlags & NODE_FLAG_DYNAMIC) == NODE_FLAG_DYNAMIC);
+    std::map<std::string, std::string>::const_iterator itr = _tags->find(name);
+    return (itr == _tags->end() ? NULL : itr->second.c_str());
 }
 
-void Node::setDynamic(bool dynamic)
+void Node::setTag(const char* name, const char* value)
 {
-    if (dynamic)
-        _nodeFlags |= NODE_FLAG_DYNAMIC;
+    GP_ASSERT(name);
+
+    if (value == NULL)
+    {
+        // Removing tag
+        if (_tags)
+        {
+            _tags->erase(name);
+            if (_tags->size() == 0)
+                SAFE_DELETE(_tags);
+        }
+    }
     else
-        _nodeFlags &= ~NODE_FLAG_DYNAMIC;
+    {
+        // Setting tag
+        if (_tags == NULL)
+            _tags = new std::map<std::string, std::string>();
+
+        (*_tags)[name] = value;
+    }
 }
 
 void* Node::getUserPointer() const

+ 22 - 42
gameplay/src/Node.h

@@ -116,59 +116,39 @@ public:
     Node* getParent() const;
 
     /**
-     * Returns whether this node is visible (true by default).
+     * Determines if a custom tag with the specified name is set.
      *
-     * @return Whether the node is visible.
-     */
-    bool isVisible() const;
-
-    /**
-     * Sets whether this node is visible.
+     * @param name Name of the tag to query.
      *
-     * @return Whether this node is visible.
+     * @return true if the tag is set, false otherwise.
      */
-    void setVisible(bool visible);
+    bool hasTag(const char* name) const;
 
     /**
-     * Returns whether this node is transparent (false by default).
+     * Returns the value of the custom tag with the given name.
      *
-     * All nodes are opaque by default, unless otherwise set as
-     * transparent using the setTransparent method. These methods
-     * can be used to flag nodes as transparent and then query the
-     * property during game execution, for example to render all
-     * opaque objects first, followed by transparent objects with
-     * alpha blending enabled.
-     *
-     * @return Whether the node is transparent.
-     */
-    bool isTransparent() const;
-
-    /**
-     * Sets whether this node is transparent.
+     * @param name Name of the tag to return.
      *
-     * @param transparent Whether the node is transparent.
+     * @return The value of the given tag, or NULL if the tag is not set.
      */
-    void setTransparent(bool transparent);
+    const char* getTag(const char* name) const;
 
     /**
-     * Returns whether this node is dynamic.
+     * Sets a custom tag on this Node.
      *
-     * The dynamic propery can be used to flag nodes as being non-static.
-     * This can be useful for modifying behavior or rendering/material
-     * logic at runtime for static vs dynamic (moving) objects. An
-     * example would be determing whether to use static or  dyanmic
-     * lighting materials for node models during loading.
+     * Custom tags can be used for a variety of purposes within a game. For example,
+     * a tag called "transparent" can be added to nodes, to indicate which nodes in
+     * a scene are transparent. This tag can then be read during rendering to sort
+     * transparent and opaque objects for correct drawing order. Another example
+     * is using a "visible" tag to mark nodes as invisible to be skipped during
+     * rendering.
      *
-     * @return Whether this node is dynamic (false by default).
-     */
-    bool isDynamic() const;
-
-    /**
-     * Sets whether this node is dynamic.
+     * Setting a tag to NULL removes the tag from the Node.
      *
-     * @param dynamic Whether the node is dynamic.
+     * @param name Name of the tag to set.
+     * @param value Optional value of the tag (empty string by default).
      */
-    void setDynamic(bool dynamic);
+    void setTag(const char* name, const char* value = "");
 
     /**
      * Returns the user pointer for this node.
@@ -730,9 +710,9 @@ protected:
     unsigned int _childCount;
 
     /**
-     * Node property flags. 
-     */ 
-    unsigned int _nodeFlags;
+     * List of custom tags for a node.
+     */
+    std::map<std::string, std::string>* _tags;
 
     /**
      * Pointer to the Camera attached to the Node.

+ 154 - 60
gameplay/src/SceneLoader.cpp

@@ -10,15 +10,14 @@ namespace gameplay
 // Utility functions (shared with Properties).
 extern void calculateNamespacePath(const std::string& urlString, std::string& fileString, std::vector<std::string>& namespacePath);
 extern Properties* getPropertiesFromNamespacePath(Properties* properties, const std::vector<std::string>& namespacePath);
-    
-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)
+{
+    SceneLoader loader;
+    return loader.loadInternal(url);
+}
+
+Scene* SceneLoader::loadInternal(const char* url)
 {
     // Get the file part of the url that we are loading the scene from.
     std::string urlStr = url ? url : "";
@@ -70,10 +69,21 @@ Scene* SceneLoader::load(const char* url)
         SceneNodeProperty::PARTICLE |
         SceneNodeProperty::ROTATE |
         SceneNodeProperty::SCALE |
-        SceneNodeProperty::TRANSLATE | 
-        SceneNodeProperty::TRANSPARENT |
-        SceneNodeProperty::DYNAMIC);
+        SceneNodeProperty::TRANSLATE);
     applyNodeProperties(scene, sceneProperties, SceneNodeProperty::COLLISION_OBJECT);
+
+    // Apply node tags
+    for (unsigned int i = 0, sncount = _sceneNodes.size(); i < sncount; ++i)
+    {
+        SceneNode& sceneNode = _sceneNodes[i];
+        for (std::map<std::string, std::string>::const_iterator itr = sceneNode._tags.begin(); itr != sceneNode._tags.end(); ++itr)
+        {
+            for (unsigned int n = 0, ncount = sceneNode._nodes.size(); n < ncount; ++n)
+                sceneNode._nodes[n]->setTag(itr->first.c_str(), itr->second.c_str());
+        }
+    }
+
+    // Create animations for scene
     createAnimations(scene);
 
     // Find the physics properties object.
@@ -95,7 +105,6 @@ Scene* SceneLoader::load(const char* url)
         loadPhysics(physics, scene);
 
     // Clean up all loaded properties objects.
-    _properties.clear();
     std::map<std::string, Properties*>::iterator iter = _propertiesFromFile.begin();
     for (; iter != _propertiesFromFile.end(); iter++)
     {
@@ -105,11 +114,6 @@ Scene* SceneLoader::load(const char* url)
     // Clean up the .scene file's properties object.
     SAFE_DELETE(properties);
 
-    // Clear all temporary data stores.
-    _properties.clear();
-    _animations.clear();
-    _sceneNodes.clear();
-
     return scene;
 }
 
@@ -135,30 +139,36 @@ void SceneLoader::addSceneNodeProperty(SceneNode& sceneNode, SceneNodeProperty::
     if (urlStr.length() > 0 && urlStr.find(".") != urlStr.npos && urlStr.find(".gpb") == urlStr.npos && _properties.count(urlStr) == 0)
         _properties[urlStr] = NULL;
 
+    SceneNodeProperty prop(type, urlStr, index);
+
+    // Parse for wildcharacter character (only supported on the URL attribute)
+    if (type == SceneNodeProperty::URL)
+    {
+        if (urlStr.length() > 1 && urlStr.at(urlStr.length()-1) == '*')
+        {
+            prop._url = urlStr.substr(0, urlStr.length()-1);
+            sceneNode._exactMatch = false;
+        }
+    }
+
     // Add the node property to the list of node properties to be resolved later.
-    sceneNode._properties.push_back(SceneNodeProperty(type, urlStr, index));
+    sceneNode._properties.push_back(prop);
 }
 
 void SceneLoader::applyNodeProperties(const Scene* scene, const Properties* sceneProperties, unsigned int typeFlags)
 {
-    for (unsigned int i = 0, ncount = _sceneNodes.size(); i < ncount; ++i)
+    for (unsigned int i = 0, sncount = _sceneNodes.size(); i < sncount; ++i)
     {
         SceneNode& sceneNode = _sceneNodes[i];
-        GP_ASSERT(sceneNode._nodeID);
-
-        // Find the node matching the specified ID.
-        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)
+        for (unsigned int p = 0, pcount = sceneNode._properties.size(); p < pcount; ++p)
         {
-            SceneNodeProperty& snp = sceneNode._properties[j];
+            SceneNodeProperty& snp = sceneNode._properties[p];
             if (typeFlags & snp._type)
-                applyNodeProperty(sceneNode, node, sceneProperties, snp, scene);
+            {
+                for (unsigned int n = 0, ncount = sceneNode._nodes.size(); n < ncount; ++n)
+                    applyNodeProperty(sceneNode, sceneNode._nodes[n], sceneProperties, snp, scene);
+            }
         }
     }
 }
@@ -191,6 +201,10 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             break;
         }
         case SceneNodeProperty::MATERIAL:
+            {
+                const char* id = node->getId();
+                id = NULL;
+            }
             if (!node->getModel())
             {
                 GP_ERROR("Attempting to set a material on node '%s', which has no model.", sceneNode._nodeID);
@@ -299,16 +313,6 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
                 node->setScale(s);
             break;
         }
-        case SceneNodeProperty::TRANSPARENT:
-        {
-            node->setTransparent(true);
-            break;
-        }
-        case SceneNodeProperty::DYNAMIC:
-        {
-            node->setDynamic(true);
-            break;
-        }
         default:
             GP_ERROR("Unsupported node property type (%d).", snp._type);
             break;
@@ -328,12 +332,15 @@ void SceneLoader::applyNodeUrls(Scene* scene)
 
         // Iterate backwards over the properties list so we can remove properties as we go
         // without danger of indexing out of bounds.
+        bool hasURL = false;
         for (int j = sceneNode._properties.size() - 1; j >= 0; --j)
         {
             SceneNodeProperty& snp = sceneNode._properties[j];
             if (snp._type != SceneNodeProperty::URL)
                 continue;
 
+            hasURL = true;
+
             std::string file;
             std::string id;
             splitURL(snp._url, &file, &id);
@@ -344,19 +351,45 @@ void SceneLoader::applyNodeUrls(Scene* scene)
 
                 // 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?
-                Node* node = scene->findNode(id.c_str());
-                if (node)
+                if (sceneNode._exactMatch)
                 {
-                    node->setId(sceneNode._nodeID);
+                    Node* node = scene->findNode(id.c_str());
+                    if (node)
+                    {
+                        node->setId(sceneNode._nodeID);
+                    }
+                    else
+                    {
+                        GP_ERROR("Could not find node '%s' in main scene GPB file.", id.c_str());
+                    }
+                    sceneNode._nodes.push_back(node);
                 }
                 else
                 {
-                    GP_ERROR("Could not find node '%s' in main scene GPB file.", id.c_str());
+                    // Search for nodes using a partial match
+                    std::vector<Node*> nodes;
+                    unsigned int nodeCount = scene->findNodes(id.c_str(), nodes, true, false);
+                    if (nodeCount > 0)
+                    {
+                        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];
+                            std::string newID(sceneNode._nodeID);
+                            newID += (node->getId() + id.length());
+                            node->setId(newID.c_str());
+                            sceneNode._nodes.push_back(node);
+                        }
+                    }
+                    else
+                    {
+                        GP_ERROR("Could not find any nodes matching '%s' in main scene GPB file.", id.c_str());
+                    }
                 }
             }
             else
             {
-                // An external file was referenced, so load the node from file and then insert it into the scene with the new ID.
+                // An external file was referenced, so load the node(s) from file and then insert it into the scene with the new ID.
 
                 // 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
@@ -364,16 +397,51 @@ void SceneLoader::applyNodeUrls(Scene* scene)
                 Bundle* tmpBundle = Bundle::create(file.c_str());
                 if (tmpBundle)
                 {
-                    Node* node = tmpBundle->loadNode(id.c_str(), scene);
-                    if (node)
+                    if (sceneNode._exactMatch)
                     {
-                        node->setId(sceneNode._nodeID);
-                        scene->addNode(node);
-                        SAFE_RELEASE(node);
+                        Node* node = tmpBundle->loadNode(id.c_str(), scene);
+                        if (node)
+                        {
+                            node->setId(sceneNode._nodeID);
+                            scene->addNode(node);
+                            sceneNode._nodes.push_back(node);
+                            SAFE_RELEASE(node);
+                        }
+                        else
+                        {
+                            GP_ERROR("Could not load node '%s' from GPB file '%s'.", id.c_str(), file.c_str());
+                        }
                     }
                     else
                     {
-                        GP_ERROR("Could not load node '%s' from GPB file '%s'.", id.c_str(), file.c_str());
+                        // Search for nodes in the package using a partial match
+                        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, 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() + id.length());
+                                    node->setId(newID.c_str());
+                                    scene->addNode(node);
+                                    sceneNode._nodes.push_back(node);
+                                    SAFE_RELEASE(node);
+                                    matchCount++;
+                                }
+                            }
+                        }
+                        if (matchCount == 0)
+                        {
+                            GP_ERROR("Could not find any nodes matching '%s' in GPB file '%s'.", id.c_str(), file.c_str());
+                        }
                     }
 
                     SAFE_RELEASE(tmpBundle);
@@ -384,8 +452,25 @@ void SceneLoader::applyNodeUrls(Scene* scene)
                 }
             }
 
-            // Remove the node property since we are done applying it.
+            // Remove the 'url' node property since we are done applying it.
             sceneNode._properties.erase(sceneNode._properties.begin() + j);
+
+            // Processed URL property, no need to inspect remaining properties
+            break;
+        }
+
+        if (!hasURL)
+        {
+            // No explicit URL, find the node in the main scene with the existing ID
+            Node* node = scene->findNode(sceneNode._nodeID);
+            if (node)
+            {
+                sceneNode._nodes.push_back(node);
+            }
+            else
+            {
+                GP_ERROR("Failed to locate node with id '%s' in bundle '%s'.", sceneNode._nodeID, _gpbPath.c_str());
+            }
         }
     }
 }
@@ -439,6 +524,13 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::COLLISION_OBJECT, propertyUrl.c_str());
                     _properties[propertyUrl] = subns;
                 }
+                else if (strcmp(subns->getNamespace(), "tags") == 0)
+                {
+                    while ((name = subns->getNextProperty()) != NULL)
+                    {
+                        sceneNode._tags[name] = subns->getString();
+                    }
+                }
                 else
                 {
                     GP_ERROR("Unsupported child namespace '%s' of 'node' namespace.", subns->getNamespace());
@@ -492,14 +584,6 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::SCALE);
                 }
-                else if (strcmp(name, "transparent") == 0)
-                {
-                    addSceneNodeProperty(sceneNode, SceneNodeProperty::TRANSPARENT);
-                }
-                else if (strcmp(name, "dynamic") == 0)
-                {
-                    addSceneNodeProperty(sceneNode, SceneNodeProperty::DYNAMIC);
-                }
                 else
                 {
                     GP_ERROR("Unsupported node property: %s = %s", name, ns->getString());
@@ -1007,4 +1091,14 @@ void splitURL(const std::string& url, std::string* file, std::string* id)
     }
 }
 
+SceneLoader::SceneNode::SceneNode()
+    : _nodeID(""), _exactMatch(true)
+{
+}
+
+SceneLoader::SceneNodeProperty::SceneNodeProperty(Type type, std::string url, int index)
+    : _type(type), _url(url), _index(index)
+{
+}
+
 }

+ 30 - 28
gameplay/src/SceneLoader.h

@@ -53,12 +53,10 @@ private:
             TRANSLATE = 16,
             ROTATE = 32,
             SCALE = 64,
-            URL = 128,
-            TRANSPARENT = 256,
-            DYNAMIC = 512
+            URL = 128
         };
 
-        SceneNodeProperty(Type type, std::string url, int index) : _type(type), _url(url), _index(index) { }
+        SceneNodeProperty(Type type, std::string url, int index);
 
         Type _type;
         std::string _url;
@@ -67,49 +65,53 @@ private:
 
     struct SceneNode
     {
-        SceneNode() : _nodeID("") { }
+        SceneNode();
 
         const char* _nodeID;
+        bool _exactMatch;
+        std::vector<Node*> _nodes;
         std::vector<SceneNodeProperty> _properties;
+        std::map<std::string, std::string> _tags;
     };
 
-    static void addSceneAnimation(const char* animationID, const char* targetID, const char* url);
+    Scene* loadInternal(const char* url);
 
-    static void addSceneNodeProperty(SceneNode& sceneNode, SceneNodeProperty::Type type, const char* url = NULL, int index = 0);
+    void addSceneAnimation(const char* animationID, const char* targetID, const char* url);
 
-    static void applyNodeProperties(const Scene* scene, const Properties* sceneProperties, unsigned int typeFlags);
+    void addSceneNodeProperty(SceneNode& sceneNode, SceneNodeProperty::Type type, const char* url = NULL, int index = 0);
 
-    static void applyNodeProperty(SceneNode& sceneNode, Node* node, const Properties* sceneProperties, const SceneNodeProperty& snp, const Scene* scene);
+    void applyNodeProperties(const Scene* scene, const Properties* sceneProperties, unsigned int typeFlags);
 
-    static void applyNodeUrls(Scene* scene);
+    void applyNodeProperty(SceneNode& sceneNode, Node* node, const Properties* sceneProperties, const SceneNodeProperty& snp, const Scene* scene);
 
-    static void buildReferenceTables(Properties* sceneProperties);
+    void applyNodeUrls(Scene* scene);
 
-    static void calculateNodesWithMeshRigidBodies(const Properties* sceneProperties);
+    void buildReferenceTables(Properties* sceneProperties);
 
-    static void createAnimations(const Scene* scene);
+    void calculateNodesWithMeshRigidBodies(const Properties* sceneProperties);
 
-    static PhysicsConstraint* loadGenericConstraint(const Properties* constraint, PhysicsRigidBody* rbA, PhysicsRigidBody* rbB);
+    void createAnimations(const Scene* scene);
 
-    static PhysicsConstraint* loadHingeConstraint(const Properties* constraint, PhysicsRigidBody* rbA, PhysicsRigidBody* rbB);
+    PhysicsConstraint* loadGenericConstraint(const Properties* constraint, PhysicsRigidBody* rbA, PhysicsRigidBody* rbB);
 
-    static Scene* loadMainSceneData(const Properties* sceneProperties);
+    PhysicsConstraint* loadHingeConstraint(const Properties* constraint, PhysicsRigidBody* rbA, PhysicsRigidBody* rbB);
 
-    static void loadPhysics(Properties* physics, Scene* scene);
+    Scene* loadMainSceneData(const Properties* sceneProperties);
 
-    static void loadReferencedFiles();
+    void loadPhysics(Properties* physics, Scene* scene);
 
-    static PhysicsConstraint* loadSocketConstraint(const Properties* constraint, PhysicsRigidBody* rbA, PhysicsRigidBody* rbB);
+    void loadReferencedFiles();
 
-    static PhysicsConstraint* loadSpringConstraint(const Properties* constraint, PhysicsRigidBody* rbA, PhysicsRigidBody* rbB);
-    
-    
-    static std::map<std::string, Properties*> _propertiesFromFile;      // Holds the properties object for a given file.
-    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 _gpbPath;                                        // The path of the main GPB for the scene being loaded.
-    static std::string _path;                                           // The path of the scene file being loaded.
+    PhysicsConstraint* loadSocketConstraint(const Properties* constraint, PhysicsRigidBody* rbA, PhysicsRigidBody* rbB);
+
+    PhysicsConstraint* loadSpringConstraint(const Properties* constraint, PhysicsRigidBody* rbA, PhysicsRigidBody* rbB);
+
+    std::map<std::string, Properties*> _propertiesFromFile;      // Holds the properties object for a given file.
+    std::map<std::string, Properties*> _properties;              // Holds the properties object for a given URL.
+    std::vector<SceneAnimation> _animations;                     // Holds the animations declared in the .scene file.
+    std::vector<SceneNode> _sceneNodes;                          // Holds all the nodes+properties declared in the .scene file.
+    std::string _gpbPath;                                        // The path of the main GPB for the scene being loaded.
+    std::string _path;                                           // The path of the scene file being loaded.
 };
 
 /**

+ 97 - 181
gameplay/src/lua/lua_Joint.cpp

@@ -81,6 +81,7 @@ void luaRegister_Joint()
         {"getScaleY", lua_Joint_getScaleY},
         {"getScaleZ", lua_Joint_getScaleZ},
         {"getScene", lua_Joint_getScene},
+        {"getTag", lua_Joint_getTag},
         {"getTranslation", lua_Joint_getTranslation},
         {"getTranslationView", lua_Joint_getTranslationView},
         {"getTranslationWorld", lua_Joint_getTranslationWorld},
@@ -95,9 +96,7 @@ void luaRegister_Joint()
         {"getWorldMatrix", lua_Joint_getWorldMatrix},
         {"getWorldViewMatrix", lua_Joint_getWorldViewMatrix},
         {"getWorldViewProjectionMatrix", lua_Joint_getWorldViewProjectionMatrix},
-        {"isDynamic", lua_Joint_isDynamic},
-        {"isTransparent", lua_Joint_isTransparent},
-        {"isVisible", lua_Joint_isVisible},
+        {"hasTag", lua_Joint_hasTag},
         {"release", lua_Joint_release},
         {"removeAllChildren", lua_Joint_removeAllChildren},
         {"removeChild", lua_Joint_removeChild},
@@ -117,7 +116,6 @@ void luaRegister_Joint()
         {"setAudioSource", lua_Joint_setAudioSource},
         {"setCamera", lua_Joint_setCamera},
         {"setCollisionObject", lua_Joint_setCollisionObject},
-        {"setDynamic", lua_Joint_setDynamic},
         {"setForm", lua_Joint_setForm},
         {"setId", lua_Joint_setId},
         {"setIdentity", lua_Joint_setIdentity},
@@ -129,12 +127,11 @@ void luaRegister_Joint()
         {"setScaleX", lua_Joint_setScaleX},
         {"setScaleY", lua_Joint_setScaleY},
         {"setScaleZ", lua_Joint_setScaleZ},
+        {"setTag", lua_Joint_setTag},
         {"setTranslation", lua_Joint_setTranslation},
         {"setTranslationX", lua_Joint_setTranslationX},
         {"setTranslationY", lua_Joint_setTranslationY},
         {"setTranslationZ", lua_Joint_setTranslationZ},
-        {"setTransparent", lua_Joint_setTransparent},
-        {"setVisible", lua_Joint_setVisible},
         {"transformPoint", lua_Joint_transformPoint},
         {"transformVector", lua_Joint_transformVector},
         {"translate", lua_Joint_translate},
@@ -3064,6 +3061,47 @@ int lua_Joint_getScene(lua_State* state)
     return 0;
 }
 
+int lua_Joint_getTag(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(2, false);
+
+                Joint* instance = getInstance(state);
+                const char* result = instance->getTag(param1);
+
+                // Push the return value onto the stack.
+                lua_pushstring(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_Joint_getTag - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_Joint_getTranslation(lua_State* state)
 {
     // Get the number of parameters.
@@ -3712,7 +3750,7 @@ int lua_Joint_getWorldViewProjectionMatrix(lua_State* state)
     return 0;
 }
 
-int lua_Joint_isDynamic(lua_State* state)
+int lua_Joint_hasTag(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -3720,86 +3758,16 @@ int lua_Joint_isDynamic(lua_State* state)
     // Attempt to match the parameters to a valid binding.
     switch (paramCount)
     {
-        case 1:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
-                Joint* instance = getInstance(state);
-                bool result = instance->isDynamic();
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-            else
-            {
-                lua_pushstring(state, "lua_Joint_isDynamic - Failed to match the given parameters to a valid function signature.");
-                lua_error(state);
-            }
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Joint_isTransparent(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 1:
+        case 2:
         {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
-                Joint* instance = getInstance(state);
-                bool result = instance->isTransparent();
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-            else
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
             {
-                lua_pushstring(state, "lua_Joint_isTransparent - Failed to match the given parameters to a valid function signature.");
-                lua_error(state);
-            }
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Joint_isVisible(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(2, false);
 
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 1:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
                 Joint* instance = getInstance(state);
-                bool result = instance->isVisible();
+                bool result = instance->hasTag(param1);
 
                 // Push the return value onto the stack.
                 lua_pushboolean(state, result);
@@ -3808,14 +3776,14 @@ int lua_Joint_isVisible(lua_State* state)
             }
             else
             {
-                lua_pushstring(state, "lua_Joint_isVisible - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Joint_hasTag - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
         default:
         {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
             lua_error(state);
             break;
         }
@@ -4892,44 +4860,6 @@ int lua_Joint_setCollisionObject(lua_State* state)
     return 0;
 }
 
-int lua_Joint_setDynamic(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 2:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TBOOLEAN)
-            {
-                // Get parameter 1 off the stack.
-                bool param1 = ScriptUtil::luaCheckBool(state, 2);
-
-                Joint* instance = getInstance(state);
-                instance->setDynamic(param1);
-                
-                return 0;
-            }
-            else
-            {
-                lua_pushstring(state, "lua_Joint_setDynamic - Failed to match the given parameters to a valid function signature.");
-                lua_error(state);
-            }
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 2).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
 int lua_Joint_setForm(lua_State* state)
 {
     // Get the number of parameters.
@@ -5450,7 +5380,7 @@ int lua_Joint_setScaleZ(lua_State* state)
     return 0;
 }
 
-int lua_Joint_setTranslation(lua_State* state)
+int lua_Joint_setTag(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5461,54 +5391,50 @@ int lua_Joint_setTranslation(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                (lua_type(state, 2) == LUA_TUSERDATA || lua_type(state, 2) == LUA_TNIL))
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
             {
                 // Get parameter 1 off the stack.
-                Vector3* param1 = ScriptUtil::getObjectPointer<Vector3>(2, "Vector3", true);
+                const char* param1 = ScriptUtil::getString(2, false);
 
                 Joint* instance = getInstance(state);
-                instance->setTranslation(*param1);
+                instance->setTag(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Joint_setTranslation - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Joint_setTag - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
-        case 4:
+        case 3:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER &&
-                lua_type(state, 3) == LUA_TNUMBER &&
-                lua_type(state, 4) == LUA_TNUMBER)
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL) &&
+                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL))
             {
                 // Get parameter 1 off the stack.
-                float param1 = (float)luaL_checknumber(state, 2);
+                const char* param1 = ScriptUtil::getString(2, false);
 
                 // Get parameter 2 off the stack.
-                float param2 = (float)luaL_checknumber(state, 3);
-
-                // Get parameter 3 off the stack.
-                float param3 = (float)luaL_checknumber(state, 4);
+                const char* param2 = ScriptUtil::getString(3, false);
 
                 Joint* instance = getInstance(state);
-                instance->setTranslation(param1, param2, param3);
+                instance->setTag(param1, param2);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Joint_setTranslation - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Joint_setTag - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
         default:
         {
-            lua_pushstring(state, "Invalid number of parameters (expected 2 or 4).");
+            lua_pushstring(state, "Invalid number of parameters (expected 2 or 3).");
             lua_error(state);
             break;
         }
@@ -5516,7 +5442,7 @@ int lua_Joint_setTranslation(lua_State* state)
     return 0;
 }
 
-int lua_Joint_setTranslationX(lua_State* state)
+int lua_Joint_setTranslation(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5527,64 +5453,54 @@ int lua_Joint_setTranslationX(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER)
+                (lua_type(state, 2) == LUA_TUSERDATA || lua_type(state, 2) == LUA_TNIL))
             {
                 // Get parameter 1 off the stack.
-                float param1 = (float)luaL_checknumber(state, 2);
+                Vector3* param1 = ScriptUtil::getObjectPointer<Vector3>(2, "Vector3", true);
 
                 Joint* instance = getInstance(state);
-                instance->setTranslationX(param1);
+                instance->setTranslation(*param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Joint_setTranslationX - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Joint_setTranslation - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 2).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Joint_setTranslationY(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 2:
+        case 4:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER)
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER &&
+                lua_type(state, 4) == LUA_TNUMBER)
             {
                 // Get parameter 1 off the stack.
                 float param1 = (float)luaL_checknumber(state, 2);
 
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 3);
+
+                // Get parameter 3 off the stack.
+                float param3 = (float)luaL_checknumber(state, 4);
+
                 Joint* instance = getInstance(state);
-                instance->setTranslationY(param1);
+                instance->setTranslation(param1, param2, param3);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Joint_setTranslationY - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Joint_setTranslation - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
         default:
         {
-            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_pushstring(state, "Invalid number of parameters (expected 2 or 4).");
             lua_error(state);
             break;
         }
@@ -5592,7 +5508,7 @@ int lua_Joint_setTranslationY(lua_State* state)
     return 0;
 }
 
-int lua_Joint_setTranslationZ(lua_State* state)
+int lua_Joint_setTranslationX(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5609,13 +5525,13 @@ int lua_Joint_setTranslationZ(lua_State* state)
                 float param1 = (float)luaL_checknumber(state, 2);
 
                 Joint* instance = getInstance(state);
-                instance->setTranslationZ(param1);
+                instance->setTranslationX(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Joint_setTranslationZ - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Joint_setTranslationX - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -5630,7 +5546,7 @@ int lua_Joint_setTranslationZ(lua_State* state)
     return 0;
 }
 
-int lua_Joint_setTransparent(lua_State* state)
+int lua_Joint_setTranslationY(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5641,19 +5557,19 @@ int lua_Joint_setTransparent(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TBOOLEAN)
+                lua_type(state, 2) == LUA_TNUMBER)
             {
                 // Get parameter 1 off the stack.
-                bool param1 = ScriptUtil::luaCheckBool(state, 2);
+                float param1 = (float)luaL_checknumber(state, 2);
 
                 Joint* instance = getInstance(state);
-                instance->setTransparent(param1);
+                instance->setTranslationY(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Joint_setTransparent - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Joint_setTranslationY - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -5668,7 +5584,7 @@ int lua_Joint_setTransparent(lua_State* state)
     return 0;
 }
 
-int lua_Joint_setVisible(lua_State* state)
+int lua_Joint_setTranslationZ(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5679,19 +5595,19 @@ int lua_Joint_setVisible(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TBOOLEAN)
+                lua_type(state, 2) == LUA_TNUMBER)
             {
                 // Get parameter 1 off the stack.
-                bool param1 = ScriptUtil::luaCheckBool(state, 2);
+                float param1 = (float)luaL_checknumber(state, 2);
 
                 Joint* instance = getInstance(state);
-                instance->setVisible(param1);
+                instance->setTranslationZ(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Joint_setVisible - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Joint_setTranslationZ - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;

+ 3 - 6
gameplay/src/lua/lua_Joint.h

@@ -59,6 +59,7 @@ int lua_Joint_getScaleX(lua_State* state);
 int lua_Joint_getScaleY(lua_State* state);
 int lua_Joint_getScaleZ(lua_State* state);
 int lua_Joint_getScene(lua_State* state);
+int lua_Joint_getTag(lua_State* state);
 int lua_Joint_getTranslation(lua_State* state);
 int lua_Joint_getTranslationView(lua_State* state);
 int lua_Joint_getTranslationWorld(lua_State* state);
@@ -73,9 +74,7 @@ int lua_Joint_getViewProjectionMatrix(lua_State* state);
 int lua_Joint_getWorldMatrix(lua_State* state);
 int lua_Joint_getWorldViewMatrix(lua_State* state);
 int lua_Joint_getWorldViewProjectionMatrix(lua_State* state);
-int lua_Joint_isDynamic(lua_State* state);
-int lua_Joint_isTransparent(lua_State* state);
-int lua_Joint_isVisible(lua_State* state);
+int lua_Joint_hasTag(lua_State* state);
 int lua_Joint_release(lua_State* state);
 int lua_Joint_removeAllChildren(lua_State* state);
 int lua_Joint_removeChild(lua_State* state);
@@ -95,7 +94,6 @@ int lua_Joint_setAnimationPropertyValue(lua_State* state);
 int lua_Joint_setAudioSource(lua_State* state);
 int lua_Joint_setCamera(lua_State* state);
 int lua_Joint_setCollisionObject(lua_State* state);
-int lua_Joint_setDynamic(lua_State* state);
 int lua_Joint_setForm(lua_State* state);
 int lua_Joint_setId(lua_State* state);
 int lua_Joint_setIdentity(lua_State* state);
@@ -107,12 +105,11 @@ int lua_Joint_setScale(lua_State* state);
 int lua_Joint_setScaleX(lua_State* state);
 int lua_Joint_setScaleY(lua_State* state);
 int lua_Joint_setScaleZ(lua_State* state);
+int lua_Joint_setTag(lua_State* state);
 int lua_Joint_setTranslation(lua_State* state);
 int lua_Joint_setTranslationX(lua_State* state);
 int lua_Joint_setTranslationY(lua_State* state);
 int lua_Joint_setTranslationZ(lua_State* state);
-int lua_Joint_setTransparent(lua_State* state);
-int lua_Joint_setVisible(lua_State* state);
 int lua_Joint_static_ANIMATE_ROTATE(lua_State* state);
 int lua_Joint_static_ANIMATE_ROTATE_TRANSLATE(lua_State* state);
 int lua_Joint_static_ANIMATE_SCALE(lua_State* state);

+ 97 - 181
gameplay/src/lua/lua_Node.cpp

@@ -79,6 +79,7 @@ void luaRegister_Node()
         {"getScaleY", lua_Node_getScaleY},
         {"getScaleZ", lua_Node_getScaleZ},
         {"getScene", lua_Node_getScene},
+        {"getTag", lua_Node_getTag},
         {"getTranslation", lua_Node_getTranslation},
         {"getTranslationView", lua_Node_getTranslationView},
         {"getTranslationWorld", lua_Node_getTranslationWorld},
@@ -93,9 +94,7 @@ void luaRegister_Node()
         {"getWorldMatrix", lua_Node_getWorldMatrix},
         {"getWorldViewMatrix", lua_Node_getWorldViewMatrix},
         {"getWorldViewProjectionMatrix", lua_Node_getWorldViewProjectionMatrix},
-        {"isDynamic", lua_Node_isDynamic},
-        {"isTransparent", lua_Node_isTransparent},
-        {"isVisible", lua_Node_isVisible},
+        {"hasTag", lua_Node_hasTag},
         {"release", lua_Node_release},
         {"removeAllChildren", lua_Node_removeAllChildren},
         {"removeChild", lua_Node_removeChild},
@@ -115,7 +114,6 @@ void luaRegister_Node()
         {"setAudioSource", lua_Node_setAudioSource},
         {"setCamera", lua_Node_setCamera},
         {"setCollisionObject", lua_Node_setCollisionObject},
-        {"setDynamic", lua_Node_setDynamic},
         {"setForm", lua_Node_setForm},
         {"setId", lua_Node_setId},
         {"setIdentity", lua_Node_setIdentity},
@@ -127,12 +125,11 @@ void luaRegister_Node()
         {"setScaleX", lua_Node_setScaleX},
         {"setScaleY", lua_Node_setScaleY},
         {"setScaleZ", lua_Node_setScaleZ},
+        {"setTag", lua_Node_setTag},
         {"setTranslation", lua_Node_setTranslation},
         {"setTranslationX", lua_Node_setTranslationX},
         {"setTranslationY", lua_Node_setTranslationY},
         {"setTranslationZ", lua_Node_setTranslationZ},
-        {"setTransparent", lua_Node_setTransparent},
-        {"setVisible", lua_Node_setVisible},
         {"transformPoint", lua_Node_transformPoint},
         {"transformVector", lua_Node_transformVector},
         {"translate", lua_Node_translate},
@@ -3017,6 +3014,47 @@ int lua_Node_getScene(lua_State* state)
     return 0;
 }
 
+int lua_Node_getTag(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(2, false);
+
+                Node* instance = getInstance(state);
+                const char* result = instance->getTag(param1);
+
+                // Push the return value onto the stack.
+                lua_pushstring(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_Node_getTag - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_Node_getTranslation(lua_State* state)
 {
     // Get the number of parameters.
@@ -3665,7 +3703,7 @@ int lua_Node_getWorldViewProjectionMatrix(lua_State* state)
     return 0;
 }
 
-int lua_Node_isDynamic(lua_State* state)
+int lua_Node_hasTag(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -3673,86 +3711,16 @@ int lua_Node_isDynamic(lua_State* state)
     // Attempt to match the parameters to a valid binding.
     switch (paramCount)
     {
-        case 1:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
-                Node* instance = getInstance(state);
-                bool result = instance->isDynamic();
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-            else
-            {
-                lua_pushstring(state, "lua_Node_isDynamic - Failed to match the given parameters to a valid function signature.");
-                lua_error(state);
-            }
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Node_isTransparent(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 1:
+        case 2:
         {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
-                Node* instance = getInstance(state);
-                bool result = instance->isTransparent();
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-            else
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
             {
-                lua_pushstring(state, "lua_Node_isTransparent - Failed to match the given parameters to a valid function signature.");
-                lua_error(state);
-            }
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Node_isVisible(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(2, false);
 
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 1:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
                 Node* instance = getInstance(state);
-                bool result = instance->isVisible();
+                bool result = instance->hasTag(param1);
 
                 // Push the return value onto the stack.
                 lua_pushboolean(state, result);
@@ -3761,14 +3729,14 @@ int lua_Node_isVisible(lua_State* state)
             }
             else
             {
-                lua_pushstring(state, "lua_Node_isVisible - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Node_hasTag - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
         default:
         {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
             lua_error(state);
             break;
         }
@@ -4845,44 +4813,6 @@ int lua_Node_setCollisionObject(lua_State* state)
     return 0;
 }
 
-int lua_Node_setDynamic(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 2:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TBOOLEAN)
-            {
-                // Get parameter 1 off the stack.
-                bool param1 = ScriptUtil::luaCheckBool(state, 2);
-
-                Node* instance = getInstance(state);
-                instance->setDynamic(param1);
-                
-                return 0;
-            }
-            else
-            {
-                lua_pushstring(state, "lua_Node_setDynamic - Failed to match the given parameters to a valid function signature.");
-                lua_error(state);
-            }
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 2).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
 int lua_Node_setForm(lua_State* state)
 {
     // Get the number of parameters.
@@ -5403,7 +5333,7 @@ int lua_Node_setScaleZ(lua_State* state)
     return 0;
 }
 
-int lua_Node_setTranslation(lua_State* state)
+int lua_Node_setTag(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5414,54 +5344,50 @@ int lua_Node_setTranslation(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                (lua_type(state, 2) == LUA_TUSERDATA || lua_type(state, 2) == LUA_TNIL))
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
             {
                 // Get parameter 1 off the stack.
-                Vector3* param1 = ScriptUtil::getObjectPointer<Vector3>(2, "Vector3", true);
+                const char* param1 = ScriptUtil::getString(2, false);
 
                 Node* instance = getInstance(state);
-                instance->setTranslation(*param1);
+                instance->setTag(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Node_setTranslation - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Node_setTag - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
-        case 4:
+        case 3:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER &&
-                lua_type(state, 3) == LUA_TNUMBER &&
-                lua_type(state, 4) == LUA_TNUMBER)
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL) &&
+                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL))
             {
                 // Get parameter 1 off the stack.
-                float param1 = (float)luaL_checknumber(state, 2);
+                const char* param1 = ScriptUtil::getString(2, false);
 
                 // Get parameter 2 off the stack.
-                float param2 = (float)luaL_checknumber(state, 3);
-
-                // Get parameter 3 off the stack.
-                float param3 = (float)luaL_checknumber(state, 4);
+                const char* param2 = ScriptUtil::getString(3, false);
 
                 Node* instance = getInstance(state);
-                instance->setTranslation(param1, param2, param3);
+                instance->setTag(param1, param2);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Node_setTranslation - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Node_setTag - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
         default:
         {
-            lua_pushstring(state, "Invalid number of parameters (expected 2 or 4).");
+            lua_pushstring(state, "Invalid number of parameters (expected 2 or 3).");
             lua_error(state);
             break;
         }
@@ -5469,7 +5395,7 @@ int lua_Node_setTranslation(lua_State* state)
     return 0;
 }
 
-int lua_Node_setTranslationX(lua_State* state)
+int lua_Node_setTranslation(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5480,64 +5406,54 @@ int lua_Node_setTranslationX(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER)
+                (lua_type(state, 2) == LUA_TUSERDATA || lua_type(state, 2) == LUA_TNIL))
             {
                 // Get parameter 1 off the stack.
-                float param1 = (float)luaL_checknumber(state, 2);
+                Vector3* param1 = ScriptUtil::getObjectPointer<Vector3>(2, "Vector3", true);
 
                 Node* instance = getInstance(state);
-                instance->setTranslationX(param1);
+                instance->setTranslation(*param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Node_setTranslationX - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Node_setTranslation - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 2).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Node_setTranslationY(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 2:
+        case 4:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER)
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER &&
+                lua_type(state, 4) == LUA_TNUMBER)
             {
                 // Get parameter 1 off the stack.
                 float param1 = (float)luaL_checknumber(state, 2);
 
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 3);
+
+                // Get parameter 3 off the stack.
+                float param3 = (float)luaL_checknumber(state, 4);
+
                 Node* instance = getInstance(state);
-                instance->setTranslationY(param1);
+                instance->setTranslation(param1, param2, param3);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Node_setTranslationY - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Node_setTranslation - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
         }
         default:
         {
-            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_pushstring(state, "Invalid number of parameters (expected 2 or 4).");
             lua_error(state);
             break;
         }
@@ -5545,7 +5461,7 @@ int lua_Node_setTranslationY(lua_State* state)
     return 0;
 }
 
-int lua_Node_setTranslationZ(lua_State* state)
+int lua_Node_setTranslationX(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5562,13 +5478,13 @@ int lua_Node_setTranslationZ(lua_State* state)
                 float param1 = (float)luaL_checknumber(state, 2);
 
                 Node* instance = getInstance(state);
-                instance->setTranslationZ(param1);
+                instance->setTranslationX(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Node_setTranslationZ - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Node_setTranslationX - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -5583,7 +5499,7 @@ int lua_Node_setTranslationZ(lua_State* state)
     return 0;
 }
 
-int lua_Node_setTransparent(lua_State* state)
+int lua_Node_setTranslationY(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5594,19 +5510,19 @@ int lua_Node_setTransparent(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TBOOLEAN)
+                lua_type(state, 2) == LUA_TNUMBER)
             {
                 // Get parameter 1 off the stack.
-                bool param1 = ScriptUtil::luaCheckBool(state, 2);
+                float param1 = (float)luaL_checknumber(state, 2);
 
                 Node* instance = getInstance(state);
-                instance->setTransparent(param1);
+                instance->setTranslationY(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Node_setTransparent - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Node_setTranslationY - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -5621,7 +5537,7 @@ int lua_Node_setTransparent(lua_State* state)
     return 0;
 }
 
-int lua_Node_setVisible(lua_State* state)
+int lua_Node_setTranslationZ(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -5632,19 +5548,19 @@ int lua_Node_setVisible(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TBOOLEAN)
+                lua_type(state, 2) == LUA_TNUMBER)
             {
                 // Get parameter 1 off the stack.
-                bool param1 = ScriptUtil::luaCheckBool(state, 2);
+                float param1 = (float)luaL_checknumber(state, 2);
 
                 Node* instance = getInstance(state);
-                instance->setVisible(param1);
+                instance->setTranslationZ(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_Node_setVisible - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_Node_setTranslationZ - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;

+ 3 - 6
gameplay/src/lua/lua_Node.h

@@ -58,6 +58,7 @@ int lua_Node_getScaleX(lua_State* state);
 int lua_Node_getScaleY(lua_State* state);
 int lua_Node_getScaleZ(lua_State* state);
 int lua_Node_getScene(lua_State* state);
+int lua_Node_getTag(lua_State* state);
 int lua_Node_getTranslation(lua_State* state);
 int lua_Node_getTranslationView(lua_State* state);
 int lua_Node_getTranslationWorld(lua_State* state);
@@ -72,9 +73,7 @@ int lua_Node_getViewProjectionMatrix(lua_State* state);
 int lua_Node_getWorldMatrix(lua_State* state);
 int lua_Node_getWorldViewMatrix(lua_State* state);
 int lua_Node_getWorldViewProjectionMatrix(lua_State* state);
-int lua_Node_isDynamic(lua_State* state);
-int lua_Node_isTransparent(lua_State* state);
-int lua_Node_isVisible(lua_State* state);
+int lua_Node_hasTag(lua_State* state);
 int lua_Node_release(lua_State* state);
 int lua_Node_removeAllChildren(lua_State* state);
 int lua_Node_removeChild(lua_State* state);
@@ -94,7 +93,6 @@ int lua_Node_setAnimationPropertyValue(lua_State* state);
 int lua_Node_setAudioSource(lua_State* state);
 int lua_Node_setCamera(lua_State* state);
 int lua_Node_setCollisionObject(lua_State* state);
-int lua_Node_setDynamic(lua_State* state);
 int lua_Node_setForm(lua_State* state);
 int lua_Node_setId(lua_State* state);
 int lua_Node_setIdentity(lua_State* state);
@@ -106,12 +104,11 @@ int lua_Node_setScale(lua_State* state);
 int lua_Node_setScaleX(lua_State* state);
 int lua_Node_setScaleY(lua_State* state);
 int lua_Node_setScaleZ(lua_State* state);
+int lua_Node_setTag(lua_State* state);
 int lua_Node_setTranslation(lua_State* state);
 int lua_Node_setTranslationX(lua_State* state);
 int lua_Node_setTranslationY(lua_State* state);
 int lua_Node_setTranslationZ(lua_State* state);
-int lua_Node_setTransparent(lua_State* state);
-int lua_Node_setVisible(lua_State* state);
 int lua_Node_static_ANIMATE_ROTATE(lua_State* state);
 int lua_Node_static_ANIMATE_ROTATE_TRANSLATE(lua_State* state);
 int lua_Node_static_ANIMATE_SCALE(lua_State* state);

+ 28 - 1
gameplay/src/lua/lua_Properties.cpp

@@ -181,9 +181,36 @@ int lua_Properties_getBool(lua_State* state)
             }
             break;
         }
+        case 3:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL) &&
+                lua_type(state, 3) == LUA_TBOOLEAN)
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(2, false);
+
+                // Get parameter 2 off the stack.
+                bool param2 = ScriptUtil::luaCheckBool(state, 3);
+
+                Properties* instance = getInstance(state);
+                bool result = instance->getBool(param1, param2);
+
+                // Push the return value onto the stack.
+                lua_pushboolean(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_Properties_getBool - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
         default:
         {
-            lua_pushstring(state, "Invalid number of parameters (expected 1 or 2).");
+            lua_pushstring(state, "Invalid number of parameters (expected 1, 2 or 3).");
             lua_error(state);
             break;
         }