|
|
@@ -10,6 +10,8 @@
|
|
|
#include "PhysicsCharacter.h"
|
|
|
#include "Terrain.h"
|
|
|
#include "Game.h"
|
|
|
+#include "Drawable.h"
|
|
|
+#include "Form.h"
|
|
|
|
|
|
// Node dirty flags
|
|
|
#define NODE_DIRTY_WORLD 1
|
|
|
@@ -20,13 +22,11 @@ namespace gameplay
|
|
|
{
|
|
|
|
|
|
Node::Node(const char* id)
|
|
|
- : _scene(NULL), _firstChild(NULL), _nextSibling(NULL), _prevSibling(NULL), _parent(NULL), _childCount(0),
|
|
|
- _enabled(true), _tags(NULL), _camera(NULL), _light(NULL), _model(NULL), _sprite(NULL), _tileset(NULL), _text(NULL),
|
|
|
- _form(NULL), _particleEmitter(NULL), _terrain(NULL), _audioSource(NULL), _collisionObject(NULL), _agent(NULL),
|
|
|
- _dirtyBits(NODE_DIRTY_ALL), _notifyHierarchyChanged(true), _userData(NULL)
|
|
|
+ : _scene(NULL), _firstChild(NULL), _nextSibling(NULL), _prevSibling(NULL), _parent(NULL), _childCount(0), _enabled(true), _tags(NULL),
|
|
|
+ _drawable(NULL), _camera(NULL), _light(NULL), _audioSource(NULL), _collisionObject(NULL), _agent(NULL),
|
|
|
+ _dirtyBits(NODE_DIRTY_ALL), _notifyHierarchyChanged(true)
|
|
|
{
|
|
|
GP_REGISTER_SCRIPT_EVENTS();
|
|
|
-
|
|
|
if (id)
|
|
|
{
|
|
|
_id = id;
|
|
|
@@ -37,38 +37,18 @@ Node::~Node()
|
|
|
{
|
|
|
removeAllChildren();
|
|
|
|
|
|
- if (_model)
|
|
|
- _model->setNode(NULL);
|
|
|
+ if (_drawable)
|
|
|
+ _drawable->setNode(NULL);
|
|
|
if (_audioSource)
|
|
|
_audioSource->setNode(NULL);
|
|
|
- if (_particleEmitter)
|
|
|
- _particleEmitter->setNode(NULL);
|
|
|
- if (_form)
|
|
|
- _form->setNode(NULL);
|
|
|
-
|
|
|
+ Ref* ref = dynamic_cast<Ref*>(_drawable);
|
|
|
+ SAFE_RELEASE(ref);
|
|
|
SAFE_RELEASE(_camera);
|
|
|
SAFE_RELEASE(_light);
|
|
|
- SAFE_RELEASE(_model);
|
|
|
- SAFE_RELEASE(_terrain);
|
|
|
SAFE_RELEASE(_audioSource);
|
|
|
- SAFE_RELEASE(_particleEmitter);
|
|
|
- SAFE_RELEASE(_sprite);
|
|
|
- SAFE_RELEASE(_tileset);
|
|
|
- SAFE_RELEASE(_text);
|
|
|
- SAFE_RELEASE(_form);
|
|
|
SAFE_DELETE(_collisionObject);
|
|
|
SAFE_DELETE(_tags);
|
|
|
-
|
|
|
setAgent(NULL);
|
|
|
-
|
|
|
- // Cleanup user data
|
|
|
- if (_userData)
|
|
|
- {
|
|
|
- // Call custom cleanup callback if specified
|
|
|
- if (_userData->cleanupCallback)
|
|
|
- _userData->cleanupCallback(_userData->pointer);
|
|
|
- SAFE_DELETE(_userData);
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
Node* Node::create(const char* id)
|
|
|
@@ -232,130 +212,43 @@ Node* Node::getParent() const
|
|
|
return _parent;
|
|
|
}
|
|
|
|
|
|
-bool Node::hasTag(const char* name) const
|
|
|
-{
|
|
|
- GP_ASSERT(name);
|
|
|
-
|
|
|
- return (_tags ? _tags->find(name) != _tags->end() : false);
|
|
|
-}
|
|
|
-
|
|
|
-const char* Node::getTag(const char* name) const
|
|
|
-{
|
|
|
- GP_ASSERT(name);
|
|
|
-
|
|
|
- if (!_tags)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- std::map<std::string, std::string>::const_iterator itr = _tags->find(name);
|
|
|
- return (itr == _tags->end() ? NULL : itr->second.c_str());
|
|
|
-}
|
|
|
-
|
|
|
-void Node::setTag(const char* name, const char* value)
|
|
|
-{
|
|
|
- GP_ASSERT(name);
|
|
|
-
|
|
|
- if (value == NULL)
|
|
|
- {
|
|
|
- // Removing tag
|
|
|
- if (_tags)
|
|
|
- {
|
|
|
- _tags->erase(name);
|
|
|
- if (_tags->size() == 0)
|
|
|
- SAFE_DELETE(_tags);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Setting tag
|
|
|
- if (_tags == NULL)
|
|
|
- _tags = new std::map<std::string, std::string>();
|
|
|
-
|
|
|
- (*_tags)[name] = value;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void* Node::getUserPointer() const
|
|
|
-{
|
|
|
- return (_userData ? _userData->pointer : NULL);
|
|
|
-}
|
|
|
-
|
|
|
-void Node::setUserPointer(void* pointer, void (*cleanupCallback)(void*))
|
|
|
+unsigned int Node::getChildCount() const
|
|
|
{
|
|
|
- // If existing user pointer is being changed, call cleanup function to free previous pointer
|
|
|
- if (_userData && _userData->pointer && _userData->cleanupCallback && pointer != _userData->pointer)
|
|
|
- {
|
|
|
- _userData->cleanupCallback(_userData->pointer);
|
|
|
- }
|
|
|
-
|
|
|
- if (pointer)
|
|
|
- {
|
|
|
- // Assign user pointer
|
|
|
- if (_userData == NULL)
|
|
|
- _userData = new UserData();
|
|
|
-
|
|
|
- _userData->pointer = pointer;
|
|
|
- _userData->cleanupCallback = cleanupCallback;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Clear user pointer
|
|
|
- SAFE_DELETE(_userData);
|
|
|
- }
|
|
|
+ return _childCount;
|
|
|
}
|
|
|
|
|
|
-void Node::setEnabled(bool enabled)
|
|
|
+Node* Node::getRootNode() const
|
|
|
{
|
|
|
- if (_enabled != enabled)
|
|
|
+ Node* n = const_cast<Node*>(this);
|
|
|
+ while (n->getParent())
|
|
|
{
|
|
|
- if (_collisionObject)
|
|
|
- _collisionObject->setEnabled(enabled);
|
|
|
-
|
|
|
- _enabled = enabled;
|
|
|
+ n = n->getParent();
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-bool Node::isEnabled() const
|
|
|
-{
|
|
|
- return _enabled;
|
|
|
-}
|
|
|
-
|
|
|
-bool Node::isEnabledInHierarchy() const
|
|
|
-{
|
|
|
- if (!_enabled)
|
|
|
- return false;
|
|
|
- Node* node = _parent;
|
|
|
- while (node)
|
|
|
- {
|
|
|
- if (!node->_enabled)
|
|
|
- return false;
|
|
|
- node = node->_parent;
|
|
|
- }
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-unsigned int Node::getChildCount() const
|
|
|
-{
|
|
|
- return _childCount;
|
|
|
+ return n;
|
|
|
}
|
|
|
|
|
|
Node* Node::findNode(const char* id, bool recursive, bool exactMatch) const
|
|
|
{
|
|
|
GP_ASSERT(id);
|
|
|
|
|
|
- // If the node has a model with a mesh skin, search the skin's hierarchy as well.
|
|
|
+ // If the drawable is a model with a mesh skin, search the skin's hierarchy as well.
|
|
|
Node* rootNode = NULL;
|
|
|
- if (_model != NULL && _model->getSkin() != NULL && (rootNode = _model->getSkin()->_rootNode) != NULL)
|
|
|
+ Model* model = dynamic_cast<Model*>(_drawable);
|
|
|
+ if (model)
|
|
|
{
|
|
|
- if ((exactMatch && rootNode->_id == id) || (!exactMatch && rootNode->_id.find(id) == 0))
|
|
|
- return rootNode;
|
|
|
-
|
|
|
- Node* match = rootNode->findNode(id, true, exactMatch);
|
|
|
- if (match)
|
|
|
+ if (model->getSkin() != NULL && (rootNode = model->getSkin()->_rootNode) != NULL)
|
|
|
{
|
|
|
- return match;
|
|
|
+ if ((exactMatch && rootNode->_id == id) || (!exactMatch && rootNode->_id.find(id) == 0))
|
|
|
+ return rootNode;
|
|
|
+
|
|
|
+ Node* match = rootNode->findNode(id, true, exactMatch);
|
|
|
+ if (match)
|
|
|
+ {
|
|
|
+ return match;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Search immediate children first.
|
|
|
for (Node* child = getFirstChild(); child != NULL; child = child->getNextSibling())
|
|
|
{
|
|
|
@@ -380,22 +273,26 @@ Node* Node::findNode(const char* id, bool recursive, bool exactMatch) const
|
|
|
}
|
|
|
|
|
|
return NULL;
|
|
|
-}
|
|
|
+}
|
|
|
|
|
|
unsigned int Node::findNodes(const char* id, std::vector<Node*>& nodes, bool recursive, bool exactMatch) const
|
|
|
{
|
|
|
GP_ASSERT(id);
|
|
|
-
|
|
|
+
|
|
|
unsigned int count = 0;
|
|
|
|
|
|
- // If the node has a model with a mesh skin, search the skin's hierarchy as well.
|
|
|
+ // If the drawable is a model with a mesh skin, search the skin's hierarchy as well.
|
|
|
Node* rootNode = NULL;
|
|
|
- if (_model != NULL && _model->getSkin() != NULL && (rootNode = _model->getSkin()->_rootNode) != NULL)
|
|
|
+ Model* model = dynamic_cast<Model*>(_drawable);
|
|
|
+ if (model)
|
|
|
{
|
|
|
- if ((exactMatch && rootNode->_id == id) || (!exactMatch && rootNode->_id.find(id) == 0))
|
|
|
+ if (model->getSkin() != NULL && (rootNode = model->getSkin()->_rootNode) != NULL)
|
|
|
{
|
|
|
- nodes.push_back(rootNode);
|
|
|
- ++count;
|
|
|
+ if ((exactMatch && rootNode->_id == id) || (!exactMatch && rootNode->_id.find(id) == 0))
|
|
|
+ {
|
|
|
+ nodes.push_back(rootNode);
|
|
|
+ ++count;
|
|
|
+ }
|
|
|
}
|
|
|
count += rootNode->findNodes(id, nodes, true, exactMatch);
|
|
|
}
|
|
|
@@ -439,14 +336,83 @@ Scene* Node::getScene() const
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-Node* Node::getRootNode() const
|
|
|
+bool Node::hasTag(const char* name) const
|
|
|
{
|
|
|
- Node* n = const_cast<Node*>(this);
|
|
|
- while (n->getParent())
|
|
|
+ GP_ASSERT(name);
|
|
|
+
|
|
|
+ return (_tags ? _tags->find(name) != _tags->end() : false);
|
|
|
+}
|
|
|
+
|
|
|
+const char* Node::getTag(const char* name) const
|
|
|
+{
|
|
|
+ GP_ASSERT(name);
|
|
|
+
|
|
|
+ if (!_tags)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ std::map<std::string, std::string>::const_iterator itr = _tags->find(name);
|
|
|
+ return (itr == _tags->end() ? NULL : itr->second.c_str());
|
|
|
+}
|
|
|
+
|
|
|
+void Node::setTag(const char* name, const char* value)
|
|
|
+{
|
|
|
+ GP_ASSERT(name);
|
|
|
+
|
|
|
+ if (value == NULL)
|
|
|
{
|
|
|
- n = n->getParent();
|
|
|
+ // Removing tag
|
|
|
+ if (_tags)
|
|
|
+ {
|
|
|
+ _tags->erase(name);
|
|
|
+ if (_tags->size() == 0)
|
|
|
+ {
|
|
|
+ SAFE_DELETE(_tags);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- return n;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Setting tag
|
|
|
+ if (_tags == NULL)
|
|
|
+ {
|
|
|
+ _tags = new std::map<std::string, std::string>();
|
|
|
+ }
|
|
|
+ (*_tags)[name] = value;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Node::setEnabled(bool enabled)
|
|
|
+{
|
|
|
+ if (_enabled != enabled)
|
|
|
+ {
|
|
|
+ if (_collisionObject)
|
|
|
+ {
|
|
|
+ _collisionObject->setEnabled(enabled);
|
|
|
+ }
|
|
|
+ _enabled = enabled;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool Node::isEnabled() const
|
|
|
+{
|
|
|
+ return _enabled;
|
|
|
+}
|
|
|
+
|
|
|
+bool Node::isEnabledInHierarchy() const
|
|
|
+{
|
|
|
+ if (!_enabled)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ Node* node = _parent;
|
|
|
+ while (node)
|
|
|
+ {
|
|
|
+ if (!node->_enabled)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ node = node->_parent;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
void Node::update(float elapsedTime)
|
|
|
@@ -454,9 +420,10 @@ void Node::update(float elapsedTime)
|
|
|
for (Node* node = _firstChild; node != NULL; node = node->_nextSibling)
|
|
|
{
|
|
|
if (node->isEnabled())
|
|
|
+ {
|
|
|
node->update(elapsedTime);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(Node, update), dynamic_cast<void*>(this), elapsedTime);
|
|
|
}
|
|
|
|
|
|
@@ -502,9 +469,7 @@ const Matrix& Node::getWorldMatrix() const
|
|
|
const Matrix& Node::getWorldViewMatrix() const
|
|
|
{
|
|
|
static Matrix worldView;
|
|
|
-
|
|
|
Matrix::multiply(getViewMatrix(), getWorldMatrix(), &worldView);
|
|
|
-
|
|
|
return worldView;
|
|
|
}
|
|
|
|
|
|
@@ -590,18 +555,15 @@ const Matrix& Node::getInverseViewProjectionMatrix() const
|
|
|
{
|
|
|
return camera->getInverseViewProjectionMatrix();
|
|
|
}
|
|
|
-
|
|
|
return Matrix::identity();
|
|
|
}
|
|
|
|
|
|
const Matrix& Node::getWorldViewProjectionMatrix() const
|
|
|
{
|
|
|
- static Matrix worldViewProj;
|
|
|
-
|
|
|
// Always re-calculate worldViewProjection matrix since it's extremely difficult
|
|
|
// to track whether the camera has changed (it may frequently change every frame).
|
|
|
+ static Matrix worldViewProj;
|
|
|
Matrix::multiply(getViewProjectionMatrix(), getWorldMatrix(), &worldViewProj);
|
|
|
-
|
|
|
return worldViewProj;
|
|
|
}
|
|
|
|
|
|
@@ -736,7 +698,7 @@ Animation* Node::getAnimation(const char* id) const
|
|
|
return animation;
|
|
|
|
|
|
// See if this node has a model, then drill down.
|
|
|
- Model* model = this->getModel();
|
|
|
+ Model* model = dynamic_cast<Model*>(_drawable);
|
|
|
if (model)
|
|
|
{
|
|
|
// Check to see if there's any animations with the ID on the joints.
|
|
|
@@ -770,7 +732,7 @@ Animation* Node::getAnimation(const char* id) const
|
|
|
}
|
|
|
|
|
|
// look through form for animations.
|
|
|
- Form* form = this->getForm();
|
|
|
+ Form* form = dynamic_cast<Form*>(_drawable);
|
|
|
if (form)
|
|
|
{
|
|
|
animation = form->getAnimation(id);
|
|
|
@@ -841,181 +803,34 @@ void Node::setLight(Light* light)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-Model* Node::getModel() const
|
|
|
+Drawable* Node::getDrawable() const
|
|
|
{
|
|
|
- return _model;
|
|
|
+ return _drawable;
|
|
|
}
|
|
|
|
|
|
-void Node::setModel(Model* model)
|
|
|
+void Node::setDrawable(Drawable* drawable)
|
|
|
{
|
|
|
- if (_model != model)
|
|
|
+ if (_drawable != drawable)
|
|
|
{
|
|
|
- if (_model)
|
|
|
- {
|
|
|
- _model->setNode(NULL);
|
|
|
- SAFE_RELEASE(_model);
|
|
|
- }
|
|
|
-
|
|
|
- _model = model;
|
|
|
-
|
|
|
- if (_model)
|
|
|
+ if (_drawable)
|
|
|
{
|
|
|
- _model->addRef();
|
|
|
- _model->setNode(this);
|
|
|
+ _drawable->setNode(NULL);
|
|
|
+ Ref* ref = dynamic_cast<Ref*>(_drawable);
|
|
|
+ if (ref)
|
|
|
+ ref->release();
|
|
|
}
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
-Sprite* Node::getSprite() const
|
|
|
-{
|
|
|
- return _sprite;
|
|
|
-}
|
|
|
+ _drawable = drawable;
|
|
|
|
|
|
-void Node::setSprite(Sprite* sprite)
|
|
|
-{
|
|
|
- if (_sprite != sprite)
|
|
|
- {
|
|
|
- if (_sprite)
|
|
|
- {
|
|
|
- _sprite->setNode(NULL);
|
|
|
- SAFE_RELEASE(_sprite);
|
|
|
- }
|
|
|
-
|
|
|
- _sprite = sprite;
|
|
|
-
|
|
|
- if (_sprite)
|
|
|
+ if (_drawable)
|
|
|
{
|
|
|
- _sprite->addRef();
|
|
|
- _sprite->setNode(this);
|
|
|
+ Ref* ref = dynamic_cast<Ref*>(_drawable);
|
|
|
+ if (ref)
|
|
|
+ ref->addRef();
|
|
|
+ _drawable->setNode(this);
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-TileSet* Node::getTileSet() const
|
|
|
-{
|
|
|
- return _tileset;
|
|
|
-}
|
|
|
-
|
|
|
-void Node::setTileSet(TileSet* tileset)
|
|
|
-{
|
|
|
- if (_tileset != tileset)
|
|
|
- {
|
|
|
- if (_tileset)
|
|
|
- {
|
|
|
- _tileset->setNode(NULL);
|
|
|
- SAFE_RELEASE(_tileset);
|
|
|
- }
|
|
|
-
|
|
|
- _tileset = tileset;
|
|
|
-
|
|
|
- if (_tileset)
|
|
|
- {
|
|
|
- _tileset->addRef();
|
|
|
- _tileset->setNode(this);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-Text* Node::getText() const
|
|
|
-{
|
|
|
- return _text;
|
|
|
-}
|
|
|
-
|
|
|
-void Node::setText(Text* text)
|
|
|
-{
|
|
|
- if (_text != text)
|
|
|
- {
|
|
|
- if (_text)
|
|
|
- {
|
|
|
- _text->setNode(NULL);
|
|
|
- SAFE_RELEASE(_text);
|
|
|
- }
|
|
|
-
|
|
|
- _text = text;
|
|
|
-
|
|
|
- if (_text)
|
|
|
- {
|
|
|
- _text->addRef();
|
|
|
- _text->setNode(this);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-Form* Node::getForm() const
|
|
|
-{
|
|
|
- return _form;
|
|
|
-}
|
|
|
-
|
|
|
-void Node::setForm(Form* form)
|
|
|
-{
|
|
|
- if (_form != form)
|
|
|
- {
|
|
|
- if (_form)
|
|
|
- {
|
|
|
- _form->setNode(NULL);
|
|
|
- SAFE_RELEASE(_form);
|
|
|
- }
|
|
|
-
|
|
|
- _form = form;
|
|
|
-
|
|
|
- if (_form)
|
|
|
- {
|
|
|
- _form->addRef();
|
|
|
- _form->setNode(this);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-ParticleEmitter* Node::getParticleEmitter() const
|
|
|
-{
|
|
|
- return _particleEmitter;
|
|
|
-}
|
|
|
-
|
|
|
-void Node::setParticleEmitter(ParticleEmitter* emitter)
|
|
|
-{
|
|
|
- if (_particleEmitter != emitter)
|
|
|
- {
|
|
|
- if (_particleEmitter)
|
|
|
- {
|
|
|
- _particleEmitter->setNode(NULL);
|
|
|
- SAFE_RELEASE(_particleEmitter);
|
|
|
- }
|
|
|
-
|
|
|
- _particleEmitter = emitter;
|
|
|
-
|
|
|
- if (_particleEmitter)
|
|
|
- {
|
|
|
- _particleEmitter->addRef();
|
|
|
- _particleEmitter->setNode(this);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-Terrain* Node::getTerrain() const
|
|
|
-{
|
|
|
- return _terrain;
|
|
|
-}
|
|
|
-
|
|
|
-void Node::setTerrain(Terrain* terrain)
|
|
|
-{
|
|
|
- if (_terrain != terrain)
|
|
|
- {
|
|
|
- if (_terrain)
|
|
|
- {
|
|
|
- _terrain->setNode(NULL);
|
|
|
- SAFE_RELEASE(_terrain);
|
|
|
- }
|
|
|
-
|
|
|
- _terrain = terrain;
|
|
|
-
|
|
|
- if (_terrain)
|
|
|
- {
|
|
|
- _terrain->addRef();
|
|
|
- _terrain->setNode(this);
|
|
|
- }
|
|
|
-
|
|
|
- setBoundsDirty();
|
|
|
- }
|
|
|
+ setBoundsDirty();
|
|
|
}
|
|
|
|
|
|
const BoundingSphere& Node::getBoundingSphere() const
|
|
|
@@ -1027,23 +842,25 @@ const BoundingSphere& Node::getBoundingSphere() const
|
|
|
const Matrix& worldMatrix = getWorldMatrix();
|
|
|
|
|
|
// Start with our local bounding sphere
|
|
|
- // TODO: Incorporate bounds from entities other than mesh (i.e. emitters, audiosource, etc)
|
|
|
+ // TODO: Incorporate bounds from entities other than mesh (i.e. particleemitters, audiosource, etc)
|
|
|
bool empty = true;
|
|
|
- if (_terrain)
|
|
|
+ Terrain* terrain = dynamic_cast<Terrain*>(_drawable);
|
|
|
+ if (terrain)
|
|
|
{
|
|
|
- _bounds.set(_terrain->getBoundingBox());
|
|
|
+ _bounds.set(terrain->getBoundingBox());
|
|
|
empty = false;
|
|
|
}
|
|
|
- if (_model && _model->getMesh())
|
|
|
+ Model* model = dynamic_cast<Model*>(_drawable);
|
|
|
+ if (model && model->getMesh())
|
|
|
{
|
|
|
if (empty)
|
|
|
{
|
|
|
- _bounds.set(_model->getMesh()->getBoundingSphere());
|
|
|
+ _bounds.set(model->getMesh()->getBoundingSphere());
|
|
|
empty = false;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- _bounds.merge(_model->getMesh()->getBoundingSphere());
|
|
|
+ _bounds.merge(model->getMesh()->getBoundingSphere());
|
|
|
}
|
|
|
}
|
|
|
if (_light)
|
|
|
@@ -1077,7 +894,7 @@ const BoundingSphere& Node::getBoundingSphere() const
|
|
|
if (!empty)
|
|
|
{
|
|
|
bool applyWorldTransform = true;
|
|
|
- if (_model && _model->getSkin())
|
|
|
+ if (model && model->getSkin())
|
|
|
{
|
|
|
// Special case: If the root joint of our mesh skin is parented by any nodes,
|
|
|
// multiply the world matrix of the root joint's parent by this node's
|
|
|
@@ -1087,8 +904,8 @@ const BoundingSphere& Node::getBoundingSphere() const
|
|
|
// since joint parent nodes that are not in the matrix palette do not need to
|
|
|
// be considered as directly transforming vertices on the GPU (they can instead
|
|
|
// be applied directly to the bounding volume transformation below).
|
|
|
- GP_ASSERT(_model->getSkin()->getRootJoint());
|
|
|
- Node* jointParent = _model->getSkin()->getRootJoint()->getParent();
|
|
|
+ GP_ASSERT(model->getSkin()->getRootJoint());
|
|
|
+ Node* jointParent = model->getSkin()->getRootJoint()->getParent();
|
|
|
if (jointParent)
|
|
|
{
|
|
|
// TODO: Should we protect against the case where joints are nested directly
|
|
|
@@ -1158,72 +975,53 @@ Node* Node::cloneRecursive(NodeCloneContext &context) const
|
|
|
return copy;
|
|
|
}
|
|
|
|
|
|
-void Node::cloneInto(Node* node, NodeCloneContext &context) const
|
|
|
+void Node::cloneInto(Node* node, NodeCloneContext& context) const
|
|
|
{
|
|
|
GP_ASSERT(node);
|
|
|
- Transform::cloneInto(node, context);
|
|
|
|
|
|
- // TODO: Clone the rest of the node data.
|
|
|
+ Transform::cloneInto(node, context);
|
|
|
|
|
|
+ if (Drawable* drawable = getDrawable())
|
|
|
+ {
|
|
|
+ Drawable* clone = drawable->clone(context);
|
|
|
+ node->setDrawable(clone);
|
|
|
+ Ref* ref = dynamic_cast<Ref*>(clone);
|
|
|
+ if (ref)
|
|
|
+ ref->release();
|
|
|
+ }
|
|
|
if (Camera* camera = getCamera())
|
|
|
{
|
|
|
- Camera* cameraClone = camera->clone(context);
|
|
|
- node->setCamera(cameraClone);
|
|
|
- cameraClone->release();
|
|
|
+ Camera* clone = camera->clone(context);
|
|
|
+ node->setCamera(clone);
|
|
|
+ Ref* ref = dynamic_cast<Ref*>(clone);
|
|
|
+ if (ref)
|
|
|
+ ref->release();
|
|
|
}
|
|
|
if (Light* light = getLight())
|
|
|
{
|
|
|
- Light* lightClone = light->clone(context);
|
|
|
- node->setLight(lightClone);
|
|
|
- lightClone->release();
|
|
|
+ Light* clone = light->clone(context);
|
|
|
+ node->setLight(clone);
|
|
|
+ Ref* ref = dynamic_cast<Ref*>(clone);
|
|
|
+ if (ref)
|
|
|
+ ref->release();
|
|
|
}
|
|
|
if (AudioSource* audio = getAudioSource())
|
|
|
{
|
|
|
- AudioSource* audioClone = audio->clone(context);
|
|
|
- node->setAudioSource(audioClone);
|
|
|
- audioClone->release();
|
|
|
- }
|
|
|
- if (Model* model = getModel())
|
|
|
- {
|
|
|
- Model* modelClone = model->clone(context);
|
|
|
- node->setModel(modelClone);
|
|
|
- modelClone->release();
|
|
|
- }
|
|
|
- if (ParticleEmitter* emitter = getParticleEmitter())
|
|
|
- {
|
|
|
- ParticleEmitter* emitterClone = emitter->clone();
|
|
|
- node->setParticleEmitter(emitterClone);
|
|
|
- emitterClone->release();
|
|
|
+ AudioSource* clone = audio->clone(context);
|
|
|
+ node->setAudioSource(clone);
|
|
|
+ Ref* ref = dynamic_cast<Ref*>(clone);
|
|
|
+ if (ref)
|
|
|
+ ref->release();
|
|
|
}
|
|
|
- if (Sprite* sprite = getSprite())
|
|
|
- {
|
|
|
- Sprite* spriteClone = sprite->clone(context);
|
|
|
- node->setSprite(spriteClone);
|
|
|
- spriteClone->release();
|
|
|
- }
|
|
|
- if (TileSet* tileset = getTileSet())
|
|
|
- {
|
|
|
- TileSet* tilesetClone = tileset->clone(context);
|
|
|
- node->setTileSet(tilesetClone);
|
|
|
- tilesetClone->release();
|
|
|
- }
|
|
|
- if (Text* text = getText())
|
|
|
+ if (_tags)
|
|
|
{
|
|
|
- Text* textClone = text->clone(context);
|
|
|
- node->setText(textClone);
|
|
|
- textClone->release();
|
|
|
+ node->_tags = new std::map<std::string, std::string>(_tags->begin(), _tags->end());
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
node->_world = _world;
|
|
|
node->_bounds = _bounds;
|
|
|
|
|
|
- // Note: Do not clone _userData - we can't make any assumptions about its content and how it's managed,
|
|
|
- // so it's the caller's responsibility to clone user data if needed.
|
|
|
-
|
|
|
- if (_tags)
|
|
|
- {
|
|
|
- node->_tags = new std::map<std::string, std::string>(_tags->begin(), _tags->end());
|
|
|
- }
|
|
|
+ // TODO: Clone the rest of the node data.
|
|
|
}
|
|
|
|
|
|
AudioSource* Node::getAudioSource() const
|