Editor: UI panels and GameObject updates
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "Application.h"
|
||||
#include "Layers/EditorLayer.h"
|
||||
#include <imgui_impl_win32.h>
|
||||
#include <imgui_impl_dx12.h>
|
||||
#include <imgui_internal.h>
|
||||
@@ -45,14 +46,6 @@ bool Application::Initialize(HWND hwnd) {
|
||||
m_srvHeap->GetCPUDescriptorHandleForHeapStart(),
|
||||
m_srvHeap->GetGPUDescriptorHandleForHeapStart());
|
||||
|
||||
m_menuBar = std::make_unique<MenuBar>();
|
||||
m_hierarchyPanel = std::make_unique<HierarchyPanel>();
|
||||
m_sceneViewPanel = std::make_unique<SceneViewPanel>();
|
||||
m_gameViewPanel = std::make_unique<GameViewPanel>();
|
||||
m_inspectorPanel = std::make_unique<InspectorPanel>();
|
||||
m_consolePanel = std::make_unique<ConsolePanel>();
|
||||
m_projectPanel = std::make_unique<ProjectPanel>();
|
||||
|
||||
wchar_t exePath[MAX_PATH];
|
||||
GetModuleFileNameW(nullptr, exePath, MAX_PATH);
|
||||
std::wstring exeDirW(exePath);
|
||||
@@ -66,12 +59,18 @@ bool Application::Initialize(HWND hwnd) {
|
||||
exeDir.resize(len - 1);
|
||||
WideCharToMultiByte(CP_UTF8, 0, exeDirW.c_str(), -1, &exeDir[0], len, nullptr, nullptr);
|
||||
}
|
||||
m_projectPanel->Initialize(exeDir);
|
||||
|
||||
m_editorLayer = new EditorLayer();
|
||||
m_editorLayer->SetProjectPath(exeDir);
|
||||
m_layerStack.pushLayer(std::unique_ptr<Core::Layer>(m_editorLayer));
|
||||
m_layerStack.onAttach();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::Shutdown() {
|
||||
m_layerStack.onDetach();
|
||||
|
||||
ImGui_ImplDX12_Shutdown();
|
||||
ImGui_ImplWin32_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
@@ -93,8 +92,7 @@ void Application::Render() {
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
SetupDockspace();
|
||||
RenderUI();
|
||||
m_layerStack.onImGuiRender();
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
@@ -243,63 +241,5 @@ void Application::CleanupRenderTarget() {
|
||||
}
|
||||
}
|
||||
|
||||
void Application::SetupDockspace() {
|
||||
static ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_NoWindowMenuButton;
|
||||
|
||||
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
ImGui::SetNextWindowSize(viewport->Size);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
windowFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
|
||||
windowFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::Begin("MainDockspace", nullptr, windowFlags);
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGuiID dockspaceId = ImGui::GetID("MyDockspace");
|
||||
ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);
|
||||
|
||||
static bool firstTime = true;
|
||||
if (firstTime) {
|
||||
firstTime = false;
|
||||
ImGui::DockBuilderRemoveNode(dockspaceId);
|
||||
ImGui::DockBuilderAddNode(dockspaceId, dockspaceFlags | ImGuiDockNodeFlags_DockSpace);
|
||||
ImGui::DockBuilderSetNodeSize(dockspaceId, viewport->Size);
|
||||
|
||||
ImGuiID dockMain = dockspaceId;
|
||||
ImGuiID dockBottom = ImGui::DockBuilderSplitNode(dockMain, ImGuiDir_Down, 0.25f, nullptr, &dockMain);
|
||||
ImGuiID dockLeft = ImGui::DockBuilderSplitNode(dockMain, ImGuiDir_Left, 0.15f, nullptr, &dockMain);
|
||||
ImGuiID dockRight = ImGui::DockBuilderSplitNode(dockMain, ImGuiDir_Right, 0.25f, nullptr, &dockMain);
|
||||
|
||||
ImGui::DockBuilderDockWindow("Hierarchy", dockLeft);
|
||||
ImGui::DockBuilderDockWindow("Scene", dockMain);
|
||||
ImGui::DockBuilderDockWindow("Game", dockMain);
|
||||
ImGui::DockBuilderDockWindow("Inspector", dockRight);
|
||||
ImGui::DockBuilderDockWindow("Console", dockBottom);
|
||||
ImGui::DockBuilderDockWindow("Project", dockBottom);
|
||||
|
||||
ImGui::DockBuilderFinish(dockspaceId);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Application::RenderUI() {
|
||||
m_menuBar->Render();
|
||||
|
||||
m_hierarchyPanel->Render();
|
||||
m_sceneViewPanel->Render();
|
||||
m_gameViewPanel->Render();
|
||||
m_inspectorPanel->Render();
|
||||
m_consolePanel->Render();
|
||||
m_projectPanel->Render();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -5,19 +5,15 @@
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_6.h>
|
||||
|
||||
#include <XCEngine/Core/LayerStack.h>
|
||||
|
||||
#include "Theme.h"
|
||||
#include "panels/Panel.h"
|
||||
#include "panels/MenuBar.h"
|
||||
#include "panels/HierarchyPanel.h"
|
||||
#include "panels/SceneViewPanel.h"
|
||||
#include "panels/GameViewPanel.h"
|
||||
#include "panels/InspectorPanel.h"
|
||||
#include "panels/ConsolePanel.h"
|
||||
#include "panels/ProjectPanel.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
|
||||
class EditorLayer;
|
||||
|
||||
class Application {
|
||||
public:
|
||||
static Application& Get();
|
||||
@@ -34,8 +30,6 @@ private:
|
||||
bool CreateDevice();
|
||||
bool CreateRenderTarget();
|
||||
void CleanupRenderTarget();
|
||||
void SetupDockspace();
|
||||
void RenderUI();
|
||||
|
||||
HWND m_hwnd = nullptr;
|
||||
int m_width = 1280;
|
||||
@@ -54,13 +48,8 @@ private:
|
||||
UINT m_rtvDescriptorSize = 0;
|
||||
UINT m_frameIndex = 0;
|
||||
|
||||
std::unique_ptr<MenuBar> m_menuBar;
|
||||
std::unique_ptr<HierarchyPanel> m_hierarchyPanel;
|
||||
std::unique_ptr<SceneViewPanel> m_sceneViewPanel;
|
||||
std::unique_ptr<GameViewPanel> m_gameViewPanel;
|
||||
std::unique_ptr<InspectorPanel> m_inspectorPanel;
|
||||
std::unique_ptr<ConsolePanel> m_consolePanel;
|
||||
std::unique_ptr<ProjectPanel> m_projectPanel;
|
||||
Core::LayerStack m_layerStack;
|
||||
EditorLayer* m_editorLayer = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
112
editor/src/Layers/EditorLayer.cpp
Normal file
112
editor/src/Layers/EditorLayer.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "EditorLayer.h"
|
||||
#include "panels/MenuBar.h"
|
||||
#include "panels/HierarchyPanel.h"
|
||||
#include "panels/SceneViewPanel.h"
|
||||
#include "panels/GameViewPanel.h"
|
||||
#include "panels/InspectorPanel.h"
|
||||
#include "panels/ConsolePanel.h"
|
||||
#include "panels/ProjectPanel.h"
|
||||
#include "Managers/SelectionManager.h"
|
||||
#include "Managers/SceneManager.h"
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
|
||||
EditorLayer::EditorLayer() : Layer("Editor") {}
|
||||
|
||||
void EditorLayer::onAttach() {
|
||||
m_menuBar = std::make_unique<MenuBar>();
|
||||
m_hierarchyPanel = std::make_unique<HierarchyPanel>();
|
||||
m_sceneViewPanel = std::make_unique<SceneViewPanel>();
|
||||
m_gameViewPanel = std::make_unique<GameViewPanel>();
|
||||
m_inspectorPanel = std::make_unique<InspectorPanel>();
|
||||
m_consolePanel = std::make_unique<ConsolePanel>();
|
||||
m_projectPanel = std::make_unique<ProjectPanel>();
|
||||
|
||||
m_projectPanel->Initialize(m_projectPath);
|
||||
|
||||
auto& selection = SelectionManager::Get();
|
||||
selection.OnSelectionChanged.Subscribe([](uint64_t id) {
|
||||
});
|
||||
}
|
||||
|
||||
void EditorLayer::onDetach() {
|
||||
}
|
||||
|
||||
void EditorLayer::onUpdate(float dt) {
|
||||
}
|
||||
|
||||
void EditorLayer::onEvent(void* event) {
|
||||
}
|
||||
|
||||
void EditorLayer::onImGuiRender() {
|
||||
setupDockspace();
|
||||
renderAllPanels();
|
||||
}
|
||||
|
||||
void EditorLayer::SetProjectPath(const std::string& path) {
|
||||
m_projectPath = path;
|
||||
}
|
||||
|
||||
void EditorLayer::setupDockspace() {
|
||||
static ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_NoWindowMenuButton;
|
||||
|
||||
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
ImGui::SetNextWindowSize(viewport->Size);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
windowFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
|
||||
windowFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::Begin("MainDockspace", nullptr, windowFlags);
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGuiID dockspaceId = ImGui::GetID("MyDockspace");
|
||||
ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);
|
||||
|
||||
static bool firstTime = true;
|
||||
if (firstTime) {
|
||||
firstTime = false;
|
||||
ImGui::DockBuilderRemoveNode(dockspaceId);
|
||||
ImGui::DockBuilderAddNode(dockspaceId, dockspaceFlags | ImGuiDockNodeFlags_DockSpace);
|
||||
ImGui::DockBuilderSetNodeSize(dockspaceId, viewport->Size);
|
||||
|
||||
ImGuiID dockMain = dockspaceId;
|
||||
ImGuiID dockBottom = ImGui::DockBuilderSplitNode(dockMain, ImGuiDir_Down, 0.25f, nullptr, &dockMain);
|
||||
ImGuiID dockLeft = ImGui::DockBuilderSplitNode(dockMain, ImGuiDir_Left, 0.15f, nullptr, &dockMain);
|
||||
ImGuiID dockRight = ImGui::DockBuilderSplitNode(dockMain, ImGuiDir_Right, 0.25f, nullptr, &dockMain);
|
||||
|
||||
ImGui::DockBuilderDockWindow("Hierarchy", dockLeft);
|
||||
ImGui::DockBuilderDockWindow("Scene", dockMain);
|
||||
ImGui::DockBuilderDockWindow("Game", dockMain);
|
||||
ImGui::DockBuilderDockWindow("Inspector", dockRight);
|
||||
ImGui::DockBuilderDockWindow("Console", dockBottom);
|
||||
ImGui::DockBuilderDockWindow("Project", dockBottom);
|
||||
|
||||
ImGui::DockBuilderFinish(dockspaceId);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void EditorLayer::renderAllPanels() {
|
||||
m_menuBar->Render();
|
||||
|
||||
m_hierarchyPanel->Render();
|
||||
m_sceneViewPanel->Render();
|
||||
m_gameViewPanel->Render();
|
||||
m_inspectorPanel->Render();
|
||||
m_consolePanel->Render();
|
||||
m_projectPanel->Render();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
48
editor/src/Layers/EditorLayer.h
Normal file
48
editor/src/Layers/EditorLayer.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Core/Layer.h>
|
||||
#include <XCEngine/Core/LayerStack.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
|
||||
class MenuBar;
|
||||
class HierarchyPanel;
|
||||
class SceneViewPanel;
|
||||
class GameViewPanel;
|
||||
class InspectorPanel;
|
||||
class ConsolePanel;
|
||||
class ProjectPanel;
|
||||
|
||||
class EditorLayer : public Core::Layer {
|
||||
public:
|
||||
EditorLayer();
|
||||
~EditorLayer() override = default;
|
||||
|
||||
void onAttach() override;
|
||||
void onDetach() override;
|
||||
void onUpdate(float dt) override;
|
||||
void onEvent(void* event) override;
|
||||
void onImGuiRender() override;
|
||||
|
||||
void SetProjectPath(const std::string& path);
|
||||
|
||||
private:
|
||||
void setupDockspace();
|
||||
void renderAllPanels();
|
||||
|
||||
std::string m_projectPath;
|
||||
|
||||
std::unique_ptr<MenuBar> m_menuBar;
|
||||
std::unique_ptr<HierarchyPanel> m_hierarchyPanel;
|
||||
std::unique_ptr<SceneViewPanel> m_sceneViewPanel;
|
||||
std::unique_ptr<GameViewPanel> m_gameViewPanel;
|
||||
std::unique_ptr<InspectorPanel> m_inspectorPanel;
|
||||
std::unique_ptr<ConsolePanel> m_consolePanel;
|
||||
std::unique_ptr<ProjectPanel> m_projectPanel;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,9 @@ EditorSceneManager::ClipboardData EditorSceneManager::CopyEntityRecursive(const
|
||||
data.name = entity->GetName();
|
||||
|
||||
if (auto* transform = entity->GetComponent<::XCEngine::Components::TransformComponent>()) {
|
||||
// Transform 数据会被复制
|
||||
data.localPosition = transform->GetLocalPosition();
|
||||
data.localRotation = transform->GetLocalRotation();
|
||||
data.localScale = transform->GetLocalScale();
|
||||
}
|
||||
|
||||
for (auto* child : entity->GetChildren()) {
|
||||
@@ -75,6 +77,12 @@ void EditorSceneManager::CopyEntity(::XCEngine::Components::GameObject::ID id) {
|
||||
|
||||
::XCEngine::Components::GameObject* newEntity = m_scene->CreateGameObject(data.name, parentObj);
|
||||
|
||||
if (auto* transform = newEntity->GetComponent<::XCEngine::Components::TransformComponent>()) {
|
||||
transform->SetLocalPosition(data.localPosition);
|
||||
transform->SetLocalRotation(data.localRotation);
|
||||
transform->SetLocalScale(data.localScale);
|
||||
}
|
||||
|
||||
if (parentObj == nullptr) {
|
||||
m_rootEntities.push_back(newEntity);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <optional>
|
||||
|
||||
#include <XCEngine/Core/Event.h>
|
||||
#include <XCEngine/Core/Math/Vector3.h>
|
||||
#include <XCEngine/Core/Math/Quaternion.h>
|
||||
#include <XCEngine/Components/GameObject.h>
|
||||
#include <XCEngine/Scene/Scene.h>
|
||||
|
||||
@@ -61,7 +63,9 @@ private:
|
||||
|
||||
struct ClipboardData {
|
||||
std::string name;
|
||||
std::vector<std::unique_ptr<::XCEngine::Components::Component>> components;
|
||||
Math::Vector3 localPosition = Math::Vector3::Zero();
|
||||
Math::Quaternion localRotation = Math::Quaternion::Identity();
|
||||
Math::Vector3 localScale = Math::Vector3::One();
|
||||
std::vector<ClipboardData> children;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <XCEngine/Core/Event.h>
|
||||
#include <XCEngine/Components/GameObject.h>
|
||||
@@ -15,26 +16,65 @@ public:
|
||||
return instance;
|
||||
}
|
||||
|
||||
::XCEngine::Components::GameObject* GetSelectedEntity() const { return m_selectedEntity; }
|
||||
|
||||
void SetSelectedEntity(::XCEngine::Components::GameObject* entity) {
|
||||
m_selectedEntity = entity;
|
||||
if (m_selectedEntities.empty()) {
|
||||
m_selectedEntities.push_back(entity);
|
||||
} else {
|
||||
m_selectedEntities[0] = entity;
|
||||
m_selectedEntities.resize(1);
|
||||
}
|
||||
OnSelectionChanged.Invoke(entity ? entity->GetID() : 0);
|
||||
}
|
||||
|
||||
void ClearSelection() {
|
||||
SetSelectedEntity(nullptr);
|
||||
void SetSelectedEntities(const std::vector<::XCEngine::Components::GameObject*>& entities) {
|
||||
m_selectedEntities = entities;
|
||||
if (!entities.empty()) {
|
||||
OnSelectionChanged.Invoke(entities.back()->GetID());
|
||||
} else {
|
||||
OnSelectionChanged.Invoke(0);
|
||||
}
|
||||
}
|
||||
|
||||
void AddToSelection(::XCEngine::Components::GameObject* entity) {
|
||||
if (entity && !IsSelected(entity)) {
|
||||
m_selectedEntities.push_back(entity);
|
||||
OnSelectionChanged.Invoke(entity->GetID());
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveFromSelection(::XCEngine::Components::GameObject* entity) {
|
||||
auto it = std::find(m_selectedEntities.begin(), m_selectedEntities.end(), entity);
|
||||
if (it != m_selectedEntities.end()) {
|
||||
m_selectedEntities.erase(it);
|
||||
OnSelectionChanged.Invoke(entity ? entity->GetID() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearSelection() {
|
||||
m_selectedEntities.clear();
|
||||
OnSelectionChanged.Invoke(0);
|
||||
}
|
||||
|
||||
::XCEngine::Components::GameObject* GetSelectedEntity() const {
|
||||
return m_selectedEntities.empty() ? nullptr : m_selectedEntities.back();
|
||||
}
|
||||
|
||||
const std::vector<::XCEngine::Components::GameObject*>& GetSelectedEntities() const {
|
||||
return m_selectedEntities;
|
||||
}
|
||||
|
||||
bool HasSelection() const { return !m_selectedEntities.empty(); }
|
||||
size_t GetSelectionCount() const { return m_selectedEntities.size(); }
|
||||
|
||||
bool IsSelected(::XCEngine::Components::GameObject* entity) const {
|
||||
return m_selectedEntity == entity;
|
||||
return std::find(m_selectedEntities.begin(), m_selectedEntities.end(), entity) != m_selectedEntities.end();
|
||||
}
|
||||
|
||||
::XCEngine::Core::Event<uint64_t> OnSelectionChanged;
|
||||
|
||||
private:
|
||||
SelectionManager() = default;
|
||||
::XCEngine::Components::GameObject* m_selectedEntity = nullptr;
|
||||
std::vector<::XCEngine::Components::GameObject*> m_selectedEntities;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -93,4 +93,4 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "HierarchyPanel.h"
|
||||
#include "Managers/SceneManager.h"
|
||||
#include "Managers/SelectionManager.h"
|
||||
#include <XCEngine/Core/Math/Vector3.h>
|
||||
#include <XCEngine/Core/Math/Quaternion.h>
|
||||
#include <imgui.h>
|
||||
#include <cstring>
|
||||
|
||||
@@ -31,8 +33,8 @@ void HierarchyPanel::Render() {
|
||||
|
||||
ImGui::BeginChild("EntityList");
|
||||
|
||||
for (auto* entity : EditorSceneManager::Get().GetRootEntities()) {
|
||||
RenderEntity(entity, filter);
|
||||
for (auto* gameObject : EditorSceneManager::Get().GetRootEntities()) {
|
||||
RenderEntity(gameObject, filter);
|
||||
}
|
||||
|
||||
if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(0) && !ImGui::IsAnyItemHovered()) {
|
||||
@@ -49,9 +51,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;
|
||||
if (sourceEntity && sourceEntity->GetParent() != nullptr) {
|
||||
EditorSceneManager::Get().MoveEntity(sourceEntity->GetID(), 0);
|
||||
::XCEngine::Components::GameObject* sourceGameObject = *(::XCEngine::Components::GameObject**)payload->Data;
|
||||
if (sourceGameObject && sourceGameObject->GetParent() != nullptr) {
|
||||
EditorSceneManager::Get().MoveEntity(sourceGameObject->GetID(), 0);
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
@@ -67,26 +69,26 @@ void HierarchyPanel::RenderSearchBar() {
|
||||
ImGui::InputTextWithHint("##Search", "Search...", m_searchBuffer, sizeof(m_searchBuffer));
|
||||
}
|
||||
|
||||
void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* entity, const std::string& filter) {
|
||||
if (!entity) return;
|
||||
void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject, const std::string& filter) {
|
||||
if (!gameObject) return;
|
||||
|
||||
if (!filter.empty() && !PassesFilter(entity, filter)) {
|
||||
if (!filter.empty() && !PassesFilter(gameObject, filter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::PushID(static_cast<int>(entity->GetID()));
|
||||
ImGui::PushID(static_cast<int>(gameObject->GetID()));
|
||||
|
||||
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth;
|
||||
|
||||
if (entity->GetChildCount() == 0) {
|
||||
if (gameObject->GetChildCount() == 0) {
|
||||
flags |= ImGuiTreeNodeFlags_Leaf;
|
||||
}
|
||||
|
||||
if (SelectionManager::Get().IsSelected(entity)) {
|
||||
if (SelectionManager::Get().IsSelected(gameObject)) {
|
||||
flags |= ImGuiTreeNodeFlags_Selected;
|
||||
}
|
||||
|
||||
if (m_renaming && m_renamingEntity == entity) {
|
||||
if (m_renaming && m_renamingEntity == gameObject) {
|
||||
if (m_renameJustStarted) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
m_renameJustStarted = false;
|
||||
@@ -95,7 +97,7 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* entity, co
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
if (ImGui::InputText("##Rename", m_renameBuffer, sizeof(m_renameBuffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
if (strlen(m_renameBuffer) > 0) {
|
||||
EditorSceneManager::Get().RenameEntity(entity->GetID(), m_renameBuffer);
|
||||
EditorSceneManager::Get().RenameEntity(gameObject->GetID(), m_renameBuffer);
|
||||
}
|
||||
m_renaming = false;
|
||||
m_renamingEntity = nullptr;
|
||||
@@ -103,35 +105,42 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* entity, co
|
||||
|
||||
if (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)) {
|
||||
if (strlen(m_renameBuffer) > 0) {
|
||||
EditorSceneManager::Get().RenameEntity(entity->GetID(), m_renameBuffer);
|
||||
EditorSceneManager::Get().RenameEntity(gameObject->GetID(), m_renameBuffer);
|
||||
}
|
||||
m_renaming = false;
|
||||
m_renamingEntity = nullptr;
|
||||
}
|
||||
} else {
|
||||
bool isOpen = ImGui::TreeNodeEx(entity->GetName().c_str(), flags);
|
||||
bool isOpen = ImGui::TreeNodeEx((void*)gameObject->GetUUID(), flags, "%s", gameObject->GetName().c_str());
|
||||
|
||||
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) {
|
||||
SelectionManager::Get().SetSelectedEntity(entity);
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.KeyCtrl) {
|
||||
if (!SelectionManager::Get().IsSelected(gameObject)) {
|
||||
SelectionManager::Get().AddToSelection(gameObject);
|
||||
}
|
||||
} else {
|
||||
SelectionManager::Get().SetSelectedEntity(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
|
||||
m_renaming = true;
|
||||
m_renamingEntity = entity;
|
||||
strcpy_s(m_renameBuffer, entity->GetName().c_str());
|
||||
m_renamingEntity = gameObject;
|
||||
strcpy_s(m_renameBuffer, gameObject->GetName().c_str());
|
||||
m_renameJustStarted = true;
|
||||
}
|
||||
|
||||
HandleDragDrop(entity);
|
||||
HandleDragDrop(gameObject);
|
||||
|
||||
if (ImGui::BeginPopupContextItem("EntityContextMenu")) {
|
||||
RenderContextMenu(entity);
|
||||
RenderContextMenu(gameObject);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (isOpen) {
|
||||
for (size_t i = 0; i < entity->GetChildCount(); i++) {
|
||||
RenderEntity(entity->GetChild(i), filter);
|
||||
for (size_t i = 0; i < gameObject->GetChildCount(); i++) {
|
||||
RenderEntity(gameObject->GetChild(i), filter);
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
@@ -140,44 +149,54 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* entity, co
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
void HierarchyPanel::RenderContextMenu(::XCEngine::Components::GameObject* entity) {
|
||||
void HierarchyPanel::RenderContextMenu(::XCEngine::Components::GameObject* gameObject) {
|
||||
auto& sceneManager = EditorSceneManager::Get();
|
||||
auto& selectionManager = SelectionManager::Get();
|
||||
|
||||
if (ImGui::BeginMenu("Create")) {
|
||||
RenderCreateMenu(entity);
|
||||
RenderCreateMenu(gameObject);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (gameObject != nullptr && ImGui::MenuItem("Create Child")) {
|
||||
auto* child = sceneManager.CreateEntity("GameObject", gameObject);
|
||||
selectionManager.SetSelectedEntity(child);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (gameObject != nullptr && gameObject->GetParent() != nullptr) {
|
||||
if (ImGui::MenuItem("Detach from Parent")) {
|
||||
gameObject->DetachFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Rename", "F2")) {
|
||||
if (entity) {
|
||||
if (gameObject) {
|
||||
m_renaming = true;
|
||||
m_renamingEntity = entity;
|
||||
strcpy_s(m_renameBuffer, entity->GetName().c_str());
|
||||
m_renamingEntity = gameObject;
|
||||
strcpy_s(m_renameBuffer, gameObject->GetName().c_str());
|
||||
m_renameJustStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Delete", "Delete")) {
|
||||
sceneManager.DeleteEntity(entity->GetID());
|
||||
sceneManager.DeleteEntity(gameObject->GetID());
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Copy", "Ctrl+C")) {
|
||||
sceneManager.CopyEntity(entity->GetID());
|
||||
sceneManager.CopyEntity(gameObject->GetID());
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Paste", "Ctrl+V", false, sceneManager.HasClipboardData())) {
|
||||
sceneManager.PasteEntity(entity->GetID());
|
||||
sceneManager.PasteEntity(gameObject->GetID());
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Duplicate", "Ctrl+D")) {
|
||||
uint64_t newId = sceneManager.DuplicateEntity(entity->GetID());
|
||||
uint64_t newId = sceneManager.DuplicateEntity(gameObject->GetID());
|
||||
if (newId != 0) {
|
||||
// Selection handled via callback
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,24 +244,23 @@ void HierarchyPanel::RenderCreateMenu(::XCEngine::Components::GameObject* parent
|
||||
}
|
||||
}
|
||||
|
||||
void HierarchyPanel::HandleDragDrop(::XCEngine::Components::GameObject* entity) {
|
||||
void HierarchyPanel::HandleDragDrop(::XCEngine::Components::GameObject* gameObject) {
|
||||
auto& sceneManager = EditorSceneManager::Get();
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
|
||||
m_dragSource = entity;
|
||||
ImGui::SetDragDropPayload("ENTITY_PTR", &entity, sizeof(::XCEngine::Components::GameObject*));
|
||||
ImGui::Text("%s", entity->GetName().c_str());
|
||||
ImGui::SetDragDropPayload("ENTITY_PTR", &gameObject, sizeof(::XCEngine::Components::GameObject*));
|
||||
ImGui::Text("%s", gameObject->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;
|
||||
if (sourceEntity != entity && sourceEntity != nullptr) {
|
||||
::XCEngine::Components::GameObject* sourceGameObject = *(::XCEngine::Components::GameObject**)payload->Data;
|
||||
if (sourceGameObject != gameObject && sourceGameObject != nullptr) {
|
||||
bool isValidMove = true;
|
||||
::XCEngine::Components::GameObject* checkParent = entity;
|
||||
::XCEngine::Components::GameObject* checkParent = gameObject;
|
||||
while (checkParent != nullptr) {
|
||||
if (checkParent == sourceEntity) {
|
||||
if (checkParent == sourceGameObject) {
|
||||
isValidMove = false;
|
||||
break;
|
||||
}
|
||||
@@ -250,7 +268,16 @@ void HierarchyPanel::HandleDragDrop(::XCEngine::Components::GameObject* entity)
|
||||
}
|
||||
|
||||
if (isValidMove) {
|
||||
sceneManager.MoveEntity(sourceEntity->GetID(), entity->GetID());
|
||||
auto* srcTransform = sourceGameObject->GetTransform();
|
||||
Math::Vector3 worldPos = srcTransform->GetPosition();
|
||||
Math::Quaternion worldRot = srcTransform->GetRotation();
|
||||
Math::Vector3 worldScale = srcTransform->GetScale();
|
||||
|
||||
sceneManager.MoveEntity(sourceGameObject->GetID(), gameObject->GetID());
|
||||
|
||||
srcTransform->SetPosition(worldPos);
|
||||
srcTransform->SetRotation(worldRot);
|
||||
srcTransform->SetScale(worldScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -262,20 +289,20 @@ void HierarchyPanel::HandleKeyboardShortcuts() {
|
||||
auto& sceneManager = EditorSceneManager::Get();
|
||||
auto& selectionManager = SelectionManager::Get();
|
||||
|
||||
::XCEngine::Components::GameObject* selectedEntity = selectionManager.GetSelectedEntity();
|
||||
::XCEngine::Components::GameObject* selectedGameObject = selectionManager.GetSelectedEntity();
|
||||
|
||||
if (ImGui::IsWindowFocused()) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Delete)) {
|
||||
if (selectedEntity != nullptr) {
|
||||
sceneManager.DeleteEntity(selectedEntity->GetID());
|
||||
if (selectedGameObject != nullptr) {
|
||||
sceneManager.DeleteEntity(selectedGameObject->GetID());
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_F2)) {
|
||||
if (selectedEntity != nullptr) {
|
||||
if (selectedGameObject != nullptr) {
|
||||
m_renaming = true;
|
||||
m_renamingEntity = selectedEntity;
|
||||
strcpy_s(m_renameBuffer, selectedEntity->GetName().c_str());
|
||||
m_renamingEntity = selectedGameObject;
|
||||
strcpy_s(m_renameBuffer, selectedGameObject->GetName().c_str());
|
||||
m_renameJustStarted = true;
|
||||
}
|
||||
}
|
||||
@@ -283,35 +310,35 @@ void HierarchyPanel::HandleKeyboardShortcuts() {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.KeyCtrl) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_C)) {
|
||||
if (selectedEntity != nullptr) {
|
||||
sceneManager.CopyEntity(selectedEntity->GetID());
|
||||
if (selectedGameObject != nullptr) {
|
||||
sceneManager.CopyEntity(selectedGameObject->GetID());
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_V)) {
|
||||
if (sceneManager.HasClipboardData()) {
|
||||
sceneManager.PasteEntity(selectedEntity ? selectedEntity->GetID() : 0);
|
||||
sceneManager.PasteEntity(selectedGameObject ? selectedGameObject->GetID() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_D)) {
|
||||
if (selectedEntity != nullptr) {
|
||||
sceneManager.DuplicateEntity(selectedEntity->GetID());
|
||||
if (selectedGameObject != nullptr) {
|
||||
sceneManager.DuplicateEntity(selectedGameObject->GetID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HierarchyPanel::PassesFilter(::XCEngine::Components::GameObject* entity, const std::string& filter) {
|
||||
if (!entity) return false;
|
||||
bool HierarchyPanel::PassesFilter(::XCEngine::Components::GameObject* gameObject, const std::string& filter) {
|
||||
if (!gameObject) return false;
|
||||
|
||||
if (entity->GetName().find(filter) != std::string::npos) {
|
||||
if (gameObject->GetName().find(filter) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < entity->GetChildCount(); i++) {
|
||||
if (PassesFilter(entity->GetChild(i), filter)) {
|
||||
for (size_t i = 0; i < gameObject->GetChildCount(); i++) {
|
||||
if (PassesFilter(gameObject->GetChild(i), filter)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ public:
|
||||
|
||||
private:
|
||||
void RenderSearchBar();
|
||||
void RenderEntity(::XCEngine::Components::GameObject* entity, const std::string& filter);
|
||||
void RenderContextMenu(::XCEngine::Components::GameObject* entity);
|
||||
void RenderEntity(::XCEngine::Components::GameObject* gameObject, const std::string& filter);
|
||||
void RenderContextMenu(::XCEngine::Components::GameObject* gameObject);
|
||||
void RenderCreateMenu(::XCEngine::Components::GameObject* parent);
|
||||
void HandleDragDrop(::XCEngine::Components::GameObject* entity);
|
||||
void HandleDragDrop(::XCEngine::Components::GameObject* gameObject);
|
||||
void HandleKeyboardShortcuts();
|
||||
bool PassesFilter(::XCEngine::Components::GameObject* entity, const std::string& filter);
|
||||
bool PassesFilter(::XCEngine::Components::GameObject* gameObject, const std::string& filter);
|
||||
|
||||
uint64_t m_selectionHandlerId = 0;
|
||||
|
||||
@@ -29,7 +29,6 @@ private:
|
||||
::XCEngine::Components::GameObject* m_renamingEntity = nullptr;
|
||||
char m_renameBuffer[256] = "";
|
||||
bool m_renameJustStarted = false;
|
||||
::XCEngine::Components::GameObject* m_dragSource = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Editor {
|
||||
|
||||
InspectorPanel::InspectorPanel() : Panel("Inspector") {
|
||||
m_selectionHandlerId = SelectionManager::Get().OnSelectionChanged.Subscribe([this](uint64_t) {
|
||||
m_selectedGameObject = SelectionManager::Get().GetSelectedEntity();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,10 +21,10 @@ InspectorPanel::~InspectorPanel() {
|
||||
void InspectorPanel::Render() {
|
||||
ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None);
|
||||
|
||||
::XCEngine::Components::GameObject* entity = SelectionManager::Get().GetSelectedEntity();
|
||||
m_selectedGameObject = SelectionManager::Get().GetSelectedEntity();
|
||||
|
||||
if (entity) {
|
||||
RenderEntity(entity);
|
||||
if (m_selectedGameObject) {
|
||||
RenderGameObject(m_selectedGameObject);
|
||||
} else {
|
||||
ImGui::Text("No object selected");
|
||||
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Select an object in Hierarchy");
|
||||
@@ -32,27 +33,80 @@ void InspectorPanel::Render() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void InspectorPanel::RenderEntity(::XCEngine::Components::GameObject* entity) {
|
||||
ImGui::Text("%s", entity->GetName().c_str());
|
||||
ImGui::Separator();
|
||||
void InspectorPanel::RenderGameObject(::XCEngine::Components::GameObject* gameObject) {
|
||||
char nameBuffer[256];
|
||||
strcpy_s(nameBuffer, gameObject->GetName().c_str());
|
||||
ImGui::InputText("##Name", nameBuffer, sizeof(nameBuffer));
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
gameObject->SetName(nameBuffer);
|
||||
}
|
||||
|
||||
auto components = entity->GetComponents<::XCEngine::Components::Component>();
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Add Component")) {
|
||||
ImGui::OpenPopup("AddComponent");
|
||||
}
|
||||
|
||||
RenderAddComponentPopup(gameObject);
|
||||
|
||||
auto components = gameObject->GetComponents<::XCEngine::Components::Component>();
|
||||
for (auto* component : components) {
|
||||
RenderComponent(component);
|
||||
ImGui::Separator();
|
||||
RenderComponent(component, gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
void InspectorPanel::RenderComponent(::XCEngine::Components::Component* component) {
|
||||
void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject* gameObject) {
|
||||
if (!ImGui::BeginPopup("AddComponent")) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12.0f, 10.0f));
|
||||
|
||||
ImGui::SeparatorText("Components");
|
||||
|
||||
if (ImGui::MenuItem("Transform", nullptr, false, !gameObject->GetComponent<::XCEngine::Components::TransformComponent>())) {
|
||||
gameObject->AddComponent<::XCEngine::Components::TransformComponent>();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Other");
|
||||
ImGui::TextDisabled("No more components available");
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
void InspectorPanel::RenderComponent(::XCEngine::Components::Component* component, ::XCEngine::Components::GameObject* gameObject) {
|
||||
if (!component) return;
|
||||
|
||||
const char* name = component->GetName().c_str();
|
||||
|
||||
std::string headerId = std::string(name) + "##" + std::to_string(reinterpret_cast<uintptr_t>(component));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{4, 2});
|
||||
|
||||
if (ImGui::CollapsingHeader(headerId.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::Indent(10.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);
|
||||
|
||||
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();
|
||||
@@ -71,7 +125,23 @@ void InspectorPanel::RenderComponent(::XCEngine::Components::Component* componen
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Unindent(10.0f);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,13 @@ public:
|
||||
void Render() override;
|
||||
|
||||
private:
|
||||
void RenderEntity(::XCEngine::Components::GameObject* entity);
|
||||
void RenderComponent(::XCEngine::Components::Component* component);
|
||||
void RenderGameObject(::XCEngine::Components::GameObject* gameObject);
|
||||
void RenderAddComponentPopup(::XCEngine::Components::GameObject* gameObject);
|
||||
void RenderComponent(::XCEngine::Components::Component* component, ::XCEngine::Components::GameObject* gameObject);
|
||||
void RemoveComponentByType(::XCEngine::Components::Component* component, ::XCEngine::Components::GameObject* gameObject);
|
||||
|
||||
uint64_t m_selectionHandlerId = 0;
|
||||
::XCEngine::Components::GameObject* m_selectedGameObject = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Core/Layer.h>
|
||||
#include <string>
|
||||
#include <imgui.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
|
||||
class Panel {
|
||||
class Panel : public Core::Layer {
|
||||
public:
|
||||
Panel(const std::string& name) : m_name(name), m_isOpen(true) {}
|
||||
Panel(const std::string& name) : Layer(name), m_isOpen(true) {}
|
||||
virtual ~Panel() = default;
|
||||
|
||||
virtual void Render() = 0;
|
||||
|
||||
const std::string& GetName() const { return m_name; }
|
||||
bool IsOpen() const { return m_isOpen; }
|
||||
void SetOpen(bool open) { m_isOpen = open; }
|
||||
void Toggle() { m_isOpen = !m_isOpen; }
|
||||
|
||||
void onImGuiRender() override { Render(); }
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
bool m_isOpen;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user