Refactor editor dock and panel chrome styling

This commit is contained in:
2026-03-26 16:43:06 +08:00
parent e174862b8a
commit 45842e961e
13 changed files with 623 additions and 328 deletions

View File

@@ -9,6 +9,7 @@
#include "Core/IEditorContext.h" #include "Core/IEditorContext.h"
#include "Core/EditorContext.h" #include "Core/EditorContext.h"
#include "Core/IUndoManager.h" #include "Core/IUndoManager.h"
#include "UI/DockHostStyle.h"
#include <filesystem> #include <filesystem>
#include <imgui.h> #include <imgui.h>
#include <imgui_internal.h> #include <imgui_internal.h>
@@ -119,7 +120,10 @@ void EditorLayer::setupDockspace() {
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2);
ImGuiID dockspaceId = ImGui::GetID("MyDockspace"); ImGuiID dockspaceId = ImGui::GetID("MyDockspace");
{
UI::DockHostStyleScope dockHostStyle;
ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags); ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);
}
static bool firstTime = true; static bool firstTime = true;
if (firstTime) { if (firstTime) {

View File

@@ -1,4 +1,5 @@
#include "Theme.h" #include "Theme.h"
#include "UI/StyleTokens.h"
#include <imgui.h> #include <imgui.h>
namespace XCEngine { namespace XCEngine {
@@ -8,76 +9,89 @@ void ApplyUnityDarkTheme() {
ImGuiStyle& style = ImGui::GetStyle(); ImGuiStyle& style = ImGui::GetStyle();
ImVec4* colors = style.Colors; ImVec4* colors = style.Colors;
colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); colors[ImGuiCol_Text] = ImVec4(0.80f, 0.80f, 0.80f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); colors[ImGuiCol_TextDisabled] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.12f, 0.12f, 0.12f, 1.00f); colors[ImGuiCol_WindowBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.15f, 0.15f, 1.00f); colors[ImGuiCol_ChildBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.18f, 0.18f, 0.18f, 0.94f); colors[ImGuiCol_PopupBg] = ImVec4(0.17f, 0.17f, 0.17f, 0.98f);
colors[ImGuiCol_Border] = ImVec4(0.08f, 0.08f, 0.08f, 1.00f); 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_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); colors[ImGuiCol_FrameBg] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.28f, 0.28f, 0.28f, 1.00f); colors[ImGuiCol_FrameBgHovered] = ImVec4(0.21f, 0.21f, 0.21f, 1.00f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); colors[ImGuiCol_FrameBgActive] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f);
colors[ImGuiCol_TitleBg] = ImVec4(0.15f, 0.15f, 0.15f, 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_TitleBgActive] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.12f, 0.12f, 0.12f, 0.75f); colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); colors[ImGuiCol_MenuBarBg] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.10f, 0.10f, 0.10f, 0.53f); 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_ScrollbarGrab] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f); colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); colors[ImGuiCol_CheckMark] = ImVec4(0.72f, 0.72f, 0.72f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); colors[ImGuiCol_SliderGrab] = ImVec4(0.44f, 0.44f, 0.44f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.80f, 0.80f, 1.00f); colors[ImGuiCol_SliderGrabActive] = ImVec4(0.54f, 0.54f, 0.54f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); colors[ImGuiCol_Button] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); colors[ImGuiCol_ButtonHovered] = ImVec4(0.28f, 0.28f, 0.28f, 1.00f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f); colors[ImGuiCol_ButtonActive] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); colors[ImGuiCol_Header] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); colors[ImGuiCol_HeaderHovered] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f); colors[ImGuiCol_HeaderActive] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f);
colors[ImGuiCol_Separator] = ImVec4(0.08f, 0.08f, 0.08f, 1.00f); colors[ImGuiCol_Separator] = ImVec4(0.13f, 0.13f, 0.13f, 1.00f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.34f, 0.34f, 0.34f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f); colors[ImGuiCol_ResizeGrip] = ImVec4(0.24f, 0.24f, 0.24f, 0.00f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.36f, 0.36f, 0.36f, 0.25f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.52f, 0.52f, 0.52f, 0.25f);
colors[ImGuiCol_Tab] = ImVec4(0.18f, 0.18f, 0.18f, 0.86f); colors[ImGuiCol_Tab] = UI::DockTabColor();
colors[ImGuiCol_TabHovered] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); colors[ImGuiCol_TabHovered] = UI::DockTabHoveredColor();
colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); colors[ImGuiCol_TabSelected] = UI::DockTabSelectedColor();
colors[ImGuiCol_TabUnfocused] = ImVec4(0.15f, 0.15f, 0.15f, 0.97f); colors[ImGuiCol_TabSelectedOverline] = UI::DockTabSelectedOverlineColor();
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f); colors[ImGuiCol_TabDimmed] = UI::DockTabDimmedColor();
colors[ImGuiCol_DockingPreview] = ImVec4(0.40f, 0.40f, 0.40f, 0.70f); colors[ImGuiCol_TabDimmedSelected] = UI::DockTabDimmedSelectedColor();
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.12f, 0.12f, 0.12f, 1.00f); 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_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.56f, 0.56f, 0.56f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.66f, 0.66f, 0.66f, 1.00f);
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f); colors[ImGuiCol_TableHeaderBg] = ImVec4(0.21f, 0.21f, 0.21f, 1.00f);
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f); colors[ImGuiCol_TableBorderStrong] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 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_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.03f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.40f, 0.40f, 0.40f, 0.50f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.48f, 0.48f, 0.48f, 0.28f);
colors[ImGuiCol_DragDropTarget] = ImVec4(0.60f, 0.60f, 0.60f, 0.90f); colors[ImGuiCol_DragDropTarget] = ImVec4(0.62f, 0.62f, 0.62f, 0.72f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); 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_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
style.WindowRounding = 4.0f; style.WindowRounding = 0.0f;
style.ChildRounding = 4.0f; style.ChildRounding = 0.0f;
style.FrameRounding = 4.0f; style.FrameRounding = 2.0f;
style.GrabRounding = 4.0f; style.GrabRounding = 2.0f;
style.PopupRounding = 4.0f; style.PopupRounding = 0.0f;
style.ScrollbarRounding = 4.0f; style.ScrollbarRounding = 2.0f;
style.TabRounding = 4.0f; style.TabRounding = 0.0f;
style.WindowBorderSize = 1.0f; style.WindowBorderSize = 1.0f;
style.ChildBorderSize = 1.0f; style.ChildBorderSize = 0.0f;
style.FrameBorderSize = 0.0f; style.PopupBorderSize = 1.0f;
style.WindowPadding = ImVec2(8.0f, 8.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.FramePadding = ImVec2(6.0f, 4.0f);
style.ItemSpacing = ImVec2(8.0f, 4.0f); style.ItemSpacing = ImVec2(6.0f, 4.0f);
style.ItemInnerSpacing = 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);
} }
} }

View File

@@ -1,11 +1,30 @@
#pragma once #pragma once
#include "StyleTokens.h"
#include <imgui.h> #include <imgui.h>
namespace XCEngine { namespace XCEngine {
namespace Editor { namespace Editor {
namespace UI { 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) { inline void StyleVarPush(ImGuiStyleVar idx, float val) {
ImGui::PushStyleVar(idx, 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;
}
} }
} }
} }

View File

@@ -0,0 +1,40 @@
#pragma once
#include "StyleTokens.h"
#include <imgui.h>
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;
};
}
}
}

120
editor/src/UI/PanelChrome.h Normal file
View File

@@ -0,0 +1,120 @@
#pragma once
#include "Core.h"
#include "StyleTokens.h"
#include <imgui.h>
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;
};
}
}
}

103
editor/src/UI/StyleTokens.h Normal file
View File

@@ -0,0 +1,103 @@
#pragma once
#include <imgui.h>
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);
}
}
}
}

View File

@@ -1,6 +1,9 @@
#pragma once #pragma once
#include "Core.h" #include "Core.h"
#include "DockHostStyle.h"
#include "PanelChrome.h"
#include "StyleTokens.h"
#include "VectorControls.h" #include "VectorControls.h"
#include "ScalarControls.h" #include "ScalarControls.h"

View File

@@ -1,58 +1,59 @@
#include "ConsolePanel.h" #include "ConsolePanel.h"
#include "Core/EditorConsoleSink.h" #include "Core/EditorConsoleSink.h"
#include "UI/Core.h"
#include "UI/PanelChrome.h"
#include <XCEngine/Debug/LogCategory.h>
#include <XCEngine/Debug/Logger.h> #include <XCEngine/Debug/Logger.h>
#include <imgui.h> #include <imgui.h>
namespace XCEngine { namespace XCEngine {
namespace Editor { namespace Editor {
namespace {
constexpr float kConsoleToolbarHeight = 34.0f;
} // namespace
ConsolePanel::ConsolePanel() : Panel("Console") { ConsolePanel::ConsolePanel() : Panel("Console") {
} }
void ConsolePanel::Render() { 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(); auto* sink = Debug::EditorConsoleSink::GetInstance();
if (ImGui::Button("Clear")) { {
UI::PanelToolbarScope toolbar("ConsoleToolbar", kConsoleToolbarHeight);
if (toolbar.IsOpen()) {
if (UI::ToolbarButton("Clear")) {
sink->Clear(); sink->Clear();
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Filter:"); ImGui::TextDisabled("Filter");
ImGui::SameLine(); ImGui::SameLine();
ImGui::Separator(); if (UI::ToolbarButton("Info", m_showInfo)) {
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; m_showInfo = !m_showInfo;
} }
ImGui::PopStyleColor();
ImGui::SameLine(); ImGui::SameLine();
if (UI::ToolbarButton("Warn", m_showWarning)) {
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; m_showWarning = !m_showWarning;
} }
ImGui::PopStyleColor();
ImGui::SameLine(); ImGui::SameLine();
if (UI::ToolbarButton("Error", m_showError)) {
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; m_showError = !m_showError;
} }
ImGui::PopStyleColor(); }
}
ImGui::PopStyleVar(); UI::PanelContentScope content("LogScroll", UI::DefaultPanelContentPadding(), ImGuiWindowFlags_HorizontalScrollbar);
if (!content.IsOpen()) {
ImGui::Separator(); return;
}
ImGui::BeginChild("LogScroll", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
const auto logs = sink->GetLogs(); const auto logs = sink->GetLogs();
size_t logIndex = 0; size_t logIndex = 0;
@@ -77,34 +78,28 @@ void ConsolePanel::Render() {
continue; continue;
} }
ImVec4 color;
const char* prefix; const char* prefix;
switch (log.level) { switch (log.level) {
case ::XCEngine::Debug::LogLevel::Verbose: case ::XCEngine::Debug::LogLevel::Verbose:
case ::XCEngine::Debug::LogLevel::Debug: case ::XCEngine::Debug::LogLevel::Debug:
case ::XCEngine::Debug::LogLevel::Info: case ::XCEngine::Debug::LogLevel::Info:
color = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
prefix = "[INFO] "; prefix = "[INFO] ";
break; break;
case ::XCEngine::Debug::LogLevel::Warning: case ::XCEngine::Debug::LogLevel::Warning:
color = ImVec4(1.0f, 0.8f, 0.0f, 1.0f);
prefix = "[WARN] "; prefix = "[WARN] ";
break; break;
case ::XCEngine::Debug::LogLevel::Error: case ::XCEngine::Debug::LogLevel::Error:
case ::XCEngine::Debug::LogLevel::Fatal: case ::XCEngine::Debug::LogLevel::Fatal:
color = ImVec4(1.0f, 0.3f, 0.3f, 1.0f);
prefix = "[ERROR] "; prefix = "[ERROR] ";
break; break;
} }
ImGui::PushID(static_cast<int>(logIndex)); ImGui::PushID(static_cast<int>(logIndex));
ImGui::TextColored(ImVec4(0.4f, 0.4f, 0.4f, 1.0f), "%s", log.message.CStr()); const char* category = ::XCEngine::Debug::LogCategoryToString(log.category);
ImGui::SameLine(); std::string fullMessage = std::string(prefix) + "[" + category + "] " + log.message.CStr();
ImGui::TextUnformatted(fullMessage.c_str());
std::string fullMessage = std::string(prefix) + log.message.CStr();
ImGui::TextColored(color, "%s", fullMessage.c_str());
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
ImGui::SetClipboardText(fullMessage.c_str()); ImGui::SetClipboardText(fullMessage.c_str());
@@ -114,8 +109,6 @@ void ConsolePanel::Render() {
logIndex++; logIndex++;
} }
ImGui::EndChild();
ImGui::End();
} }
} }

View File

@@ -1,6 +1,6 @@
#include "GameViewPanel.h" #include "GameViewPanel.h"
#include "UI/PanelChrome.h"
#include <imgui.h> #include <imgui.h>
#include <imgui_internal.h>
namespace XCEngine { namespace XCEngine {
namespace Editor { namespace Editor {
@@ -8,25 +8,8 @@ namespace Editor {
GameViewPanel::GameViewPanel() : Panel("Game") {} GameViewPanel::GameViewPanel() : Panel("Game") {}
void GameViewPanel::Render() { void GameViewPanel::Render() {
ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); UI::PanelWindowScope panel(m_name.c_str());
(void)panel;
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);
} }
} }

View File

@@ -5,6 +5,8 @@
#include "Core/IUndoManager.h" #include "Core/IUndoManager.h"
#include "Core/EditorEvents.h" #include "Core/EditorEvents.h"
#include "Core/EventBus.h" #include "Core/EventBus.h"
#include "UI/Core.h"
#include "UI/PanelChrome.h"
#include "Utils/UndoUtils.h" #include "Utils/UndoUtils.h"
#include <XCEngine/Core/Math/Vector3.h> #include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Core/Math/Quaternion.h> #include <XCEngine/Core/Math/Quaternion.h>
@@ -16,6 +18,12 @@
namespace XCEngine { namespace XCEngine {
namespace Editor { namespace Editor {
namespace {
constexpr float kHierarchyToolbarHeight = 34.0f;
} // namespace
HierarchyPanel::HierarchyPanel() : Panel("Hierarchy") { HierarchyPanel::HierarchyPanel() : Panel("Hierarchy") {
} }
@@ -38,17 +46,21 @@ void HierarchyPanel::OnSelectionChanged(const SelectionChangedEvent& event) {
} }
void HierarchyPanel::Render() { void HierarchyPanel::Render() {
ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); UI::PanelWindowScope panel(m_name.c_str());
if (!panel.IsOpen()) {
return;
}
RenderSearchBar(); RenderSearchBar();
ImGui::Separator();
HandleKeyboardShortcuts(); HandleKeyboardShortcuts();
std::string filter = m_searchBuffer; std::string filter = m_searchBuffer;
ImGui::BeginChild("EntityList"); UI::PanelContentScope content("EntityList");
if (!content.IsOpen()) {
return;
}
auto& sceneManager = m_context->GetSceneManager(); auto& sceneManager = m_context->GetSceneManager();
auto rootEntities = sceneManager.GetRootEntities(); auto rootEntities = sceneManager.GetRootEntities();
@@ -93,21 +105,39 @@ void HierarchyPanel::Render() {
ImGui::EndDragDropTarget(); ImGui::EndDragDropTarget();
} }
ImGui::EndChild();
ImGui::End();
} }
void HierarchyPanel::RenderSearchBar() { void HierarchyPanel::RenderSearchBar() {
ImGui::SetNextItemWidth(120); UI::PanelToolbarScope toolbar("HierarchyToolbar", kHierarchyToolbarHeight);
const char* sortLabels[] = { "Name", "Components", "Transform First" }; if (!toolbar.IsOpen()) {
int currentSort = static_cast<int>(m_sortMode); return;
if (ImGui::Combo("##Sort", &currentSort, sortLabels, 3)) {
m_sortMode = static_cast<SortMode>(currentSort);
} }
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::SameLine();
ImGui::SetNextItemWidth(-1); if (UI::ToolbarButton("...", false, ImVec2(buttonWidth, 0.0f))) {
ImGui::InputTextWithHint("##Search", "Search...", m_searchBuffer, sizeof(m_searchBuffer)); 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) { 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<int>(gameObject->GetID())); ImGui::PushID(static_cast<int>(gameObject->GetID()));
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth; ImGuiTreeNodeFlags flags =
ImGuiTreeNodeFlags_OpenOnArrow |
ImGuiTreeNodeFlags_SpanAvailWidth |
ImGuiTreeNodeFlags_FramePadding;
if (gameObject->GetChildCount() == 0) { if (gameObject->GetChildCount() == 0) {
flags |= ImGuiTreeNodeFlags_Leaf; flags |= ImGuiTreeNodeFlags_Leaf;
@@ -156,7 +189,9 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject
m_renamingEntity = nullptr; m_renamingEntity = nullptr;
} }
} else { } else {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, 3.0f));
bool isOpen = ImGui::TreeNodeEx((void*)gameObject->GetUUID(), flags, "%s", gameObject->GetName().c_str()); bool isOpen = ImGui::TreeNodeEx((void*)gameObject->GetUUID(), flags, "%s", gameObject->GetName().c_str());
ImGui::PopStyleVar();
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) { if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();

View File

@@ -7,6 +7,7 @@
#include "Core/EditorEvents.h" #include "Core/EditorEvents.h"
#include "ComponentEditors/ComponentEditorRegistry.h" #include "ComponentEditors/ComponentEditorRegistry.h"
#include "ComponentEditors/IComponentEditor.h" #include "ComponentEditors/IComponentEditor.h"
#include "UI/PanelChrome.h"
#include "Utils/UndoUtils.h" #include "Utils/UndoUtils.h"
#include <imgui.h> #include <imgui.h>
#include <string> #include <string>
@@ -30,9 +31,10 @@ void InspectorPanel::OnSelectionChanged(const SelectionChangedEvent& event) {
} }
void InspectorPanel::Render() { void InspectorPanel::Render() {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); UI::PanelWindowScope panel(m_name.c_str());
ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); if (!panel.IsOpen()) {
ImGui::PopStyleVar(); return;
}
if (!m_selectionHandlerId && m_context) { if (!m_selectionHandlerId && m_context) {
m_selectionHandlerId = m_context->GetEventBus().Subscribe<SelectionChangedEvent>( m_selectionHandlerId = m_context->GetEventBus().Subscribe<SelectionChangedEvent>(
@@ -60,16 +62,19 @@ void InspectorPanel::Render() {
ImGui::TextColored(ImVec4(0.55f, 0.55f, 0.55f, 1.0f), "Select an object in Hierarchy"); 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) { void InspectorPanel::RenderGameObject(::XCEngine::Components::GameObject* gameObject) {
ImGuiStyle& style = ImGui::GetStyle(); ImGuiStyle& style = ImGui::GetStyle();
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 0.0f)); UI::PanelContentScope content(
ImGui::BeginChild("InspectorContent", ImVec2(0.0f, 0.0f), false, ImGuiWindowFlags_None); "InspectorContent",
ImGui::PopStyleVar(); UI::InspectorPanelContentPadding(),
ImGuiWindowFlags_None,
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, 0.0f)); true,
ImVec2(style.ItemSpacing.x, 0.0f));
if (!content.IsOpen()) {
return;
}
auto components = gameObject->GetComponents<::XCEngine::Components::Component>(); auto components = gameObject->GetComponents<::XCEngine::Components::Component>();
for (auto* component : components) { for (auto* component : components) {
@@ -80,13 +85,10 @@ void InspectorPanel::RenderGameObject(::XCEngine::Components::GameObject* gameOb
ImGui::OpenPopup("AddComponent"); ImGui::OpenPopup("AddComponent");
} }
RenderAddComponentPopup(gameObject); RenderAddComponentPopup(gameObject);
ImGui::PopStyleVar();
if (m_context->GetUndoManager().HasPendingInteractiveChange() && !ImGui::IsAnyItemActive()) { if (m_context->GetUndoManager().HasPendingInteractiveChange() && !ImGui::IsAnyItemActive()) {
m_context->GetUndoManager().FinalizeInteractiveChange(); m_context->GetUndoManager().FinalizeInteractiveChange();
} }
ImGui::EndChild();
} }
void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject* gameObject) { void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject* gameObject) {

View File

@@ -5,6 +5,8 @@
#include "Core/IUndoManager.h" #include "Core/IUndoManager.h"
#include "Core/ISelectionManager.h" #include "Core/ISelectionManager.h"
#include "Core/AssetItem.h" #include "Core/AssetItem.h"
#include "UI/Core.h"
#include "UI/PanelChrome.h"
#include "Utils/SceneEditorUtils.h" #include "Utils/SceneEditorUtils.h"
#include <imgui.h> #include <imgui.h>
#include <imgui_internal.h> #include <imgui_internal.h>
@@ -14,6 +16,31 @@ namespace Editor {
const char* DRAG_DROP_TYPE = "ASSET_ITEM"; 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") { ProjectPanel::ProjectPanel() : Panel("Project") {
} }
@@ -29,13 +56,19 @@ void ProjectPanel::Render() {
m_draggingPath.clear(); 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(); auto& manager = m_context->GetProjectManager();
UI::PanelToolbarScope toolbar("ProjectToolbar", kProjectToolbarHeight);
if (toolbar.IsOpen()) {
bool canGoBack = manager.CanNavigateBack(); bool canGoBack = manager.CanNavigateBack();
ImGui::BeginDisabled(!canGoBack); ImGui::BeginDisabled(!canGoBack);
if (ImGui::Button("<")) { if (UI::ToolbarButton("<", false, ImVec2(28.0f, 0.0f))) {
if (canGoBack) { if (canGoBack) {
manager.NavigateBack(); manager.NavigateBack();
} }
@@ -43,13 +76,16 @@ void ProjectPanel::Render() {
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
size_t pathDepth = manager.GetPathDepth(); size_t pathDepth = manager.GetPathDepth();
if (pathDepth == 0) {
ImGui::TextUnformatted("Assets");
} else {
for (size_t i = 0; i < pathDepth; i++) { for (size_t i = 0; i < pathDepth; i++) {
if (i > 0) { if (i > 0) {
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("/"); ImGui::TextDisabled("/");
ImGui::SameLine(); ImGui::SameLine();
} }
std::string name = manager.GetPathName(i); std::string name = manager.GetPathName(i);
@@ -61,26 +97,26 @@ void ProjectPanel::Render() {
ImGui::Text("%s", name.c_str()); ImGui::Text("%s", name.c_str());
} }
} }
}
ImGui::PopStyleColor(2); ImGui::PopStyleColor(2);
ImGui::SameLine(); ImGui::Dummy(ImVec2(0.0f, 2.0f));
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 80.0f); ImGui::SetNextItemWidth(-1.0f);
if (ImGui::Button("Refresh")) { ImGui::InputTextWithHint("##Search", "Search assets", m_searchBuffer, sizeof(m_searchBuffer));
manager.RefreshCurrentFolder();
} }
ImGui::Separator(); UI::PanelContentScope content(
"ProjectContent",
UI::AssetPanelContentPadding(),
ImGuiWindowFlags_None,
true,
ImVec2(8.0f, 10.0f));
if (!content.IsOpen()) {
return;
}
ImGui::PushItemWidth(-1); float buttonWidth = 104.0f;
ImGui::InputTextWithHint("##Search", "Search...", m_searchBuffer, sizeof(m_searchBuffer)); float padding = 8.0f;
ImGui::PopItemWidth();
ImGui::Separator();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(10, 10));
float buttonWidth = 80.0f;
float padding = 10.0f;
float panelWidth = ImGui::GetContentRegionAvail().x; float panelWidth = ImGui::GetContentRegionAvail().x;
int columns = (int)(panelWidth / (buttonWidth + padding)); int columns = (int)(panelWidth / (buttonWidth + padding));
if (columns < 1) columns = 1; if (columns < 1) columns = 1;
@@ -103,8 +139,6 @@ void ProjectPanel::Render() {
displayedCount++; displayedCount++;
} }
ImGui::PopStyleVar();
if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered()) { if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered()) {
manager.SetSelectedIndex(-1); manager.SetSelectedIndex(-1);
} }
@@ -142,15 +176,9 @@ void ProjectPanel::Render() {
m_showCreateFolderPopup = true; m_showCreateFolderPopup = true;
strcpy_s(m_newFolderName, "NewFolder"); strcpy_s(m_newFolderName, "NewFolder");
} }
ImGui::Separator();
if (ImGui::MenuItem("Refresh")) {
manager.RefreshCurrentFolder();
}
ImGui::EndPopup(); ImGui::EndPopup();
} }
ImGui::End();
if (m_showCreateFolderPopup) { if (m_showCreateFolderPopup) {
ImGui::OpenPopup("Create Folder"); ImGui::OpenPopup("Create Folder");
m_showCreateFolderPopup = false; m_showCreateFolderPopup = false;
@@ -177,16 +205,10 @@ void ProjectPanel::RenderAssetItem(const AssetItemPtr& item, int index) {
ImGui::PushID(index); ImGui::PushID(index);
if (isSelected) { ImVec2 buttonSize(104.0f, 82.0f);
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); ImGui::InvisibleButton("##AssetBtn", buttonSize);
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
if (ImGui::Button("##AssetBtn", buttonSize)) {
manager.SetSelectedIndex(index); manager.SetSelectedIndex(index);
} }
@@ -202,46 +224,39 @@ void ProjectPanel::RenderAssetItem(const AssetItemPtr& item, int index) {
openContextMenu = true; openContextMenu = true;
} }
if (isSelected) {
ImGui::PopStyleColor();
} else {
ImGui::PopStyleColor(2);
}
ImVec2 min = ImGui::GetItemRectMin(); ImVec2 min = ImGui::GetItemRectMin();
ImVec2 max = ImVec2(min.x + buttonSize.x, min.y + buttonSize.y); ImVec2 max = ImVec2(min.x + buttonSize.x, min.y + buttonSize.y);
ImDrawList* drawList = ImGui::GetWindowDrawList(); 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) { if (!m_draggingPath.empty() && item->fullPath == m_draggingPath) {
drawList->AddRectFilled(min, max, IM_COL32(0, 0, 0, 60), 0.0f); 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) { if (item->isFolder) {
iconColor = IM_COL32(200, 180, 100, 255); DrawFolderIcon(drawList, iconMin, iconMax, iconFillColor, iconLineColor);
} 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);
} else { } else {
iconColor = IM_COL32(100, 150, 200, 255); DrawFileIcon(drawList, iconMin, iconMax, iconFillColor, iconLineColor);
} }
float iconSize = 40.0f; ImVec4 textColor = isSelected ? ImVec4(0.93f, 0.93f, 0.93f, 1.0f) : ImVec4(0.76f, 0.76f, 0.76f, 1.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);
ImVec2 textSize = ImGui::CalcTextSize(item->name.c_str()); ImVec2 textSize = ImGui::CalcTextSize(item->name.c_str());
float textOffset = std::max(0.0f, (80.0f - textSize.x) * 0.5f); float textY = max.y - textSize.y - 10.0f;
ImGui::PushClipRect(min, ImVec2(min.x + 80.0f, min.y + 90.0f), true); ImGui::PushClipRect(ImVec2(min.x + 6.0f, min.y), ImVec2(max.x - 6.0f, max.y), true);
drawList->AddText(ImVec2(min.x + textOffset, min.y + 60.0f), ImGui::GetColorU32(textColor), item->name.c_str()); drawList->AddText(ImVec2(min.x + 6.0f, textY), ImGui::GetColorU32(textColor), item->name.c_str());
ImGui::PopClipRect(); ImGui::PopClipRect();
if (item->isFolder) { if (item->isFolder) {
@@ -253,35 +268,19 @@ void ProjectPanel::RenderAssetItem(const AssetItemPtr& item, int index) {
} }
ImGui::EndDragDropTarget(); 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 (!item->fullPath.empty()) {
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
ImGui::SetDragDropPayload(DRAG_DROP_TYPE, item->fullPath.c_str(), item->fullPath.length() + 1); 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 previewMin = ImGui::GetMousePos();
ImVec2 previewMax = ImVec2(previewMin.x + 40, previewMin.y + 40); ImVec2 previewMax = ImVec2(previewMin.x + 24.0f, previewMin.y + 20.0f);
ImGui::GetForegroundDrawList()->AddRectFilled(previewMin, previewMax, iconColor, 4.0f); if (item->isFolder) {
DrawFolderIcon(ImGui::GetForegroundDrawList(), previewMin, previewMax, iconFillColor, iconLineColor);
} else {
DrawFileIcon(ImGui::GetForegroundDrawList(), previewMin, previewMax, iconFillColor, iconLineColor);
}
ImGui::EndDragDropSource(); ImGui::EndDragDropSource();
} }

View File

@@ -1,6 +1,6 @@
#include "SceneViewPanel.h" #include "SceneViewPanel.h"
#include "UI/PanelChrome.h"
#include <imgui.h> #include <imgui.h>
#include <imgui_internal.h>
namespace XCEngine { namespace XCEngine {
namespace Editor { namespace Editor {
@@ -8,48 +8,8 @@ namespace Editor {
SceneViewPanel::SceneViewPanel() : Panel("Scene") {} SceneViewPanel::SceneViewPanel() : Panel("Scene") {}
void SceneViewPanel::Render() { void SceneViewPanel::Render() {
ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); UI::PanelWindowScope panel(m_name.c_str());
(void)panel;
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);
} }
} }