Refactor editor UI architecture
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
#include "Actions/EditorActions.h"
|
||||
#include "Commands/ComponentCommands.h"
|
||||
#include "InspectorPanel.h"
|
||||
#include "Core/IEditorContext.h"
|
||||
#include "Core/ISceneManager.h"
|
||||
#include "Core/ISelectionManager.h"
|
||||
#include "Core/IUndoManager.h"
|
||||
#include "Core/EventBus.h"
|
||||
#include "Core/EditorEvents.h"
|
||||
#include "ComponentEditors/ComponentEditorRegistry.h"
|
||||
#include "ComponentEditors/IComponentEditor.h"
|
||||
#include "UI/PanelChrome.h"
|
||||
#include "Utils/UndoUtils.h"
|
||||
#include "UI/UI.h"
|
||||
#include <imgui.h>
|
||||
#include <string>
|
||||
|
||||
@@ -52,14 +52,10 @@ void InspectorPanel::Render() {
|
||||
if (gameObject) {
|
||||
RenderGameObject(gameObject);
|
||||
} else {
|
||||
ImGui::SetCursorPos(ImVec2(10.0f, 10.0f));
|
||||
ImGui::Text("Object not found");
|
||||
RenderEmptyState("Object not found");
|
||||
}
|
||||
} else {
|
||||
ImGui::SetCursorPos(ImVec2(10.0f, 10.0f));
|
||||
ImGui::Text("No Selection");
|
||||
ImGui::SetCursorPos(ImVec2(10.0f, 30.0f));
|
||||
ImGui::TextColored(ImVec4(0.55f, 0.55f, 0.55f, 1.0f), "Select an object in Hierarchy");
|
||||
RenderEmptyState("No Selection", "Select an object in Hierarchy");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -81,7 +77,7 @@ void InspectorPanel::RenderGameObject(::XCEngine::Components::GameObject* gameOb
|
||||
RenderComponent(component, gameObject);
|
||||
}
|
||||
|
||||
if (ImGui::Button("Add Component", ImVec2(-1.0f, 0.0f))) {
|
||||
if (Actions::DrawInspectorAction(Actions::MakeAddComponentButtonAction(gameObject != nullptr))) {
|
||||
ImGui::OpenPopup("AddComponent");
|
||||
}
|
||||
RenderAddComponentPopup(gameObject);
|
||||
@@ -91,13 +87,19 @@ void InspectorPanel::RenderGameObject(::XCEngine::Components::GameObject* gameOb
|
||||
}
|
||||
}
|
||||
|
||||
void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject* gameObject) {
|
||||
if (!ImGui::BeginPopup("AddComponent")) {
|
||||
void InspectorPanel::RenderEmptyState(const char* title, const char* subtitle) {
|
||||
UI::PanelContentScope content("InspectorEmptyState", UI::InspectorPanelContentPadding());
|
||||
if (!content.IsOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Text("Components");
|
||||
ImGui::Separator();
|
||||
UI::DrawEmptyState(title, subtitle);
|
||||
}
|
||||
|
||||
void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject* gameObject) {
|
||||
if (!UI::BeginTitledPopup("AddComponent", "Components")) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool drewAnyEntry = false;
|
||||
for (const auto& editor : ComponentEditorRegistry::Get().GetEditors()) {
|
||||
@@ -106,7 +108,7 @@ void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject*
|
||||
}
|
||||
|
||||
drewAnyEntry = true;
|
||||
const bool canAdd = editor->CanAddTo(gameObject);
|
||||
const bool canAdd = Commands::CanAddComponent(*editor, gameObject);
|
||||
std::string label = editor->GetDisplayName();
|
||||
if (!canAdd) {
|
||||
const char* reason = editor->GetAddDisabledReason(gameObject);
|
||||
@@ -117,88 +119,49 @@ void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject*
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem(label.c_str(), nullptr, false, canAdd)) {
|
||||
bool added = false;
|
||||
UndoUtils::ExecuteSceneCommand(*m_context, std::string("Add ") + editor->GetDisplayName() + " Component", [&]() {
|
||||
added = editor->AddTo(gameObject) != nullptr;
|
||||
if (added) {
|
||||
m_context->GetSceneManager().MarkSceneDirty();
|
||||
}
|
||||
});
|
||||
if (added) {
|
||||
Actions::DrawMenuAction(Actions::MakeAddComponentMenuAction(label, canAdd), [&]() {
|
||||
if (Commands::AddComponent(*m_context, *editor, gameObject)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!drewAnyEntry) {
|
||||
ImGui::TextDisabled("No registered component editors");
|
||||
UI::DrawHintText("No registered component editors");
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
UI::EndTitledPopup();
|
||||
}
|
||||
|
||||
void InspectorPanel::RenderComponent(::XCEngine::Components::Component* component, ::XCEngine::Components::GameObject* gameObject) {
|
||||
if (!component) return;
|
||||
|
||||
IComponentEditor* editor = ComponentEditorRegistry::Get().FindEditor(component);
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
|
||||
const std::string name = component->GetName();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{6, 4});
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, 0.0f));
|
||||
|
||||
ImGuiTreeNodeFlags flags =
|
||||
ImGuiTreeNodeFlags_DefaultOpen |
|
||||
ImGuiTreeNodeFlags_Framed |
|
||||
ImGuiTreeNodeFlags_SpanAvailWidth |
|
||||
ImGuiTreeNodeFlags_FramePadding |
|
||||
ImGuiTreeNodeFlags_AllowOverlap;
|
||||
|
||||
bool open = ImGui::TreeNodeEx((void*)typeid(*component).hash_code(), flags, "%s", name.c_str());
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
bool removeComponent = false;
|
||||
const bool canRemoveComponent = editor ? editor->CanRemove(component) : false;
|
||||
if (ImGui::BeginPopupContextItem("ComponentSettings")) {
|
||||
if (ImGui::MenuItem("Remove Component", nullptr, false, canRemoveComponent)) {
|
||||
removeComponent = true;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (removeComponent) {
|
||||
RemoveComponentByType(component, gameObject);
|
||||
|
||||
const UI::ComponentSectionResult section =
|
||||
UI::BeginComponentSection(
|
||||
(void*)typeid(*component).hash_code(),
|
||||
name.c_str(),
|
||||
Commands::CanRemoveComponent(component, editor));
|
||||
|
||||
if (section.removeRequested) {
|
||||
Commands::RemoveComponent(*m_context, component, gameObject, editor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (open) {
|
||||
if (section.open) {
|
||||
if (editor) {
|
||||
if (editor->Render(component, &m_context->GetUndoManager())) {
|
||||
m_context->GetSceneManager().MarkSceneDirty();
|
||||
}
|
||||
} else {
|
||||
ImGui::TextDisabled("No registered editor for this component");
|
||||
UI::DrawHintText("No registered editor for this component");
|
||||
}
|
||||
|
||||
ImGui::TreePop();
|
||||
UI::EndComponentSection();
|
||||
}
|
||||
}
|
||||
|
||||
void InspectorPanel::RemoveComponentByType(::XCEngine::Components::Component* component, ::XCEngine::Components::GameObject* gameObject) {
|
||||
if (!component || !gameObject) return;
|
||||
|
||||
if (dynamic_cast<::XCEngine::Components::TransformComponent*>(component)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UndoUtils::ExecuteSceneCommand(*m_context, std::string("Remove ") + component->GetName() + " Component", [&]() {
|
||||
gameObject->RemoveComponent(component);
|
||||
m_context->GetSceneManager().MarkSceneDirty();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user