diff options
author | rtk0c <[email protected]> | 2025-05-17 20:28:55 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2025-05-17 20:29:03 -0700 |
commit | 81e957ef919709c0cf9f0a82e818227ea545e405 (patch) | |
tree | d588cdee6157a03b4da8e745d3c00821cf0c4374 /src | |
parent | 5f4a323ae13243be2d8dfcb8cf080f04d08ebd1e (diff) |
Moar interactive
Popup for changing sandbox params, and slightly cleaner code?
Diffstat (limited to 'src')
-rw-r--r-- | src/ui.cpp | 90 |
1 files changed, 64 insertions, 26 deletions
@@ -18,34 +18,76 @@ struct ImRect { ImVec2 bottom_right; }; -struct SandboxCfg { - int width = 40, height = 100; - float tile_size = 4.0f; +/// Helpers for displaying and coordinate space tracking of the sandbox image display. +struct SandboxDisplay { + float tile_size; + int sandbox_width = 40; + int sandbox_height = 100; - ImVec2 tr_sandbox2screen(ImVec2 origin, Pt pt) const { + ImVec2 size_screenspace; + ImVec2 origin; + + SandboxDisplay(float tile_size, const Sandbox& sb) + : tile_size(tile_size) + , sandbox_width{ sb.width } + , sandbox_height{ sb.height } + , size_screenspace(sandbox_width * tile_size, sandbox_height * tile_size) {} + + ImVec2 tr_sandbox2screen(Pt pt) const { return ImVec2(origin.x + tile_size * pt.x, origin.y - tile_size * pt.y); } // Assuming inclusive-inclusive rectangle - ImRect tr_sandbox2screen(ImVec2 origin, Rect r) const { + ImRect tr_sandbox2screen(Rect r) const { return { ImVec2(origin.x + tile_size * r.bl.x, origin.y - tile_size * (r.tr.y + 1)), ImVec2(origin.x + tile_size * (r.tr.x + 1), origin.y - tile_size * r.bl.y), }; } - std::unique_ptr<Sandbox> make_sandbox() const { - return std::make_unique<Sandbox>(width, height); + void show_image(ImTextureID texid) { + auto img_topleft = ImGui::GetCursorScreenPos(); + ImGui::Image(texid, size_screenspace, ImVec2(0, 1), ImVec2(1, 0)); + // bottom-left corner of the sandbox, in screen space + origin = img_topleft; + origin.y += size_screenspace.y; } }; void ShowEverything() { - ImGui::Begin("Sandbox"); + ImGui::Begin("Options"); - static SandboxCfg cfg; - static std::unique_ptr<Sandbox> sandbox = cfg.make_sandbox(); + static float tile_size = 4.0f; + static std::unique_ptr<Sandbox> sandbox = std::make_unique<Sandbox>(40, 100); static OglImage gl; + ImGui::InputFloat("Tile size", &tile_size); + + { + constexpr auto kModify = "Modify sandbox parameters"; + static int new_width, new_height; + + ImGui::Text("size = (%d, %d)", sandbox->width, sandbox->height); + if (ImGui::Button("Modify")) { + ImGui::OpenPopup(kModify); + new_width = sandbox->width; + new_height = sandbox->height; + } + if (ImGui::BeginPopup(kModify)) { + ImGui::InputInt("Sandbox width", &new_width); + ImGui::InputInt("Sandbox height", &new_height); + if (ImGui::Button("Confirm")) { + sandbox = std::make_unique<Sandbox>(new_width, new_height); + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button("Cancel")) { + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + } + static bool running = false; ImGui::Checkbox("Run", &running); static bool show_dirty_rect = true; @@ -59,32 +101,28 @@ void ShowEverything() { sandbox->simulate_step(); } - // TODO popup for changing these params? - // TODO migrate existing content - ImGui::InputInt("Sandbox width", &cfg.width); - ImGui::InputInt("Sandbox height", &cfg.height); - if (ImGui::Button("Recreate")) { - sandbox = cfg.make_sandbox(); - } - ImGui::SameLine(); if (ImGui::Button("Add sand")) { AddSand(*sandbox); } - ImVec2 img_size(cfg.tile_size * sandbox->width, cfg.tile_size * sandbox->height); - auto img_topleft = ImGui::GetCursorScreenPos(); + ImGui::End(); + + ImGui::Begin("Sandbox"); + // Update texture to the current state of the the sandbox. + // Do this every frame, because it's easier than trying to track when did the sandbox change, which may be caused by: + // - Initialization + // - Simulation step + // - User interaction (painting, save/load, etc.) gl.upload(reinterpret_cast<const char*>(sandbox->bitmap), sandbox->width, sandbox->height); - ImGui::Image(gl.as_imgui(), img_size, ImVec2(0, 1), ImVec2(1, 0)); - // bottom-left corner of the sandbox, in screen space - auto origin = img_topleft; - origin.y += img_size.y; + + SandboxDisplay dis(tile_size, *sandbox); + dis.show_image(gl.as_imgui()); if (show_dirty_rect) { auto dl = ImGui::GetWindowDrawList(); - auto [top_left, bottom_right] = cfg.tr_sandbox2screen(origin, sandbox->dirty_writeto); + auto [top_left, bottom_right] = dis.tr_sandbox2screen(sandbox->dirty_writeto); dl->AddRect(top_left, bottom_right, IM_COL32(255, 0, 0, 255)); } - ImGui::End(); ImGui::ShowDemoWindow(); |