Editor: 更新编辑器面板和UI控件系统

- 添加新的UI控件系统(Core.h, ScalarControls.h, VectorControls.h, UI.h)
- 更新SceneManager支持场景层级管理
- 优化SelectionManager选择管理
- 改进InspectorPanel/GameViewPanel/HierarchyPanel等面板
- 更新RHI文档说明Vulkan实现计划
This commit is contained in:
2026-03-24 20:02:38 +08:00
parent cab290b17d
commit 9fae910854
36 changed files with 757 additions and 148 deletions

View File

@@ -3,14 +3,15 @@
#include "Core/LogEntry.h"
#include <imgui.h>
namespace UI {
namespace XCEngine {
namespace Editor {
ConsolePanel::ConsolePanel() : Panel("Console") {
LogSystem::Get().AddLog(XCEngine::Debug::LogLevel::Info, "Engine initialized successfully");
LogSystem::Get().AddLog(XCEngine::Debug::LogLevel::Info, "Loading default scene...");
LogSystem::Get().AddLog(XCEngine::Debug::LogLevel::Warning, "Missing material on object 'Cube'");
LogSystem::Get().AddLog(XCEngine::Debug::LogLevel::Error, "Failed to load texture: 'Assets/Textures/missing.png'");
LogSystem::Get().AddLog(XCEngine::Debug::LogLevel::Info, "Scene loaded successfully");
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Info, "Engine initialized successfully");
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Info, "Loading default scene...");
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Warning, "Missing material on object 'Cube'");
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Error, "Failed to load texture: 'Assets/Textures/missing.png'");
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Info, "Scene loaded successfully");
}
void ConsolePanel::Render() {
@@ -21,15 +22,15 @@ void ConsolePanel::Render() {
}
ImGui::SameLine();
if (ImGui::Button("Info")) {
LogSystem::Get().AddLog(XCEngine::Debug::LogLevel::Info, "Test info message");
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Info, "Test info message");
}
ImGui::SameLine();
if (ImGui::Button("Warn")) {
LogSystem::Get().AddLog(XCEngine::Debug::LogLevel::Warning, "Test warning message");
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Warning, "Test warning message");
}
ImGui::SameLine();
if (ImGui::Button("Error")) {
LogSystem::Get().AddLog(XCEngine::Debug::LogLevel::Error, "Test error message");
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Error, "Test error message");
}
ImGui::Separator();
@@ -41,15 +42,15 @@ void ConsolePanel::Render() {
const char* prefix;
switch (log.level) {
case XCEngine::Debug::LogLevel::Info:
case ::XCEngine::Debug::LogLevel::Info:
color = ImVec4(0.7f, 0.7f, 0.7f, 1.0f);
prefix = "[Info] ";
break;
case XCEngine::Debug::LogLevel::Warning:
case ::XCEngine::Debug::LogLevel::Warning:
color = ImVec4(1.0f, 0.8f, 0.0f, 1.0f);
prefix = "[Warn] ";
break;
case XCEngine::Debug::LogLevel::Error:
case ::XCEngine::Debug::LogLevel::Error:
color = ImVec4(1.0f, 0.3f, 0.3f, 1.0f);
prefix = "[Error]";
break;
@@ -67,4 +68,5 @@ void ConsolePanel::Render() {
ImGui::End();
}
}
}

View File

@@ -2,7 +2,8 @@
#include "Panel.h"
namespace UI {
namespace XCEngine {
namespace Editor {
class ConsolePanel : public Panel {
public:
@@ -13,4 +14,5 @@ private:
bool m_scrollToBottom = false;
};
}
}

View File

@@ -2,7 +2,8 @@
#include <imgui.h>
#include <imgui_internal.h>
namespace UI {
namespace XCEngine {
namespace Editor {
GameViewPanel::GameViewPanel() : Panel("Game") {}
@@ -29,3 +30,4 @@ void GameViewPanel::RenderGameView() {
}
}
}

View File

@@ -2,7 +2,8 @@
#include "Panel.h"
namespace UI {
namespace XCEngine {
namespace Editor {
class GameViewPanel : public Panel {
public:
@@ -14,3 +15,4 @@ private:
};
}
}

View File

@@ -4,10 +4,11 @@
#include <imgui.h>
#include <cstring>
namespace UI {
namespace XCEngine {
namespace Editor {
HierarchyPanel::HierarchyPanel() : Panel("Hierarchy") {
SceneManager::Get().CreateDemoScene();
EditorSceneManager::Get().CreateDemoScene();
m_selectionHandlerId = SelectionManager::Get().OnSelectionChanged.Subscribe([this](uint64_t) {
});
@@ -30,7 +31,7 @@ void HierarchyPanel::Render() {
ImGui::BeginChild("EntityList");
for (auto* entity : SceneManager::Get().GetRootEntities()) {
for (auto* entity : EditorSceneManager::Get().GetRootEntities()) {
RenderEntity(entity, filter);
}
@@ -48,9 +49,9 @@ void HierarchyPanel::Render() {
ImGui::InvisibleButton("##DragTarget", ImVec2(-1, -1));
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_PTR")) {
XCEngine::Components::GameObject* sourceEntity = *(XCEngine::Components::GameObject**)payload->Data;
::XCEngine::Components::GameObject* sourceEntity = *(::XCEngine::Components::GameObject**)payload->Data;
if (sourceEntity && sourceEntity->GetParent() != nullptr) {
SceneManager::Get().MoveEntity(sourceEntity->GetID(), 0);
EditorSceneManager::Get().MoveEntity(sourceEntity->GetID(), 0);
}
}
ImGui::EndDragDropTarget();
@@ -66,7 +67,7 @@ void HierarchyPanel::RenderSearchBar() {
ImGui::InputTextWithHint("##Search", "Search...", m_searchBuffer, sizeof(m_searchBuffer));
}
void HierarchyPanel::RenderEntity(XCEngine::Components::GameObject* entity, const std::string& filter) {
void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* entity, const std::string& filter) {
if (!entity) return;
if (!filter.empty() && !PassesFilter(entity, filter)) {
@@ -94,7 +95,7 @@ void HierarchyPanel::RenderEntity(XCEngine::Components::GameObject* entity, cons
ImGui::SetNextItemWidth(-1);
if (ImGui::InputText("##Rename", m_renameBuffer, sizeof(m_renameBuffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
if (strlen(m_renameBuffer) > 0) {
SceneManager::Get().RenameEntity(entity->GetID(), m_renameBuffer);
EditorSceneManager::Get().RenameEntity(entity->GetID(), m_renameBuffer);
}
m_renaming = false;
m_renamingEntity = nullptr;
@@ -102,7 +103,7 @@ void HierarchyPanel::RenderEntity(XCEngine::Components::GameObject* entity, cons
if (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)) {
if (strlen(m_renameBuffer) > 0) {
SceneManager::Get().RenameEntity(entity->GetID(), m_renameBuffer);
EditorSceneManager::Get().RenameEntity(entity->GetID(), m_renameBuffer);
}
m_renaming = false;
m_renamingEntity = nullptr;
@@ -139,8 +140,8 @@ void HierarchyPanel::RenderEntity(XCEngine::Components::GameObject* entity, cons
ImGui::PopID();
}
void HierarchyPanel::RenderContextMenu(XCEngine::Components::GameObject* entity) {
auto& sceneManager = SceneManager::Get();
void HierarchyPanel::RenderContextMenu(::XCEngine::Components::GameObject* entity) {
auto& sceneManager = EditorSceneManager::Get();
auto& selectionManager = SelectionManager::Get();
if (ImGui::BeginMenu("Create")) {
@@ -181,8 +182,8 @@ void HierarchyPanel::RenderContextMenu(XCEngine::Components::GameObject* entity)
}
}
void HierarchyPanel::RenderCreateMenu(XCEngine::Components::GameObject* parent) {
auto& sceneManager = SceneManager::Get();
void HierarchyPanel::RenderCreateMenu(::XCEngine::Components::GameObject* parent) {
auto& sceneManager = EditorSceneManager::Get();
auto& selectionManager = SelectionManager::Get();
if (ImGui::MenuItem("Empty Object")) {
@@ -194,7 +195,7 @@ void HierarchyPanel::RenderCreateMenu(XCEngine::Components::GameObject* parent)
if (ImGui::MenuItem("Camera")) {
auto* newEntity = sceneManager.CreateEntity("Camera", parent);
newEntity->AddComponent<XCEngine::Components::TransformComponent>();
newEntity->AddComponent<::XCEngine::Components::TransformComponent>();
selectionManager.SetSelectedEntity(newEntity);
}
@@ -207,37 +208,39 @@ void HierarchyPanel::RenderCreateMenu(XCEngine::Components::GameObject* parent)
if (ImGui::MenuItem("Cube")) {
auto* newEntity = sceneManager.CreateEntity("Cube", parent);
newEntity->AddComponent<XCEngine::Components::TransformComponent>();
newEntity->AddComponent<::XCEngine::Components::TransformComponent>();
selectionManager.SetSelectedEntity(newEntity);
}
if (ImGui::MenuItem("Sphere")) {
auto* newEntity = sceneManager.CreateEntity("Sphere", parent);
newEntity->AddComponent<XCEngine::Components::TransformComponent>();
newEntity->AddComponent<::XCEngine::Components::TransformComponent>();
selectionManager.SetSelectedEntity(newEntity);
}
if (ImGui::MenuItem("Plane")) {
auto* newEntity = sceneManager.CreateEntity("Plane", parent);
newEntity->AddComponent<XCEngine::Components::TransformComponent>();
newEntity->AddComponent<::XCEngine::Components::TransformComponent>();
selectionManager.SetSelectedEntity(newEntity);
}
}
void HierarchyPanel::HandleDragDrop(XCEngine::Components::GameObject* entity) {
void HierarchyPanel::HandleDragDrop(::XCEngine::Components::GameObject* entity) {
auto& sceneManager = EditorSceneManager::Get();
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
m_dragSource = entity;
ImGui::SetDragDropPayload("ENTITY_PTR", &entity, sizeof(XCEngine::Components::GameObject*));
ImGui::SetDragDropPayload("ENTITY_PTR", &entity, sizeof(::XCEngine::Components::GameObject*));
ImGui::Text("%s", entity->GetName().c_str());
ImGui::EndDragDropSource();
}
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_PTR")) {
XCEngine::Components::GameObject* sourceEntity = *(XCEngine::Components::GameObject**)payload->Data;
::XCEngine::Components::GameObject* sourceEntity = *(::XCEngine::Components::GameObject**)payload->Data;
if (sourceEntity != entity && sourceEntity != nullptr) {
bool isValidMove = true;
XCEngine::Components::GameObject* checkParent = entity;
::XCEngine::Components::GameObject* checkParent = entity;
while (checkParent != nullptr) {
if (checkParent == sourceEntity) {
isValidMove = false;
@@ -256,10 +259,10 @@ void HierarchyPanel::HandleDragDrop(XCEngine::Components::GameObject* entity) {
}
void HierarchyPanel::HandleKeyboardShortcuts() {
auto& sceneManager = SceneManager::Get();
auto& sceneManager = EditorSceneManager::Get();
auto& selectionManager = SelectionManager::Get();
XCEngine::Components::GameObject* selectedEntity = selectionManager.GetSelectedEntity();
::XCEngine::Components::GameObject* selectedEntity = selectionManager.GetSelectedEntity();
if (ImGui::IsWindowFocused()) {
if (ImGui::IsKeyPressed(ImGuiKey_Delete)) {
@@ -300,7 +303,7 @@ void HierarchyPanel::HandleKeyboardShortcuts() {
}
}
bool HierarchyPanel::PassesFilter(XCEngine::Components::GameObject* entity, const std::string& filter) {
bool HierarchyPanel::PassesFilter(::XCEngine::Components::GameObject* entity, const std::string& filter) {
if (!entity) return false;
if (entity->GetName().find(filter) != std::string::npos) {
@@ -317,3 +320,4 @@ bool HierarchyPanel::PassesFilter(XCEngine::Components::GameObject* entity, cons
}
}
}

View File

@@ -3,7 +3,8 @@
#include "Panel.h"
#include <XCEngine/Components/GameObject.h>
namespace UI {
namespace XCEngine {
namespace Editor {
class HierarchyPanel : public Panel {
public:
@@ -14,21 +15,22 @@ public:
private:
void RenderSearchBar();
void RenderEntity(XCEngine::Components::GameObject* entity, const std::string& filter);
void RenderContextMenu(XCEngine::Components::GameObject* entity);
void RenderCreateMenu(XCEngine::Components::GameObject* parent);
void HandleDragDrop(XCEngine::Components::GameObject* entity);
void RenderEntity(::XCEngine::Components::GameObject* entity, const std::string& filter);
void RenderContextMenu(::XCEngine::Components::GameObject* entity);
void RenderCreateMenu(::XCEngine::Components::GameObject* parent);
void HandleDragDrop(::XCEngine::Components::GameObject* entity);
void HandleKeyboardShortcuts();
bool PassesFilter(XCEngine::Components::GameObject* entity, const std::string& filter);
bool PassesFilter(::XCEngine::Components::GameObject* entity, const std::string& filter);
uint64_t m_selectionHandlerId = 0;
char m_searchBuffer[256] = "";
bool m_renaming = false;
XCEngine::Components::GameObject* m_renamingEntity = nullptr;
::XCEngine::Components::GameObject* m_renamingEntity = nullptr;
char m_renameBuffer[256] = "";
bool m_renameJustStarted = false;
XCEngine::Components::GameObject* m_dragSource = nullptr;
::XCEngine::Components::GameObject* m_dragSource = nullptr;
};
}
}

View File

@@ -1,11 +1,12 @@
#include "InspectorPanel.h"
#include "Managers/SceneManager.h"
#include "Managers/SelectionManager.h"
#include "UI/UI.h"
#include <imgui.h>
#include <string>
#include <glm/glm.hpp>
namespace UI {
namespace XCEngine {
namespace Editor {
InspectorPanel::InspectorPanel() : Panel("Inspector") {
m_selectionHandlerId = SelectionManager::Get().OnSelectionChanged.Subscribe([this](uint64_t) {
@@ -19,7 +20,7 @@ InspectorPanel::~InspectorPanel() {
void InspectorPanel::Render() {
ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None);
XCEngine::Components::GameObject* entity = SelectionManager::Get().GetSelectedEntity();
::XCEngine::Components::GameObject* entity = SelectionManager::Get().GetSelectedEntity();
if (entity) {
RenderEntity(entity);
@@ -31,17 +32,18 @@ void InspectorPanel::Render() {
ImGui::End();
}
void InspectorPanel::RenderEntity(XCEngine::Components::GameObject* entity) {
void InspectorPanel::RenderEntity(::XCEngine::Components::GameObject* entity) {
ImGui::Text("%s", entity->GetName().c_str());
ImGui::Separator();
for (auto& component : entity->m_components) {
RenderComponent(component.get());
auto components = entity->GetComponents<::XCEngine::Components::Component>();
for (auto* component : components) {
RenderComponent(component);
ImGui::Separator();
}
}
void InspectorPanel::RenderComponent(XCEngine::Components::Component* component) {
void InspectorPanel::RenderComponent(::XCEngine::Components::Component* component) {
if (!component) return;
const char* name = component->GetName().c_str();
@@ -51,20 +53,20 @@ void InspectorPanel::RenderComponent(XCEngine::Components::Component* component)
if (ImGui::CollapsingHeader(headerId.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::Indent(10.0f);
if (auto* transform = dynamic_cast<XCEngine::Components::TransformComponent*>(component)) {
glm::vec3 position = transform->GetLocalPosition();
glm::vec3 rotation = transform->GetLocalEulerAngles();
glm::vec3 scale = transform->GetLocalScale();
if (auto* transform = dynamic_cast<::XCEngine::Components::TransformComponent*>(component)) {
::XCEngine::Math::Vector3 position = transform->GetLocalPosition();
::XCEngine::Math::Vector3 rotation = transform->GetLocalEulerAngles();
::XCEngine::Math::Vector3 scale = transform->GetLocalScale();
if (ImGui::DragFloat3("Position", &position.x, 0.1f)) {
if (UI::DrawVec3("Position", position, 0.0f, 80.0f, 0.1f)) {
transform->SetLocalPosition(position);
}
if (ImGui::DragFloat3("Rotation", &rotation.x, 1.0f)) {
if (UI::DrawVec3("Rotation", rotation, 0.0f, 80.0f, 1.0f)) {
transform->SetLocalEulerAngles(rotation);
}
if (ImGui::DragFloat3("Scale", &scale.x, 0.1f)) {
if (UI::DrawVec3("Scale", scale, 1.0f, 80.0f, 0.1f)) {
transform->SetLocalScale(scale);
}
}
@@ -74,3 +76,4 @@ void InspectorPanel::RenderComponent(XCEngine::Components::Component* component)
}
}
}

View File

@@ -4,7 +4,8 @@
#include <XCEngine/Components/GameObject.h>
#include <XCEngine/Components/TransformComponent.h>
namespace UI {
namespace XCEngine {
namespace Editor {
class InspectorPanel : public Panel {
public:
@@ -14,10 +15,11 @@ public:
void Render() override;
private:
void RenderEntity(XCEngine::Components::GameObject* entity);
void RenderComponent(XCEngine::Components::Component* component);
void RenderEntity(::XCEngine::Components::GameObject* entity);
void RenderComponent(::XCEngine::Components::Component* component);
uint64_t m_selectionHandlerId = 0;
};
}
}

View File

@@ -1,7 +1,8 @@
#include "MenuBar.h"
#include <imgui.h>
namespace UI {
namespace XCEngine {
namespace Editor {
MenuBar::MenuBar() : Panel("MenuBar") {}
@@ -52,4 +53,5 @@ void MenuBar::ShowHelpMenu() {
}
}
}
}

View File

@@ -2,7 +2,8 @@
#include "Panel.h"
namespace UI {
namespace XCEngine {
namespace Editor {
class MenuBar : public Panel {
public:
@@ -16,4 +17,5 @@ private:
void ShowHelpMenu();
};
}
}

View File

@@ -1,4 +1,6 @@
#include "Panel.h"
namespace UI {
namespace XCEngine {
namespace Editor {
}
}

View File

@@ -3,7 +3,8 @@
#include <string>
#include <imgui.h>
namespace UI {
namespace XCEngine {
namespace Editor {
class Panel {
public:
@@ -22,4 +23,5 @@ protected:
bool m_isOpen;
};
}
}

View File

@@ -4,7 +4,8 @@
#include <imgui.h>
#include <imgui_internal.h>
namespace UI {
namespace XCEngine {
namespace Editor {
const char* DRAG_DROP_TYPE = "ASSET_ITEM";
@@ -294,4 +295,5 @@ bool ProjectPanel::HandleDrop(const AssetItemPtr& targetFolder) {
return false;
}
}
}

View File

@@ -3,7 +3,8 @@
#include "Panel.h"
#include "Core/AssetItem.h"
namespace UI {
namespace XCEngine {
namespace Editor {
class ProjectPanel : public Panel {
public:
@@ -23,4 +24,5 @@ private:
std::string m_draggingPath;
};
}
}

View File

@@ -2,7 +2,8 @@
#include <imgui.h>
#include <imgui_internal.h>
namespace UI {
namespace XCEngine {
namespace Editor {
SceneViewPanel::SceneViewPanel() : Panel("Scene") {}
@@ -51,4 +52,5 @@ void SceneViewPanel::RenderGrid() {
drawList->AddText(labelPos, IM_COL32(100, 100, 100, 255), label);
}
}
}

View File

@@ -2,7 +2,8 @@
#include "Panel.h"
namespace UI {
namespace XCEngine {
namespace Editor {
class SceneViewPanel : public Panel {
public:
@@ -13,4 +14,5 @@ private:
void RenderGrid();
};
}
}