diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..2b12c25 --- /dev/null +++ b/config.toml @@ -0,0 +1 @@ +style = "../uistyles/basic.toml" \ No newline at end of file diff --git a/src/gui.cpp b/src/gui.cpp new file mode 100644 index 0000000..7dabbc8 --- /dev/null +++ b/src/gui.cpp @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include "gui.h" +#include "project.h" + + +void Gui::render() { + if (imgui_demo_open) ImGui::ShowTestWindow(&imgui_demo_open); + if (project_overlay_open) this->render_project_overlay(); + this->render_menubar(); +} + +void Gui::render_menubar() { + if (ImGui::BeginMainMenuBar()) { + if (ImGui::BeginMenu("File")) + render_mmb_file(); + + if (ImGui::BeginMenu("View")) + render_mmb_view(); + + if (ImGui::BeginMenu("Debug")) + render_mmb_debug(); + + ImGui::EndMainMenuBar(); + } +} + +void Gui::render_project_overlay() { + ImGui::SetNextWindowPos(ImVec2(20, 30)); + if (ImGui::Begin("", &this->project_overlay_open, ImVec2(200,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) { + ImGui::Text("[project]"); + ImGui::Separator(); + if (state->current_project != nullptr) { + ImGui::Text("name: %s", state->current_project->name.c_str()); + ImGui::Text("n_scenes: %i", state->current_project->scenes.size()); + if (!state->current_project->scene_loaded) { + ImGui::Text("no scene loaded"); + } else { + ImGui::Text("current scene: %s", + state->current_project->current_scene->name.c_str()); + } + } else { + ImGui::Text("no project loaded."); + } + ImGui::End(); + } +} + +void Gui::render_mmb_file() { + if (ImGui::MenuItem("Load project", "CTRL+O")) { + nfdchar_t *out_path = nullptr; + nfdresult_t result = NFD_OpenDialog(NULL, NULL, &out_path); + if (result == NFD_OKAY) { + // Load project + auto new_project = Project::fromFile(std::string(out_path)); + state->current_project = std::move(new_project); + + free(out_path); + } else if (result == NFD_ERROR) { + std::cout << "Error in filepicker: " << NFD_GetError() << '\n'; + } + } + + ImGui::Separator(); + if (ImGui::MenuItem("Exit", "CTRL+Q")) + state->running = false; + + ImGui::EndMenu(); +} + +void Gui::render_mmb_view() { + ImGui::MenuItem("Show project meta overlay", NULL, &this->project_overlay_open); + + ImGui::Separator(); + + if (ImGui::MenuItem("Reload ImGui styling")) + this->load_style(cpptoml::parse_file(state->config->stylepath)); + + ImGui::MenuItem("Show ImGui demo window", NULL, &this->imgui_demo_open); + + ImGui::EndMenu(); +} + +void Gui::render_mmb_debug() { + ImGui::MenuItem("Profiler"); + + if (ImGui::MenuItem("Reload shaders", "CTRL+R")) { + if (state->current_project != nullptr) { + if (state->current_project->scene_loaded) { + std::cout << "=== reloading shaders ===\n"; + state->current_project->shader_bundle->recompile().link(); + } + } + } + + ImGui::EndMenu(); +} + + +static cpptoml::option vec2im2(cpptoml::option> vec) { + if (vec) { + assert((*vec).size() == 2); + return ImVec2((*vec)[0], (*vec)[1]); + } else { + return cpptoml::option(); + } +} + +static cpptoml::option vec2im4(cpptoml::option> vec) { + if (vec) { + assert((*vec).size() == 4); + return ImVec4((*vec)[0], (*vec)[1], (*vec)[2], (*vec)[3]); + } else { + return cpptoml::option(); + } +} + +#define st_lds_d(n, k) style.n = conf->get_qualified_as(k).value_or(defaultstyle.n) +#define st_lds_v2(n, k) style.n = vec2im2(conf->get_qualified_array_of(k)).value_or(defaultstyle.n) +#define st_lds_v4(n, k) style.n = vec2im4(conf->get_qualified_array_of(k)).value_or(defaultstyle.n) + + +void Gui::load_style(std::shared_ptr conf) { + ImGuiStyle &style = ImGui::GetStyle(); + auto defaultstyle = ImGuiStyle(); + + st_lds_d(Alpha, "alpha"); + st_lds_v2(WindowPadding, "window.padding"); + st_lds_v2(WindowMinSize, "window.min_size"); + st_lds_d(WindowRounding, "window.rounding"); + st_lds_v2(WindowTitleAlign, "window.title_align"); + st_lds_d(ChildWindowRounding, "window.child_rounding"); + st_lds_v2(FramePadding, "frame.padding"); + st_lds_d(FrameRounding, "frame.rounding"); +} diff --git a/src/gui.h b/src/gui.h new file mode 100644 index 0000000..aeb9f8f --- /dev/null +++ b/src/gui.h @@ -0,0 +1,35 @@ +#pragma once + +#include "state.h" +#include +#include + +class Gui { +public: + Gui(DemoState *state) : + perf_open(false), + state(state) + { + this->load_style(cpptoml::parse_file(state->config->stylepath)); + } + + void render(); + + bool perf_open = false; + bool project_overlay_open = true; + + bool imgui_demo_open = false; + +private: + DemoState *state; + + void render_project_overlay(); + + void render_menubar(); + void render_mmb_file(); + void render_mmb_view(); + void render_mmb_debug(); + + void load_style(std::shared_ptr style); +}; + diff --git a/uistyles/basic.toml b/uistyles/basic.toml new file mode 100644 index 0000000..b2d882a --- /dev/null +++ b/uistyles/basic.toml @@ -0,0 +1 @@ +alpha=0.95 \ No newline at end of file