lju/refactorize #2

Merged
lejulien merged 11 commits from lju/refactorize into main 2026-01-13 13:50:59 +00:00
5 changed files with 156 additions and 80 deletions
Showing only changes of commit f45c83dd77 - Show all commits

View File

@@ -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"

View File

@@ -18,12 +18,14 @@ class Render;
namespace gol {
class SettingsMenu;
class SelectionMenu;
typedef struct ctx {
std::shared_ptr<World> world = nullptr;
std::shared_ptr<Rules> rules = nullptr;
std::shared_ptr<Render> render = nullptr;
std::shared_ptr<SettingsMenu> settings_menu = nullptr;
std::shared_ptr<SelectionMenu> selection_menu = nullptr;
nlohmann::json config_json;
} ctx;

View 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

View File

@@ -8,7 +8,6 @@
#include <fstream>
#include <iostream>
#include <filesystem>
#include <unistd.h>
#include <nlohmann/json.hpp>
@@ -23,6 +22,7 @@
#include <context.hpp>
#include <control_menu.hpp>
#include <settings_menu.hpp>
#include <selection_menu.hpp>
Vector2 snapToGrid(Vector2 screen, int 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);
rlImGuiSetup(context->config_json["dark_theme"]);
// Selection window
RenderTexture2D selectionTexture = LoadRenderTexture(200, 200);
// Initialize objects
context->world = std::make_shared<World>(context);
context->rules = std::make_shared<Rules>();
context->settings_menu = std::make_shared<gol::SettingsMenu>(context);
context->render = std::make_shared<Render>(context->settings_menu->getCellSize());
context->selection_menu = std::make_shared<gol::SelectionMenu>(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<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
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;

109
src/selection_menu.cpp Normal file
View 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