From 3df1703839ccad13835242de31168601dec5da42 Mon Sep 17 00:00:00 2001 From: ChestnutYueyue <952134128@qq.com> Date: Mon, 16 Mar 2026 19:16:00 +0800 Subject: [PATCH] =?UTF-8?q?perf(scene):=20=E4=BD=BF=E7=94=A8=E5=93=88?= =?UTF-8?q?=E5=B8=8C=E8=A1=A8=E4=BC=98=E5=8C=96=E8=8A=82=E7=82=B9=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=92=8C=E5=88=A0=E9=99=A4=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化 Scene 和 Node 类的子节点管理,通过引入 unordered_map 存储节点索引,将删除操作的时间复杂度从 O(n) 降低到 O(1)。同时防止重复添加相同节点。 --- include/scene/node.h | 2 ++ include/scene/scene.h | 2 ++ src/scene/node.cpp | 21 +++++++++++++++------ src/scene/scene.cpp | 21 +++++++++++++++------ 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/include/scene/node.h b/include/scene/node.h index ee10db9..e245f14 100644 --- a/include/scene/node.h +++ b/include/scene/node.h @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace extra2d { @@ -315,6 +316,7 @@ private: bool visible_ = true; Node* parent_ = nullptr; std::vector> children_; + std::unordered_map childIndices_; std::vector> components_; TransformComponent* transform_ = nullptr; }; diff --git a/include/scene/scene.h b/include/scene/scene.h index dea5f9b..a4979c9 100644 --- a/include/scene/scene.h +++ b/include/scene/scene.h @@ -3,6 +3,7 @@ #include #include #include +#include #include namespace extra2d { @@ -115,6 +116,7 @@ public: protected: std::vector> rootNodes_; + std::unordered_map rootNodeIndices_; CameraComponent* mainCamera_ = nullptr; bool entered_ = false; }; diff --git a/src/scene/node.cpp b/src/scene/node.cpp index f216b1e..3a69f2d 100644 --- a/src/scene/node.cpp +++ b/src/scene/node.cpp @@ -29,6 +29,7 @@ Node::~Node() { void Node::addChild(Ptr 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 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(); } // ======================================== diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index eb9b879..ffd8487 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -16,21 +16,29 @@ Scene::~Scene() { void Scene::addChild(Ptr 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) {