selection_menu: Move it to it's dedicated class
This commit is contained in:
@@ -72,6 +72,7 @@ set(SRC_CXX_FILES "./src/main.cpp"
|
|||||||
"./src/render.cpp"
|
"./src/render.cpp"
|
||||||
"./src/control_menu.cpp"
|
"./src/control_menu.cpp"
|
||||||
"./src/settings_menu.cpp"
|
"./src/settings_menu.cpp"
|
||||||
|
"./src/selection_menu.cpp"
|
||||||
"${rlImGui_SOURCE_DIR}/rlImGui.cpp"
|
"${rlImGui_SOURCE_DIR}/rlImGui.cpp"
|
||||||
"${imgui_SOURCE_DIR}/imgui.cpp"
|
"${imgui_SOURCE_DIR}/imgui.cpp"
|
||||||
"${imgui_SOURCE_DIR}/imgui_draw.cpp"
|
"${imgui_SOURCE_DIR}/imgui_draw.cpp"
|
||||||
|
|||||||
@@ -18,12 +18,14 @@ class Render;
|
|||||||
|
|
||||||
namespace gol {
|
namespace gol {
|
||||||
class SettingsMenu;
|
class SettingsMenu;
|
||||||
|
class SelectionMenu;
|
||||||
|
|
||||||
typedef struct ctx {
|
typedef struct ctx {
|
||||||
std::shared_ptr<World> world = nullptr;
|
std::shared_ptr<World> world = nullptr;
|
||||||
std::shared_ptr<Rules> rules = nullptr;
|
std::shared_ptr<Rules> rules = nullptr;
|
||||||
std::shared_ptr<Render> render = nullptr;
|
std::shared_ptr<Render> render = nullptr;
|
||||||
std::shared_ptr<SettingsMenu> settings_menu = nullptr;
|
std::shared_ptr<SettingsMenu> settings_menu = nullptr;
|
||||||
|
std::shared_ptr<SelectionMenu> selection_menu = nullptr;
|
||||||
nlohmann::json config_json;
|
nlohmann::json config_json;
|
||||||
} ctx;
|
} ctx;
|
||||||
|
|
||||||
|
|||||||
38
includes/selection_menu.hpp
Normal file
38
includes/selection_menu.hpp
Normal file
@@ -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 <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <raylib.h>
|
||||||
|
#include <rlImGui.h>
|
||||||
|
|
||||||
|
#include <context.hpp>
|
||||||
|
|
||||||
|
namespace gol {
|
||||||
|
|
||||||
|
class SelectionMenu {
|
||||||
|
public:
|
||||||
|
SelectionMenu(std::shared_ptr<ctx> context);
|
||||||
|
~SelectionMenu();
|
||||||
|
void update();
|
||||||
|
void display();
|
||||||
|
void setSelection(std::vector<uint32_t> selection);
|
||||||
|
void open();
|
||||||
|
private:
|
||||||
|
std::shared_ptr<ctx> context_;
|
||||||
|
RenderTexture2D selectionTexture_;
|
||||||
|
std::vector<uint32_t> sel_data_ = {};
|
||||||
|
bool sel_ctrl_ = false;
|
||||||
|
char patern_name_[255];
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gol
|
||||||
86
src/main.cpp
86
src/main.cpp
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <filesystem>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
@@ -23,6 +22,7 @@
|
|||||||
#include <context.hpp>
|
#include <context.hpp>
|
||||||
#include <control_menu.hpp>
|
#include <control_menu.hpp>
|
||||||
#include <settings_menu.hpp>
|
#include <settings_menu.hpp>
|
||||||
|
#include <selection_menu.hpp>
|
||||||
|
|
||||||
Vector2 snapToGrid(Vector2 screen, int cell_size) {
|
Vector2 snapToGrid(Vector2 screen, int cell_size) {
|
||||||
return {static_cast<float>(round(screen.x / cell_size) * cell_size),
|
return {static_cast<float>(round(screen.x / cell_size) * cell_size),
|
||||||
@@ -96,15 +96,13 @@ int main(int ac, char **av) {
|
|||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
|
|
||||||
rlImGuiSetup(context->config_json["dark_theme"]);
|
rlImGuiSetup(context->config_json["dark_theme"]);
|
||||||
// Selection window
|
|
||||||
|
|
||||||
RenderTexture2D selectionTexture = LoadRenderTexture(200, 200);
|
|
||||||
|
|
||||||
// Initialize objects
|
// Initialize objects
|
||||||
context->world = std::make_shared<World>(context);
|
context->world = std::make_shared<World>(context);
|
||||||
context->rules = std::make_shared<Rules>();
|
context->rules = std::make_shared<Rules>();
|
||||||
context->settings_menu = std::make_shared<gol::SettingsMenu>(context);
|
context->settings_menu = std::make_shared<gol::SettingsMenu>(context);
|
||||||
context->render = std::make_shared<Render>(context->settings_menu->getCellSize());
|
context->render = std::make_shared<Render>(context->settings_menu->getCellSize());
|
||||||
|
context->selection_menu = std::make_shared<gol::SelectionMenu>(context);
|
||||||
|
|
||||||
// Imgui control menu
|
// Imgui control menu
|
||||||
gol::ControlMenu control_menu(context);
|
gol::ControlMenu control_menu(context);
|
||||||
@@ -117,11 +115,6 @@ int main(int ac, char **av) {
|
|||||||
// Selection window
|
// Selection window
|
||||||
Vector2 sel_pos = {0., 0.};
|
Vector2 sel_pos = {0., 0.};
|
||||||
bool selecting = false;
|
bool selecting = false;
|
||||||
std::vector<uint32_t> sel_data = {};
|
|
||||||
bool sel_ctrl = false;
|
|
||||||
char patern_name[255];
|
|
||||||
patern_name[0] = '\0';
|
|
||||||
std::string sel_txt_input_hint("patern name");
|
|
||||||
|
|
||||||
// Setups
|
// Setups
|
||||||
context->rules->setup(context->world);
|
context->rules->setup(context->world);
|
||||||
@@ -165,14 +158,12 @@ int main(int ac, char **av) {
|
|||||||
};
|
};
|
||||||
// Ensure there is at least one cell selected
|
// Ensure there is at least one cell selected
|
||||||
if (!(sel_size.x == 0 || sel_size.y == 0)) {
|
if (!(sel_size.x == 0 || sel_size.y == 0)) {
|
||||||
sel_data = std::move(context->world->getSelection(orig, sel_size));
|
context->selection_menu->setSelection(context->world->getSelection(orig, sel_size));
|
||||||
sel_ctrl = true;
|
context->selection_menu->open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!sel_ctrl) {
|
context->selection_menu->update();
|
||||||
patern_name[0] = '\0';
|
|
||||||
}
|
|
||||||
context->settings_menu->update();
|
context->settings_menu->update();
|
||||||
|
|
||||||
// Accumulate time and update simulation at the adjusted speed
|
// Accumulate time and update simulation at the adjusted speed
|
||||||
@@ -210,70 +201,7 @@ int main(int ac, char **av) {
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
context->settings_menu->display();
|
context->settings_menu->display();
|
||||||
if (sel_ctrl) {
|
context->selection_menu->display();
|
||||||
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();
|
|
||||||
}
|
|
||||||
// End ImGui frame
|
// End ImGui frame
|
||||||
rlImGuiEnd();
|
rlImGuiEnd();
|
||||||
EndDrawing();
|
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.open(config_file_name, std::ios::out | std::ios::trunc);
|
||||||
config_file << context->config_json.dump(2);
|
config_file << context->config_json.dump(2);
|
||||||
config_file.close();
|
config_file.close();
|
||||||
// Cleanup Selection texture
|
|
||||||
UnloadRenderTexture(selectionTexture);
|
|
||||||
rlImGuiShutdown();
|
rlImGuiShutdown();
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
109
src/selection_menu.cpp
Normal file
109
src/selection_menu.cpp
Normal file
@@ -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 <unistd.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include <selection_menu.hpp>
|
||||||
|
|
||||||
|
namespace gol {
|
||||||
|
|
||||||
|
SelectionMenu::SelectionMenu(std::shared_ptr<ctx> 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<uint32_t> 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
|
||||||
Reference in New Issue
Block a user