mirror of https://github.com/axmolengine/axmol.git
#improve node sort performance by std::sort + long long (_localZOrder) (#16126)
* #improve node sort performance by std::sort + unsigned long long (_localZOrder) * Use bit field for make _localZOrder storage more clearly. * #Comment _localZOrder members for meaningful. * fix issues * #use explicit bits integer of localZOrder storage * #Fix compile error, add include <cstdint> to CCNode.h * use the optimization for 64bit and no optimization solution for 32bit
This commit is contained in:
parent
30118aff6b
commit
3a14388087
|
@ -57,9 +57,17 @@ NS_CC_BEGIN
|
|||
|
||||
bool nodeComparisonLess(Node* n1, Node* n2)
|
||||
{
|
||||
return( n1->getLocalZOrder() < n2->getLocalZOrder() );
|
||||
#if defined(_M_X64) || defined(_LP64) || defined(__x86_64) || defined(_WIN64)
|
||||
return (n1->_localZOrder.value < n2->_localZOrder.value);
|
||||
#else
|
||||
return n1->_localZOrder.detail.z < n2->_localZOrder.detail.z ||
|
||||
(n1->_localZOrder.detail.z == n2->_localZOrder.detail.z && n1->_localZOrder.detail.a < n2->_localZOrder.detail.a);
|
||||
#endif
|
||||
}
|
||||
|
||||
// FIXME:: Yes, nodes might have a sort problem once every 30 days if the game runs at 60 FPS and each frame sprites are reordered.
|
||||
unsigned int Node::s_globalOrderOfArrival = 0;
|
||||
|
||||
// MARK: Constructor, Destructor, Init
|
||||
|
||||
Node::Node()
|
||||
|
@ -84,7 +92,6 @@ Node::Node()
|
|||
, _transformUpdated(true)
|
||||
// children (lazy allocs)
|
||||
// lazy alloc
|
||||
, _localZOrder(0)
|
||||
, _globalZOrder(0)
|
||||
, _parent(nullptr)
|
||||
// "whole screen" objects. like Scenes and Layers, should set _ignoreAnchorPointForPosition to true
|
||||
|
@ -115,6 +122,8 @@ Node::Node()
|
|||
, _physicsBody(nullptr)
|
||||
#endif
|
||||
{
|
||||
_localZOrder.value = 0;
|
||||
|
||||
// set default scheduler and actionManager
|
||||
_director = Director::getInstance();
|
||||
_actionManager = _director->getActionManager();
|
||||
|
@ -254,10 +263,10 @@ void Node::setSkewY(float skewY)
|
|||
|
||||
void Node::setLocalZOrder(int z)
|
||||
{
|
||||
if (_localZOrder == z)
|
||||
if (getLocalZOrder() == z)
|
||||
return;
|
||||
|
||||
_localZOrder = z;
|
||||
_setLocalZOrder(z);
|
||||
if (_parent)
|
||||
{
|
||||
_parent->reorderChild(this, z);
|
||||
|
@ -270,7 +279,12 @@ void Node::setLocalZOrder(int z)
|
|||
/// used internally to alter the zOrder variable. DON'T call this method manually
|
||||
void Node::_setLocalZOrder(int z)
|
||||
{
|
||||
_localZOrder = z;
|
||||
_localZOrder.detail.z = z;
|
||||
}
|
||||
|
||||
void Node::updateOrderOfArrival()
|
||||
{
|
||||
_localZOrder.detail.a = s_globalOrderOfArrival++;
|
||||
}
|
||||
|
||||
void Node::setGlobalZOrder(float globalZOrder)
|
||||
|
@ -950,6 +964,8 @@ void Node::addChildHelper(Node* child, int localZOrder, int tag, const std::stri
|
|||
child->setParent(this);
|
||||
child->setCameraMask(getCameraMask());
|
||||
|
||||
child->updateOrderOfArrival();
|
||||
|
||||
if( _running )
|
||||
{
|
||||
child->onEnter();
|
||||
|
@ -980,7 +996,7 @@ void Node::addChild(Node *child, int zOrder)
|
|||
void Node::addChild(Node *child)
|
||||
{
|
||||
CCASSERT( child != nullptr, "Argument must be non-nil");
|
||||
this->addChild(child, child->_localZOrder, child->_name);
|
||||
this->addChild(child, child->_localZOrder.detail.z, child->_name);
|
||||
}
|
||||
|
||||
void Node::removeFromParent()
|
||||
|
@ -1127,21 +1143,22 @@ void Node::insertChild(Node* child, int z)
|
|||
_transformUpdated = true;
|
||||
_reorderChildDirty = true;
|
||||
_children.pushBack(child);
|
||||
child->_localZOrder = z;
|
||||
child->_setLocalZOrder(z);
|
||||
}
|
||||
|
||||
void Node::reorderChild(Node *child, int zOrder)
|
||||
{
|
||||
CCASSERT( child != nullptr, "Child must be non-nil");
|
||||
_reorderChildDirty = true;
|
||||
child->_localZOrder = zOrder;
|
||||
child->updateOrderOfArrival();
|
||||
child->_setLocalZOrder(zOrder);
|
||||
}
|
||||
|
||||
void Node::sortAllChildren()
|
||||
{
|
||||
if (_reorderChildDirty)
|
||||
{
|
||||
std::stable_sort(std::begin(_children), std::end(_children), nodeComparisonLess);
|
||||
std::sort(std::begin(_children), std::end(_children), nodeComparisonLess);
|
||||
_reorderChildDirty = false;
|
||||
}
|
||||
}
|
||||
|
@ -1234,7 +1251,7 @@ void Node::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t paren
|
|||
{
|
||||
auto node = _children.at(i);
|
||||
|
||||
if (node && node->_localZOrder < 0)
|
||||
if (node && node->_localZOrder.detail.z < 0)
|
||||
node->visit(renderer, _modelViewTransform, flags);
|
||||
else
|
||||
break;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#ifndef __CCNODE_H__
|
||||
#define __CCNODE_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/CCVector.h"
|
||||
#include "base/CCProtocols.h"
|
||||
|
@ -108,6 +109,7 @@ class EventListener;
|
|||
|
||||
class CC_DLL Node : public Ref
|
||||
{
|
||||
friend bool nodeComparisonLess(Node* n1, Node* n2);
|
||||
public:
|
||||
/** Default tag used for all the nodes */
|
||||
static const int INVALID_TAG = -1;
|
||||
|
@ -168,6 +170,18 @@ public:
|
|||
*/
|
||||
CC_DEPRECATED_ATTRIBUTE virtual void _setLocalZOrder(int z);
|
||||
|
||||
/** !!! ONLY FOR INTERNAL USE
|
||||
* Sets the arrival order when this node has a same ZOrder with other children.
|
||||
*
|
||||
* A node which called addChild subsequently will take a larger arrival order,
|
||||
* If two children have the same Z order, the child with larger arrival order will be drawn later.
|
||||
*
|
||||
* @warning This method is used internally for localZOrder sorting, don't change this manually
|
||||
*
|
||||
* @param orderOfArrival The arrival order.
|
||||
*/
|
||||
void updateOrderOfArrival();
|
||||
|
||||
/**
|
||||
* Gets the local Z order of this node.
|
||||
*
|
||||
|
@ -175,7 +189,7 @@ public:
|
|||
*
|
||||
* @return The local (relative to its siblings) Z order.
|
||||
*/
|
||||
virtual int getLocalZOrder() const { return _localZOrder; }
|
||||
virtual int getLocalZOrder() const { return _localZOrder.detail.z; }
|
||||
CC_DEPRECATED_ATTRIBUTE virtual int getZOrder() const { return getLocalZOrder(); }
|
||||
|
||||
/**
|
||||
|
@ -1881,9 +1895,17 @@ protected:
|
|||
mutable bool _additionalTransformDirty; ///< transform dirty ?
|
||||
bool _transformUpdated; ///< Whether or not the Transform object was updated since the last frame
|
||||
|
||||
int _localZOrder; ///< Local order (relative to its siblings) used to sort the node
|
||||
union {
|
||||
struct {
|
||||
std::int32_t z; // The original localZOrder
|
||||
std::uint32_t a; // Order Of Arrival, for avoid sort problem with unstable_sort algorithm.
|
||||
} detail;
|
||||
std::int64_t value; // The value to be used in sort
|
||||
} _localZOrder; ///< Local order (relative to its siblings) used to sort the node
|
||||
float _globalZOrder; ///< Global order used to sort the node
|
||||
|
||||
static unsigned int s_globalOrderOfArrival;
|
||||
|
||||
Vector<Node*> _children; ///< array of children nodes
|
||||
Node *_parent; ///< weak reference to parent node
|
||||
Director* _director; //cached director pointer to improve rendering performance
|
||||
|
|
|
@ -102,6 +102,8 @@ void ProtectedNode::addProtectedChild(Node *child, int zOrder, int tag)
|
|||
child->setTag(tag);
|
||||
|
||||
child->setParent(this);
|
||||
|
||||
child->updateOrderOfArrival();
|
||||
|
||||
if( _running )
|
||||
{
|
||||
|
@ -252,7 +254,7 @@ void ProtectedNode::insertProtectedChild(cocos2d::Node *child, int z)
|
|||
void ProtectedNode::sortAllProtectedChildren()
|
||||
{
|
||||
if( _reorderProtectedChildDirty ) {
|
||||
std::stable_sort( std::begin(_protectedChildren), std::end(_protectedChildren), nodeComparisonLess );
|
||||
std::sort( std::begin(_protectedChildren), std::end(_protectedChildren), nodeComparisonLess );
|
||||
_reorderProtectedChildDirty = false;
|
||||
}
|
||||
}
|
||||
|
@ -261,6 +263,7 @@ void ProtectedNode::reorderProtectedChild(cocos2d::Node *child, int localZOrder)
|
|||
{
|
||||
CCASSERT( child != nullptr, "Child must be non-nil");
|
||||
_reorderProtectedChildDirty = true;
|
||||
child->updateOrderOfArrival();
|
||||
child->setLocalZOrder(localZOrder);
|
||||
}
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ void Bone::setBoneData(BoneData *boneData)
|
|||
}
|
||||
|
||||
_name = _boneData->name;
|
||||
_localZOrder = _boneData->zOrder;
|
||||
_setLocalZOrder(_boneData->zOrder);
|
||||
|
||||
_displayManager->initDisplayList(boneData);
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ Tween *Bone::getTween()
|
|||
|
||||
void Bone::setLocalZOrder(int zOrder)
|
||||
{
|
||||
if (_localZOrder != zOrder)
|
||||
if (getLocalZOrder() != zOrder)
|
||||
Node::setLocalZOrder(zOrder);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue