#include "InspectorPanel.h" #include "Core/EditorContext.h" #include "Managers/SceneManager.h" #include "UI/UI.h" #include #include #include namespace XCEngine { namespace Editor { InspectorPanel::InspectorPanel() : Panel("Inspector") { Debug::Logger::Get().Debug(Debug::LogCategory::General, "InspectorPanel constructed"); } InspectorPanel::~InspectorPanel() { if (m_context) { m_context->GetEventBus().Unsubscribe(m_selectionHandlerId); } } void InspectorPanel::OnSelectionChanged(const SelectionChangedEvent& event) { m_selectedEntityId = event.primarySelection; } void InspectorPanel::Render() { Debug::Logger::Get().Debug(Debug::LogCategory::General, "InspectorPanel::Render START"); ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); if (!m_selectionHandlerId && m_context) { m_selectionHandlerId = m_context->GetEventBus().Subscribe( [this](const SelectionChangedEvent& event) { OnSelectionChanged(event); } ); } m_selectedEntityId = m_context->GetSelectionManager().GetSelectedEntity(); if (m_selectedEntityId) { auto* sceneManager = static_cast(m_context->GetSceneManager()); auto* gameObject = sceneManager->GetEntity(m_selectedEntityId); if (gameObject) { RenderGameObject(gameObject); } else { ImGui::Text("Object not found"); } } else { ImGui::Text("No object selected"); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Select an object in Hierarchy"); } ImGui::End(); Debug::Logger::Get().Debug(Debug::LogCategory::General, "InspectorPanel::Render END"); } void InspectorPanel::RenderGameObject(::XCEngine::Components::GameObject* gameObject) { Debug::Logger::Get().Debug(Debug::LogCategory::General, "RenderGameObject START"); char nameBuffer[256]; strcpy_s(nameBuffer, gameObject->GetName().c_str()); ImGui::InputText("##Name", nameBuffer, sizeof(nameBuffer)); if (ImGui::IsItemDeactivatedAfterEdit()) { gameObject->SetName(nameBuffer); } ImGui::SameLine(); if (ImGui::Button("Add Component")) { Debug::Logger::Get().Debug(Debug::LogCategory::General, "Add Component BUTTON CLICKED"); ImGui::OpenPopup("AddComponent"); } RenderAddComponentPopup(gameObject); auto components = gameObject->GetComponents<::XCEngine::Components::Component>(); for (auto* component : components) { RenderComponent(component, gameObject); } Debug::Logger::Get().Debug(Debug::LogCategory::General, "RenderGameObject END"); } void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject* gameObject) { Debug::Logger::Get().Debug(Debug::LogCategory::General, "RenderAddComponentPopup called"); if (!gameObject) { Debug::Logger::Get().Error(Debug::LogCategory::General, "ERROR: gameObject is nullptr!"); return; } if (!ImGui::BeginPopup("AddComponent")) { Debug::Logger::Get().Debug(Debug::LogCategory::General, "BeginPopup returned false"); return; } Debug::Logger::Get().Debug(Debug::LogCategory::General, "BeginPopup succeeded"); ImGui::Text("Components"); ImGui::Separator(); bool hasTransform = gameObject->GetComponent<::XCEngine::Components::TransformComponent>() != nullptr; Debug::Logger::Get().Debug(Debug::LogCategory::General, hasTransform ? "Has Transform: yes" : "Has Transform: no"); Debug::Logger::Get().Debug(Debug::LogCategory::General, "About to check MenuItem condition"); if (ImGui::MenuItem("Transform", nullptr, false, !hasTransform)) { Debug::Logger::Get().Debug(Debug::LogCategory::General, "MenuItem CLICKED! Before AddComponent"); auto* newComp = gameObject->AddComponent<::XCEngine::Components::TransformComponent>(); Debug::Logger::Get().Debug(Debug::LogCategory::General, newComp ? "AddComponent SUCCEEDED" : "AddComponent FAILED"); ImGui::CloseCurrentPopup(); } else { Debug::Logger::Get().Debug(Debug::LogCategory::General, "MenuItem not clicked (disabled or condition false)"); } ImGui::Separator(); ImGui::TextDisabled("No more components available"); Debug::Logger::Get().Debug(Debug::LogCategory::General, "About to EndPopup - calling EndPopup"); ImGui::EndPopup(); Debug::Logger::Get().Debug(Debug::LogCategory::General, "Popup closed"); } void InspectorPanel::RenderComponent(::XCEngine::Components::Component* component, ::XCEngine::Components::GameObject* gameObject) { if (!component) return; const char* name = component->GetName().c_str(); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{4, 2}); ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_FramePadding | ImGuiTreeNodeFlags_AllowOverlap; bool open = ImGui::TreeNodeEx((void*)typeid(*component).hash_code(), flags, "%s", name); ImGui::PopStyleVar(); bool removeComponent = false; if (ImGui::BeginPopupContextItem("ComponentSettings")) { if (ImGui::MenuItem("Remove Component")) { removeComponent = true; } ImGui::EndPopup(); } if (removeComponent) { RemoveComponentByType(component, gameObject); return; } if (open) { 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 (UI::DrawVec3("Position", position, 0.0f, 80.0f, 0.1f)) { transform->SetLocalPosition(position); } if (UI::DrawVec3("Rotation", rotation, 0.0f, 80.0f, 1.0f)) { transform->SetLocalEulerAngles(rotation); } if (UI::DrawVec3("Scale", scale, 1.0f, 80.0f, 0.1f)) { transform->SetLocalScale(scale); } } ImGui::TreePop(); } } void InspectorPanel::RemoveComponentByType(::XCEngine::Components::Component* component, ::XCEngine::Components::GameObject* gameObject) { if (!component || !gameObject) return; if (dynamic_cast<::XCEngine::Components::TransformComponent*>(component)) { return; } auto components = gameObject->GetComponents<::XCEngine::Components::Component>(); for (auto* comp : components) { if (comp == component) { gameObject->RemoveComponent<::XCEngine::Components::Component>(); break; } } } } }