Skip to content

Commit

Permalink
Merge pull request #1812 from benloong/fix_findNode
Browse files Browse the repository at this point in the history
fix findNode with mesh skin may lead to stack overflow.
  • Loading branch information
seanpaultaylor committed Jan 15, 2016
2 parents 01690d1 + bf3d182 commit c1893ab
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 21 deletions.
61 changes: 40 additions & 21 deletions gameplay/src/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,23 +218,32 @@ Node* Node::getRootNode() const
}

Node* Node::findNode(const char* id, bool recursive, bool exactMatch) const
{
return findNode(id, recursive, exactMatch, false);
}

Node* Node::findNode(const char* id, bool recursive, bool exactMatch, bool skipSkin) const
{
GP_ASSERT(id);

// If the drawable is a model with a mesh skin, search the skin's hierarchy as well.
Node* rootNode = NULL;
Model* model = dynamic_cast<Model*>(_drawable);
if (model)
// If not skipSkin hierarchy, try searching the skin hierarchy
if (!skipSkin)
{
if (model->getSkin() != NULL && (rootNode = model->getSkin()->_rootNode) != NULL)
// If the drawable is a model with a mesh skin, search the skin's hierarchy as well.
Node* 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, true);
if (match)
{
return match;
}
}
}
}
Expand All @@ -252,7 +261,7 @@ Node* Node::findNode(const char* id, bool recursive, bool exactMatch) const
{
for (Node* child = getFirstChild(); child != NULL; child = child->getNextSibling())
{
Node* match = child->findNode(id, true, exactMatch);
Node* match = child->findNode(id, true, exactMatch, skipSkin);
if (match)
{
return match;
Expand All @@ -263,25 +272,35 @@ Node* Node::findNode(const char* id, bool recursive, bool exactMatch) const
}

unsigned int Node::findNodes(const char* id, std::vector<Node*>& nodes, bool recursive, bool exactMatch) const
{
return findNodes(id, nodes, recursive, exactMatch, false);
}

unsigned int Node::findNodes(const char* id, std::vector<Node*>& nodes, bool recursive, bool exactMatch, bool skipSkin) const
{
GP_ASSERT(id);

// If the drawable is a model with a mesh skin, search the skin's hierarchy as well.
unsigned int count = 0;
Node* rootNode = NULL;
Model* model = dynamic_cast<Model*>(_drawable);
if (model)

if (!skipSkin)
{
if (model->getSkin() != NULL && (rootNode = model->getSkin()->_rootNode) != NULL)
Node* 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, recursive, exactMatch, true);
}
count += rootNode->findNodes(id, nodes, true, exactMatch);
}
}

// Search immediate children first.
for (Node* child = getFirstChild(); child != NULL; child = child->getNextSibling())
{
Expand All @@ -297,7 +316,7 @@ unsigned int Node::findNodes(const char* id, std::vector<Node*>& nodes, bool rec
{
for (Node* child = getFirstChild(); child != NULL; child = child->getNextSibling())
{
count += child->findNodes(id, nodes, true, exactMatch);
count += child->findNodes(id, nodes, recursive, exactMatch, skipSkin);
}
}

Expand Down
33 changes: 33 additions & 0 deletions gameplay/src/Node.h
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,39 @@ class Node : public Transform, public Ref
*/
void setBoundsDirty();

/**
* Returns the first child node that matches the given ID.
*
* This method checks the specified ID against its immediate child nodes
* but does not check the ID against itself.
* If recursive is true, it also traverses the Node's hierarchy with a breadth first search.
*
* @param id The ID of the child to find.
* @param recursive True to search recursively all the node's children, false for only direct children.
* @param exactMatch true if only nodes whose ID exactly matches the specified ID are returned,
* or false if nodes that start with the given ID are returned.
* @param skipSkin Set true to skip skin hierarchy, initial find may set false to include skin hierarchy.
*
* @return The Node found or NULL if not found.
*/
Node* findNode(const char* id, bool recursive, bool exactMatch, bool skipSkin) const;


/**
* Returns all child nodes that match the given ID.
*
* @param id The ID of the node to find.
* @param nodes A vector of nodes to be populated with matches.
* @param recursive true if a recursive search should be performed, false otherwise.
* @param exactMatch true if only nodes whose ID exactly matches the specified ID are returned,
* or false if nodes that start with the given ID are returned.
* @param skipSkin Set true to skip skin hierarchy, initial find may set false to include skin hierarchy.
*
* @return The number of matches found.
* @script{ignore}
*/
unsigned int findNodes(const char* id, std::vector<Node*>& nodes, bool recursive, bool exactMatch, bool skipSkin) const;

private:

/**
Expand Down

0 comments on commit c1893ab

Please sign in to comment.