diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id index 8e489a0d1e..f0adc63a8a 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -68ac83318dc8df5fee3badc4eb3f0e75ee0a9ce0 \ No newline at end of file +ebeb897c2c3303710c06b9de3cb3d499f89fb78c \ No newline at end of file diff --git a/cocos/2d/CCNode.cpp b/cocos/2d/CCNode.cpp index 9125d50393..b086275606 100644 --- a/cocos/2d/CCNode.cpp +++ b/cocos/2d/CCNode.cpp @@ -72,7 +72,7 @@ bool nodeComparisonLess(Node* n1, Node* n2) } // XXX: Yes, nodes might have a sort problem once every 15 days if the game runs at 60 FPS and each frame sprites are reordered. -static int s_globalOrderOfArrival = 1; +int Node::s_globalOrderOfArrival = 1; Node::Node(void) : _rotationX(0.0f) diff --git a/cocos/2d/CCNode.h b/cocos/2d/CCNode.h index 249ef11de9..d1f6859315 100644 --- a/cocos/2d/CCNode.h +++ b/cocos/2d/CCNode.h @@ -1452,6 +1452,8 @@ protected: bool _cascadeColorEnabled; bool _cascadeOpacityEnabled; + static int s_globalOrderOfArrival; + private: CC_DISALLOW_COPY_AND_ASSIGN(Node); }; diff --git a/cocos/2d/CCScene.h b/cocos/2d/CCScene.h index 880d0c9946..45d35540d9 100644 --- a/cocos/2d/CCScene.h +++ b/cocos/2d/CCScene.h @@ -68,6 +68,7 @@ CC_CONSTRUCTOR_ACCESS: protected: friend class Node; + friend class ProtectedNode; friend class SpriteBatchNode; private: diff --git a/cocos/physics/CCPhysicsBody.h b/cocos/physics/CCPhysicsBody.h index 80cd31c041..d9ac83a12a 100644 --- a/cocos/physics/CCPhysicsBody.h +++ b/cocos/physics/CCPhysicsBody.h @@ -349,6 +349,7 @@ protected: friend class PhysicsShape; friend class PhysicsJoint; friend class Node; + friend class ProtectedNode; }; NS_CC_END diff --git a/cocos/ui/Android.mk b/cocos/ui/Android.mk index ed93d6060a..bf3e2ce5a5 100644 --- a/cocos/ui/Android.mk +++ b/cocos/ui/Android.mk @@ -24,7 +24,8 @@ UITextBMFont.cpp \ UILoadingBar.cpp \ UISlider.cpp \ UITextField.cpp \ -UIRichText.cpp +UIRichText.cpp \ +CCProtectedNode.cpp LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/.. \ diff --git a/cocos/ui/CCProtectedNode.cpp b/cocos/ui/CCProtectedNode.cpp new file mode 100644 index 0000000000..d8a12940ec --- /dev/null +++ b/cocos/ui/CCProtectedNode.cpp @@ -0,0 +1,415 @@ +/**************************************************************************** + Copyright (c) 2008-2010 Ricardo Quesada + Copyright (c) 2009 Valentin Milea + Copyright (c) 2010-2012 cocos2d-x.org + Copyright (c) 2011 Zynga Inc. + Copyright (c) 2013-2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCProtectedNode.h" + +#include "kazmath/GL/matrix.h" + +#if CC_USE_PHYSICS +#include "CCPhysicsBody.h" +#endif +#include "CCScene.h" + +NS_CC_BEGIN + +ProtectedNode::ProtectedNode() : _reorderProtectedChildDirty(false) +{ +} + +ProtectedNode::~ProtectedNode() +{ + + CCLOGINFO( "deallocing ProtectedNode: %p - tag: %i", this, _tag ); +} + +ProtectedNode * ProtectedNode::create(void) +{ + ProtectedNode * ret = new ProtectedNode(); + if (ret && ret->init()) + { + ret->autorelease(); + } + else + { + CC_SAFE_DELETE(ret); + } + return ret; +} + +void ProtectedNode::cleanup() +{ + Node::cleanup(); + // timers + for( const auto &child: _protectedChildren) + child->cleanup(); +} + +void ProtectedNode::addProtectedChild(cocos2d::Node *child) +{ + addProtectedChild(child, child->getLocalZOrder(), child->getTag()); +} + +void ProtectedNode::addProtectedChild(cocos2d::Node *child, int localZOrder) +{ + addProtectedChild(child, localZOrder, child->getTag()); +} + +/* "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 + */ +void ProtectedNode::addProtectedChild(Node *child, int zOrder, int tag) +{ + CCASSERT( child != nullptr, "Argument must be non-nil"); + CCASSERT( child->getParent() == nullptr, "child already added. It can't be added again"); + + if (_protectedChildren.empty()) + { + _protectedChildren.reserve(4); + } + + this->insertProtectedChild(child, zOrder); + +#if CC_USE_PHYSICS + if (child->getPhysicsBody() != nullptr) + { + child->getPhysicsBody()->setPosition(this->convertToWorldSpace(child->getPosition())); + } + + for (Node* node = this->getParent(); node != nullptr; node = node->getParent()) + { + if (dynamic_cast(node) != nullptr) + { + (dynamic_cast(node))->addChildToPhysicsWorld(child); + break; + } + } +#endif + + child->setTag(tag); + + child->setParent(this); + child->setOrderOfArrival(s_globalOrderOfArrival++); + + if( _running ) + { + child->onEnter(); + // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter + if (_isTransitionFinished) { + child->onEnterTransitionDidFinish(); + } + } + + if (_cascadeColorEnabled) + { + updateCascadeColor(); + } + + if (_cascadeOpacityEnabled) + { + updateCascadeOpacity(); + } +} + +Node* ProtectedNode::getProtectedChildByTag(int tag) +{ + CCASSERT( tag != Node::INVALID_TAG, "Invalid tag"); + + for (auto& child : _protectedChildren) + { + if(child && child->getTag() == tag) + return child; + } + return nullptr; +} + +/* "remove" logic MUST only be on this method + * If a class want's to extend the 'removeChild' behavior it only needs + * to override this method + */ +void ProtectedNode::removeProtectedChild(cocos2d::Node *child, bool cleanup) +{ + // explicit nil handling + if (_protectedChildren.empty()) + { + return; + } + + ssize_t index = _protectedChildren.getIndex(child); + if( index != CC_INVALID_INDEX ) + { + + // IMPORTANT: + // -1st do onExit + // -2nd cleanup + if (_running) + { + child->onExitTransitionDidStart(); + child->onExit(); + } + +#if CC_USE_PHYSICS + if (child->getPhysicsBody() != nullptr) + { + child->getPhysicsBody()->removeFromWorld(); + } + +#endif + // If you don't do cleanup, the child's actions will not get removed and the + // its scheduledSelectors_ dict will not get released! + if (cleanup) + { + child->cleanup(); + } + + // set parent nil at the end + child->setParent(nullptr); + + _protectedChildren.erase(index); + } +} + +void ProtectedNode::removeAllProtectedChildren() +{ + removeAllProtectedChildrenWithCleanup(true); +} + +void ProtectedNode::removeAllProtectedChildrenWithCleanup(bool cleanup) +{ + // not using detachChild improves speed here + for (auto& child : _protectedChildren) + { + // IMPORTANT: + // -1st do onExit + // -2nd cleanup + if(_running) + { + child->onExitTransitionDidStart(); + child->onExit(); + } + +#if CC_USE_PHYSICS + if (child->getPhysicsBody() != nullptr) + { + child->getPhysicsBody()->removeFromWorld(); + } +#endif + + if (cleanup) + { + child->cleanup(); + } + // set parent nil at the end + child->setParent(nullptr); + } + + _protectedChildren.clear(); +} + +void ProtectedNode::removeProtectedChildByTag(int tag, bool cleanup) +{ + CCASSERT( tag != Node::INVALID_TAG, "Invalid tag"); + + Node *child = this->getProtectedChildByTag(tag); + + if (child == nullptr) + { + CCLOG("cocos2d: removeChildByTag(tag = %d): child not found!", tag); + } + else + { + this->removeProtectedChild(child, cleanup); + } +} + +// helper used by reorderChild & add +void ProtectedNode::insertProtectedChild(cocos2d::Node *child, int z) +{ + _reorderProtectedChildDirty = true; + _protectedChildren.pushBack(child); + child->_setLocalZOrder(z); +} + +void ProtectedNode::sortAllProtectedChildren() +{ + if( _reorderProtectedChildDirty ) { + std::sort( std::begin(_protectedChildren), std::end(_protectedChildren), nodeComparisonLess ); + _reorderProtectedChildDirty = false; + } +} + +void ProtectedNode::reorderProtectedChild(cocos2d::Node *child, int localZOrder) +{ + CCASSERT( child != nullptr, "Child must be non-nil"); + _reorderProtectedChildDirty = true; + child->setOrderOfArrival(s_globalOrderOfArrival++); + child->_setLocalZOrder(localZOrder); +} + +void ProtectedNode::visit(Renderer* renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) +{ + // quick return if not visible. children won't be drawn. + if (!_visible) + { + return; + } + + bool dirty = _transformUpdated || parentTransformUpdated; + if(dirty) + _modelViewTransform = this->transform(parentTransform); + _transformUpdated = false; + + + // IMPORTANT: + // To ease the migration to v3.0, we still support the kmGL stack, + // but it is deprecated and your code should not rely on it + kmGLPushMatrix(); + kmGLLoadMatrix(&_modelViewTransform); + + int i = 0; // used by _children + int j = 0; // used by _protectedChildren + + sortAllChildren(); + sortAllProtectedChildren(); + + // + // draw children and protectedChildren zOrder < 0 + // + for( ; i < _children.size(); i++ ) + { + auto node = _children.at(i); + + if ( node && node->getZOrder() < 0 ) + node->visit(renderer, _modelViewTransform, dirty); + else + break; + } + + for( ; j < _protectedChildren.size(); j++ ) + { + auto node = _protectedChildren.at(j); + + if ( node && node->getZOrder() < 0 ) + node->visit(renderer, _modelViewTransform, dirty); + else + break; + } + + // + // draw self + // + this->draw(renderer, _modelViewTransform, dirty); + + // + // draw children and protectedChildren zOrder >= 0 + // + for(auto it=_protectedChildren.cbegin()+j; it != _protectedChildren.cend(); ++it) + (*it)->visit(renderer, _modelViewTransform, dirty); + + for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) + (*it)->visit(renderer, _modelViewTransform, dirty); + + // reset for next frame + _orderOfArrival = 0; + + kmGLPopMatrix(); +} + +void ProtectedNode::onEnter() +{ + Node::onEnter(); + for( const auto &child: _protectedChildren) + child->onEnter(); +} + +void ProtectedNode::onEnterTransitionDidFinish() +{ + Node::onEnterTransitionDidFinish(); + for( const auto &child: _protectedChildren) + child->onEnterTransitionDidFinish(); +} + +void ProtectedNode::onExitTransitionDidStart() +{ + Node::onExitTransitionDidStart(); + for( const auto &child: _protectedChildren) + child->onExitTransitionDidStart(); +} + +void ProtectedNode::onExit() +{ + Node::onExit(); + for( const auto &child: _protectedChildren) + child->onExit(); +} + +void ProtectedNode::updateDisplayedOpacity(GLubyte parentOpacity) +{ + _displayedOpacity = _realOpacity * parentOpacity/255.0; + updateColor(); + + if (_cascadeOpacityEnabled) + { + for(auto child : _children){ + child->updateDisplayedOpacity(_displayedOpacity); + } + for(auto child : _protectedChildren){ + child->updateDisplayedOpacity(_displayedOpacity); + } + } +} + +void ProtectedNode::updateDisplayedColor(const Color3B& parentColor) +{ + _displayedColor.r = _realColor.r * parentColor.r/255.0; + _displayedColor.g = _realColor.g * parentColor.g/255.0; + _displayedColor.b = _realColor.b * parentColor.b/255.0; + updateColor(); + + if (_cascadeColorEnabled) + { + for(const auto &child : _children){ + child->updateDisplayedColor(_displayedColor); + } + for(const auto &child : _protectedChildren){ + child->updateDisplayedColor(_displayedColor); + } + } +} + +void ProtectedNode::disableCascadeColor() +{ + for(auto child : _children){ + child->updateDisplayedColor(Color3B::WHITE); + } + for(auto child : _protectedChildren){ + child->updateDisplayedColor(Color3B::WHITE); + } +} + +NS_CC_END \ No newline at end of file diff --git a/cocos/ui/CCProtectedNode.h b/cocos/ui/CCProtectedNode.h new file mode 100644 index 0000000000..f2b297d430 --- /dev/null +++ b/cocos/ui/CCProtectedNode.h @@ -0,0 +1,184 @@ +/**************************************************************************** + Copyright (c) 2008-2010 Ricardo Quesada + Copyright (c) 2009 Valentin Milea + Copyright (c) 2010-2012 cocos2d-x.org + Copyright (c) 2011 Zynga Inc. + Copyright (c) 2013-2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#ifndef __CPROTECTEDCNODE_H__ +#define __CPROTECTEDCNODE_H__ + + +#include "CCNode.h" + +NS_CC_BEGIN + +class CC_DLL ProtectedNode : public Node +{ +public: + static ProtectedNode * create(void); + + /// @{ + /// @name Children and Parent + + /** + * Adds a child to the container with z-order as 0. + * + * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. + * + * @param child A child node + */ + virtual void addProtectedChild(Node * child); + /** + * Adds a child to the container with a local z-order + * + * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. + * + * @param child A child node + * @param zOrder Z order for drawing priority. Please refer to `setLocalZOrder(int)` + */ + virtual void addProtectedChild(Node * child, int localZOrder); + /** + * Adds a child to the container with z order and tag + * + * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. + * + * @param child A child node + * @param zOrder Z order for drawing priority. Please refer to `setLocalZOrder(int)` + * @param tag An integer to identify the node easily. Please refer to `setTag(int)` + */ + virtual void addProtectedChild(Node* child, int localZOrder, int tag); + /** + * Gets a child from the container with its tag + * + * @param tag An identifier to find the child node. + * + * @return a Node object whose tag equals to the input parameter + */ + virtual Node * getProtectedChildByTag(int tag); + + ////// REMOVES ////// + + /** + * Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter. + * + * @param child The child node which will be removed. + * @param cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. + */ + virtual void removeProtectedChild(Node* child, bool cleanup = true); + + /** + * Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter + * + * @param tag An interger number that identifies a child node + * @param cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. + */ + virtual void removeProtectedChildByTag(int tag, bool cleanup = true); + /** + * Removes all children from the container with a cleanup. + * + * @see `removeAllChildrenWithCleanup(bool)` + */ + virtual void removeAllProtectedChildren(); + /** + * Removes all children from the container, and do a cleanup to all running actions depending on the cleanup parameter. + * + * @param cleanup true if all running actions on all children nodes should be cleanup, false oterwise. + * @js removeAllChildren + * @lua removeAllChildren + */ + virtual void removeAllProtectedChildrenWithCleanup(bool cleanup); + + /** + * Reorders a child according to a new z value. + * + * @param child An already added child node. It MUST be already added. + * @param localZOrder Z order for drawing priority. Please refer to setLocalZOrder(int) + */ + virtual void reorderProtectedChild(Node * child, int localZOrder); + + /** + * Sorts the children array once before drawing, instead of every time when a child is added or reordered. + * This appraoch can improves the performance massively. + * @note Don't call this manually unless a child added needs to be removed in the same frame + */ + virtual void sortAllProtectedChildren(); + + /// @} end of Children and Parent + + virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool transformUpdated) override; + + virtual void cleanup() override; + + virtual void onEnter() override; + + /** Event callback that is invoked when the Node enters in the 'stage'. + * If the Node enters the 'stage' with a transition, this event is called when the transition finishes. + * If you override onEnterTransitionDidFinish, you shall call its parent's one, e.g. Node::onEnterTransitionDidFinish() + * @js NA + * @lua NA + */ + virtual void onEnterTransitionDidFinish() override; + + /** + * Event callback that is invoked every time the Node leaves the 'stage'. + * If the Node leaves the 'stage' with a transition, this event is called when the transition finishes. + * During onExit you can't access a sibling node. + * If you override onExit, you shall call its parent's one, e.g., Node::onExit(). + * @js NA + * @lua NA + */ + virtual void onExit() override; + + /** + * Event callback that is called every time the Node leaves the 'stage'. + * If the Node leaves the 'stage' with a transition, this callback is called when the transition starts. + * @js NA + * @lua NA + */ + virtual void onExitTransitionDidStart() override; + + virtual void updateDisplayedOpacity(GLubyte parentOpacity) override; + virtual void updateDisplayedColor(const Color3B& parentColor) override; + virtual void disableCascadeColor() override; + +protected: + ProtectedNode(); + virtual ~ProtectedNode(); + + + /// helper that reorder a child + void insertProtectedChild(Node* child, int z); + + Vector _protectedChildren; ///< array of children nodes + bool _reorderProtectedChildDirty; + +private: + CC_DISALLOW_COPY_AND_ASSIGN(ProtectedNode); +}; + + +NS_CC_END + +#endif // __CPROTECTEDCNODE_H__ \ No newline at end of file diff --git a/cocos/ui/CMakeLists.txt b/cocos/ui/CMakeLists.txt index 8843bed83e..cc41a5f95b 100644 --- a/cocos/ui/CMakeLists.txt +++ b/cocos/ui/CMakeLists.txt @@ -18,6 +18,7 @@ set(GUI_SRC UISlider.cpp UITextField.cpp UIRichText.cpp + CCProtectedNode.cpp ) add_library(ui STATIC diff --git a/cocos/ui/UIButton.cpp b/cocos/ui/UIButton.cpp index 114b73b419..8dac6ccf49 100644 --- a/cocos/ui/UIButton.cpp +++ b/cocos/ui/UIButton.cpp @@ -102,10 +102,10 @@ void Button::initRenderer() _titleRenderer = Label::create(); _titleRenderer->setAnchorPoint(Point::ANCHOR_MIDDLE); - Node::addChild(_buttonNormalRenderer, NORMAL_RENDERER_Z, -1); - Node::addChild(_buttonClickedRenderer, PRESSED_RENDERER_Z, -1); - Node::addChild(_buttonDisableRenderer, DISABLED_RENDERER_Z, -1); - Node::addChild(_titleRenderer, TITLE_RENDERER_Z, -1); + addProtectedChild(_buttonNormalRenderer, NORMAL_RENDERER_Z, -1); + addProtectedChild(_buttonClickedRenderer, PRESSED_RENDERER_Z, -1); + addProtectedChild(_buttonDisableRenderer, DISABLED_RENDERER_Z, -1); + addProtectedChild(_titleRenderer, TITLE_RENDERER_Z, -1); } void Button::setScale9Enabled(bool able) @@ -116,9 +116,9 @@ void Button::setScale9Enabled(bool able) } _brightStyle = BRIGHT_NONE; _scale9Enabled = able; - Node::removeChild(_buttonNormalRenderer); - Node::removeChild(_buttonClickedRenderer); - Node::removeChild(_buttonDisableRenderer); + removeProtectedChild(_buttonNormalRenderer); + removeProtectedChild(_buttonClickedRenderer); + removeProtectedChild(_buttonDisableRenderer); _buttonNormalRenderer = nullptr; _buttonClickedRenderer = nullptr; _buttonDisableRenderer = nullptr; @@ -138,9 +138,9 @@ void Button::setScale9Enabled(bool able) loadTextureNormal(_normalFileName.c_str(), _normalTexType); loadTexturePressed(_clickedFileName.c_str(), _pressedTexType); loadTextureDisabled(_disabledFileName.c_str(), _disabledTexType); - Node::addChild(_buttonNormalRenderer, NORMAL_RENDERER_Z, -1); - Node::addChild(_buttonClickedRenderer, PRESSED_RENDERER_Z, -1); - Node::addChild(_buttonDisableRenderer, DISABLED_RENDERER_Z, -1); + addProtectedChild(_buttonNormalRenderer, NORMAL_RENDERER_Z, -1); + addProtectedChild(_buttonClickedRenderer, PRESSED_RENDERER_Z, -1); + addProtectedChild(_buttonDisableRenderer, DISABLED_RENDERER_Z, -1); if (_scale9Enabled) { bool ignoreBefore = _ignoreSize; diff --git a/cocos/ui/UICheckBox.cpp b/cocos/ui/UICheckBox.cpp index 86cf8ed815..d24edfdacb 100644 --- a/cocos/ui/UICheckBox.cpp +++ b/cocos/ui/UICheckBox.cpp @@ -95,11 +95,11 @@ void CheckBox::initRenderer() _backGroundBoxDisabledRenderer = Sprite::create(); _frontCrossDisabledRenderer = Sprite::create(); - Node::addChild(_backGroundBoxRenderer, BACKGROUNDBOX_RENDERER_Z, -1); - Node::addChild(_backGroundSelectedBoxRenderer, BACKGROUNDSELECTEDBOX_RENDERER_Z, -1); - Node::addChild(_frontCrossRenderer, FRONTCROSS_RENDERER_Z, -1); - Node::addChild(_backGroundBoxDisabledRenderer, BACKGROUNDBOXDISABLED_RENDERER_Z, -1); - Node::addChild(_frontCrossDisabledRenderer, FRONTCROSSDISABLED_RENDERER_Z, -1); + addProtectedChild(_backGroundBoxRenderer, BACKGROUNDBOX_RENDERER_Z, -1); + addProtectedChild(_backGroundSelectedBoxRenderer, BACKGROUNDSELECTEDBOX_RENDERER_Z, -1); + addProtectedChild(_frontCrossRenderer, FRONTCROSS_RENDERER_Z, -1); + addProtectedChild(_backGroundBoxDisabledRenderer, BACKGROUNDBOXDISABLED_RENDERER_Z, -1); + addProtectedChild(_frontCrossDisabledRenderer, FRONTCROSSDISABLED_RENDERER_Z, -1); } void CheckBox::loadTextures(const char *backGround, const char *backGroundSelected, const char *cross,const char* backGroundDisabled,const char* frontCrossDisabled,TextureResType texType) diff --git a/cocos/ui/UIHelper.cpp b/cocos/ui/UIHelper.cpp index 4bb3d4ee8b..ebbf2c1265 100644 --- a/cocos/ui/UIHelper.cpp +++ b/cocos/ui/UIHelper.cpp @@ -42,11 +42,14 @@ Widget* Helper::seekWidgetByTag(Widget* root, int tag) ssize_t length = arrayRootChildren.size(); for (ssize_t i=0;i(arrayRootChildren.at(i)); - Widget* res = seekWidgetByTag(child,tag); - if (res != nullptr) + Widget* child = dynamic_cast(arrayRootChildren.at(i)); + if (child) { - return res; + Widget* res = seekWidgetByTag(child,tag); + if (res != nullptr) + { + return res; + } } } return nullptr; @@ -65,11 +68,14 @@ Widget* Helper::seekWidgetByName(Widget* root, const char *name) const auto& arrayRootChildren = root->getChildren(); for (auto& subWidget : arrayRootChildren) { - Widget* child = static_cast(subWidget); - Widget* res = seekWidgetByName(child,name); - if (res != nullptr) + Widget* child = dynamic_cast(subWidget); + if (child) { - return res; + Widget* res = seekWidgetByName(child,name); + if (res != nullptr) + { + return res; + } } } return nullptr; @@ -84,11 +90,14 @@ Widget* Helper::seekWidgetByRelativeName(Widget *root, const char *name) const auto& arrayRootChildren = root->getChildren(); for (auto& subWidget : arrayRootChildren) { - Widget* child = static_cast(subWidget); - RelativeLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter(LAYOUT_PARAMETER_RELATIVE)); - if (layoutParameter && strcmp(layoutParameter->getRelativeName(), name) == 0) + Widget* child = dynamic_cast(subWidget); + if (child) { - return child; + RelativeLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter(LAYOUT_PARAMETER_RELATIVE)); + if (layoutParameter && strcmp(layoutParameter->getRelativeName(), name) == 0) + { + return child; + } } } return nullptr; @@ -108,12 +117,15 @@ Widget* Helper::seekActionWidgetByActionTag(Widget* root, int tag) const auto& arrayRootChildren = root->getChildren(); for (auto& subWidget : arrayRootChildren) { - Widget* child = static_cast(subWidget); - Widget* res = seekActionWidgetByActionTag(child,tag); - if (res != nullptr) - { - return res; - } + Widget* child = dynamic_cast(subWidget); + if (child) + { + Widget* res = seekActionWidgetByActionTag(child,tag); + if (res != nullptr) + { + return res; + } + } } return nullptr; } diff --git a/cocos/ui/UIImageView.cpp b/cocos/ui/UIImageView.cpp index 83d93b06b3..097bc0ff7d 100644 --- a/cocos/ui/UIImageView.cpp +++ b/cocos/ui/UIImageView.cpp @@ -69,7 +69,7 @@ ImageView* ImageView::create() void ImageView::initRenderer() { _imageRenderer = Sprite::create(); - Node::addChild(_imageRenderer, IMAGE_RENDERER_Z, -1); + addProtectedChild(_imageRenderer, IMAGE_RENDERER_Z, -1); } void ImageView::loadTexture(const char *fileName, TextureResType texType) @@ -166,7 +166,7 @@ void ImageView::setScale9Enabled(bool able) _scale9Enabled = able; - Node::removeChild(_imageRenderer); + removeProtectedChild(_imageRenderer); _imageRenderer = nullptr; if (_scale9Enabled) { @@ -177,7 +177,7 @@ void ImageView::setScale9Enabled(bool able) _imageRenderer = Sprite::create(); } loadTexture(_textureFile.c_str(),_imageTexType); - Node::addChild(_imageRenderer, IMAGE_RENDERER_Z, -1); + addProtectedChild(_imageRenderer, IMAGE_RENDERER_Z, -1); if (_scale9Enabled) { bool ignoreBefore = _ignoreSize; diff --git a/cocos/ui/UILayout.cpp b/cocos/ui/UILayout.cpp index 1c488618d4..e2a8e53dad 100644 --- a/cocos/ui/UILayout.cpp +++ b/cocos/ui/UILayout.cpp @@ -127,7 +127,7 @@ Layout* Layout::create() bool Layout::init() { - if (Node::init()) + if (ProtectedNode::init()) { initRenderer(); setBright(true); @@ -211,7 +211,7 @@ void Layout::visit(Renderer *renderer, const kmMat4 &parentTransform, bool paren } else { - Node::visit(renderer, parentTransform, parentTransformUpdated); + ProtectedNode::visit(renderer, parentTransform, parentTransformUpdated); } } @@ -254,32 +254,50 @@ void Layout::stencilClippingVisit(Renderer *renderer, const kmMat4 &parentTransf _afterDrawStencilCmd.func = CC_CALLBACK_0(Layout::onAfterDrawStencil, this); renderer->addCommand(&_afterDrawStencilCmd); - int i = 0; + int i = 0; // used by _children + int j = 0; // used by _protectedChildren - if(!_children.empty()) + sortAllChildren(); + sortAllProtectedChildren(); + + // + // draw children and protectedChildren zOrder < 0 + // + for( ; i < _children.size(); i++ ) { - sortAllChildren(); - // draw children zOrder < 0 - for( ; i < _children.size(); i++ ) - { - auto node = _children.at(i); - - if ( node && node->getLocalZOrder() < 0 ) - node->visit(renderer, _modelViewTransform, dirty); - else - break; - } - // self draw - this->draw(renderer, _modelViewTransform, dirty); + auto node = _children.at(i); - for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) - (*it)->visit(renderer, _modelViewTransform, dirty); + if ( node && node->getZOrder() < 0 ) + node->visit(renderer, _modelViewTransform, dirty); + else + break; } - else + + for( ; j < _protectedChildren.size(); j++ ) { - this->draw(renderer, _modelViewTransform, dirty); + auto node = _protectedChildren.at(j); + + if ( node && node->getZOrder() < 0 ) + node->visit(renderer, _modelViewTransform, dirty); + else + break; } + // + // draw self + // + this->draw(renderer, _modelViewTransform, dirty); + + // + // draw children and protectedChildren zOrder >= 0 + // + for(auto it=_protectedChildren.cbegin()+j; it != _protectedChildren.cend(); ++it) + (*it)->visit(renderer, _modelViewTransform, dirty); + + for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) + (*it)->visit(renderer, _modelViewTransform, dirty); + + _afterVisitCmdStencil.init(_globalZOrder); _afterVisitCmdStencil.func = CC_CALLBACK_0(Layout::onAfterVisitStencil, this); renderer->addCommand(&_afterVisitCmdStencil); @@ -368,7 +386,7 @@ void Layout::scissorClippingVisit(Renderer *renderer, const kmMat4& parentTransf _beforeVisitCmdScissor.func = CC_CALLBACK_0(Layout::onBeforeVisitScissor, this); renderer->addCommand(&_beforeVisitCmdScissor); - Node::visit(renderer, parentTransform, parentTransformUpdated); + ProtectedNode::visit(renderer, parentTransform, parentTransformUpdated); _afterVisitCmdScissor.init(_globalZOrder); _afterVisitCmdScissor.func = CC_CALLBACK_0(Layout::onAfterVisitScissor, this); @@ -566,19 +584,10 @@ void Layout::setBackGroundImageScale9Enabled(bool able) { return; } - Node::removeChild(_backGroundImage); + removeProtectedChild(_backGroundImage); _backGroundImage = nullptr; _backGroundScale9Enabled = able; - if (_backGroundScale9Enabled) - { - _backGroundImage = extension::Scale9Sprite::create(); - Node::addChild(_backGroundImage, BACKGROUNDIMAGE_Z, -1); - } - else - { - _backGroundImage = Sprite::create(); - Node::addChild(_backGroundImage, BACKGROUNDIMAGE_Z, -1); - } + addBackGroundImage(); setBackGroundImage(_backGroundImageFileName.c_str(),_bgImageTexType); setBackGroundImageCapInsets(_backGroundImageCapInsets); } @@ -688,15 +697,13 @@ void Layout::addBackGroundImage() if (_backGroundScale9Enabled) { _backGroundImage = extension::Scale9Sprite::create(); - _backGroundImage->setLocalZOrder(-1); - Node::addChild(_backGroundImage, BACKGROUNDIMAGE_Z, -1); + addProtectedChild(_backGroundImage, BACKGROUNDIMAGE_Z, -1); static_cast(_backGroundImage)->setPreferredSize(_size); } else { _backGroundImage = Sprite::create(); - _backGroundImage->setLocalZOrder(-1); - Node::addChild(_backGroundImage, BACKGROUNDIMAGE_Z, -1); + addProtectedChild(_backGroundImage, BACKGROUNDIMAGE_Z, -1); } _backGroundImage->setPosition(Point(_size.width/2.0f, _size.height/2.0f)); } @@ -707,7 +714,7 @@ void Layout::removeBackGroundImage() { return; } - Node::removeChild(_backGroundImage); + removeProtectedChild(_backGroundImage); _backGroundImage = nullptr; _backGroundImageFileName = ""; _backGroundImageTextureSize = Size::ZERO; @@ -724,26 +731,26 @@ void Layout::setBackGroundColorType(LayoutBackGroundColorType type) case LAYOUT_COLOR_NONE: if (_colorRender) { - Node::removeChild(_colorRender); + removeProtectedChild(_colorRender); _colorRender = nullptr; } if (_gradientRender) { - Node::removeChild(_gradientRender); + removeProtectedChild(_gradientRender); _gradientRender = nullptr; } break; case LAYOUT_COLOR_SOLID: if (_colorRender) { - Node::removeChild(_colorRender); + removeProtectedChild(_colorRender); _colorRender = nullptr; } break; case LAYOUT_COLOR_GRADIENT: if (_gradientRender) { - Node::removeChild(_gradientRender); + removeProtectedChild(_gradientRender); _gradientRender = nullptr; } break; @@ -760,7 +767,7 @@ void Layout::setBackGroundColorType(LayoutBackGroundColorType type) _colorRender->setContentSize(_size); _colorRender->setOpacity(_cOpacity); _colorRender->setColor(_cColor); - Node::addChild(_colorRender, BCAKGROUNDCOLORRENDERER_Z, -1); + addProtectedChild(_colorRender, BCAKGROUNDCOLORRENDERER_Z, -1); break; case LAYOUT_COLOR_GRADIENT: _gradientRender = LayerGradient::create(); @@ -769,7 +776,7 @@ void Layout::setBackGroundColorType(LayoutBackGroundColorType type) _gradientRender->setStartColor(_gStartColor); _gradientRender->setEndColor(_gEndColor); _gradientRender->setVector(_alongVector); - Node::addChild(_gradientRender, BCAKGROUNDCOLORRENDERER_Z, -1); + addProtectedChild(_gradientRender, BCAKGROUNDCOLORRENDERER_Z, -1); break; default: break; @@ -911,9 +918,10 @@ const Size& Layout::getBackGroundImageTextureSize() const void Layout::setLayoutType(LayoutType type) { _layoutType = type; - for (auto& child : _widgetChildren) + for (auto& child : _children) { - if (child) + Widget* widgetChild = dynamic_cast(child); + if (widgetChild) { supplyTheLayoutParameterLackToChild(static_cast(child)); } @@ -946,37 +954,40 @@ void Layout::doLayout() Size layoutSize = getSize(); float topBoundary = layoutSize.height; - for (auto& subWidget : _widgetChildren) + for (auto& subWidget : _children) { - Widget* child = static_cast(subWidget); - LinearLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter(LAYOUT_PARAMETER_LINEAR)); - - if (layoutParameter) + Widget* child = dynamic_cast(subWidget); + if (child) { - LinearGravity childGravity = layoutParameter->getGravity(); - Point ap = child->getAnchorPoint(); - Size cs = child->getSize(); - float finalPosX = ap.x * cs.width; - float finalPosY = topBoundary - ((1.0f-ap.y) * cs.height); - switch (childGravity) + LinearLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter(LAYOUT_PARAMETER_LINEAR)); + + if (layoutParameter) { - case LINEAR_GRAVITY_NONE: - case LINEAR_GRAVITY_LEFT: - break; - case LINEAR_GRAVITY_RIGHT: - finalPosX = layoutSize.width - ((1.0f - ap.x) * cs.width); - break; - case LINEAR_GRAVITY_CENTER_HORIZONTAL: - finalPosX = layoutSize.width / 2.0f - cs.width * (0.5f-ap.x); - break; - default: - break; + LinearGravity childGravity = layoutParameter->getGravity(); + Point ap = child->getAnchorPoint(); + Size cs = child->getSize(); + float finalPosX = ap.x * cs.width; + float finalPosY = topBoundary - ((1.0f-ap.y) * cs.height); + switch (childGravity) + { + case LINEAR_GRAVITY_NONE: + case LINEAR_GRAVITY_LEFT: + break; + case LINEAR_GRAVITY_RIGHT: + finalPosX = layoutSize.width - ((1.0f - ap.x) * cs.width); + break; + case LINEAR_GRAVITY_CENTER_HORIZONTAL: + finalPosX = layoutSize.width / 2.0f - cs.width * (0.5f-ap.x); + break; + default: + break; + } + Margin mg = layoutParameter->getMargin(); + finalPosX += mg.left; + finalPosY -= mg.top; + child->setPosition(Point(finalPosX, finalPosY)); + topBoundary = child->getBottomInParent() - mg.bottom; } - Margin mg = layoutParameter->getMargin(); - finalPosX += mg.left; - finalPosY -= mg.top; - child->setPosition(Point(finalPosX, finalPosY)); - topBoundary = child->getBottomInParent() - mg.bottom; } } break; @@ -985,54 +996,62 @@ void Layout::doLayout() { Size layoutSize = getSize(); float leftBoundary = 0.0f; - for (auto& subWidget : _widgetChildren) + for (auto& subWidget : _children) { - Widget* child = static_cast(subWidget); - LinearLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter(LAYOUT_PARAMETER_LINEAR)); - - if (layoutParameter) + Widget* child = dynamic_cast(subWidget); + if (child) { - LinearGravity childGravity = layoutParameter->getGravity(); - Point ap = child->getAnchorPoint(); - Size cs = child->getSize(); - float finalPosX = leftBoundary + (ap.x * cs.width); - float finalPosY = layoutSize.height - (1.0f - ap.y) * cs.height; - switch (childGravity) + LinearLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter(LAYOUT_PARAMETER_LINEAR)); + if (layoutParameter) { - case LINEAR_GRAVITY_NONE: - case LINEAR_GRAVITY_TOP: - break; - case LINEAR_GRAVITY_BOTTOM: - finalPosY = ap.y * cs.height; - break; - case LINEAR_GRAVITY_CENTER_VERTICAL: - finalPosY = layoutSize.height / 2.0f - cs.height * (0.5f - ap.y); - break; - default: - break; + LinearGravity childGravity = layoutParameter->getGravity(); + Point ap = child->getAnchorPoint(); + Size cs = child->getSize(); + float finalPosX = leftBoundary + (ap.x * cs.width); + float finalPosY = layoutSize.height - (1.0f - ap.y) * cs.height; + switch (childGravity) + { + case LINEAR_GRAVITY_NONE: + case LINEAR_GRAVITY_TOP: + break; + case LINEAR_GRAVITY_BOTTOM: + finalPosY = ap.y * cs.height; + break; + case LINEAR_GRAVITY_CENTER_VERTICAL: + finalPosY = layoutSize.height / 2.0f - cs.height * (0.5f - ap.y); + break; + default: + break; + } + Margin mg = layoutParameter->getMargin(); + finalPosX += mg.left; + finalPosY -= mg.top; + child->setPosition(Point(finalPosX, finalPosY)); + leftBoundary = child->getRightInParent() + mg.right; } - Margin mg = layoutParameter->getMargin(); - finalPosX += mg.left; - finalPosY -= mg.top; - child->setPosition(Point(finalPosX, finalPosY)); - leftBoundary = child->getRightInParent() + mg.right; } } break; } case LAYOUT_RELATIVE: { - ssize_t unlayoutChildCount = _widgetChildren.size(); + ssize_t unlayoutChildCount = 0; Size layoutSize = getSize(); - for (auto& subWidget : _widgetChildren) + Vector widgetChildren; + for (auto& subWidget : _children) { - Widget* child = static_cast(subWidget); - RelativeLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter(LAYOUT_PARAMETER_RELATIVE)); - layoutParameter->_put = false; + Widget* child = dynamic_cast(subWidget); + if (child) + { + RelativeLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter(LAYOUT_PARAMETER_RELATIVE)); + layoutParameter->_put = false; + unlayoutChildCount++; + widgetChildren.pushBack(child); + } } while (unlayoutChildCount > 0) { - for (auto& subWidget : _widgetChildren) + for (auto& subWidget : widgetChildren) { Widget* child = static_cast(subWidget); RelativeLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter(LAYOUT_PARAMETER_RELATIVE)); @@ -1359,6 +1378,7 @@ void Layout::doLayout() } } } + widgetChildren.clear(); break; } default: diff --git a/cocos/ui/UILoadingBar.cpp b/cocos/ui/UILoadingBar.cpp index 643ff18a47..cefe8ed382 100644 --- a/cocos/ui/UILoadingBar.cpp +++ b/cocos/ui/UILoadingBar.cpp @@ -67,7 +67,7 @@ LoadingBar* LoadingBar::create() void LoadingBar::initRenderer() { _barRenderer = Sprite::create(); - Node::addChild(_barRenderer, BAR_RENDERER_Z, -1); + addProtectedChild(_barRenderer, BAR_RENDERER_Z, -1); _barRenderer->setAnchorPoint(Point(0.0,0.5)); } @@ -172,7 +172,7 @@ void LoadingBar::setScale9Enabled(bool enabled) return; } _scale9Enabled = enabled; - Node::removeChild(_barRenderer); + removeProtectedChild(_barRenderer); _barRenderer = nullptr; if (_scale9Enabled) { @@ -183,7 +183,7 @@ void LoadingBar::setScale9Enabled(bool enabled) _barRenderer = Sprite::create(); } loadTexture(_textureFile.c_str(),_renderBarTexType); - Node::addChild(_barRenderer, BAR_RENDERER_Z, -1); + addProtectedChild(_barRenderer, BAR_RENDERER_Z, -1); if (_scale9Enabled) { bool ignoreBefore = _ignoreSize; diff --git a/cocos/ui/UIRichText.cpp b/cocos/ui/UIRichText.cpp index dda09ed551..48a64f7c88 100644 --- a/cocos/ui/UIRichText.cpp +++ b/cocos/ui/UIRichText.cpp @@ -148,7 +148,7 @@ void RichText::initRenderer() { _elementRenderersContainer = Node::create(); _elementRenderersContainer->setAnchorPoint(Point(0.5f, 0.5f)); - Node::addChild(_elementRenderersContainer, 0, -1); + addProtectedChild(_elementRenderersContainer, 0, -1); } void RichText::insertElement(RichElement *element, int index) @@ -436,6 +436,11 @@ void RichText::ignoreContentAdaptWithSize(bool ignore) Widget::ignoreContentAdaptWithSize(ignore); } } + +std::string RichText::getDescription() const +{ + return "RichText"; +} } diff --git a/cocos/ui/UIRichText.h b/cocos/ui/UIRichText.h index 9cf21e3058..d5e0f176b2 100644 --- a/cocos/ui/UIRichText.h +++ b/cocos/ui/UIRichText.h @@ -108,7 +108,8 @@ public: virtual const Size& getContentSize() const; void formatText(); virtual void ignoreContentAdaptWithSize(bool ignore); - + virtual std::string getDescription() const override; + CC_CONSTRUCTOR_ACCESS: virtual bool init() override; diff --git a/cocos/ui/UIScrollView.cpp b/cocos/ui/UIScrollView.cpp index 3b6b4e4421..9d16aa3f80 100644 --- a/cocos/ui/UIScrollView.cpp +++ b/cocos/ui/UIScrollView.cpp @@ -311,46 +311,6 @@ Widget* ScrollView::getChildByName(const char *name) return _innerContainer->getChildByName(name); } -void ScrollView::addNode(Node* node) -{ - Layout::addNode(node); -} - -void ScrollView::addNode(Node * node, int zOrder) -{ - Layout::addNode(node, zOrder); -} - -void ScrollView::addNode(Node* node, int zOrder, int tag) -{ - _innerContainer->addNode(node, zOrder, tag); -} - -Node* ScrollView::getNodeByTag(int tag) -{ - return _innerContainer->getNodeByTag(tag); -} - -Vector& ScrollView::getNodes() -{ - return _innerContainer->getNodes(); -} - -void ScrollView::removeNode(Node* node) -{ - _innerContainer->removeNode(node); -} - -void ScrollView::removeNodeByTag(int tag) -{ - _innerContainer->removeNodeByTag(tag); -} - -void ScrollView::removeAllNodes() -{ - _innerContainer->removeAllNodes(); -} - void ScrollView::moveChildren(float offsetX, float offsetY) { _moveChildPoint = _innerContainer->getPosition() + Point(offsetX, offsetY); diff --git a/cocos/ui/UIScrollView.h b/cocos/ui/UIScrollView.h index 0099b103ca..382bf68533 100644 --- a/cocos/ui/UIScrollView.h +++ b/cocos/ui/UIScrollView.h @@ -286,22 +286,6 @@ public: virtual Widget* getChildByName(const char* name) override; - virtual void addNode(Node* node) override; - - virtual void addNode(Node * node, int zOrder) override; - - virtual void addNode(Node* node, int zOrder, int tag) override; - - virtual Node * getNodeByTag(int tag) override; - - virtual Vector& getNodes() override; - - virtual void removeNode(Node* node) override; - - virtual void removeNodeByTag(int tag) override; - - virtual void removeAllNodes() override; - virtual bool onTouchBegan(Touch *touch, Event *unusedEvent) override; virtual void onTouchMoved(Touch *touch, Event *unusedEvent) override; virtual void onTouchEnded(Touch *touch, Event *unusedEvent) override; diff --git a/cocos/ui/UISlider.cpp b/cocos/ui/UISlider.cpp index 3b0737ef0e..37d6845325 100644 --- a/cocos/ui/UISlider.cpp +++ b/cocos/ui/UISlider.cpp @@ -97,8 +97,8 @@ void Slider::initRenderer() _barRenderer = Sprite::create(); _progressBarRenderer = Sprite::create(); _progressBarRenderer->setAnchorPoint(Point(0.0f, 0.5f)); - Node::addChild(_barRenderer, BASEBAR_RENDERER_Z, -1); - Node::addChild(_progressBarRenderer, PROGRESSBAR_RENDERER_Z, -1); + addProtectedChild(_barRenderer, BASEBAR_RENDERER_Z, -1); + addProtectedChild(_progressBarRenderer, PROGRESSBAR_RENDERER_Z, -1); _slidBallNormalRenderer = Sprite::create(); _slidBallPressedRenderer = Sprite::create(); _slidBallPressedRenderer->setVisible(false); @@ -108,7 +108,7 @@ void Slider::initRenderer() _slidBallRenderer->addChild(_slidBallNormalRenderer); _slidBallRenderer->addChild(_slidBallPressedRenderer); _slidBallRenderer->addChild(_slidBallDisabledRenderer); - Node::addChild(_slidBallRenderer, SLIDBALL_RENDERER_Z, -1); + addProtectedChild(_slidBallRenderer, SLIDBALL_RENDERER_Z, -1); } void Slider::loadBarTexture(const char* fileName, TextureResType texType) @@ -196,8 +196,8 @@ void Slider::setScale9Enabled(bool able) } _scale9Enabled = able; - Node::removeChild(_barRenderer); - Node::removeChild(_progressBarRenderer); + removeProtectedChild(_barRenderer); + removeProtectedChild(_progressBarRenderer); _barRenderer = nullptr; _progressBarRenderer = nullptr; if (_scale9Enabled) @@ -212,8 +212,8 @@ void Slider::setScale9Enabled(bool able) } loadBarTexture(_textureFile.c_str(), _barTexType); loadProgressBarTexture(_progressBarTextureFile.c_str(), _progressBarTexType); - Node::addChild(_barRenderer, BASEBAR_RENDERER_Z, -1); - Node::addChild(_progressBarRenderer, PROGRESSBAR_RENDERER_Z, -1); + addProtectedChild(_barRenderer, BASEBAR_RENDERER_Z, -1); + addProtectedChild(_progressBarRenderer, PROGRESSBAR_RENDERER_Z, -1); if (_scale9Enabled) { bool ignoreBefore = _ignoreSize; diff --git a/cocos/ui/UIText.cpp b/cocos/ui/UIText.cpp index 6dae8a1970..15a021c15d 100644 --- a/cocos/ui/UIText.cpp +++ b/cocos/ui/UIText.cpp @@ -72,7 +72,7 @@ bool Text::init() void Text::initRenderer() { _labelRenderer = Label::create(); - Node::addChild(_labelRenderer, LABEL_RENDERER_Z, -1); + addProtectedChild(_labelRenderer, LABEL_RENDERER_Z, -1); } void Text::setText(const std::string& text) diff --git a/cocos/ui/UITextAtlas.cpp b/cocos/ui/UITextAtlas.cpp index 2258be841a..b3710def7a 100644 --- a/cocos/ui/UITextAtlas.cpp +++ b/cocos/ui/UITextAtlas.cpp @@ -62,7 +62,7 @@ TextAtlas* TextAtlas::create() void TextAtlas::initRenderer() { _labelAtlasRenderer = LabelAtlas::create(); - Node::addChild(_labelAtlasRenderer, LABELATLAS_RENDERER_Z, -1); + addProtectedChild(_labelAtlasRenderer, LABELATLAS_RENDERER_Z, -1); } void TextAtlas::setProperty(const std::string& stringValue, const std::string& charMapFile, int itemWidth, int itemHeight, const std::string& startCharMap) diff --git a/cocos/ui/UITextBMFont.cpp b/cocos/ui/UITextBMFont.cpp index 80906e85d2..d1e31379db 100644 --- a/cocos/ui/UITextBMFont.cpp +++ b/cocos/ui/UITextBMFont.cpp @@ -60,7 +60,7 @@ TextBMFont* TextBMFont::create() void TextBMFont::initRenderer() { _labelBMFontRenderer = cocos2d::LabelBMFont::create(); - Node::addChild(_labelBMFontRenderer, LABELBMFONT_RENDERER_Z, -1); + addProtectedChild(_labelBMFontRenderer, LABELBMFONT_RENDERER_Z, -1); } void TextBMFont::setFntFile(const char *fileName) diff --git a/cocos/ui/UITextField.cpp b/cocos/ui/UITextField.cpp index 41c3d6b583..36b95ff6e1 100644 --- a/cocos/ui/UITextField.cpp +++ b/cocos/ui/UITextField.cpp @@ -392,7 +392,7 @@ void TextField::onEnter() void TextField::initRenderer() { _textFieldRenderer = UICCTextField::create("input words here", "Thonburi", 20); - Node::addChild(_textFieldRenderer, TEXTFIELD_RENDERER_Z, -1); + addProtectedChild(_textFieldRenderer, TEXTFIELD_RENDERER_Z, -1); } void TextField::setTouchSize(const Size &size) diff --git a/cocos/ui/UIWidget.cpp b/cocos/ui/UIWidget.cpp index 9b0068f26f..d35c7b38a2 100644 --- a/cocos/ui/UIWidget.cpp +++ b/cocos/ui/UIWidget.cpp @@ -56,7 +56,6 @@ _positionPercent(Point::ZERO), _reorderWidgetChildDirty(true), _hitted(false), _touchListener(nullptr), -_nodes(NULL), _color(Color3B::WHITE), _opacity(255), _flippedX(false), @@ -69,9 +68,7 @@ Widget::~Widget() { _touchEventListener = nullptr; _touchEventSelector = nullptr; - _widgetChildren.clear(); setTouchEnabled(false); - _nodes.clear(); } Widget* Widget::create() @@ -88,7 +85,7 @@ Widget* Widget::create() bool Widget::init() { - if (Node::init()) + if (ProtectedNode::init()) { initRenderer(); setBright(true); @@ -102,229 +99,75 @@ bool Widget::init() void Widget::onEnter() { updateSizeAndPosition(); - Node::onEnter(); + ProtectedNode::onEnter(); } void Widget::onExit() { unscheduleUpdate(); - Node::onExit(); + ProtectedNode::onExit(); } void Widget::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) { if (_enabled) { - Node::visit(renderer, parentTransform, parentTransformUpdated); + ProtectedNode::visit(renderer, parentTransform, parentTransformUpdated); } } -void Widget::addChild(Node *child) -{ - Node::addChild(child); -} - -void Widget::addChild(Node * child, int zOrder) -{ - Node::addChild(child, zOrder); -} - -void Widget::addChild(Node* child, int zOrder, int tag) -{ - CCASSERT(dynamic_cast(child) != nullptr, "Widget only supports Widgets as children"); - Node::addChild(child, zOrder, tag); - _widgetChildren.pushBack(child); -} - -void Widget::sortAllChildren() -{ - _reorderWidgetChildDirty = _reorderChildDirty; - Node::sortAllChildren(); - if( _reorderWidgetChildDirty ) - { - std::sort( std::begin(_widgetChildren), std::end(_widgetChildren), nodeComparisonLess ); - _reorderWidgetChildDirty = false; - } -} - -Node* Widget::getChildByTag(int aTag) -{ - CCASSERT( aTag != Node::INVALID_TAG, "Invalid tag"); - - for (auto& child : _widgetChildren) - { - if(child && child->getTag() == aTag) - return child; - } - return nullptr; -} - -Vector& Widget::getChildren() -{ - return _widgetChildren; -} - -const Vector& Widget::getChildren() const -{ - return _widgetChildren; -} - -ssize_t Widget::getChildrenCount() const -{ - return _widgetChildren.size(); -} - Widget* Widget::getWidgetParent() { return dynamic_cast(getParent()); } -void Widget::removeFromParent() -{ - removeFromParentAndCleanup(true); -} - -void Widget::removeFromParentAndCleanup(bool cleanup) -{ - Node::removeFromParentAndCleanup(cleanup); -} - -void Widget::removeChild(Node *child, bool cleanup) -{ - Node::removeChild(child, cleanup); - _widgetChildren.eraseObject(child); -} - -void Widget::removeChildByTag(int tag, bool cleanup) -{ - CCASSERT( tag != Node::INVALID_TAG, "Invalid tag"); - - Node *child = getChildByTag(tag); - - if (child == nullptr) - { - CCLOG("cocos2d: removeChildByTag(tag = %d): child not found!", tag); - } - else - { - removeChild(child, cleanup); - } -} - -void Widget::removeAllChildren() -{ - removeAllChildrenWithCleanup(true); -} - -void Widget::removeAllChildrenWithCleanup(bool cleanup) -{ - for (auto& child : _widgetChildren) - { - if (child) - { - Node::removeChild(child); - } - } - _widgetChildren.clear(); -} - void Widget::setEnabled(bool enabled) { _enabled = enabled; - for (auto& child : _widgetChildren) + for (auto& child : _children) { if (child) { - static_cast(child)->setEnabled(enabled); + Widget* widgetChild = dynamic_cast(child); + if (widgetChild) + { + widgetChild->setEnabled(enabled); + } + } + } + + for (auto& child : _protectedChildren) + { + if (child) + { + Widget* widgetChild = dynamic_cast(child); + if (widgetChild) + { + widgetChild->setEnabled(enabled); + } } } } Widget* Widget::getChildByName(const char *name) { - for (auto& child : _widgetChildren) + for (auto& child : _children) { if (child) { - Widget* widgetChild = static_cast(child); - if (strcmp(widgetChild->getName(), name) == 0) + Widget* widgetChild = dynamic_cast(child); + if (widgetChild) { - return widgetChild; + if (strcmp(widgetChild->getName(), name) == 0) + { + return widgetChild; + } } } } return nullptr; } - -void Widget::addNode(Node* node) -{ - addNode(node, node->getLocalZOrder(), node->getTag()); -} - -void Widget::addNode(Node * node, int zOrder) -{ - addNode(node, zOrder, node->getTag()); -} - -void Widget::addNode(Node* node, int zOrder, int tag) -{ - CCAssert(dynamic_cast(node) == nullptr, "Widget only supports Nodes as renderer"); - Node::addChild(node, zOrder, tag); - _nodes.pushBack(node); -} - -Node* Widget::getNodeByTag(int tag) -{ - CCAssert( tag != Node::INVALID_TAG, "Invalid tag"); - - for (auto& node : _nodes) - { - if(node && node->getTag() == tag) - return node; - } - return nullptr; -} - -Vector& Widget::getNodes() -{ - return _nodes; -} - -void Widget::removeNode(Node* node) -{ - Node::removeChild(node); - _nodes.eraseObject(node); -} - -void Widget::removeNodeByTag(int tag) -{ - CCAssert( tag != Node::INVALID_TAG, "Invalid tag"); - - Node *node = this->getNodeByTag(tag); - - if (node == nullptr) - { - CCLOG("cocos2d: removeNodeByTag(tag = %d): child not found!", tag); - } - else - { - this->removeNode(node); - } -} - -void Widget::removeAllNodes() -{ - for (auto& node : _nodes) - { - if (node) - { - Node::removeChild(node); - } - } - _nodes.clear(); -} - - + void Widget::initRenderer() { } @@ -544,9 +387,10 @@ void Widget::onSizeChanged() { for (auto& child : getChildren()) { - if (child) + Widget* widgetChild = dynamic_cast(child); + if (widgetChild) { - static_cast(child)->updateSizeAndPosition(); + widgetChild->updateSizeAndPosition(); } } } @@ -850,7 +694,7 @@ void Widget::setPosition(const Point &pos) } } } - Node::setPosition(pos); + ProtectedNode::setPosition(pos); } void Widget::setPositionPercent(const Point &percent) @@ -986,8 +830,11 @@ void Widget::copyClonedWidgetChildren(Widget* model) for (auto& subWidget : modelChildren) { - Widget* child = static_cast(subWidget); - addChild(child->clone()); + Widget* child = dynamic_cast(subWidget); + if (child) + { + addChild(child->clone()); + } } } diff --git a/cocos/ui/UIWidget.h b/cocos/ui/UIWidget.h index 9e0f70e7db..fd08ce6d41 100644 --- a/cocos/ui/UIWidget.h +++ b/cocos/ui/UIWidget.h @@ -25,7 +25,7 @@ THE SOFTWARE. #ifndef __UIWIDGET_H__ #define __UIWIDGET_H__ -#include "CCNode.h" +#include "ui/CCProtectedNode.h" #include "ui/UILayoutDefine.h" #include "ui/UILayoutParameter.h" #include "ui/GUIDefine.h" @@ -79,7 +79,7 @@ typedef void (Ref::*SEL_TouchEvent)(Ref*,TouchEventType); * @js NA * @lua NA */ -class Widget : public Node +class Widget : public ProtectedNode { public: /** @@ -199,114 +199,6 @@ public: */ float getTopInParent(); - /** - * Adds a child to the container with z-order as 0. - * - * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. - * - * @param child A child node - */ - virtual void addChild(Node * child) override; - /** - * Adds a child to the container with a z-order - * - * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. - * - * @param child A child node - * @param zOrder Z order for drawing priority. Please refer to setLocalZOrder(int) - */ - virtual void addChild(Node * child, int zOrder) override; - /** - * Adds a child to the container with z order and tag - * - * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. - * - * @param child A child node - * @param zOrder Z order for drawing priority. Please refer to setLocalZOrder(int) - * @param tag A interger to identify the node easily. Please refer to setTag(int) - */ - virtual void addChild(Node* child, int zOrder, int tag) override; - /** - * Gets a child from the container with its tag - * - * @param tag An identifier to find the child node. - * - * @return a Node object whose tag equals to the input parameter - */ - virtual Node * getChildByTag(int tag) override; - - virtual void sortAllChildren() override; - /** - * Return an array of children - * - * Composing a "tree" structure is a very important feature of Node - * Here's a sample code of traversing children array: - @code - Node* node = NULL; - CCARRAY_FOREACH(parent->getChildren(), node) - { - node->setPosition(0,0); - } - @endcode - * This sample code traverses all children nodes, and set their position to (0,0) - * - * @return An array of children - */ - virtual Vector& getChildren() override; - virtual const Vector& getChildren() const override; - - /** - * Get the amount of children. - * - * @return The amount of children. - */ - virtual ssize_t getChildrenCount() const override; - - /** - * Removes this node itself from its parent node with a cleanup. - * If the node orphan, then nothing happens. - * @see `removeFromParentAndCleanup(bool)` - */ - virtual void removeFromParent() override; - /** - * Removes this node itself from its parent node. - * If the node orphan, then nothing happens. - * @param cleanup true if all actions and callbacks on this node should be removed, false otherwise. - * @js removeFromParent - * @lua removeFromParent - */ - virtual void removeFromParentAndCleanup(bool cleanup) override; - - /** - * Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter. - * - * @param child The child node which will be removed. - * @param cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. - */ - virtual void removeChild(Node* child, bool cleanup = true) override; - - /** - * Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter - * - * @param tag An interger number that identifies a child node - * @param cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. - */ - virtual void removeChildByTag(int tag, bool cleanup = true) override; - /** - * Removes all children from the container with a cleanup. - * - * @see `removeAllChildrenWithCleanup(bool)` - */ - virtual void removeAllChildren() override; - /** - * Removes all children from the container, and do a cleanup to all running actions depending on the cleanup parameter. - * - * @param cleanup true if all running actions on all children nodes should be cleanup, false oterwise. - * @js removeAllChildren - * @lua removeAllChildren - */ - virtual void removeAllChildrenWithCleanup(bool cleanup) override; - /** * Gets a child from the container with its name * @@ -316,22 +208,6 @@ public: */ virtual Widget* getChildByName(const char* name); - virtual void addNode(Node* node); - - virtual void addNode(Node * node, int zOrder); - - virtual void addNode(Node* node, int zOrder, int tag); - - virtual Node * getNodeByTag(int tag); - - virtual Vector& getNodes(); - - virtual void removeNode(Node* node); - - virtual void removeNodeByTag(int tag); - - virtual void removeAllNodes(); - virtual void visit(cocos2d::Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override; /** @@ -713,13 +589,11 @@ protected: bool _reorderWidgetChildDirty; bool _hitted; EventListenerTouchOneByOne* _touchListener; - Vector _nodes; Color3B _color; GLubyte _opacity; bool _flippedX; bool _flippedY; Map _layoutParameterDictionary; - Vector _widgetChildren; }; } diff --git a/cocos/ui/proj.win32/libGUI.vcxproj b/cocos/ui/proj.win32/libGUI.vcxproj index 3dad252cfe..7d5aa4d0e6 100644 --- a/cocos/ui/proj.win32/libGUI.vcxproj +++ b/cocos/ui/proj.win32/libGUI.vcxproj @@ -11,6 +11,7 @@ + @@ -33,6 +34,7 @@ + diff --git a/cocos/ui/proj.win32/libGUI.vcxproj.filters b/cocos/ui/proj.win32/libGUI.vcxproj.filters index d79c8a4a8d..a01b4594d2 100644 --- a/cocos/ui/proj.win32/libGUI.vcxproj.filters +++ b/cocos/ui/proj.win32/libGUI.vcxproj.filters @@ -78,6 +78,9 @@ UIWidgets + + BaseClasses + @@ -137,5 +140,8 @@ UIWidgets + + BaseClasses + \ No newline at end of file diff --git a/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest.cpp b/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest.cpp index b50be77f77..456abac008 100644 --- a/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest.cpp +++ b/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest.cpp @@ -36,7 +36,7 @@ bool UIWidgetAddNodeTest::init() Sprite* sprite = Sprite::create("cocosui/ccicon.png"); sprite->setPosition(Point(0, sprite->getBoundingBox().size.height / 4)); - widget->addNode(sprite); + widget->addChild(sprite); return true; } diff --git a/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest_Editor.cpp b/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest_Editor.cpp index 6bc4101250..d4ad1b94f9 100644 --- a/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest_Editor.cpp +++ b/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest_Editor.cpp @@ -41,7 +41,7 @@ bool UIWidgetAddNodeTest_Editor::init() _layout->addChild(widget); Sprite* sprite = Sprite::create("cocosui/ccicon.png"); - widget->addNode(sprite); + widget->addChild(sprite); return true; }