diff --git a/editor/src/Layers/EditorLayer.cpp b/editor/src/Layers/EditorLayer.cpp index a5b7c5f2..8fc0d99b 100644 --- a/editor/src/Layers/EditorLayer.cpp +++ b/editor/src/Layers/EditorLayer.cpp @@ -9,6 +9,7 @@ #include "Core/IEditorContext.h" #include "Core/EditorContext.h" #include "Core/IUndoManager.h" +#include "UI/DockHostStyle.h" #include #include #include @@ -119,7 +120,10 @@ void EditorLayer::setupDockspace() { ImGui::PopStyleVar(2); ImGuiID dockspaceId = ImGui::GetID("MyDockspace"); - ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags); + { + UI::DockHostStyleScope dockHostStyle; + ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags); + } static bool firstTime = true; if (firstTime) { diff --git a/editor/src/Theme.cpp b/editor/src/Theme.cpp index 91537c28..87464c02 100644 --- a/editor/src/Theme.cpp +++ b/editor/src/Theme.cpp @@ -1,4 +1,5 @@ #include "Theme.h" +#include "UI/StyleTokens.h" #include namespace XCEngine { @@ -8,77 +9,90 @@ void ApplyUnityDarkTheme() { ImGuiStyle& style = ImGui::GetStyle(); ImVec4* colors = style.Colors; - colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.12f, 0.12f, 0.12f, 1.00f); - colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.15f, 0.15f, 1.00f); - colors[ImGuiCol_PopupBg] = ImVec4(0.18f, 0.18f, 0.18f, 0.94f); - colors[ImGuiCol_Border] = ImVec4(0.08f, 0.08f, 0.08f, 1.00f); + colors[ImGuiCol_Text] = ImVec4(0.80f, 0.80f, 0.80f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f); + colors[ImGuiCol_ChildBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.17f, 0.17f, 0.17f, 0.98f); + colors[ImGuiCol_Border] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.28f, 0.28f, 0.28f, 1.00f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); - colors[ImGuiCol_TitleBg] = ImVec4(0.15f, 0.15f, 0.15f, 1.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.21f, 0.21f, 0.21f, 1.00f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f); + colors[ImGuiCol_TitleBg] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f); colors[ImGuiCol_TitleBgActive] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.12f, 0.12f, 0.12f, 0.75f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.10f, 0.10f, 0.10f, 0.53f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.16f, 0.16f, 0.16f, 1.00f); colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); - colors[ImGuiCol_SliderGrab] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.80f, 0.80f, 1.00f); - colors[ImGuiCol_Button] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); - colors[ImGuiCol_ButtonHovered] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); - colors[ImGuiCol_ButtonActive] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f); - colors[ImGuiCol_Header] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); - colors[ImGuiCol_HeaderActive] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f); - colors[ImGuiCol_Separator] = ImVec4(0.08f, 0.08f, 0.08f, 1.00f); - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_SeparatorActive] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - colors[ImGuiCol_Tab] = ImVec4(0.18f, 0.18f, 0.18f, 0.86f); - colors[ImGuiCol_TabHovered] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); - colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - colors[ImGuiCol_TabUnfocused] = ImVec4(0.15f, 0.15f, 0.15f, 0.97f); - colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f); - colors[ImGuiCol_DockingPreview] = ImVec4(0.40f, 0.40f, 0.40f, 0.70f); - colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.12f, 0.12f, 0.12f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.72f, 0.72f, 0.72f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.44f, 0.44f, 0.44f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.54f, 0.54f, 0.54f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.28f, 0.28f, 0.28f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f); + colors[ImGuiCol_Separator] = ImVec4(0.13f, 0.13f, 0.13f, 1.00f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.34f, 0.34f, 0.34f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.24f, 0.24f, 0.24f, 0.00f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.36f, 0.36f, 0.36f, 0.25f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.52f, 0.52f, 0.52f, 0.25f); + colors[ImGuiCol_Tab] = UI::DockTabColor(); + colors[ImGuiCol_TabHovered] = UI::DockTabHoveredColor(); + colors[ImGuiCol_TabSelected] = UI::DockTabSelectedColor(); + colors[ImGuiCol_TabSelectedOverline] = UI::DockTabSelectedOverlineColor(); + colors[ImGuiCol_TabDimmed] = UI::DockTabDimmedColor(); + colors[ImGuiCol_TabDimmedSelected] = UI::DockTabDimmedSelectedColor(); + colors[ImGuiCol_TabDimmedSelectedOverline] = UI::DockTabDimmedSelectedOverlineColor(); + colors[ImGuiCol_DockingPreview] = ImVec4(0.58f, 0.58f, 0.58f, 0.22f); + colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f); colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); - colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); - colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - colors[ImGuiCol_TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f); - colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f); - colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.56f, 0.56f, 0.56f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.66f, 0.66f, 0.66f, 1.00f); + colors[ImGuiCol_TableHeaderBg] = ImVec4(0.21f, 0.21f, 0.21f, 1.00f); + colors[ImGuiCol_TableBorderStrong] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); + colors[ImGuiCol_TableBorderLight] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f); colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); - colors[ImGuiCol_TextSelectedBg] = ImVec4(0.40f, 0.40f, 0.40f, 0.50f); - colors[ImGuiCol_DragDropTarget] = ImVec4(0.60f, 0.60f, 0.60f, 0.90f); - colors[ImGuiCol_NavHighlight] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.03f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.48f, 0.48f, 0.48f, 0.28f); + colors[ImGuiCol_DragDropTarget] = ImVec4(0.62f, 0.62f, 0.62f, 0.72f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.62f, 0.62f, 0.62f, 0.52f); colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); - style.WindowRounding = 4.0f; - style.ChildRounding = 4.0f; - style.FrameRounding = 4.0f; - style.GrabRounding = 4.0f; - style.PopupRounding = 4.0f; - style.ScrollbarRounding = 4.0f; - style.TabRounding = 4.0f; + style.WindowRounding = 0.0f; + style.ChildRounding = 0.0f; + style.FrameRounding = 2.0f; + style.GrabRounding = 2.0f; + style.PopupRounding = 0.0f; + style.ScrollbarRounding = 2.0f; + style.TabRounding = 0.0f; style.WindowBorderSize = 1.0f; - style.ChildBorderSize = 1.0f; - style.FrameBorderSize = 0.0f; - style.WindowPadding = ImVec2(8.0f, 8.0f); + style.ChildBorderSize = 0.0f; + style.PopupBorderSize = 1.0f; + style.FrameBorderSize = 1.0f; + style.TabBorderSize = 0.0f; + style.TabBarBorderSize = 1.0f; + style.TabBarOverlineSize = 2.0f; + style.WindowPadding = ImVec2(6.0f, 6.0f); style.FramePadding = ImVec2(6.0f, 4.0f); - style.ItemSpacing = ImVec2(8.0f, 4.0f); - style.ItemInnerSpacing = ImVec2(6.0f, 4.0f); + style.ItemSpacing = ImVec2(6.0f, 4.0f); + style.ItemInnerSpacing = ImVec2(5.0f, 4.0f); + style.CellPadding = ImVec2(5.0f, 4.0f); + style.IndentSpacing = 14.0f; + style.ScrollbarSize = 14.0f; + style.GrabMinSize = 10.0f; + style.WindowTitleAlign = ImVec2(0.0f, 0.5f); + style.ButtonTextAlign = ImVec2(0.5f, 0.5f); + style.SelectableTextAlign = ImVec2(0.0f, 0.5f); } } -} \ No newline at end of file +} diff --git a/editor/src/UI/Core.h b/editor/src/UI/Core.h index d049a161..cb28f405 100644 --- a/editor/src/UI/Core.h +++ b/editor/src/UI/Core.h @@ -1,11 +1,30 @@ #pragma once +#include "StyleTokens.h" + #include namespace XCEngine { namespace Editor { namespace UI { +inline float DefaultControlLabelWidth() { + return 104.0f; +} + +inline ImVec2 DefaultControlCellPadding() { + return ImVec2(0.0f, 2.0f); +} + +inline ImVec2 DefaultControlFramePadding() { + return ImVec2(6.0f, 3.0f); +} + +inline void PushControlRowStyles() { + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, DefaultControlCellPadding()); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, DefaultControlFramePadding()); +} + inline void StyleVarPush(ImGuiStyleVar idx, float val) { ImGui::PushStyleVar(idx, val); } @@ -56,6 +75,26 @@ inline void EndDisabled(bool disabled = true) { } } +inline void DrawCurrentWindowBottomBorder(ImU32 color = PanelDividerColor()) { + ImDrawList* drawList = ImGui::GetWindowDrawList(); + const ImVec2 min = ImGui::GetWindowPos(); + const ImVec2 max = ImVec2(min.x + ImGui::GetWindowSize().x, min.y + ImGui::GetWindowSize().y); + drawList->AddLine(ImVec2(min.x, max.y - 1.0f), ImVec2(max.x, max.y - 1.0f), color); +} + +inline bool ToolbarButton(const char* label, bool active = false, ImVec2 size = ImVec2(0.0f, 0.0f)) { + const ImVec4 buttonColor = ToolbarButtonColor(active); + const ImVec4 hoverColor = ToolbarButtonHoveredColor(active); + const ImVec4 activeColor = ToolbarButtonActiveColor(); + + ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, hoverColor); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, activeColor); + const bool pressed = ImGui::Button(label, size); + ImGui::PopStyleColor(3); + return pressed; +} + } } } diff --git a/editor/src/UI/DockHostStyle.h b/editor/src/UI/DockHostStyle.h new file mode 100644 index 00000000..6a5ad043 --- /dev/null +++ b/editor/src/UI/DockHostStyle.h @@ -0,0 +1,40 @@ +#pragma once + +#include "StyleTokens.h" + +#include + +namespace XCEngine { +namespace Editor { +namespace UI { + +class DockHostStyleScope { +public: + DockHostStyleScope() { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, DockHostFramePadding()); + ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, DockHostItemInnerSpacing()); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, DockHostWindowBorderSize()); + ImGui::PushStyleVar(ImGuiStyleVar_TabBarBorderSize, DockHostTabBarBorderSize()); + ImGui::PushStyleVar(ImGuiStyleVar_TabBarOverlineSize, DockHostTabBarOverlineSize()); + + ImGui::PushStyleColor(ImGuiCol_Tab, DockTabColor()); + ImGui::PushStyleColor(ImGuiCol_TabHovered, DockTabHoveredColor()); + ImGui::PushStyleColor(ImGuiCol_TabSelected, DockTabSelectedColor()); + ImGui::PushStyleColor(ImGuiCol_TabSelectedOverline, DockTabSelectedOverlineColor()); + ImGui::PushStyleColor(ImGuiCol_TabDimmed, DockTabDimmedColor()); + ImGui::PushStyleColor(ImGuiCol_TabDimmedSelected, DockTabDimmedSelectedColor()); + ImGui::PushStyleColor(ImGuiCol_TabDimmedSelectedOverline, DockTabDimmedSelectedOverlineColor()); + } + + ~DockHostStyleScope() { + ImGui::PopStyleColor(7); + ImGui::PopStyleVar(5); + } + + DockHostStyleScope(const DockHostStyleScope&) = delete; + DockHostStyleScope& operator=(const DockHostStyleScope&) = delete; +}; + +} +} +} diff --git a/editor/src/UI/PanelChrome.h b/editor/src/UI/PanelChrome.h new file mode 100644 index 00000000..564647c4 --- /dev/null +++ b/editor/src/UI/PanelChrome.h @@ -0,0 +1,120 @@ +#pragma once + +#include "Core.h" +#include "StyleTokens.h" + +#include + +namespace XCEngine { +namespace Editor { +namespace UI { + +class PanelWindowScope { +public: + explicit PanelWindowScope(const char* name, ImGuiWindowFlags flags = ImGuiWindowFlags_None) { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, PanelWindowPadding()); + m_open = ImGui::Begin(name, nullptr, flags); + ImGui::PopStyleVar(); + m_began = true; + } + + ~PanelWindowScope() { + if (m_began) { + ImGui::End(); + } + } + + PanelWindowScope(const PanelWindowScope&) = delete; + PanelWindowScope& operator=(const PanelWindowScope&) = delete; + + bool IsOpen() const { + return m_open; + } + +private: + bool m_began = false; + bool m_open = false; +}; + +class PanelToolbarScope { +public: + explicit PanelToolbarScope( + const char* id, + float height, + ImGuiWindowFlags flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse, + bool drawBottomBorder = true, + ImVec2 padding = ToolbarPadding(), + ImVec2 itemSpacing = ToolbarItemSpacing()) + : m_drawBottomBorder(drawBottomBorder) { + ImGui::PushStyleColor(ImGuiCol_ChildBg, ToolbarBackgroundColor()); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, itemSpacing); + m_open = ImGui::BeginChild(id, ImVec2(0.0f, height), false, flags); + m_began = true; + } + + ~PanelToolbarScope() { + if (m_began) { + if (m_drawBottomBorder) { + DrawCurrentWindowBottomBorder(); + } + ImGui::EndChild(); + ImGui::PopStyleVar(2); + ImGui::PopStyleColor(); + } + } + + PanelToolbarScope(const PanelToolbarScope&) = delete; + PanelToolbarScope& operator=(const PanelToolbarScope&) = delete; + + bool IsOpen() const { + return m_open; + } + +private: + bool m_began = false; + bool m_open = false; + bool m_drawBottomBorder = true; +}; + +class PanelContentScope { +public: + explicit PanelContentScope( + const char* id, + ImVec2 padding = DefaultPanelContentPadding(), + ImGuiWindowFlags flags = ImGuiWindowFlags_None, + bool pushItemSpacing = false, + ImVec2 itemSpacing = ImVec2(0.0f, 0.0f)) { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding); + m_styleVarCount = 1; + if (pushItemSpacing) { + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, itemSpacing); + ++m_styleVarCount; + } + m_open = ImGui::BeginChild(id, ImVec2(0.0f, 0.0f), false, flags); + m_began = true; + } + + ~PanelContentScope() { + if (m_began) { + ImGui::EndChild(); + ImGui::PopStyleVar(m_styleVarCount); + } + } + + PanelContentScope(const PanelContentScope&) = delete; + PanelContentScope& operator=(const PanelContentScope&) = delete; + + bool IsOpen() const { + return m_open; + } + +private: + bool m_began = false; + bool m_open = false; + int m_styleVarCount = 0; +}; + +} +} +} diff --git a/editor/src/UI/StyleTokens.h b/editor/src/UI/StyleTokens.h new file mode 100644 index 00000000..4c2bbceb --- /dev/null +++ b/editor/src/UI/StyleTokens.h @@ -0,0 +1,103 @@ +#pragma once + +#include + +namespace XCEngine { +namespace Editor { +namespace UI { + +inline ImVec2 DockHostFramePadding() { + return ImVec2(4.0f, 2.0f); +} + +inline ImVec2 DockHostItemInnerSpacing() { + return ImVec2(0.0f, 4.0f); +} + +inline float DockHostWindowBorderSize() { + return 0.0f; +} + +inline float DockHostTabBarBorderSize() { + return 0.0f; +} + +inline float DockHostTabBarOverlineSize() { + return 0.0f; +} + +inline ImVec4 DockTabColor() { + return ImVec4(0.17f, 0.17f, 0.17f, 1.00f); +} + +inline ImVec4 DockTabHoveredColor() { + return ImVec4(0.21f, 0.21f, 0.21f, 1.00f); +} + +inline ImVec4 DockTabSelectedColor() { + return ImVec4(0.24f, 0.24f, 0.24f, 1.00f); +} + +inline ImVec4 DockTabSelectedOverlineColor() { + return ImVec4(0.62f, 0.62f, 0.62f, 0.70f); +} + +inline ImVec4 DockTabDimmedColor() { + return ImVec4(0.16f, 0.16f, 0.16f, 1.00f); +} + +inline ImVec4 DockTabDimmedSelectedColor() { + return ImVec4(0.20f, 0.20f, 0.20f, 1.00f); +} + +inline ImVec4 DockTabDimmedSelectedOverlineColor() { + return ImVec4(0.44f, 0.44f, 0.44f, 0.55f); +} + +inline ImVec2 PanelWindowPadding() { + return ImVec2(0.0f, 0.0f); +} + +inline ImVec2 ToolbarPadding() { + return ImVec2(8.0f, 6.0f); +} + +inline ImVec2 ToolbarItemSpacing() { + return ImVec2(6.0f, 6.0f); +} + +inline ImVec2 DefaultPanelContentPadding() { + return ImVec2(8.0f, 6.0f); +} + +inline ImVec2 InspectorPanelContentPadding() { + return ImVec2(10.0f, 0.0f); +} + +inline ImVec2 AssetPanelContentPadding() { + return ImVec2(10.0f, 10.0f); +} + +inline ImVec4 ToolbarBackgroundColor() { + return ImVec4(0.19f, 0.19f, 0.19f, 1.0f); +} + +inline ImU32 PanelDividerColor() { + return IM_COL32(36, 36, 36, 255); +} + +inline ImVec4 ToolbarButtonColor(bool active) { + return active ? ImVec4(0.33f, 0.33f, 0.33f, 1.0f) : ImVec4(0.24f, 0.24f, 0.24f, 1.0f); +} + +inline ImVec4 ToolbarButtonHoveredColor(bool active) { + return active ? ImVec4(0.38f, 0.38f, 0.38f, 1.0f) : ImVec4(0.30f, 0.30f, 0.30f, 1.0f); +} + +inline ImVec4 ToolbarButtonActiveColor() { + return ImVec4(0.42f, 0.42f, 0.42f, 1.0f); +} + +} +} +} diff --git a/editor/src/UI/UI.h b/editor/src/UI/UI.h index 7732618b..23ec2017 100644 --- a/editor/src/UI/UI.h +++ b/editor/src/UI/UI.h @@ -1,6 +1,9 @@ #pragma once #include "Core.h" +#include "DockHostStyle.h" +#include "PanelChrome.h" +#include "StyleTokens.h" #include "VectorControls.h" #include "ScalarControls.h" diff --git a/editor/src/panels/ConsolePanel.cpp b/editor/src/panels/ConsolePanel.cpp index d03ed8b0..efafccbd 100644 --- a/editor/src/panels/ConsolePanel.cpp +++ b/editor/src/panels/ConsolePanel.cpp @@ -1,58 +1,59 @@ #include "ConsolePanel.h" #include "Core/EditorConsoleSink.h" +#include "UI/Core.h" +#include "UI/PanelChrome.h" +#include #include #include namespace XCEngine { namespace Editor { +namespace { + +constexpr float kConsoleToolbarHeight = 34.0f; + +} // namespace + ConsolePanel::ConsolePanel() : Panel("Console") { } void ConsolePanel::Render() { - ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); + UI::PanelWindowScope panel(m_name.c_str()); + if (!panel.IsOpen()) { + return; + } auto* sink = Debug::EditorConsoleSink::GetInstance(); - - if (ImGui::Button("Clear")) { - sink->Clear(); + + { + UI::PanelToolbarScope toolbar("ConsoleToolbar", kConsoleToolbarHeight); + if (toolbar.IsOpen()) { + if (UI::ToolbarButton("Clear")) { + sink->Clear(); + } + ImGui::SameLine(); + + ImGui::TextDisabled("Filter"); + ImGui::SameLine(); + if (UI::ToolbarButton("Info", m_showInfo)) { + m_showInfo = !m_showInfo; + } + ImGui::SameLine(); + if (UI::ToolbarButton("Warn", m_showWarning)) { + m_showWarning = !m_showWarning; + } + ImGui::SameLine(); + if (UI::ToolbarButton("Error", m_showError)) { + m_showError = !m_showError; + } + } } - ImGui::SameLine(); - - ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Filter:"); - ImGui::SameLine(); - ImGui::Separator(); - ImGui::SameLine(); - - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f); - - ImGui::PushStyleColor(ImGuiCol_Button, m_showInfo ? ImVec4(0.2f, 0.6f, 0.2f, 1.0f) : ImVec4(0.3f, 0.3f, 0.3f, 1.0f)); - if (ImGui::Button("Info")) { - m_showInfo = !m_showInfo; + + UI::PanelContentScope content("LogScroll", UI::DefaultPanelContentPadding(), ImGuiWindowFlags_HorizontalScrollbar); + if (!content.IsOpen()) { + return; } - ImGui::PopStyleColor(); - - ImGui::SameLine(); - - ImGui::PushStyleColor(ImGuiCol_Button, m_showWarning ? ImVec4(0.8f, 0.6f, 0.0f, 1.0f) : ImVec4(0.3f, 0.3f, 0.3f, 1.0f)); - if (ImGui::Button("Warn")) { - m_showWarning = !m_showWarning; - } - ImGui::PopStyleColor(); - - ImGui::SameLine(); - - ImGui::PushStyleColor(ImGuiCol_Button, m_showError ? ImVec4(0.8f, 0.2f, 0.2f, 1.0f) : ImVec4(0.3f, 0.3f, 0.3f, 1.0f)); - if (ImGui::Button("Error")) { - m_showError = !m_showError; - } - ImGui::PopStyleColor(); - - ImGui::PopStyleVar(); - - ImGui::Separator(); - - ImGui::BeginChild("LogScroll", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar); const auto logs = sink->GetLogs(); size_t logIndex = 0; @@ -77,35 +78,29 @@ void ConsolePanel::Render() { continue; } - ImVec4 color; const char* prefix; switch (log.level) { case ::XCEngine::Debug::LogLevel::Verbose: case ::XCEngine::Debug::LogLevel::Debug: case ::XCEngine::Debug::LogLevel::Info: - color = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); prefix = "[INFO] "; break; 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::Fatal: - color = ImVec4(1.0f, 0.3f, 0.3f, 1.0f); - prefix = "[ERROR]"; + prefix = "[ERROR] "; break; } ImGui::PushID(static_cast(logIndex)); - - ImGui::TextColored(ImVec4(0.4f, 0.4f, 0.4f, 1.0f), "%s", log.message.CStr()); - ImGui::SameLine(); - - std::string fullMessage = std::string(prefix) + log.message.CStr(); - ImGui::TextColored(color, "%s", fullMessage.c_str()); - + + const char* category = ::XCEngine::Debug::LogCategoryToString(log.category); + std::string fullMessage = std::string(prefix) + "[" + category + "] " + log.message.CStr(); + ImGui::TextUnformatted(fullMessage.c_str()); + if (ImGui::IsItemClicked()) { ImGui::SetClipboardText(fullMessage.c_str()); } @@ -114,8 +109,6 @@ void ConsolePanel::Render() { logIndex++; } - ImGui::EndChild(); - ImGui::End(); } } diff --git a/editor/src/panels/GameViewPanel.cpp b/editor/src/panels/GameViewPanel.cpp index 2dc73f30..6be4236f 100644 --- a/editor/src/panels/GameViewPanel.cpp +++ b/editor/src/panels/GameViewPanel.cpp @@ -1,6 +1,6 @@ #include "GameViewPanel.h" +#include "UI/PanelChrome.h" #include -#include namespace XCEngine { namespace Editor { @@ -8,25 +8,8 @@ namespace Editor { GameViewPanel::GameViewPanel() : Panel("Game") {} void GameViewPanel::Render() { - ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); - - RenderGameView(); - - ImGui::End(); -} - -void GameViewPanel::RenderGameView() { - ImVec2 canvasSize = ImGui::GetContentRegionAvail(); - ImDrawList* drawList = ImGui::GetWindowDrawList(); - ImVec2 canvasPos = ImGui::GetCursorScreenPos(); - - ImU32 bgColor = IM_COL32(20, 20, 25, 255); - drawList->AddRectFilled(canvasPos, ImVec2(canvasPos.x + canvasSize.x, canvasPos.y + canvasSize.y), bgColor); - - const char* text = "Game View (Press Play)"; - ImVec2 textSize = ImGui::CalcTextSize(text); - ImVec2 textPos(canvasPos.x + (canvasSize.x - textSize.x) * 0.5f, canvasPos.y + (canvasSize.y - textSize.y) * 0.5f); - drawList->AddText(textPos, IM_COL32(128, 128, 128, 255), text); + UI::PanelWindowScope panel(m_name.c_str()); + (void)panel; } } diff --git a/editor/src/panels/HierarchyPanel.cpp b/editor/src/panels/HierarchyPanel.cpp index 7d88d2c8..66bd0f82 100644 --- a/editor/src/panels/HierarchyPanel.cpp +++ b/editor/src/panels/HierarchyPanel.cpp @@ -5,6 +5,8 @@ #include "Core/IUndoManager.h" #include "Core/EditorEvents.h" #include "Core/EventBus.h" +#include "UI/Core.h" +#include "UI/PanelChrome.h" #include "Utils/UndoUtils.h" #include #include @@ -16,6 +18,12 @@ namespace XCEngine { namespace Editor { +namespace { + +constexpr float kHierarchyToolbarHeight = 34.0f; + +} // namespace + HierarchyPanel::HierarchyPanel() : Panel("Hierarchy") { } @@ -38,18 +46,22 @@ void HierarchyPanel::OnSelectionChanged(const SelectionChangedEvent& event) { } void HierarchyPanel::Render() { - ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); - + UI::PanelWindowScope panel(m_name.c_str()); + if (!panel.IsOpen()) { + return; + } + RenderSearchBar(); - - ImGui::Separator(); - + HandleKeyboardShortcuts(); - + std::string filter = m_searchBuffer; - - ImGui::BeginChild("EntityList"); - + + UI::PanelContentScope content("EntityList"); + if (!content.IsOpen()) { + return; + } + auto& sceneManager = m_context->GetSceneManager(); auto rootEntities = sceneManager.GetRootEntities(); SortEntities(const_cast&>(rootEntities)); @@ -93,21 +105,39 @@ void HierarchyPanel::Render() { ImGui::EndDragDropTarget(); } - ImGui::EndChild(); - - ImGui::End(); } void HierarchyPanel::RenderSearchBar() { - ImGui::SetNextItemWidth(120); - const char* sortLabels[] = { "Name", "Components", "Transform First" }; - int currentSort = static_cast(m_sortMode); - if (ImGui::Combo("##Sort", ¤tSort, sortLabels, 3)) { - m_sortMode = static_cast(currentSort); + UI::PanelToolbarScope toolbar("HierarchyToolbar", kHierarchyToolbarHeight); + if (!toolbar.IsOpen()) { + return; } + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(7.0f, 4.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 2.0f); + + const float buttonWidth = 26.0f; + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - buttonWidth - 4.0f); + ImGui::InputTextWithHint("##Search", "Search hierarchy", m_searchBuffer, sizeof(m_searchBuffer)); ImGui::SameLine(); - ImGui::SetNextItemWidth(-1); - ImGui::InputTextWithHint("##Search", "Search...", m_searchBuffer, sizeof(m_searchBuffer)); + if (UI::ToolbarButton("...", false, ImVec2(buttonWidth, 0.0f))) { + ImGui::OpenPopup("HierarchyOptions"); + } + + if (ImGui::BeginPopup("HierarchyOptions")) { + if (ImGui::MenuItem("Sort By Name", nullptr, m_sortMode == SortMode::Name)) { + m_sortMode = SortMode::Name; + } + if (ImGui::MenuItem("Sort By Component Count", nullptr, m_sortMode == SortMode::ComponentCount)) { + m_sortMode = SortMode::ComponentCount; + } + if (ImGui::MenuItem("Transform First", nullptr, m_sortMode == SortMode::TransformFirst)) { + m_sortMode = SortMode::TransformFirst; + } + ImGui::EndPopup(); + } + + ImGui::PopStyleVar(2); } void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject, const std::string& filter) { @@ -119,7 +149,10 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject ImGui::PushID(static_cast(gameObject->GetID())); - ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth; + ImGuiTreeNodeFlags flags = + ImGuiTreeNodeFlags_OpenOnArrow | + ImGuiTreeNodeFlags_SpanAvailWidth | + ImGuiTreeNodeFlags_FramePadding; if (gameObject->GetChildCount() == 0) { flags |= ImGuiTreeNodeFlags_Leaf; @@ -156,7 +189,9 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject m_renamingEntity = nullptr; } } else { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, 3.0f)); bool isOpen = ImGui::TreeNodeEx((void*)gameObject->GetUUID(), flags, "%s", gameObject->GetName().c_str()); + ImGui::PopStyleVar(); if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) { ImGuiIO& io = ImGui::GetIO(); diff --git a/editor/src/panels/InspectorPanel.cpp b/editor/src/panels/InspectorPanel.cpp index bac4653b..8baefd6c 100644 --- a/editor/src/panels/InspectorPanel.cpp +++ b/editor/src/panels/InspectorPanel.cpp @@ -7,6 +7,7 @@ #include "Core/EditorEvents.h" #include "ComponentEditors/ComponentEditorRegistry.h" #include "ComponentEditors/IComponentEditor.h" +#include "UI/PanelChrome.h" #include "Utils/UndoUtils.h" #include #include @@ -30,9 +31,10 @@ void InspectorPanel::OnSelectionChanged(const SelectionChangedEvent& event) { } void InspectorPanel::Render() { - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); - ImGui::PopStyleVar(); + UI::PanelWindowScope panel(m_name.c_str()); + if (!panel.IsOpen()) { + return; + } if (!m_selectionHandlerId && m_context) { m_selectionHandlerId = m_context->GetEventBus().Subscribe( @@ -60,17 +62,20 @@ void InspectorPanel::Render() { ImGui::TextColored(ImVec4(0.55f, 0.55f, 0.55f, 1.0f), "Select an object in Hierarchy"); } - ImGui::End(); } void InspectorPanel::RenderGameObject(::XCEngine::Components::GameObject* gameObject) { ImGuiStyle& style = ImGui::GetStyle(); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 0.0f)); - ImGui::BeginChild("InspectorContent", ImVec2(0.0f, 0.0f), false, ImGuiWindowFlags_None); - ImGui::PopStyleVar(); + UI::PanelContentScope content( + "InspectorContent", + UI::InspectorPanelContentPadding(), + ImGuiWindowFlags_None, + true, + ImVec2(style.ItemSpacing.x, 0.0f)); + if (!content.IsOpen()) { + return; + } - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, 0.0f)); - auto components = gameObject->GetComponents<::XCEngine::Components::Component>(); for (auto* component : components) { RenderComponent(component, gameObject); @@ -80,13 +85,10 @@ void InspectorPanel::RenderGameObject(::XCEngine::Components::GameObject* gameOb ImGui::OpenPopup("AddComponent"); } RenderAddComponentPopup(gameObject); - ImGui::PopStyleVar(); if (m_context->GetUndoManager().HasPendingInteractiveChange() && !ImGui::IsAnyItemActive()) { m_context->GetUndoManager().FinalizeInteractiveChange(); } - - ImGui::EndChild(); } void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject* gameObject) { diff --git a/editor/src/panels/ProjectPanel.cpp b/editor/src/panels/ProjectPanel.cpp index c123347c..aed8ed79 100644 --- a/editor/src/panels/ProjectPanel.cpp +++ b/editor/src/panels/ProjectPanel.cpp @@ -5,6 +5,8 @@ #include "Core/IUndoManager.h" #include "Core/ISelectionManager.h" #include "Core/AssetItem.h" +#include "UI/Core.h" +#include "UI/PanelChrome.h" #include "Utils/SceneEditorUtils.h" #include #include @@ -14,6 +16,31 @@ namespace Editor { const char* DRAG_DROP_TYPE = "ASSET_ITEM"; +namespace { + +constexpr float kProjectToolbarHeight = 60.0f; + +void DrawFolderIcon(ImDrawList* drawList, const ImVec2& min, const ImVec2& max, ImU32 fillColor, ImU32 lineColor) { + const float width = max.x - min.x; + const float height = max.y - min.y; + const ImVec2 tabMax(min.x + width * 0.45f, min.y + height * 0.35f); + drawList->AddRectFilled(ImVec2(min.x, min.y + height * 0.14f), tabMax, fillColor, 2.0f); + drawList->AddRectFilled(ImVec2(min.x, min.y + height * 0.28f), max, fillColor, 2.0f); + drawList->AddRect(ImVec2(min.x, min.y + height * 0.14f), tabMax, lineColor, 2.0f); + drawList->AddRect(ImVec2(min.x, min.y + height * 0.28f), max, lineColor, 2.0f); +} + +void DrawFileIcon(ImDrawList* drawList, const ImVec2& min, const ImVec2& max, ImU32 fillColor, ImU32 lineColor) { + const ImVec2 foldA(max.x - 8.0f, min.y); + const ImVec2 foldB(max.x, min.y + 8.0f); + drawList->AddRectFilled(min, max, fillColor, 2.0f); + drawList->AddRect(min, max, lineColor, 2.0f); + drawList->AddTriangleFilled(foldA, ImVec2(max.x, min.y), foldB, IM_COL32(235, 235, 235, 40)); + drawList->AddLine(foldA, foldB, lineColor); +} + +} // namespace + ProjectPanel::ProjectPanel() : Panel("Project") { } @@ -29,58 +56,67 @@ void ProjectPanel::Render() { m_draggingPath.clear(); } - ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); + UI::PanelWindowScope panel(m_name.c_str()); + if (!panel.IsOpen()) { + return; + } auto& manager = m_context->GetProjectManager(); - - bool canGoBack = manager.CanNavigateBack(); - ImGui::BeginDisabled(!canGoBack); - if (ImGui::Button("<")) { - if (canGoBack) { - manager.NavigateBack(); - } - } - ImGui::EndDisabled(); - ImGui::SameLine(); - - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0)); - size_t pathDepth = manager.GetPathDepth(); - for (size_t i = 0; i < pathDepth; i++) { - if (i > 0) { - ImGui::SameLine(); - ImGui::Text("/"); - ImGui::SameLine(); - } - std::string name = manager.GetPathName(i); - if (i < pathDepth - 1) { - if (ImGui::Button(name.c_str())) { - manager.NavigateToIndex(i); + + UI::PanelToolbarScope toolbar("ProjectToolbar", kProjectToolbarHeight); + if (toolbar.IsOpen()) { + + bool canGoBack = manager.CanNavigateBack(); + ImGui::BeginDisabled(!canGoBack); + if (UI::ToolbarButton("<", false, ImVec2(28.0f, 0.0f))) { + if (canGoBack) { + manager.NavigateBack(); } - } else { - ImGui::Text("%s", name.c_str()); } + ImGui::EndDisabled(); + ImGui::SameLine(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); + size_t pathDepth = manager.GetPathDepth(); + if (pathDepth == 0) { + ImGui::TextUnformatted("Assets"); + } else { + for (size_t i = 0; i < pathDepth; i++) { + if (i > 0) { + ImGui::SameLine(); + ImGui::TextDisabled("/"); + ImGui::SameLine(); + } + std::string name = manager.GetPathName(i); + if (i < pathDepth - 1) { + if (ImGui::Button(name.c_str())) { + manager.NavigateToIndex(i); + } + } else { + ImGui::Text("%s", name.c_str()); + } + } + } + ImGui::PopStyleColor(2); + + ImGui::Dummy(ImVec2(0.0f, 2.0f)); + ImGui::SetNextItemWidth(-1.0f); + ImGui::InputTextWithHint("##Search", "Search assets", m_searchBuffer, sizeof(m_searchBuffer)); } - ImGui::PopStyleColor(2); - - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 80.0f); - if (ImGui::Button("Refresh")) { - manager.RefreshCurrentFolder(); + + UI::PanelContentScope content( + "ProjectContent", + UI::AssetPanelContentPadding(), + ImGuiWindowFlags_None, + true, + ImVec2(8.0f, 10.0f)); + if (!content.IsOpen()) { + return; } - - ImGui::Separator(); - - ImGui::PushItemWidth(-1); - ImGui::InputTextWithHint("##Search", "Search...", m_searchBuffer, sizeof(m_searchBuffer)); - ImGui::PopItemWidth(); - - ImGui::Separator(); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(10, 10)); - - float buttonWidth = 80.0f; - float padding = 10.0f; + + float buttonWidth = 104.0f; + float padding = 8.0f; float panelWidth = ImGui::GetContentRegionAvail().x; int columns = (int)(panelWidth / (buttonWidth + padding)); if (columns < 1) columns = 1; @@ -102,9 +138,7 @@ void ProjectPanel::Render() { RenderAssetItem(items[i], i); displayedCount++; } - - ImGui::PopStyleVar(); - + if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered()) { manager.SetSelectedIndex(-1); } @@ -142,15 +176,9 @@ void ProjectPanel::Render() { m_showCreateFolderPopup = true; strcpy_s(m_newFolderName, "NewFolder"); } - ImGui::Separator(); - if (ImGui::MenuItem("Refresh")) { - manager.RefreshCurrentFolder(); - } ImGui::EndPopup(); } - ImGui::End(); - if (m_showCreateFolderPopup) { ImGui::OpenPopup("Create Folder"); m_showCreateFolderPopup = false; @@ -176,17 +204,11 @@ void ProjectPanel::RenderAssetItem(const AssetItemPtr& item, int index) { bool isSelected = (manager.GetSelectedIndex() == index); ImGui::PushID(index); - - if (isSelected) { - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.40f, 0.40f, 0.40f, 0.50f)); - } else { - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.30f, 0.30f, 0.30f, 0.40f)); - } - - ImVec2 buttonSize(80.0f, 90.0f); - - if (ImGui::Button("##AssetBtn", buttonSize)) { + + ImVec2 buttonSize(104.0f, 82.0f); + + ImGui::InvisibleButton("##AssetBtn", buttonSize); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { manager.SetSelectedIndex(index); } @@ -202,46 +224,39 @@ void ProjectPanel::RenderAssetItem(const AssetItemPtr& item, int index) { openContextMenu = true; } - if (isSelected) { - ImGui::PopStyleColor(); - } else { - ImGui::PopStyleColor(2); - } - ImVec2 min = ImGui::GetItemRectMin(); ImVec2 max = ImVec2(min.x + buttonSize.x, min.y + buttonSize.y); ImDrawList* drawList = ImGui::GetWindowDrawList(); - + + const bool hovered = ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); + if (hovered || isSelected) { + drawList->AddRectFilled(min, max, isSelected ? IM_COL32(156, 156, 156, 30) : IM_COL32(255, 255, 255, 10), 2.0f); + } + if (isSelected) { + drawList->AddRect(min, max, IM_COL32(188, 188, 188, 110), 2.0f); + } + if (!m_draggingPath.empty() && item->fullPath == m_draggingPath) { drawList->AddRectFilled(min, max, IM_COL32(0, 0, 0, 60), 0.0f); } - - ImU32 iconColor; + + ImU32 iconFillColor = item->isFolder ? IM_COL32(118, 118, 118, 255) : IM_COL32(104, 104, 104, 255); + ImU32 iconLineColor = item->isFolder ? IM_COL32(184, 184, 184, 220) : IM_COL32(166, 166, 166, 220); + + const ImVec2 iconMin(min.x + 14.0f, min.y + 12.0f); + const ImVec2 iconMax(iconMin.x + 28.0f, iconMin.y + 22.0f); if (item->isFolder) { - iconColor = IM_COL32(200, 180, 100, 255); - } else if (item->type == "Texture") { - iconColor = IM_COL32(150, 200, 150, 255); - } else if (item->type == "Model") { - iconColor = IM_COL32(150, 150, 200, 255); - } else if (item->type == "Script") { - iconColor = IM_COL32(200, 150, 150, 255); - } else if (item->type == "Scene") { - iconColor = IM_COL32(200, 200, 150, 255); + DrawFolderIcon(drawList, iconMin, iconMax, iconFillColor, iconLineColor); } else { - iconColor = IM_COL32(100, 150, 200, 255); + DrawFileIcon(drawList, iconMin, iconMax, iconFillColor, iconLineColor); } - - float iconSize = 40.0f; - ImVec2 iconMin(min.x + (80.0f - iconSize) * 0.5f, min.y + 10.0f); - ImVec2 iconMax(iconMin.x + iconSize, iconMin.y + iconSize); - drawList->AddRectFilled(iconMin, iconMax, iconColor, 4.0f); - - ImVec4 textColor = isSelected ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) : ImVec4(0.8f, 0.8f, 0.8f, 1.0f); + + ImVec4 textColor = isSelected ? ImVec4(0.93f, 0.93f, 0.93f, 1.0f) : ImVec4(0.76f, 0.76f, 0.76f, 1.0f); ImVec2 textSize = ImGui::CalcTextSize(item->name.c_str()); - float textOffset = std::max(0.0f, (80.0f - textSize.x) * 0.5f); - - ImGui::PushClipRect(min, ImVec2(min.x + 80.0f, min.y + 90.0f), true); - drawList->AddText(ImVec2(min.x + textOffset, min.y + 60.0f), ImGui::GetColorU32(textColor), item->name.c_str()); + float textY = max.y - textSize.y - 10.0f; + + ImGui::PushClipRect(ImVec2(min.x + 6.0f, min.y), ImVec2(max.x - 6.0f, max.y), true); + drawList->AddText(ImVec2(min.x + 6.0f, textY), ImGui::GetColorU32(textColor), item->name.c_str()); ImGui::PopClipRect(); if (item->isFolder) { @@ -253,35 +268,19 @@ void ProjectPanel::RenderAssetItem(const AssetItemPtr& item, int index) { } ImGui::EndDragDropTarget(); } - - if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { - ImDrawList* hoverDrawList = ImGui::GetWindowDrawList(); - hoverDrawList->AddRect(min, ImVec2(min.x + buttonSize.x, min.y + buttonSize.y), IM_COL32(255, 255, 255, 80), 4.0f); - } } if (!item->fullPath.empty()) { if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { ImGui::SetDragDropPayload(DRAG_DROP_TYPE, item->fullPath.c_str(), item->fullPath.length() + 1); - ImU32 iconColor; - if (item->isFolder) { - iconColor = IM_COL32(200, 180, 100, 100); - } else if (item->type == "Texture") { - iconColor = IM_COL32(150, 200, 150, 100); - } else if (item->type == "Model") { - iconColor = IM_COL32(150, 150, 200, 100); - } else if (item->type == "Script") { - iconColor = IM_COL32(200, 150, 150, 100); - } else if (item->type == "Scene") { - iconColor = IM_COL32(200, 200, 150, 100); - } else { - iconColor = IM_COL32(100, 150, 200, 100); - } - ImVec2 previewMin = ImGui::GetMousePos(); - ImVec2 previewMax = ImVec2(previewMin.x + 40, previewMin.y + 40); - ImGui::GetForegroundDrawList()->AddRectFilled(previewMin, previewMax, iconColor, 4.0f); + ImVec2 previewMax = ImVec2(previewMin.x + 24.0f, previewMin.y + 20.0f); + if (item->isFolder) { + DrawFolderIcon(ImGui::GetForegroundDrawList(), previewMin, previewMax, iconFillColor, iconLineColor); + } else { + DrawFileIcon(ImGui::GetForegroundDrawList(), previewMin, previewMax, iconFillColor, iconLineColor); + } ImGui::EndDragDropSource(); } diff --git a/editor/src/panels/SceneViewPanel.cpp b/editor/src/panels/SceneViewPanel.cpp index a1e13ff2..5b1036b5 100644 --- a/editor/src/panels/SceneViewPanel.cpp +++ b/editor/src/panels/SceneViewPanel.cpp @@ -1,6 +1,6 @@ #include "SceneViewPanel.h" +#include "UI/PanelChrome.h" #include -#include namespace XCEngine { namespace Editor { @@ -8,49 +8,9 @@ namespace Editor { SceneViewPanel::SceneViewPanel() : Panel("Scene") {} void SceneViewPanel::Render() { - ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); - - ImVec2 canvasSize = ImGui::GetContentRegionAvail(); - ImDrawList* drawList = ImGui::GetWindowDrawList(); - ImVec2 canvasPos = ImGui::GetCursorScreenPos(); - - ImU32 bgColor = IM_COL32(30, 30, 30, 255); - drawList->AddRectFilled(canvasPos, ImVec2(canvasPos.x + canvasSize.x, canvasPos.y + canvasSize.y), bgColor); - - RenderGrid(); - - ImGui::End(); -} - -void SceneViewPanel::RenderGrid() { - ImDrawList* drawList = ImGui::GetWindowDrawList(); - ImVec2 canvasPos = ImGui::GetCursorScreenPos(); - ImVec2 canvasSize = ImGui::GetContentRegionAvail(); - - float gridSize = 50.0f; - ImU32 gridColor = IM_COL32(50, 50, 50, 255); - - for (float x = fmodf(0, gridSize); x < canvasSize.x; x += gridSize) { - drawList->AddLine( - ImVec2(canvasPos.x + x, canvasPos.y), - ImVec2(canvasPos.x + x, canvasPos.y + canvasSize.y), - gridColor - ); - } - - for (float y = fmodf(0, gridSize); y < canvasSize.y; y += gridSize) { - drawList->AddLine( - ImVec2(canvasPos.x, canvasPos.y + y), - ImVec2(canvasPos.x + canvasSize.x, canvasPos.y + y), - gridColor - ); - } - - const char* label = "Scene View"; - ImVec2 labelSize = ImGui::CalcTextSize(label); - ImVec2 labelPos(canvasPos.x + 10, canvasPos.y + 10); - drawList->AddText(labelPos, IM_COL32(100, 100, 100, 255), label); + UI::PanelWindowScope panel(m_name.c_str()); + (void)panel; } } -} \ No newline at end of file +}