From f45c83dd7748725f0d5483766462284180571d5c Mon Sep 17 00:00:00 2001 From: lejulien Date: Tue, 13 Jan 2026 13:03:36 +0100 Subject: [PATCH] selection_menu: Move it to it's dedicated class --- CMakeLists.txt | 1 + includes/context.hpp | 2 + includes/selection_menu.hpp | 38 +++++++++++++ src/main.cpp | 86 ++-------------------------- src/selection_menu.cpp | 109 ++++++++++++++++++++++++++++++++++++ 5 files changed, 156 insertions(+), 80 deletions(-) create mode 100644 includes/selection_menu.hpp create mode 100644 src/selection_menu.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 77d5bf7..6cb9cc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,7 @@ set(SRC_CXX_FILES "./src/main.cpp" "./src/render.cpp" "./src/control_menu.cpp" "./src/settings_menu.cpp" + "./src/selection_menu.cpp" "${rlImGui_SOURCE_DIR}/rlImGui.cpp" "${imgui_SOURCE_DIR}/imgui.cpp" "${imgui_SOURCE_DIR}/imgui_draw.cpp" diff --git a/includes/context.hpp b/includes/context.hpp index 21fa3db..f025d49 100644 --- a/includes/context.hpp +++ b/includes/context.hpp @@ -18,12 +18,14 @@ class Render; namespace gol { class SettingsMenu; +class SelectionMenu; typedef struct ctx { std::shared_ptr world = nullptr; std::shared_ptr rules = nullptr; std::shared_ptr render = nullptr; std::shared_ptr settings_menu = nullptr; + std::shared_ptr selection_menu = nullptr; nlohmann::json config_json; } ctx; diff --git a/includes/selection_menu.hpp b/includes/selection_menu.hpp new file mode 100644 index 0000000..ccc9124 --- /dev/null +++ b/includes/selection_menu.hpp @@ -0,0 +1,38 @@ +/* +* File name: selection_menu.hpp +* Author: lejulien +* Date created: 13-01-2026 22:12:44 +// Date modified: 13-01-2026 22:18:58 +* ------ +*/ + +#pragma once + +#include +#include + +#include +#include +#include + +#include + +namespace gol { + +class SelectionMenu { +public: + SelectionMenu(std::shared_ptr context); + ~SelectionMenu(); + void update(); + void display(); + void setSelection(std::vector selection); + void open(); +private: + std::shared_ptr context_; + RenderTexture2D selectionTexture_; + std::vector sel_data_ = {}; + bool sel_ctrl_ = false; + char patern_name_[255]; +}; + +} // namespace gol diff --git a/src/main.cpp b/src/main.cpp index bf07e5b..4c68eed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -23,6 +22,7 @@ #include #include #include +#include Vector2 snapToGrid(Vector2 screen, int cell_size) { return {static_cast(round(screen.x / cell_size) * cell_size), @@ -96,15 +96,13 @@ int main(int ac, char **av) { SetTargetFPS(60); rlImGuiSetup(context->config_json["dark_theme"]); - // Selection window - - RenderTexture2D selectionTexture = LoadRenderTexture(200, 200); // Initialize objects context->world = std::make_shared(context); context->rules = std::make_shared(); context->settings_menu = std::make_shared(context); context->render = std::make_shared(context->settings_menu->getCellSize()); + context->selection_menu = std::make_shared(context); // Imgui control menu gol::ControlMenu control_menu(context); @@ -117,11 +115,6 @@ int main(int ac, char **av) { // Selection window Vector2 sel_pos = {0., 0.}; bool selecting = false; - std::vector sel_data = {}; - bool sel_ctrl = false; - char patern_name[255]; - patern_name[0] = '\0'; - std::string sel_txt_input_hint("patern name"); // Setups context->rules->setup(context->world); @@ -165,14 +158,12 @@ int main(int ac, char **av) { }; // Ensure there is at least one cell selected if (!(sel_size.x == 0 || sel_size.y == 0)) { - sel_data = std::move(context->world->getSelection(orig, sel_size)); - sel_ctrl = true; + context->selection_menu->setSelection(context->world->getSelection(orig, sel_size)); + context->selection_menu->open(); } } } - if (!sel_ctrl) { - patern_name[0] = '\0'; - } + context->selection_menu->update(); context->settings_menu->update(); // Accumulate time and update simulation at the adjusted speed @@ -210,70 +201,7 @@ int main(int ac, char **av) { ImGui::End(); } context->settings_menu->display(); - if (sel_ctrl) { - BeginTextureMode(selectionTexture); - ClearBackground(BLACK); - auto max_size = (sel_data[0] > sel_data[1]) ? sel_data[0] : sel_data[1]; - int fitted_width = 200 / max_size; - auto sel_it = sel_data.begin(); - sel_it += 2; // skip dimensions - for (int j = 0; j < sel_data[1]; j++) { - for (int i = 0; i < sel_data[0]; i++) { - if (*sel_it == 1) { - DrawRectangle(i * fitted_width, (sel_data[1] -j-1) * fitted_width, fitted_width, fitted_width, WHITE); - } - sel_it++; - } - } - EndTextureMode(); - ImGuiWindowFlags settings_flags = - ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize; - ImGui::Begin("Selection", &sel_ctrl, settings_flags); - rlImGuiImageSize(&selectionTexture.texture, 200, 200); - ImGui::InputText(sel_txt_input_hint.c_str(), patern_name, 255); - if (ImGui::Button("Save")) { - char path_buf[1024]; - ssize_t len = readlink("/proc/self/exe", path_buf, sizeof(path_buf)-1); - if (len != -1) { - // Create paterns dir if not present - std::filesystem::path paterns_dir = std::filesystem::path(path_buf).parent_path() / "paterns"; - if (!std::filesystem::exists(paterns_dir) && !std::filesystem::create_directory(paterns_dir)) { - std::cerr << "Failed to create paterns directory" << std::endl; - } else { // Could be optimized by early returning in a function - std::ofstream patern_file; - paterns_dir += '/'; - paterns_dir += patern_name; - patern_file.open(paterns_dir); - if (!patern_file) { - std::cerr << "Failed to create the patern file" << std::endl; - } else { - auto sel_it = sel_data.begin(); - sel_it += 2; // skip dimensions - patern_file << sel_data[0]; - patern_file << "|"; // Separator needed to split as ascii values - patern_file << sel_data[1]; - patern_file << "|"; // Separator needed to split as ascii values - for (int j = 0; j < sel_data[1]; j++) { - for (int i = 0; i < sel_data[0]; i++) { - patern_file << std::to_string(*sel_it); - if (*sel_it == 1) { - } - sel_it++; - } - } - patern_file << std::flush; - patern_file.close(); - } - } - sel_ctrl = false; - } - } - ImGui::SameLine(); - if (ImGui::Button("Discard")) { - sel_ctrl = false; - } - ImGui::End(); - } + context->selection_menu->display(); // End ImGui frame rlImGuiEnd(); EndDrawing(); @@ -281,8 +209,6 @@ int main(int ac, char **av) { config_file.open(config_file_name, std::ios::out | std::ios::trunc); config_file << context->config_json.dump(2); config_file.close(); - // Cleanup Selection texture - UnloadRenderTexture(selectionTexture); rlImGuiShutdown(); CloseWindow(); return 0; diff --git a/src/selection_menu.cpp b/src/selection_menu.cpp new file mode 100644 index 0000000..de9f56d --- /dev/null +++ b/src/selection_menu.cpp @@ -0,0 +1,109 @@ +/* +* File name: selection_menu.cpp +* Author: lejulien +* Date created: 13-01-2026 22:12:44 +// Date modified: 13-01-2026 22:18:58 +* ------ +*/ + +#include +#include +#include +#include + +#include + +namespace gol { + +SelectionMenu::SelectionMenu(std::shared_ptr context): context_(context) { + selectionTexture_ = LoadRenderTexture(200, 200); + patern_name_[0] = '\0'; + +} + +SelectionMenu::~SelectionMenu() { + UnloadRenderTexture(selectionTexture_); +} + +void SelectionMenu::update() { + if (!sel_ctrl_) { + patern_name_[0] = '\0'; + } +} + +void SelectionMenu::open() { + sel_ctrl_ = true; +} + +void SelectionMenu::setSelection(std::vector selection) { + sel_data_ = selection; +} + +void SelectionMenu::display() { + if (sel_ctrl_) { + BeginTextureMode(selectionTexture_); + ClearBackground(BLACK); + auto max_size = (sel_data_[0] > sel_data_[1]) ? sel_data_[0] : sel_data_[1]; + int fitted_width = 200 / max_size; + auto sel_it = sel_data_.begin(); + sel_it += 2; // skip dimensions + for (int j = 0; j < sel_data_[1]; j++) { + for (int i = 0; i < sel_data_[0]; i++) { + if (*sel_it == 1) { + DrawRectangle(i * fitted_width, (sel_data_[1] -j-1) * fitted_width, fitted_width, fitted_width, WHITE); + } + sel_it++; + } + } + EndTextureMode(); + ImGuiWindowFlags settings_flags = + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize; + ImGui::Begin("Selection", &sel_ctrl_, settings_flags); + rlImGuiImageSize(&selectionTexture_.texture, 200, 200); + ImGui::InputText("patern_name", patern_name_, 255); + if (ImGui::Button("Save")) { + char path_buf[1024]; + ssize_t len = readlink("/proc/self/exe", path_buf, sizeof(path_buf)-1); + if (len != -1) { + // Create paterns dir if not present + std::filesystem::path paterns_dir = std::filesystem::path(path_buf).parent_path() / "paterns"; + if (!std::filesystem::exists(paterns_dir) && !std::filesystem::create_directory(paterns_dir)) { + std::cerr << "Failed to create paterns directory" << std::endl; + } else { // Could be optimized by early returning in a function + std::ofstream patern_file; + paterns_dir += '/'; + paterns_dir += patern_name_; + patern_file.open(paterns_dir); + if (!patern_file) { + std::cerr << "Failed to create the patern file" << std::endl; + } else { + auto sel_it = sel_data_.begin(); + sel_it += 2; // skip dimensions + patern_file << sel_data_[0]; + patern_file << "|"; // Separator needed to split as ascii values + patern_file << sel_data_[1]; + patern_file << "|"; // Separator needed to split as ascii values + for (int j = 0; j < sel_data_[1]; j++) { + for (int i = 0; i < sel_data_[0]; i++) { + patern_file << std::to_string(*sel_it); + if (*sel_it == 1) { + } + sel_it++; + } + } + patern_file << std::flush; + patern_file.close(); + } + } + sel_ctrl_ = false; + } + } + ImGui::SameLine(); + if (ImGui::Button("Discard")) { + sel_ctrl_ = false; + } + ImGui::End(); + } +} + +} // namespace gol