If there are errors in the code, terminology, etc. in the text, please correct me
Article directory
foreword
-
of this program
Add a hierarchy interface panel to the engine to display the surviving entities in the current scene
-
How to achieve
Use ECS to traverse the entities of the current scene and display them with imgui
-
hint
Use ImGui::ShowDemoWindow(); to see the desired UI code
code flow
-
EditorLayer scene definition level panel SceneHierarchyPanel
SceneHierarchyPanel m_SceneHierarchyPanel;
-
Set which scene is currently open for SceneHierarchyPanel
m_SceneHierarchyPanel.SetContext(m_ActiveScene);// 设置上下文 SceneHierarchyPanel::SceneHierarchyPanel(const Ref<Scene>& context) { SetContext(context); } void SceneHierarchyPanel::SetContext(const Ref<Scene>& context) { m_Context = context; }
-
In the OnImGuiRender function of SceneHierarchyPanel, use ECS to traverse the entities of the current scene and display them with imgui
void SceneHierarchyPanel::OnImGuiRender() { // 新面板 ImGui::Begin("Scene Hierarchy"); m_Context->m_Registry.each([&](auto entityID){ // ImGui显示场景的实体 Entity entity{ entityID, m_Context.get()}; DrawEntityNode(entity); }); ImGui::End(); } void SceneHierarchyPanel::DrawEntityNode(Entity entity) { // 要引入 Log头文件 auto& tag = entity.GetComponent<TagComponent>().Tag; // 若是被点击标记为选中状态|有下一级 ImGuiTreeNodeFlags flags = ((m_SelectionContext == entity) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow; // 第一个参数是唯一ID 64的, bool opened = ImGui::TreeNodeEx((void*)(uint64_t)(uint32_t)entity, flags, tag.c_str()); if (ImGui::IsItemClicked()) { m_SelectionContext = entity; } if (opened) { ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow; bool opened = ImGui::TreeNodeEx((void*)98476565, flags, tag.c_str()); if (opened) { ImGui::TreePop(); } ImGui::TreePop(); } }
-
Render the UI of SceneHierarchyPanel in the OnImGuiRender function of EditorLayer.cpp
// 渲染 m_SceneHierarchyPanel.OnImGuiRender();
Effect
related code
#pragma once
#include "Hazel/Core/Core.h"
#include "Hazel/Core/Log.h"
#include "Hazel/Scene/Scene.h"
#include "Hazel/Scene/Entity.h"
namespace Hazel {
class SceneHierarchyPanel
{
public:
SceneHierarchyPanel() = default;
SceneHierarchyPanel(const Ref<Scene>& scene);
void SetContext(const Ref<Scene>& scene);
void OnImGuiRender();
private:
void DrawEntityNode(Entity entity);
private:
Ref<Scene> m_Context;// 用来标注哪个场景
Entity m_SelectionContext;
};
}
#include "SceneHierarchyPanel.h"
#include <imgui/imgui.h>
#include "Hazel/Scene/Components.h"
namespace Hazel {
SceneHierarchyPanel::SceneHierarchyPanel(const Ref<Scene>& context)
{
SetContext(context);
}
void SceneHierarchyPanel::SetContext(const Ref<Scene>& context)
{
m_Context = context;
}
void SceneHierarchyPanel::OnImGuiRender()
{
ImGui::Begin("Scene Hierarchy");
m_Context->m_Registry.each([&](auto entityID){
Entity entity{
entityID, m_Context.get()};
DrawEntityNode(entity);
});
ImGui::End();
}
void SceneHierarchyPanel::DrawEntityNode(Entity entity)
{
// 要引入 Log头文件
auto& tag = entity.GetComponent<TagComponent>().Tag;
// 若是被点击标记为选中状态|有下一级
ImGuiTreeNodeFlags flags = ((m_SelectionContext == entity) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow;
// 第一个参数是唯一ID 64的,
bool opened = ImGui::TreeNodeEx((void*)(uint64_t)(uint32_t)entity, flags, tag.c_str());
if (ImGui::IsItemClicked()) {
m_SelectionContext = entity;// 记录当前点击的实体
}
if (opened) {
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow;
bool opened = ImGui::TreeNodeEx((void*)98476565, flags, tag.c_str());
if (opened) {
ImGui::TreePop();
}
ImGui::TreePop();
}
}
}