perf(scene): 使用哈希表优化节点添加和删除操作
优化 Scene 和 Node 类的子节点管理,通过引入 unordered_map 存储节点索引,将删除操作的时间复杂度从 O(n) 降低到 O(1)。同时防止重复添加相同节点。
This commit is contained in:
parent
95d9e7c5c4
commit
3df1703839
|
|
@ -6,6 +6,7 @@
|
|||
#include <types/math/mat4.h>
|
||||
#include <types/ptr/intrusive_ptr.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace extra2d {
|
||||
|
|
@ -315,6 +316,7 @@ private:
|
|||
bool visible_ = true;
|
||||
Node* parent_ = nullptr;
|
||||
std::vector<Ptr<Node>> children_;
|
||||
std::unordered_map<Node*, size_t> childIndices_;
|
||||
std::vector<Ptr<Component>> components_;
|
||||
TransformComponent* transform_ = nullptr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <scene/node.h>
|
||||
#include <types/ptr/intrusive_ptr.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace extra2d {
|
||||
|
|
@ -115,6 +116,7 @@ public:
|
|||
|
||||
protected:
|
||||
std::vector<Ptr<Node>> rootNodes_;
|
||||
std::unordered_map<Node*, size_t> rootNodeIndices_;
|
||||
CameraComponent* mainCamera_ = nullptr;
|
||||
bool entered_ = false;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ Node::~Node() {
|
|||
|
||||
void Node::addChild(Ptr<Node> child) {
|
||||
if (!child || child.get() == this) return;
|
||||
if (childIndices_.find(child.get()) != childIndices_.end()) return;
|
||||
|
||||
// 从原父节点移除
|
||||
if (child->parent_) {
|
||||
|
|
@ -36,18 +37,25 @@ void Node::addChild(Ptr<Node> child) {
|
|||
}
|
||||
|
||||
child->parent_ = this;
|
||||
childIndices_[child.get()] = children_.size();
|
||||
children_.push_back(child);
|
||||
}
|
||||
|
||||
void Node::removeChild(Node* child) {
|
||||
if (!child) return;
|
||||
|
||||
for (auto it = children_.begin(); it != children_.end(); ++it) {
|
||||
if (it->get() == child) {
|
||||
child->parent_ = nullptr;
|
||||
children_.erase(it);
|
||||
return;
|
||||
}
|
||||
auto indexIt = childIndices_.find(child);
|
||||
if (indexIt == childIndices_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t removeIndex = indexIt->second;
|
||||
child->parent_ = nullptr;
|
||||
children_.erase(children_.begin() + removeIndex);
|
||||
childIndices_.erase(indexIt);
|
||||
|
||||
for (size_t i = removeIndex; i < children_.size(); ++i) {
|
||||
childIndices_[children_[i].get()] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,6 +70,7 @@ void Node::removeAllChildren() {
|
|||
child->parent_ = nullptr;
|
||||
}
|
||||
children_.clear();
|
||||
childIndices_.clear();
|
||||
}
|
||||
|
||||
// ========================================
|
||||
|
|
|
|||
|
|
@ -16,21 +16,29 @@ Scene::~Scene() {
|
|||
|
||||
void Scene::addChild(Ptr<Node> node) {
|
||||
if (!node) return;
|
||||
if (rootNodeIndices_.find(node.get()) != rootNodeIndices_.end()) return;
|
||||
|
||||
node->removeFromParent();
|
||||
node->onEnter();
|
||||
rootNodeIndices_[node.get()] = rootNodes_.size();
|
||||
rootNodes_.push_back(node);
|
||||
}
|
||||
|
||||
void Scene::removeChild(Node* node) {
|
||||
if (!node) return;
|
||||
|
||||
for (auto it = rootNodes_.begin(); it != rootNodes_.end(); ++it) {
|
||||
if (it->get() == node) {
|
||||
node->onExit();
|
||||
rootNodes_.erase(it);
|
||||
return;
|
||||
}
|
||||
auto indexIt = rootNodeIndices_.find(node);
|
||||
if (indexIt == rootNodeIndices_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t removeIndex = indexIt->second;
|
||||
node->onExit();
|
||||
rootNodes_.erase(rootNodes_.begin() + removeIndex);
|
||||
rootNodeIndices_.erase(indexIt);
|
||||
|
||||
for (size_t i = removeIndex; i < rootNodes_.size(); ++i) {
|
||||
rootNodeIndices_[rootNodes_[i].get()] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -39,6 +47,7 @@ void Scene::removeAllChildren() {
|
|||
node->onExit();
|
||||
}
|
||||
rootNodes_.clear();
|
||||
rootNodeIndices_.clear();
|
||||
}
|
||||
|
||||
Node* Scene::findNode(const std::string& name) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue