diff --git a/includes/context.hpp b/includes/context.hpp index 40f8704..7e3c99d 100644 --- a/includes/context.hpp +++ b/includes/context.hpp @@ -33,6 +33,7 @@ typedef struct ctx { std::shared_ptr selection = nullptr; std::shared_ptr paterns_menu = nullptr; nlohmann::json config_json; + std::filesystem::path program_dir; } ctx; } // namespace gol diff --git a/includes/paterns_menu.hpp b/includes/paterns_menu.hpp index 9af513a..5518a25 100644 --- a/includes/paterns_menu.hpp +++ b/includes/paterns_menu.hpp @@ -8,17 +8,31 @@ #pragma once +#include +#include +#include +#include +#include + namespace gol { class PaternsMenu { public: - PaternsMenu() = default; + PaternsMenu(std::shared_ptr); ~PaternsMenu() = default; void Toogle(); bool isOpen(); void display(); + void refresh(); private: + bool loadPatern(std::string &path); bool is_open_ = false; + std::shared_ptr context_ = nullptr; + std::map paterns_paths_list_; + std::vector paterns_name_list_; + int patern_width_ = 0; + int patern_height_ = 0; + std::vector loaded_patern_; }; } // namespace gol diff --git a/src/main.cpp b/src/main.cpp index 6f7ebb2..6ecc7b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -82,6 +82,15 @@ int main(int ac, char **av) { context->config_json["fps"] = 800; } + // Get program directory + char path_buf[1024]; + ssize_t len = readlink("/proc/self/exe", path_buf, sizeof(path_buf)-1); + if (len == -1) { + std::cerr << "Failed to determine program directory" << std::endl; + return 1; + } + context->program_dir = std::filesystem::path(path_buf).parent_path(); + InitWindow(context->config_json["screen_width"], context->config_json["screen_height"], &av[0][2]); @@ -97,7 +106,7 @@ int main(int ac, char **av) { context->render = std::make_shared(context->settings_menu->getCellSize()); context->selection_menu = std::make_shared(context); context->selection = std::make_shared(context); - context->paterns_menu = std::make_shared(); + context->paterns_menu = std::make_shared(context); // Speed handling values float sim_speed = 1.0f; @@ -106,6 +115,7 @@ int main(int ac, char **av) { // Setups context->rules->setup(context->world); + context->paterns_menu->refresh(); // Diplay generations while (!WindowShouldClose()) { // Frames shinenigans diff --git a/src/paterns_menu.cpp b/src/paterns_menu.cpp index ad450fa..d90212c 100644 --- a/src/paterns_menu.cpp +++ b/src/paterns_menu.cpp @@ -6,30 +6,94 @@ * ------ */ -#include - #include #include #include +#include +#include +#include +#include +#include + namespace gol { -void PaternsMenu::Toogle() { - is_open_ = !is_open_; +PaternsMenu::PaternsMenu(std::shared_ptr ctx) : context_(ctx) {} + +void PaternsMenu::Toogle() { is_open_ = !is_open_; } + +bool PaternsMenu::isOpen() { return is_open_; } + +void PaternsMenu::refresh() { + paterns_name_list_.clear(); + paterns_paths_list_.clear(); + auto paterns_path = context_->program_dir / "paterns"; + if (std::filesystem::exists(paterns_path) && + std::filesystem::is_directory(paterns_path)) { + for (const auto &entry : + std::filesystem::directory_iterator(paterns_path)) { + if (!std::filesystem::is_directory(entry) && + entry.path().has_filename()) { + paterns_paths_list_[entry.path().filename()] = entry.path(); + paterns_name_list_.push_back(entry.path().filename()); + } + } + } } -bool PaternsMenu::isOpen() { - return is_open_; +bool PaternsMenu::loadPatern(std::string &path) { + std::ifstream file(path); + std::string file_data; + if (!file.is_open()) { + std::cerr << "Failure in opening patern : " << path << std::endl; + return false; + } + loaded_patern_.clear(); + try { + std::getline(file, file_data); + std::stringstream ss(file_data); + std::string width, height, data; + std::getline(ss, width, '|'); + std::getline(ss, height, '|'); + std::getline(ss, data, '|'); + patern_width_ = std::stoi(width); + patern_height_ = std::stoi(height); + for (int i = 0; i < patern_width_ * patern_height_; i++) { + loaded_patern_.push_back((data[i] == '1') ? 1 : 0); + } + } catch (std::exception &e) { + std::cerr << "Failure in loading patern : " << path << std::endl; + return 1; + } + return true; } void PaternsMenu::display() { if (is_open_) { - ImGuiWindowFlags paterns_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize; - ImGui::SetNextWindowSize(ImVec2(150, 200), ImGuiCond_Always); + ImGuiWindowFlags paterns_flags = + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize; + ImGui::SetNextWindowSize(ImVec2(200, 250), ImGuiCond_Always); ImGui::Begin("paterns", &is_open_, paterns_flags); - ImGui::Button("refresh"); + for (auto patern_name : paterns_name_list_) { + ImGui::PushID(patern_name.c_str()); + if (ImGui::Button(patern_name.c_str()) && + loadPatern(paterns_paths_list_[patern_name])) { + // TODO: If patern is loaded successfuly, start the preview in the + // editor + } + ImGui::PopID(); + ImGui::SameLine(ImGui::GetWindowWidth() - 57.); + std::string del_id = patern_name.c_str(); + del_id.append("_del"); + ImGui::PushID(del_id.c_str()); + if (ImGui::Button("delete")) { + std::filesystem::remove(paterns_paths_list_[patern_name]); + refresh(); + } + ImGui::PopID(); + } ImGui::End(); } } -} // namespace gol +} // namespace gol diff --git a/src/selection_menu.cpp b/src/selection_menu.cpp index de9f56d..8cbb881 100644 --- a/src/selection_menu.cpp +++ b/src/selection_menu.cpp @@ -12,6 +12,7 @@ #include #include +#include namespace gol { @@ -62,41 +63,38 @@ void SelectionMenu::display() { 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++; + // Create paterns dir if not present + std::filesystem::path paterns_dir = context_->program_dir / "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(); } + patern_file << std::flush; + patern_file.close(); + context_->paterns_menu->refresh(); } - sel_ctrl_ = false; } + sel_ctrl_ = false; } ImGui::SameLine(); if (ImGui::Button("Discard")) {