diff options
| author | hachem <im@hachem.wtf> | 2026-08-28 01:01:01 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-08-28 01:01:01 +0200 |
| commit | 801c6a8916a495162b200fff0d14cfbf89ea854c (patch) | |
| tree | c68fb131e87e3098559643c707142eaeac835baa /src/ui/ui.cpp | |
| parent | 705e3914e4e820c3ac92892c32c93479691a09e7 (diff) | |
add: ui view and renderer
Diffstat (limited to 'src/ui/ui.cpp')
| -rw-r--r-- | src/ui/ui.cpp | 809 |
1 files changed, 809 insertions, 0 deletions
diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp new file mode 100644 index 0000000..91fab0a --- /dev/null +++ b/src/ui/ui.cpp @@ -0,0 +1,809 @@ +#include "ui/ui.h" + +#include "core/log.h" +#include "core/window.h" +#include "debugger/debugger.h" + +#include <imgui.h> +#include <imgui_internal.h> +#include <misc/cpp/imgui_stdlib.h> + +#include <backends/imgui_impl_glfw.h> +#include <backends/imgui_impl_opengl3.h> + +#include <filesystem> +#include <format> + +namespace Hsdbg +{ + namespace + { + constexpr const char* PANEL_SOURCE = "source"; + constexpr const char* PANEL_BREAKPOINTS = "breakpoints"; + constexpr const char* PANEL_CALL_STACK = "call stack"; + constexpr const char* PANEL_THREADS = "threads"; + constexpr const char* PANEL_LOCALS = "locals"; + constexpr const char* PANEL_REGISTERS = "registers"; + constexpr const char* PANEL_CONSOLE = "console"; + + constexpr const char* LOAD_TARGET_POPUP = "load target"; + + // macos gives us a 4.1 core context, which speaks glsl 1.50 + // #portability + constexpr const char* GLSL_VERSION = "#version 150"; + + constexpr size_t MAX_CONSOLE_LINES = 2048; + + // breathing room between the window edge and everything docked inside it + const ImVec2 ROOT_PADDING(8.0f, 6.0f); + const ImVec2 TOOLBAR_PADDING(4.0f, 4.0f); + + auto state_color(TargetState state) -> ImVec4 + { + switch (state) + { + case TargetState::Running: return ImVec4(0.45f, 0.78f, 0.45f, 1.0f); + case TargetState::Stopped: return ImVec4(0.95f, 0.76f, 0.35f, 1.0f); + case TargetState::Crashed: return ImVec4(0.89f, 0.33f, 0.33f, 1.0f); + case TargetState::Exited: return ImVec4(0.60f, 0.60f, 0.65f, 1.0f); + default: return ImVec4(0.55f, 0.55f, 0.60f, 1.0f); + } + } + + auto draw_variable(const Variable& variable) -> void + { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + if (variable.children.empty()) + { + ImGui::TreeNodeEx(variable.name.c_str(), + ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | + ImGuiTreeNodeFlags_SpanFullWidth); + + ImGui::TableNextColumn(); + ImGui::TextUnformatted(variable.type.c_str()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(variable.value.c_str()); + + return; + } + + const bool open = ImGui::TreeNodeEx(variable.name.c_str(), ImGuiTreeNodeFlags_SpanFullWidth); + + ImGui::TableNextColumn(); + ImGui::TextUnformatted(variable.type.c_str()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(variable.value.c_str()); + + if (!open) + return; + + for (const Variable& child : variable.children) + draw_variable(child); + + ImGui::TreePop(); + } + } + + Ui::Ui(Window& window) + : m_window(&window) + { + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io.ConfigWindowsMoveFromTitleBarOnly = true; + + // a saved layout beats the built in one, so only build when there is none + m_layout_built = io.IniFilename != nullptr && std::filesystem::exists(io.IniFilename); + + apply_style(); + + ImGui_ImplGlfw_InitForOpenGL(m_window->handle(), true); + ImGui_ImplOpenGL3_Init(GLSL_VERSION); + + Log::info("imgui {}", IMGUI_VERSION); + } + + Ui::~Ui() + { + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + } + + auto Ui::begin_frame() -> void + { + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + } + + auto Ui::end_frame() -> void + { + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + } + + auto Ui::open_source(const std::filesystem::path& path) -> void + { + if (const auto result = m_source_view.open(path); !result) + { + Log::error("{}", result.error()); + push_console(std::format("error: {}", result.error())); + } + } + + auto Ui::draw(Debugger& debugger) -> void + { + const ImGuiViewport* viewport = ImGui::GetMainViewport(); + + ImGui::SetNextWindowPos(viewport->WorkPos); + ImGui::SetNextWindowSize(viewport->WorkSize); + ImGui::SetNextWindowViewport(viewport->ID); + + constexpr ImGuiWindowFlags root_flags = + ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ROOT_PADDING); + + ImGui::Begin("##hsdbg_root", nullptr, root_flags); + + ImGui::PopStyleVar(3); + + draw_menu_bar(debugger); + draw_toolbar(debugger); + + const ImGuiID dockspace_id = ImGui::GetID("##hsdbg_dockspace"); + const float status_bar_height = ImGui::GetTextLineHeight() + + ImGui::GetStyle().ItemSpacing.y * 3.0f; + + ImGui::DockSpace(dockspace_id, + ImVec2(0.0f, ImGui::GetContentRegionAvail().y - status_bar_height), + ImGuiDockNodeFlags_PassthruCentralNode); + + if (!m_layout_built) + { + build_default_layout(dockspace_id); + m_layout_built = true; + } + + draw_status_bar(debugger); + draw_load_target_popup(debugger); + + ImGui::End(); + + draw_source_panel(debugger); + draw_breakpoints_panel(debugger); + draw_call_stack_panel(debugger); + draw_threads_panel(debugger); + draw_locals_panel(debugger); + draw_registers_panel(debugger); + draw_console_panel(debugger); + + if (m_visible.demo) + ImGui::ShowDemoWindow(&m_visible.demo); + } + + auto Ui::build_default_layout(uint32_t dockspace_id) -> void + { + ImGui::DockBuilderRemoveNode(dockspace_id); + ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace); + ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->WorkSize); + + ImGuiID center_id = dockspace_id; + const ImGuiID left_id = ImGui::DockBuilderSplitNode(center_id, ImGuiDir_Left, 0.20f, nullptr, ¢er_id); + const ImGuiID right_id = ImGui::DockBuilderSplitNode(center_id, ImGuiDir_Right, 0.28f, nullptr, ¢er_id); + const ImGuiID bottom_id = ImGui::DockBuilderSplitNode(center_id, ImGuiDir_Down, 0.28f, nullptr, ¢er_id); + + ImGuiID left_top_id = left_id; + const ImGuiID left_bottom_id = ImGui::DockBuilderSplitNode(left_top_id, ImGuiDir_Down, 0.5f, nullptr, &left_top_id); + + ImGuiID right_top_id = right_id; + const ImGuiID right_bottom_id = ImGui::DockBuilderSplitNode(right_top_id, ImGuiDir_Down, 0.5f, nullptr, &right_top_id); + + ImGui::DockBuilderDockWindow(PANEL_SOURCE, center_id); + ImGui::DockBuilderDockWindow(PANEL_THREADS, left_top_id); + ImGui::DockBuilderDockWindow(PANEL_CALL_STACK, left_bottom_id); + ImGui::DockBuilderDockWindow(PANEL_LOCALS, right_top_id); + ImGui::DockBuilderDockWindow(PANEL_REGISTERS, right_bottom_id); + ImGui::DockBuilderDockWindow(PANEL_BREAKPOINTS, bottom_id); + ImGui::DockBuilderDockWindow(PANEL_CONSOLE, bottom_id); + + ImGui::DockBuilderFinish(dockspace_id); + } + + auto Ui::draw_menu_bar(Debugger& debugger) -> void + { + if (!ImGui::BeginMenuBar()) + return; + + if (ImGui::BeginMenu("file")) + { + // a menu is its own popup, so the request has to be handed back to the + // root window or BeginPopupModal never sees a matching id + if (ImGui::MenuItem("load target...")) + { + m_target_input = debugger.target_path().string(); + m_load_target_pending = true; + } + + if (ImGui::MenuItem("unload target", nullptr, false, debugger.has_target())) + debugger.unload_target(); + + ImGui::Separator(); + + if (ImGui::MenuItem("quit", "cmd+q")) + m_window->set_should_close(true); + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("run")) + { + const bool has_target = debugger.has_target(); + + if (ImGui::MenuItem("continue", "f5", false, has_target)) + report(debugger.resume(), "continue"); + + if (ImGui::MenuItem("pause", nullptr, false, debugger.is_running())) + report(debugger.pause(), "pause"); + + if (ImGui::MenuItem("stop", nullptr, false, has_target)) + report(debugger.terminate(), "stop"); + + ImGui::Separator(); + + if (ImGui::MenuItem("step over", "f10", false, has_target)) + report(debugger.step_over(), "step over"); + + if (ImGui::MenuItem("step into", "f11", false, has_target)) + report(debugger.step_into(), "step into"); + + if (ImGui::MenuItem("step out", "shift+f11", false, has_target)) + report(debugger.step_out(), "step out"); + + ImGui::Separator(); + + if (ImGui::MenuItem("clear breakpoints", nullptr, false, !debugger.breakpoints().empty())) + debugger.clear_breakpoints(); + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("view")) + { + ImGui::MenuItem(PANEL_SOURCE, nullptr, &m_visible.source); + ImGui::MenuItem(PANEL_BREAKPOINTS, nullptr, &m_visible.breakpoints); + ImGui::MenuItem(PANEL_CALL_STACK, nullptr, &m_visible.call_stack); + ImGui::MenuItem(PANEL_THREADS, nullptr, &m_visible.threads); + ImGui::MenuItem(PANEL_LOCALS, nullptr, &m_visible.locals); + ImGui::MenuItem(PANEL_REGISTERS, nullptr, &m_visible.registers); + ImGui::MenuItem(PANEL_CONSOLE, nullptr, &m_visible.console); + + ImGui::Separator(); + + if (ImGui::MenuItem("reset layout")) + m_layout_built = false; + + ImGui::MenuItem("imgui demo", nullptr, &m_visible.demo); + + ImGui::EndMenu(); + } + + ImGui::EndMenuBar(); + } + + auto Ui::draw_toolbar(Debugger& debugger) -> void + { + const bool has_target = debugger.has_target(); + const bool running = debugger.is_running(); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, TOOLBAR_PADDING); + ImGui::BeginChild("##toolbar", + ImVec2(0.0f, ImGui::GetFrameHeight() + TOOLBAR_PADDING.y * 2.0f)); + + ImGui::BeginDisabled(!has_target || running); + if (ImGui::Button("run")) + { + LaunchSpec spec; + spec.executable = debugger.target_path(); + + report(debugger.launch(spec), "run"); + } + ImGui::EndDisabled(); + + ImGui::SameLine(); + + ImGui::BeginDisabled(!running); + if (ImGui::Button("pause")) + report(debugger.pause(), "pause"); + ImGui::EndDisabled(); + + ImGui::SameLine(); + + ImGui::BeginDisabled(!has_target); + if (ImGui::Button("stop")) + report(debugger.terminate(), "stop"); + + ImGui::SameLine(); + ImGui::TextDisabled("|"); + ImGui::SameLine(); + + if (ImGui::Button("step over")) + report(debugger.step_over(), "step over"); + + ImGui::SameLine(); + + if (ImGui::Button("step into")) + report(debugger.step_into(), "step into"); + + ImGui::SameLine(); + + if (ImGui::Button("step out")) + report(debugger.step_out(), "step out"); + ImGui::EndDisabled(); + + ImGui::SameLine(); + ImGui::TextDisabled("|"); + ImGui::SameLine(); + + ImGui::AlignTextToFramePadding(); + ImGui::TextColored(state_color(debugger.state()), "%s", to_string(debugger.state()).data()); + + ImGui::EndChild(); + ImGui::PopStyleVar(2); + } + + auto Ui::draw_status_bar(Debugger& debugger) -> void + { + ImGui::Separator(); + + ImGui::AlignTextToFramePadding(); + ImGui::TextColored(state_color(debugger.state()), "%s", to_string(debugger.state()).data()); + + ImGui::SameLine(); + ImGui::TextDisabled("|"); + ImGui::SameLine(); + + if (debugger.has_target()) + ImGui::Text("%s", debugger.target_path().filename().string().c_str()); + else + ImGui::TextDisabled("no target"); + + ImGui::SameLine(); + ImGui::TextDisabled("|"); + ImGui::SameLine(); + + ImGui::Text("%zu breakpoints", debugger.breakpoints().size()); + + const std::string frame_stats = std::format("{:.1f} fps", ImGui::GetIO().Framerate); + const float text_width = ImGui::CalcTextSize(frame_stats.c_str()).x; + + ImGui::SameLine(ImGui::GetContentRegionMax().x - text_width - ImGui::GetStyle().ItemSpacing.x); + ImGui::TextDisabled("%s", frame_stats.c_str()); + } + + auto Ui::draw_load_target_popup(Debugger& debugger) -> void + { + if (m_load_target_pending) + { + ImGui::OpenPopup(LOAD_TARGET_POPUP); + m_load_target_pending = false; + } + + const ImGuiViewport* viewport = ImGui::GetMainViewport(); + const ImVec2 center(viewport->WorkPos.x + viewport->WorkSize.x * 0.5f, + viewport->WorkPos.y + viewport->WorkSize.y * 0.5f); + + ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); + + if (!ImGui::BeginPopupModal(LOAD_TARGET_POPUP, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) + return; + + ImGui::TextDisabled("path to an executable to debug"); + + ImGui::SetNextItemWidth(420.0f); + + const bool submitted = ImGui::InputText("##target_path", + &m_target_input, + ImGuiInputTextFlags_EnterReturnsTrue); + + if (ImGui::Button("load") || submitted) + { + if (const auto result = debugger.load_target(m_target_input); result) + { + push_console(std::format("loaded target {}", debugger.target_path().string())); + ImGui::CloseCurrentPopup(); + } + else + { + push_console(std::format("error: {}", result.error())); + } + } + + ImGui::SameLine(); + + if (ImGui::Button("cancel")) + ImGui::CloseCurrentPopup(); + + ImGui::EndPopup(); + } + + auto Ui::draw_source_panel(Debugger& debugger) -> void + { + if (!m_visible.source) + return; + + if (ImGui::Begin(PANEL_SOURCE, &m_visible.source)) + m_source_view.draw(debugger); + + ImGui::End(); + } + + auto Ui::draw_breakpoints_panel(Debugger& debugger) -> void + { + if (!m_visible.breakpoints) + return; + + if (ImGui::Begin(PANEL_BREAKPOINTS, &m_visible.breakpoints)) + { + if (debugger.breakpoints().empty()) + { + ImGui::TextDisabled("no breakpoints, click a line gutter in the source panel"); + } + else + { + constexpr ImGuiTableFlags flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV | + ImGuiTableFlags_SizingStretchProp | + ImGuiTableFlags_ScrollY; + + if (ImGui::BeginTable("##breakpoints", 5, flags)) + { + ImGui::TableSetupColumn("on", ImGuiTableColumnFlags_WidthFixed, 26.0f); + ImGui::TableSetupColumn("id", ImGuiTableColumnFlags_WidthFixed, 30.0f); + ImGui::TableSetupColumn("location"); + ImGui::TableSetupColumn("hits", ImGuiTableColumnFlags_WidthFixed, 40.0f); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 26.0f); + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableHeadersRow(); + + uint32_t pending_removal = 0; + + for (const Breakpoint& breakpoint : debugger.breakpoints()) + { + ImGui::PushID(static_cast<int>(breakpoint.id)); + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + bool enabled = breakpoint.enabled; + if (ImGui::Checkbox("##enabled", &enabled)) + debugger.set_breakpoint_enabled(breakpoint.id, enabled); + + ImGui::TableNextColumn(); + ImGui::Text("%u", breakpoint.id); + + ImGui::TableNextColumn(); + if (breakpoint.line != 0) + { + ImGui::Text("%s:%u", + breakpoint.file.filename().string().c_str(), + breakpoint.line); + } + else + { + ImGui::Text("%s()", breakpoint.function.c_str()); + } + + if (ImGui::IsItemHovered() && !breakpoint.file.empty()) + ImGui::SetTooltip("%s", breakpoint.file.string().c_str()); + + ImGui::TableNextColumn(); + ImGui::Text("%u", breakpoint.hit_count); + + ImGui::TableNextColumn(); + if (ImGui::SmallButton("x")) + pending_removal = breakpoint.id; + + ImGui::PopID(); + } + + ImGui::EndTable(); + + if (pending_removal != 0) + debugger.remove_breakpoint(pending_removal); + } + } + } + + ImGui::End(); + } + + auto Ui::draw_call_stack_panel(Debugger& debugger) -> void + { + if (!m_visible.call_stack) + return; + + if (ImGui::Begin(PANEL_CALL_STACK, &m_visible.call_stack)) + { + if (debugger.call_stack().empty()) + { + ImGui::TextDisabled("no call stack"); + } + else + { + for (const StackFrame& frame : debugger.call_stack()) + { + const bool selected = frame.index == debugger.selected_frame(); + const std::string label = std::format("{:>2} {}", frame.index, frame.function); + + if (ImGui::Selectable(label.c_str(), selected)) + debugger.select_frame(frame.index); + + if (frame.line == 0) + continue; + + ImGui::SameLine(); + ImGui::TextDisabled("%s:%u", frame.file.filename().string().c_str(), frame.line); + } + } + } + + ImGui::End(); + } + + auto Ui::draw_threads_panel(Debugger& debugger) -> void + { + if (!m_visible.threads) + return; + + if (ImGui::Begin(PANEL_THREADS, &m_visible.threads)) + { + if (debugger.threads().empty()) + { + ImGui::TextDisabled("no threads"); + } + else + { + for (const Thread& thread : debugger.threads()) + { + const bool selected = thread.id == debugger.selected_thread(); + const std::string label = std::format("{} {}", thread.id, thread.name); + + if (ImGui::Selectable(label.c_str(), selected)) + debugger.select_thread(thread.id); + + ImGui::SameLine(); + ImGui::TextDisabled("%s", to_string(thread.stop_reason).data()); + } + } + } + + ImGui::End(); + } + + auto Ui::draw_locals_panel(Debugger& debugger) -> void + { + if (!m_visible.locals) + return; + + if (ImGui::Begin(PANEL_LOCALS, &m_visible.locals)) + { + if (debugger.locals().empty()) + { + ImGui::TextDisabled("no locals"); + } + else + { + constexpr ImGuiTableFlags flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV | + ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY; + + if (ImGui::BeginTable("##locals", 3, flags)) + { + ImGui::TableSetupColumn("name"); + ImGui::TableSetupColumn("type"); + ImGui::TableSetupColumn("value"); + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableHeadersRow(); + + for (const Variable& variable : debugger.locals()) + draw_variable(variable); + + ImGui::EndTable(); + } + } + } + + ImGui::End(); + } + + auto Ui::draw_registers_panel(Debugger& debugger) -> void + { + if (!m_visible.registers) + return; + + if (ImGui::Begin(PANEL_REGISTERS, &m_visible.registers)) + { + if (debugger.registers().empty()) + { + ImGui::TextDisabled("no registers"); + } + else + { + constexpr ImGuiTableFlags flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV | + ImGuiTableFlags_ScrollY; + + if (ImGui::BeginTable("##registers", 2, flags)) + { + ImGui::TableSetupColumn("name", ImGuiTableColumnFlags_WidthFixed, 70.0f); + ImGui::TableSetupColumn("value"); + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableHeadersRow(); + + for (const Register& entry : debugger.registers()) + { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(entry.name.c_str()); + ImGui::TableNextColumn(); + ImGui::Text("0x%016llx", static_cast<unsigned long long>(entry.value)); + } + + ImGui::EndTable(); + } + } + } + + ImGui::End(); + } + + auto Ui::draw_console_panel(Debugger& debugger) -> void + { + if (!m_visible.console) + return; + + if (ImGui::Begin(PANEL_CONSOLE, &m_visible.console)) + { + const float input_height = ImGui::GetFrameHeightWithSpacing(); + + if (ImGui::BeginChild("##console_output", ImVec2(0.0f, -input_height))) + { + for (const std::string& line : debugger.console_output()) + ImGui::TextUnformatted(line.c_str()); + + for (const std::string& line : m_console_lines) + ImGui::TextUnformatted(line.c_str()); + + if (m_console_scroll_pending) + { + ImGui::SetScrollHereY(1.0f); + m_console_scroll_pending = false; + } + } + + ImGui::EndChild(); + + ImGui::SetNextItemWidth(-1.0f); + + const bool submitted = ImGui::InputTextWithHint("##console_input", + "expression to evaluate", + &m_console_input, + ImGuiInputTextFlags_EnterReturnsTrue); + + if (submitted && !m_console_input.empty()) + { + push_console(std::format("> {}", m_console_input)); + + if (const auto result = debugger.evaluate(m_console_input); result) + push_console(*result); + else + push_console(std::format("error: {}", result.error())); + + m_console_input.clear(); + ImGui::SetKeyboardFocusHere(-1); + } + } + + ImGui::End(); + } + + auto Ui::push_console(std::string line) -> void + { + m_console_lines.push_back(std::move(line)); + + if (m_console_lines.size() > MAX_CONSOLE_LINES) + m_console_lines.erase(m_console_lines.begin()); + + m_console_scroll_pending = true; + } + + auto Ui::report(const Result<void>& result, std::string_view action) -> void + { + if (result) + return; + + push_console(std::format("{} failed: {}", action, result.error())); + } + + auto Ui::apply_style() -> void + { + ImGuiStyle& style = ImGui::GetStyle(); + + style.WindowRounding = 4.0f; + style.ChildRounding = 4.0f; + style.FrameRounding = 4.0f; + style.PopupRounding = 4.0f; + style.ScrollbarRounding = 6.0f; + style.GrabRounding = 4.0f; + style.TabRounding = 4.0f; + + style.WindowBorderSize = 1.0f; + style.FrameBorderSize = 0.0f; + style.WindowPadding = ImVec2(8.0f, 8.0f); + style.FramePadding = ImVec2(8.0f, 4.0f); + style.ItemSpacing = ImVec2(8.0f, 5.0f); + style.ScrollbarSize = 11.0f; + style.GrabMinSize = 9.0f; + style.WindowTitleAlign = ImVec2(0.0f, 0.5f); + style.SeparatorTextBorderSize = 1.0f; + + ImVec4* colors = style.Colors; + + colors[ImGuiCol_Text] = ImVec4(0.86f, 0.86f, 0.88f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.44f, 0.44f, 0.48f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.09f, 0.09f, 0.11f, 1.00f); + colors[ImGuiCol_ChildBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.12f, 0.12f, 0.15f, 1.00f); + colors[ImGuiCol_Border] = ImVec4(0.20f, 0.20f, 0.24f, 1.00f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.16f, 0.19f, 1.00f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.21f, 0.21f, 0.26f, 1.00f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.25f, 0.25f, 0.31f, 1.00f); + colors[ImGuiCol_TitleBg] = ImVec4(0.07f, 0.07f, 0.09f, 1.00f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.11f, 0.11f, 0.14f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.07f, 0.07f, 0.09f, 1.00f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.11f, 0.11f, 0.14f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.09f, 0.09f, 0.11f, 1.00f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.24f, 0.24f, 0.29f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.30f, 0.30f, 0.36f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.36f, 0.36f, 0.43f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.30f, 0.72f, 0.78f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.30f, 0.72f, 0.78f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.38f, 0.80f, 0.86f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.18f, 0.18f, 0.22f, 1.00f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.24f, 0.40f, 0.44f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.28f, 0.52f, 0.58f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.20f, 0.20f, 0.25f, 1.00f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.24f, 0.40f, 0.44f, 1.00f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.28f, 0.52f, 0.58f, 1.00f); + colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.20f, 0.24f, 1.00f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.30f, 0.72f, 0.78f, 0.60f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.30f, 0.72f, 0.78f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.24f, 0.24f, 0.29f, 1.00f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.30f, 0.72f, 0.78f, 0.60f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.30f, 0.72f, 0.78f, 1.00f); + colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.11f, 0.14f, 1.00f); + colors[ImGuiCol_TabHovered] = ImVec4(0.24f, 0.40f, 0.44f, 1.00f); + colors[ImGuiCol_TabSelected] = ImVec4(0.18f, 0.30f, 0.34f, 1.00f); + colors[ImGuiCol_TabSelectedOverline] = ImVec4(0.30f, 0.72f, 0.78f, 1.00f); + colors[ImGuiCol_TabDimmed] = ImVec4(0.09f, 0.09f, 0.11f, 1.00f); + colors[ImGuiCol_TabDimmedSelected] = ImVec4(0.14f, 0.20f, 0.22f, 1.00f); + colors[ImGuiCol_DockingPreview] = ImVec4(0.30f, 0.72f, 0.78f, 0.50f); + colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.07f, 0.07f, 0.09f, 1.00f); + colors[ImGuiCol_TableHeaderBg] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f); + colors[ImGuiCol_TableBorderStrong] = ImVec4(0.20f, 0.20f, 0.24f, 1.00f); + colors[ImGuiCol_TableBorderLight] = ImVec4(0.16f, 0.16f, 0.19f, 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.02f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.30f, 0.72f, 0.78f, 0.35f); + colors[ImGuiCol_NavCursor] = ImVec4(0.30f, 0.72f, 0.78f, 1.00f); + } +} |
