mirror of https://github.com/axmolengine/axmol.git
Merge pull request #7039 from minggo/get-child-by-name
issue #4693: add getName(), setName() and getChildByName()
This commit is contained in:
commit
6ecca08340
|
@ -29,6 +29,8 @@ THE SOFTWARE.
|
|||
#include "2d/CCNode.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "base/CCDirector.h"
|
||||
#include "base/CCScheduler.h"
|
||||
|
@ -122,6 +124,8 @@ Node::Node(void)
|
|||
, _cascadeColorEnabled(false)
|
||||
, _cascadeOpacityEnabled(false)
|
||||
, _usingNormalizedPosition(false)
|
||||
, _name("")
|
||||
, _hashOfName(0)
|
||||
{
|
||||
// set default scheduler and actionManager
|
||||
Director *director = Director::getInstance();
|
||||
|
@ -624,6 +628,18 @@ void Node::setTag(int tag)
|
|||
_tag = tag ;
|
||||
}
|
||||
|
||||
std::string Node::getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
void Node::setName(const std::string& name)
|
||||
{
|
||||
_name = name;
|
||||
std::hash<std::string> h;
|
||||
_hashOfName = h(name);
|
||||
}
|
||||
|
||||
/// userData setter
|
||||
void Node::setUserData(void *userData)
|
||||
{
|
||||
|
@ -677,7 +693,7 @@ GLProgram * Node::getGLProgram() const
|
|||
return _glProgramState ? _glProgramState->getGLProgram() : nullptr;
|
||||
}
|
||||
|
||||
Scene* Node::getScene()
|
||||
Scene* Node::getScene() const
|
||||
{
|
||||
if(!_parent)
|
||||
return nullptr;
|
||||
|
@ -750,6 +766,159 @@ Node* Node::getChildByTag(int tag) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Node* Node::getChildByName(const std::string& name) const
|
||||
{
|
||||
CCASSERT(name.length() != 0, "Invalid name");
|
||||
|
||||
std::hash<std::string> h;
|
||||
size_t hash = h(name);
|
||||
|
||||
for (const auto& child : _children)
|
||||
{
|
||||
// Different strings may have the same hash code, but can use it to compare first for speed
|
||||
if(child->_hashOfName == hash && child->_name.compare(name) == 0)
|
||||
return child;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Node::enumerateChildren(const std::string &name, std::function<bool (Node *)> callback) const
|
||||
{
|
||||
CCASSERT(name.length() != 0, "Invalid name");
|
||||
CCASSERT(callback != nullptr, "Invalid callback function");
|
||||
|
||||
size_t length = name.length();
|
||||
|
||||
size_t subStrStartPos = 0; // sub string start index
|
||||
size_t subStrlength = length; // sub string length
|
||||
|
||||
// Starts with '/' or '//'?
|
||||
bool searchFromRoot = false;
|
||||
bool searchFromRootRecursive = false;
|
||||
if (name[0] == '/')
|
||||
{
|
||||
if (length > 2 && name[1] == '/')
|
||||
{
|
||||
searchFromRootRecursive = true;
|
||||
subStrStartPos = 2;
|
||||
subStrlength -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
searchFromRoot = true;
|
||||
subStrStartPos = 1;
|
||||
subStrlength -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// End with '/..'?
|
||||
bool searchFromParent = false;
|
||||
if (length > 3 &&
|
||||
name[length-3] == '/' &&
|
||||
name[length-2] == '.' &&
|
||||
name[length-1] == '.')
|
||||
{
|
||||
searchFromParent = true;
|
||||
subStrlength -= 3;
|
||||
}
|
||||
|
||||
// Remove '/', '//' and '/..' if exist
|
||||
std::string newName = name.substr(subStrStartPos, subStrlength);
|
||||
// If search from parent, then add * at first to make it match its children, which will do make
|
||||
if (searchFromParent)
|
||||
{
|
||||
newName.insert(0, "[[:alnum:]]+/");
|
||||
}
|
||||
|
||||
if (searchFromRoot)
|
||||
{
|
||||
// name is '/xxx'
|
||||
auto root = getScene();
|
||||
if (root)
|
||||
{
|
||||
root->doEnumerate(newName, callback);
|
||||
}
|
||||
}
|
||||
else if (searchFromRootRecursive)
|
||||
{
|
||||
// name is '//xxx'
|
||||
auto root = getScene();
|
||||
if (root)
|
||||
{
|
||||
doEnumerateRecursive(root, newName, callback);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// name is xxx
|
||||
doEnumerate(newName, callback);
|
||||
}
|
||||
}
|
||||
|
||||
bool Node::doEnumerateRecursive(const Node* node, const std::string &name, std::function<bool (Node *)> callback) const
|
||||
{
|
||||
bool ret =false;
|
||||
|
||||
if (node->doEnumerate(name, callback))
|
||||
{
|
||||
// search itself
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// search its children
|
||||
for (const auto& child : node->getChildren())
|
||||
{
|
||||
if (doEnumerateRecursive(child, name, callback))
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Node::doEnumerate(std::string name, std::function<bool (Node *)> callback) const
|
||||
{
|
||||
// name may be xxx/yyy, should find its parent
|
||||
size_t pos = name.find('/');
|
||||
std::string searchName = name;
|
||||
bool needRecursive = false;
|
||||
if (pos != name.npos)
|
||||
{
|
||||
searchName = name.substr(0, pos);
|
||||
name.erase(0, pos+1);
|
||||
needRecursive = true;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
for (const auto& child : _children)
|
||||
{
|
||||
if(std::regex_match(child->_name, std::regex(searchName)))
|
||||
{
|
||||
if (!needRecursive)
|
||||
{
|
||||
// terminate enumeration if callback return true
|
||||
if (callback(child))
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = child->doEnumerate(name, callback);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* "add" logic MUST only be on this method
|
||||
* If a class want's to extend the 'addChild' behavior it only needs
|
||||
* to override this method
|
||||
|
|
|
@ -667,6 +667,48 @@ public:
|
|||
* @return a Node object whose tag equals to the input parameter
|
||||
*/
|
||||
virtual Node * getChildByTag(int tag) const;
|
||||
/**
|
||||
* Gets a child from the container with its name
|
||||
*
|
||||
* @param name An identifier to find the child node.
|
||||
*
|
||||
* @return a Node object whose name equals to the input parameter
|
||||
*
|
||||
* @since v3.2
|
||||
*/
|
||||
virtual Node* getChildByName(const std::string& name) const;
|
||||
/** Search the children of the receiving node to perform processing for nodes which share a name.
|
||||
*
|
||||
* @param name The name to search for, support c++11 regular expression
|
||||
* Search syntax options:
|
||||
* `/` : When placed at the start of the search string, this indicates that the search should be performed on the tree's node.
|
||||
* `//`: Can only be placed at the begin of the search string. This indicates that the search should be performed on the tree's node
|
||||
* and be performed recursively across the entire node tree.
|
||||
* `..`: The search should move up to the node's parent. Can only be placed at the end of string
|
||||
* `/` : When placed anywhere but the start of the search string, this indicates that the search should move to the node's children
|
||||
*
|
||||
* @code
|
||||
* enumerateChildren("/MyName", ...): This searches the root's children and matches any node with the name `MyName`.
|
||||
* enumerateChildren("//MyName", ...): This searches the root's children recursively and matches any node with the name `MyName`.
|
||||
* enumerateChildren("[[:alnum:]]+", ...): This search string matches every node of its children.
|
||||
* enumerateChildren("/MyName", ...): This searches the node tree and matches the parent node of every node named `MyName`.
|
||||
* enumerateChildren("A[[:digit:]]", ...): This searches the node's children and returns any child named `A0`, `A1`, ..., `A9`
|
||||
* enumerateChildren("Abby/Normal", ...): This searches the node's grandchildren and returns any node whose name is `Normal`
|
||||
* and whose parent is named `Abby`.
|
||||
* enumerateChildren("//Abby/Normal", ...): This searches the node tree and returns any node whose name is `Normal` and whose
|
||||
* parent is named `Abby`.
|
||||
* @endcode
|
||||
*
|
||||
* @warning Only support alpha or number for name, and not support unicode
|
||||
*
|
||||
* @param callback A callback function to execute on nodes that match the `name` parameter. The function takes the following arguments:
|
||||
* `node`
|
||||
* A node that matches the name
|
||||
* And returns a boolean result. Your callback can return `true` to terminate the enumeration.
|
||||
*
|
||||
* @since v3.2
|
||||
*/
|
||||
virtual void enumerateChildren(const std::string &name, std::function<bool(Node* node)> callback) const;
|
||||
/**
|
||||
* Returns the array of the node's children
|
||||
*
|
||||
|
@ -780,6 +822,19 @@ public:
|
|||
* @param tag A integer that identifies the node.
|
||||
*/
|
||||
virtual void setTag(int tag);
|
||||
|
||||
/** Returns a string that is used to identify the node.
|
||||
* @return A string that identifies the node.
|
||||
*
|
||||
* @since v3.2
|
||||
*/
|
||||
virtual std::string getName() const;
|
||||
/** Changes the name that is used to identify the node easily.
|
||||
* @param name A string that identifies the node.
|
||||
*
|
||||
* @since v3.2
|
||||
*/
|
||||
virtual void setName(const std::string& name);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -960,7 +1015,7 @@ public:
|
|||
It returns `nullptr` if the node doesn't belong to any Scene.
|
||||
This function recursively calls parent->getScene() until parent is a Scene object. The results are not cached. It is that the user caches the results in case this functions is being used inside a loop.
|
||||
*/
|
||||
virtual Scene* getScene();
|
||||
virtual Scene* getScene() const;
|
||||
|
||||
/**
|
||||
* Returns an AABB (axis-aligned bounding-box) in its parent's coordinate system.
|
||||
|
@ -1393,6 +1448,9 @@ protected:
|
|||
virtual void disableCascadeColor();
|
||||
virtual void updateColor() {}
|
||||
|
||||
bool doEnumerate(std::string name, std::function<bool (Node *)> callback) const;
|
||||
bool doEnumerateRecursive(const Node* node, const std::string &name, std::function<bool (Node *)> callback) const;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
virtual void updatePhysicsBodyPosition(Scene* layer);
|
||||
virtual void updatePhysicsBodyRotation(Scene* layer);
|
||||
|
@ -1443,6 +1501,7 @@ protected:
|
|||
int _tag; ///< a tag. Can be any number you assigned just to identify this node
|
||||
|
||||
std::string _name; ///<a string label, an user defined string to identify this node
|
||||
size_t _hashOfName; ///<hash value of _name, used for speed in getChildByName
|
||||
|
||||
void *_userData; ///< A user assingned void pointer, Can be point to any cpp object
|
||||
Ref *_userObject; ///< A user assigned Object
|
||||
|
|
|
@ -98,9 +98,10 @@ std::string Scene::getDescription() const
|
|||
return StringUtils::format("<Scene | tag = %d>", _tag);
|
||||
}
|
||||
|
||||
Scene* Scene::getScene()
|
||||
Scene* Scene::getScene() const
|
||||
{
|
||||
return this;
|
||||
// FIX ME: should use const_case<> to fix compiling error
|
||||
return const_cast<Scene*>(this);
|
||||
}
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
static Scene *createWithSize(const Size& size);
|
||||
|
||||
// Overrides
|
||||
virtual Scene *getScene() override;
|
||||
virtual Scene *getScene() const override;
|
||||
|
||||
using Node::addChild;
|
||||
virtual std::string getDescription() const override;
|
||||
|
|
|
@ -200,9 +200,6 @@ public:
|
|||
virtual void setArmatureData(ArmatureData *armatureData) { _armatureData = armatureData; }
|
||||
virtual ArmatureData *getArmatureData() const { return _armatureData; }
|
||||
|
||||
virtual void setName(const std::string &name) { _name = name; }
|
||||
virtual const std::string &getName() const { return _name; }
|
||||
|
||||
|
||||
virtual void setParentBone(Bone *parentBone);
|
||||
virtual Bone *getParentBone() const;
|
||||
|
@ -257,7 +254,6 @@ protected:
|
|||
|
||||
BatchNode *_batchNode;
|
||||
|
||||
std::string _name;
|
||||
Bone *_parentBone;
|
||||
float _version;
|
||||
|
||||
|
|
|
@ -207,9 +207,6 @@ public:
|
|||
|
||||
virtual FrameData *getTweenData() const { return _tweenData; }
|
||||
|
||||
virtual void setName(const std::string &name) { _name = name; }
|
||||
virtual const std::string getName() const { return _name; }
|
||||
|
||||
virtual BaseData *getWorldInfo() const { return _worldInfo; }
|
||||
protected:
|
||||
void applyParentTransform(Bone *parent);
|
||||
|
@ -242,8 +239,6 @@ protected:
|
|||
//! Used for making tween effect in every frame
|
||||
FrameData *_tweenData;
|
||||
|
||||
std::string _name;
|
||||
|
||||
Bone *_parentBone; //! A weak reference to its parent
|
||||
bool _boneTransformDirty; //! Whether or not transform dirty
|
||||
|
||||
|
|
|
@ -268,7 +268,7 @@ Node* ScrollView::getChildByTag(int tag) const
|
|||
return _innerContainer->getChildByTag(tag);
|
||||
}
|
||||
|
||||
Widget* ScrollView::getChildByName(const std::string& name)const
|
||||
Node* ScrollView::getChildByName(const std::string& name)const
|
||||
{
|
||||
return _innerContainer->getChildByName(name);
|
||||
}
|
||||
|
|
|
@ -264,7 +264,7 @@ public:
|
|||
virtual const Vector<Node*>& getChildren() const override;
|
||||
virtual ssize_t getChildrenCount() const override;
|
||||
virtual Node * getChildByTag(int tag) const override;
|
||||
virtual Widget* getChildByName(const std::string& name)const override;
|
||||
virtual Node* getChildByName(const std::string& name)const override;
|
||||
|
||||
//handle touch event
|
||||
virtual bool onTouchBegan(Touch *touch, Event *unusedEvent) override;
|
||||
|
|
|
@ -144,7 +144,6 @@ _touchMovePosition(Vec2::ZERO),
|
|||
_touchEndPosition(Vec2::ZERO),
|
||||
_touchEventListener(nullptr),
|
||||
_touchEventSelector(nullptr),
|
||||
_name("default"),
|
||||
_actionTag(0),
|
||||
_size(Size::ZERO),
|
||||
_customSize(Size::ZERO),
|
||||
|
@ -249,25 +248,6 @@ void Widget::setEnabled(bool enabled)
|
|||
{
|
||||
_enabled = enabled;
|
||||
}
|
||||
|
||||
Widget* Widget::getChildByName(const std::string& name)const
|
||||
{
|
||||
for (auto& child : _children)
|
||||
{
|
||||
if (child)
|
||||
{
|
||||
Widget* widgetChild = dynamic_cast<Widget*>(child);
|
||||
if (widgetChild)
|
||||
{
|
||||
if (widgetChild->getName() == name)
|
||||
{
|
||||
return widgetChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Widget::initRenderer()
|
||||
{
|
||||
|
@ -964,17 +944,6 @@ const Vec2& Widget::getTouchEndPosition()const
|
|||
return _touchEndPosition;
|
||||
}
|
||||
|
||||
void Widget::setName(const std::string& name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
const std::string& Widget::getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
|
||||
void Widget::setLayoutParameter(LayoutParameter *parameter)
|
||||
{
|
||||
if (!parameter)
|
||||
|
|
|
@ -228,15 +228,6 @@ public:
|
|||
CC_DEPRECATED_ATTRIBUTE float getTopInParent(){return this->getTopBoundary();}
|
||||
float getTopBoundary() const;
|
||||
|
||||
/**
|
||||
* Gets a child from the container with its name
|
||||
*
|
||||
* @param name An key to find the child widget.
|
||||
*
|
||||
* @return a Widget object whose name equals to the input parameter
|
||||
*/
|
||||
virtual Widget* getChildByName(const std::string& name) const;
|
||||
|
||||
virtual void visit(cocos2d::Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags) override;
|
||||
|
||||
/**
|
||||
|
@ -375,22 +366,6 @@ public:
|
|||
CC_DEPRECATED_ATTRIBUTE const Vec2& getTouchEndPos()const{return this->getTouchEndPosition();}
|
||||
const Vec2& getTouchEndPosition()const;
|
||||
|
||||
/**
|
||||
* Changes the name that is used to identify the widget easily.
|
||||
*
|
||||
* @param A const std::string that indentifies the widget.
|
||||
*/
|
||||
void setName(const std::string& name);
|
||||
|
||||
/**
|
||||
* Returns a name that is used to identify the widget easily.
|
||||
*
|
||||
* You can set tags to widget then identify them easily.
|
||||
*
|
||||
* @return A const std::string that identifies the widget.
|
||||
*/
|
||||
const std::string& getName() const;
|
||||
|
||||
/**
|
||||
* Changes the size that is widget's size
|
||||
*
|
||||
|
@ -682,7 +657,6 @@ protected:
|
|||
PositionType _positionType;
|
||||
|
||||
//use
|
||||
std::string _name;
|
||||
int _actionTag;
|
||||
|
||||
Size _size;
|
||||
|
|
|
@ -74,6 +74,7 @@ static std::function<Layer*()> createFunctions[] =
|
|||
CL(NodeGlobalZValueTest),
|
||||
CL(NodeNormalizedPositionTest1),
|
||||
CL(NodeNormalizedPositionTest2),
|
||||
CL(NodeNameTest),
|
||||
};
|
||||
|
||||
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
|
||||
|
@ -1231,6 +1232,198 @@ void NodeNormalizedPositionTest2::update(float dt)
|
|||
CCLOG("s: %f,%f", s.width, s.height);
|
||||
}
|
||||
|
||||
|
||||
std::string NodeNameTest::title() const
|
||||
{
|
||||
return "getName()/setName()/getChildByName()/enumerateChildren()";
|
||||
}
|
||||
|
||||
std::string NodeNameTest::subtitle() const
|
||||
{
|
||||
return "see console";
|
||||
}
|
||||
|
||||
void NodeNameTest::onEnter()
|
||||
{
|
||||
TestCocosNodeDemo::BaseTest::onEnter();
|
||||
|
||||
auto parent = Node::create();
|
||||
|
||||
// setName(), getName() and getChildByName()
|
||||
char name[20];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
sprintf(name, "node%d", i);
|
||||
auto node = Node::create();
|
||||
node->setName(name);
|
||||
parent->addChild(node);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
sprintf(name, "node%d", i);
|
||||
auto node = parent->getChildByName(name);
|
||||
log("find child: %s", node->getName().c_str());
|
||||
}
|
||||
|
||||
// enumerateChildren()
|
||||
int i = 0;
|
||||
parent->enumerateChildren("test", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return true;
|
||||
});
|
||||
CCAssert(i == 1, "");
|
||||
|
||||
i = 0;
|
||||
parent->enumerateChildren("test", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
CCAssert(i == 2, "");
|
||||
|
||||
// enumerateChildren()
|
||||
// name = regular expression
|
||||
parent = Node::create();
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
auto node = Node::create();
|
||||
sprintf(name, "node%d", i);
|
||||
node->setName(name);
|
||||
parent->addChild(node);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
parent->enumerateChildren("node[[:digit:]]+", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
CCAssert(i == 100, "");
|
||||
|
||||
i = 0;
|
||||
parent->enumerateChildren("node[[:digit:]]+", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return true;
|
||||
});
|
||||
CCAssert(i == 1, "");
|
||||
|
||||
|
||||
// enumerateChildren
|
||||
// name = node[[digit]]+/node
|
||||
|
||||
parent = Node::create();
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
auto node = Node::create();
|
||||
sprintf(name, "node%d", i);
|
||||
node->setName(name);
|
||||
parent->addChild(node);
|
||||
|
||||
for (int j = 0; j < 100; ++j)
|
||||
{
|
||||
auto child = Node::create();
|
||||
child->setName("node");
|
||||
node->addChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
parent->enumerateChildren("node1/node", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
CCAssert(i == 100, "");
|
||||
|
||||
i = 0;
|
||||
parent->enumerateChildren("node1/node", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return true;
|
||||
});
|
||||
CCAssert(i == 1, "");
|
||||
|
||||
i = 0;
|
||||
parent->enumerateChildren("node[[:digit:]]+/node", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
CCAssert(i == 10000, "");
|
||||
|
||||
i = 0;
|
||||
parent->enumerateChildren("node[[:digit:]]+/node", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return true;
|
||||
});
|
||||
CCAssert(i == 1, "");
|
||||
|
||||
// search from parent
|
||||
// name is xxx/..
|
||||
i = 0;
|
||||
parent->enumerateChildren("node/..", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return true;
|
||||
});
|
||||
CCAssert(i == 1, "");
|
||||
|
||||
i = 0;
|
||||
parent->enumerateChildren("node/..", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
CCAssert(i == 10000, "");
|
||||
|
||||
// name = /xxx : search from root
|
||||
parent = getScene();
|
||||
for (int j = 0; j < 100; j++)
|
||||
{
|
||||
auto node = Node::create();
|
||||
sprintf(name, "node%d", j);
|
||||
node->setName(name);
|
||||
parent->addChild(node);
|
||||
|
||||
for (int k = 0; k < 100; ++k)
|
||||
{
|
||||
auto child = Node::create();
|
||||
sprintf(name, "node%d", k);
|
||||
child->setName(name);
|
||||
node->addChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
enumerateChildren("/node[[:digit:]]+", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
CCAssert(i == 100, "");
|
||||
|
||||
i = 0;
|
||||
enumerateChildren("/node[[:digit:]]+", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return true;
|
||||
});
|
||||
CCAssert(i == 1, "");
|
||||
|
||||
i = 0;
|
||||
enumerateChildren("//node[[:digit:]]+", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
CCAssert(i == 10100, ""); // 10000(children) + 100(parent)
|
||||
|
||||
i = 0;
|
||||
enumerateChildren("//node[[:digit:]]+", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return true;
|
||||
});
|
||||
CCAssert(i == 1, "");
|
||||
|
||||
i = 0;
|
||||
enumerateChildren("//node[[:digit:]]+/..", [&i](Node* node) -> bool {
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
CCAssert(i == 10000, "");
|
||||
}
|
||||
|
||||
///
|
||||
/// main
|
||||
///
|
||||
|
|
|
@ -295,6 +295,15 @@ protected:
|
|||
float _accum;
|
||||
};
|
||||
|
||||
class NodeNameTest : public TestCocosNodeDemo
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(NodeNameTest);
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
|
||||
virtual void onEnter() override;
|
||||
};
|
||||
|
||||
|
||||
// main
|
||||
|
|
Loading…
Reference in New Issue