// // HierarchyPanel.cpp:实体列表实现。 // #include "HierarchyPanel.h" #include "Engine/ECS/Components.h" #include "Engine/ECS/EntityHandle.h" // CreateEntity 返回完整 EntityHandle #include using namespace Engine; namespace { struct ScopedID { explicit ScopedID(const u64 uuid) { ImGui::PushID(reinterpret_cast(uuid)); } ~ScopedID() {ImGui::PopID(); } }; } void HierarchyPanel::Draw(const EditorContext& ctx, entt::entity& selected) { ImGui::Begin("Hierarchy"); // 工具栏:创建实体(在遍历之前,不修改遍历中的注册表结构) if (ImGui::Button("+ Create Entity")) { const auto e = ctx.scene->CreateEntity("Entity"); selected = e; } ImGui::Separator(); auto& reg = ctx.scene->GetRegistry(); reg.view().each( [&](const entt::entity e, const Engine::ECS::NameComponent& name) { const bool isSelected = (selected == e); u64 rowId = static_cast < uint64_t >( static_cast < uint32_t >(e)); if (const auto * id = reg.try_get(e)) { rowId = id->uuid.Value(); } const ScopedID scope (rowId); const std::string label = name.name.empty() ? "(unnamed)" : name.name; if (ImGui::Selectable(label.c_str(), isSelected)) { selected = e; } // 右键菜单:删除(延迟销毁,帧尾统一 flush) if (ImGui::BeginPopupContextItem("entity_ctx")) { if (ImGui::MenuItem("Delete")) { ctx.scene->DestroyEntity(e); if (selected == e) { selected = entt::null; } } ImGui::EndPopup(); } // 组件徽标 + 悬停清单 std::string badge; if (reg.all_of(e)) badge += "[M]"; if (reg.all_of(e)) badge += "[A]"; if (reg.all_of(e)) badge += "[C]"; if (reg.all_of(e)) badge += "[L]"; if (!badge.empty()) { ImGui::SameLine(); ImGui::TextDisabled("%s", badge.c_str()); if (ImGui::IsItemHovered()) { ImGui::SetTooltip( "M=Mesh A=Animation C=Camera L=Light"); } } }); ImGui::End(); }