diff --git a/CMakeLists.txt b/CMakeLists.txt index e3426c4..83c4b83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,5 +2,7 @@ cmake_minimum_required(VERSION 3.23) project(MHache VERSION 0.1) +set (CMAKE_CXX_STANDARD 17) + add_subdirectory(dependencies) add_subdirectory(src) diff --git a/fonts/Sweet16mono.ttf b/fonts/Sweet16mono.ttf new file mode 100644 index 0000000..01024fd Binary files /dev/null and b/fonts/Sweet16mono.ttf differ diff --git a/include/mhache_armor.h b/include/mhache_armor.h index 656016f..41582e3 100644 --- a/include/mhache_armor.h +++ b/include/mhache_armor.h @@ -4,50 +4,123 @@ #include #include #include +#include +#include #include +#include #include "mhache_skill.h" - class MHacheSkill; +template +struct PtrLessComparator { + bool operator () (const P* a, const P* b) const + { + if (!a) return true; + if (!b) return false; + return *a < *b; + } +}; + class MHacheArmor { -private: - struct Skill { - MHacheSkill* _skill; - unsigned char _level; +public: + typedef enum: unsigned char { + FIRE, + WATER, + THUNDER, + ICE, + DRAGON, + count + } ResistanceElement; + + class Part { + public: + typedef enum : unsigned char { + HEAD, + CHEST, + ARMS, + WAIST, + LEGS, + count + } Appellation; + + private: + friend class MHacheArmor; + + Appellation _label; + + std::string _name; + std::vector _slots; + + std::map> _skills; + + const MHacheArmor* _armor; + + Part() = default; + + public: + ~Part() = default; + + const std::string& name() const { return _name; } + const std::vector slots() const { return _slots; } + + // const std::set skills() const { return _skills; } + + Part& set_name(std::string&& name) + { + _name = std::forward(name); + return *this; + } + + Part& set_slots(std::vector&& slots) + { + _slots = std::forward>(slots); + return *this; + } + + Part& add_skill(const MHacheSkill* skill, unsigned char level) + { + if (skill && level > 0) + _skills.insert_or_assign(skill, level); + + return *this; + } }; - struct Piece { - std::string _name; - std::vector _slots; - std::vector _skills; - MHacheArmor* _armor; - }; - - std::string _name; - std::array _resistances; - - Piece _head; - Piece _chest; - Piece _arms; - Piece _waist; - Piece _legs; - private: - MHacheArmor() = default; - + std::string _name; + unsigned char _rarity; + unsigned short _defense; + std::array _resistances; + std::array _parts; + +private: + MHacheArmor() = delete; MHacheArmor(const MHacheArmor&) = delete; MHacheArmor(MHacheArmor&&) = delete; MHacheArmor& operator=(const MHacheArmor&) = delete; MHacheArmor& operator=(MHacheArmor&&) = delete; public: - ~MHacheArmor() = default; + MHacheArmor(const std::string& name, unsigned char rarity, unsigned short defense, std::array resistances) + : _name(name), _rarity(rarity), _defense(defense), _resistances(resistances), _parts({}) + {} + + ~MHacheArmor() = default; - bool operator < (const MHacheArmor&) const; - bool operator == (const MHacheArmor&) const; + bool operator < (const MHacheArmor& armor) const { return _name < armor._name; } + bool operator == (const MHacheArmor& armor) const { return _name == armor._name; } - const std::string& name() const; + const std::string& name() const { return _name; } + + const Part& part(Part::Appellation appellation) const { return _parts[appellation]; } + + Part& forge_part(Part::Appellation appellation) + { + _parts[appellation]._armor = this; + return _parts[appellation]; + } }; template<> @@ -59,4 +132,15 @@ struct std::hash } }; +/* +namespace std { +template<> +struct less<> +{ + bool operator ()(const MHacheArmor::Part::Skill& a, const MHacheArmor::Part::Skill& b) const { return a < b; } + bool operator ()(const MHacheArmor::Part::Skill& a, const std::string& b) const { return a < b; } + bool operator ()(const std::string& b, const MHacheArmor::Part::Skill& a) const { return a < b; } +}; +}*/ + #endif diff --git a/include/mhache_color.h b/include/mhache_color.h index 65177e6..5f37c87 100644 --- a/include/mhache_color.h +++ b/include/mhache_color.h @@ -26,9 +26,9 @@ private: static std::unordered_map _colors; public: - MHacheColor(int r, int g, int b, int a = 255); - MHacheColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255u); - MHacheColor(float r, float g, float b, float a = 1.0f); + constexpr MHacheColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255u); + constexpr MHacheColor(int r, int g, int b, int a = 255); + constexpr MHacheColor(float r, float g, float b, float a = 1.0f); MHacheColor(const MHacheColor&) = default; MHacheColor(MHacheColor&&) = default; diff --git a/include/mhache_factory.h b/include/mhache_factory.h index dc99540..bc948e2 100644 --- a/include/mhache_factory.h +++ b/include/mhache_factory.h @@ -7,13 +7,67 @@ #include #include "mhache_skill.h" +#include "mhache_armor.h" class MHacheFactory { private: std::set _skills; + std::set _armors; + MHacheFactory() = default; - toml::table parse_root_table(const std::filesystem::path&); + bool parse_root_table(const std::filesystem::path&, toml::table&); + + template + static bool deserialize_table_node(const toml::table& table, std::string_view node_name, T& node_value) + { + const auto node = table.get_as(node_name); + + if (node) { + node_value = node->template ref(); + return true; + } + + return false; + } + + template + static bool deserialize_table_node(const toml::table& table, std::string_view node_name, + std::vector& listof_values) + { + const auto array = table.get_as(node_name); + + if (array) { + listof_values.reserve(array->size()); + + for (const auto& entry: *array) { + const auto wrap = entry.as(); + + if (wrap) + listof_values.push_back(wrap->template ref()); + } + } + + return !(listof_values.empty()); + } + + template + static bool deserialize_table_node(const toml::table& table, std::string_view node_name, + std::array& listof_values) + { + const auto array = table.get_as(node_name); + + if (array && array->size() == Length) { + for (size_t i = 0; i < Length; ++i) { + const auto wrap = array->get_as(i); + + if (wrap) + listof_values[i] = wrap->template ref(); + } + } + + return !(listof_values.empty()); + } public: ~MHacheFactory() = default; @@ -21,6 +75,7 @@ public: static MHacheFactory& singleton(); bool load_skills(const std::filesystem::path&); + bool load_armors(const std::filesystem::path&); inline const std::set& available_skills() const { return _skills; } }; diff --git a/include/mhache_skill.h b/include/mhache_skill.h index 67f4571..b2038c5 100644 --- a/include/mhache_skill.h +++ b/include/mhache_skill.h @@ -21,7 +21,6 @@ private: MHacheSkill& operator=(MHacheSkill&&) = delete; public: - inline MHacheSkill(const std::string& name, const std::string& description, const MHacheColor* color, const std::vector& levels) : _name(name), _description(description), _color(color), _levels(levels) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f1114a9..27d001c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,19 +3,15 @@ find_package(OpenGL REQUIRED) add_executable( ${PROJECT_NAME} main.cpp - # mhache_object.cpp mhache_color.cpp mhache_skill.cpp mhache_armor.cpp mhache_factory.cpp - # mhache_tomltools.cpp - # mhache_researcher.cpp mhache_window.cpp ) target_compile_options( ${PROJECT_NAME} PUBLIC - -std=c++17 -Wall -Wextra -pedantic-errors diff --git a/src/mhache_armor.cpp b/src/mhache_armor.cpp index 7829e43..0bfec5e 100644 --- a/src/mhache_armor.cpp +++ b/src/mhache_armor.cpp @@ -1,19 +1 @@ #include "mhache_armor.h" - -bool -MHacheArmor::operator < (const MHacheArmor& armor) const -{ - return _name < armor._name; -} - -bool -MHacheArmor::operator == (const MHacheArmor& armor) const -{ - return _name == armor._name; -} - -const std::string& -MHacheArmor::name() const -{ - return _name; -} diff --git a/src/mhache_color.cpp b/src/mhache_color.cpp index d7e03fd..23f3cfb 100644 --- a/src/mhache_color.cpp +++ b/src/mhache_color.cpp @@ -1,7 +1,11 @@ #include "mhache_color.h" #include -MHacheColor::MHacheColor(int r, int g, int b, int a /* = 255 */) +constexpr MHacheColor::MHacheColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a) + : _rgba({ r, g, b, a }) +{} + +constexpr MHacheColor::MHacheColor(int r, int g, int b, int a /* = 255 */) : MHacheColor( static_cast(r), static_cast(g), @@ -9,11 +13,7 @@ MHacheColor::MHacheColor(int r, int g, int b, int a /* = 255 */) static_cast(a)) {} -MHacheColor::MHacheColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a) - : _rgba({ r, g, b, a }) -{} - -MHacheColor::MHacheColor(float r, float g, float b, float a) +constexpr MHacheColor::MHacheColor(float r, float g, float b, float a) : MHacheColor(touccolor(r), touccolor(g), touccolor(b), touccolor(a)) {} diff --git a/src/mhache_factory.cpp b/src/mhache_factory.cpp index b8163b5..c88dec5 100644 --- a/src/mhache_factory.cpp +++ b/src/mhache_factory.cpp @@ -12,65 +12,125 @@ MHacheFactory::singleton() return factory; } -toml::table -MHacheFactory::parse_root_table(const std::filesystem::path& tomlfile) +bool +MHacheFactory::parse_root_table(const std::filesystem::path& tomlfile, toml::table& root) { auto result = toml::parse_file(tomlfile.u8string()); + if (!result) { std::cerr << "Parsing of TOML file << " << tomlfile << " failed." << std::endl; std::cerr << "-> " << result.error().description() << std::endl; + return false; } - return result.table(); + root = std::move(result.table()); + return true; } bool MHacheFactory::load_skills(const std::filesystem::path& tomlfile) { - const toml::table root = parse_root_table(tomlfile); - if (root.empty()) return false; + toml::table skills; + { + toml::table root; + if (!parse_root_table(tomlfile, root) || root.empty()) + return false; - const toml::table* skills = root["skills"].as_table(); - if (!skills) return false; + if (!deserialize_table_node(root, "skills", skills)) + return false; + } - for (const auto& sentry: *skills) { - const auto stable = sentry.second.as_table(); - if (!stable) continue; - - const std::string name = std::string(sentry.first.str()); - if (name.empty()) continue; + for (const auto& skill_entry: skills) { + const auto p_skill = skill_entry.second.as_table(); + if (!p_skill) continue; + + const auto& skill = *p_skill; MHacheColor* color = nullptr; { - const auto scolor = stable->get_as("color"); - if (scolor) color = MHacheColor::get_color(scolor->get()); + std::string skill_color; + if (!deserialize_table_node(skill, "color", skill_color)) + continue; + + color = MHacheColor::get_color(skill_color); if (!color) continue; } std::string description; - { - const auto sdescription = stable->get_as("description"); - if (!sdescription) continue; - description = sdescription->get(); - } + if (!deserialize_table_node(skill, "description", description) || description.empty()) + continue; std::vector levels; - { - const auto slevels = stable->get_as("levels"); - if (!slevels) continue; + if (!deserialize_table_node(skill, "levels", levels) || levels.empty()) + continue; - levels.reserve(slevels->size()); + std::string name = std::string(skill_entry.first.str()); + if (name.empty()) continue; - for (const auto& slevel: *slevels) { - if (!slevel.is_string()) continue; - levels.push_back(slevel.as_string()->get()); - } - - if (levels.empty()) continue; - } - - _skills.emplace(name, description, color, levels); + _skills.emplace(std::move(name), std::move(description), color, std::move(levels)); } - return !_skills.empty(); + return !(_skills.empty()); +} + +bool +MHacheFactory::load_armors(const std::filesystem::path& tomlfile) +{ + toml::table sets; + { + toml::table root; + if (!parse_root_table(tomlfile, root) || root.empty()) + return false; + + if (!deserialize_table_node(root, "sets", sets)) + return false; + } + + for (const auto& set_entry: sets) { + const auto p_set = set_entry.second.as_table(); + if (!p_set) continue; + + const auto& set = *p_set; + + const std::string name = std::string(set_entry.first.str()); + if (name.empty()) continue; + + int64_t rarity; + if (!deserialize_table_node(set, "rarity", rarity)) + return false; + + int64_t defense; + if (!deserialize_table_node(set, "defense", defense)) + return false; + + std::array resistances; + if (!deserialize_table_node(set, "resistances", resistances)) + return false; + + MHacheArmor armor(name, rarity, defense, resistances); + + static constexpr std::array appellations = + { + "head", "chest", "arms", "waist", "legs" + }; + + for (auto appellation: appellations) + { + toml::table part; + if (!deserialize_table_node(set, appellation, part)) + return false; + + + } + + // MHacheArmor armor() + + + /* + toml::table head; + deserialize_table_node(set, "head", head); + */ + } + + return !_armors.empty(); } diff --git a/src/mhache_window.cpp b/src/mhache_window.cpp index 6dd84a6..2f9af38 100644 --- a/src/mhache_window.cpp +++ b/src/mhache_window.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include "imgui.h" #include "imgui_impl_glfw.h" @@ -22,9 +22,11 @@ MHacheWindow::MHacheWindow(int width, int height) glfwSetErrorCallback(&MHacheWindow::callback_glfw_error); if (GLFW_TRUE == glfwInit()) { - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, _opengl_major_version); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, _opengl_minor_version); - glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, _opengl_major_version); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, _opengl_minor_version); + glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); _window = glfwCreateWindow(_width, _height, _title, nullptr, nullptr); @@ -41,6 +43,13 @@ MHacheWindow::MHacheWindow(int width, int height) ImGui::CreateContext(); ImGui_ImplGlfw_InitForOpenGL(_window, true); ImGui_ImplOpenGL3_Init(_GLSL_version); + + const std::filesystem::path filefont = "../../fonts/Sweet16mono.ttf"; + + if (std::filesystem::exists(filefont)) + ImGui::GetIO().Fonts->AddFontFromFileTTF(filefont.c_str(), 16); + else + ImGui::GetIO().Fonts->AddFontDefault(); } } @@ -107,11 +116,12 @@ void MHacheWindow::build_widgets() { ImGuiWindowFlags window_flags = 0; - window_flags |= ImGuiWindowFlags_NoBackground; - window_flags |= ImGuiWindowFlags_NoDecoration; window_flags |= ImGuiWindowFlags_MenuBar; window_flags |= ImGuiWindowFlags_NoSavedSettings; window_flags |= ImGuiWindowFlags_NoMove; + window_flags |= ImGuiWindowFlags_NoResize; + window_flags |= ImGuiWindowFlags_NoCollapse; + window_flags |= ImGuiWindowFlags_NoTitleBar; const ImGuiViewport* main_viewport = ImGui::GetMainViewport(); if (main_viewport) { @@ -141,8 +151,7 @@ MHacheWindow::build_widgets() ImGui::TextColored( ImVec4(rgba[0], rgba[1], rgba[2], rgba[3]), - "%s", - skill.name().c_str() + "%s", skill.name().c_str() ); if (ImGui::IsItemHovered()) { @@ -186,6 +195,9 @@ MHacheWindow::build_menu() void MHacheWindow::resize(int width, int height) { + _width = width; + _height = height; + if (!ready()) return; GLFWmonitor* monitor = glfwGetPrimaryMonitor(); @@ -194,20 +206,18 @@ MHacheWindow::resize(int width, int height) const GLFWvidmode* videomode = glfwGetVideoMode(monitor); if (!videomode) return; - _width = width; - _height = height; - glfwSetWindowPos(_window, (videomode->width - _width) * 0.5, (videomode->height - _height) * 0.5); - glfwSetWindowSize(_window, width, height); + glfwSetWindowSize(_window, _width, _height); } bool MHacheWindow::ready() { - return ( - !(SIGINT == _signal_status || SIGTERM == _signal_status || SIGABRT == _signal_status) - && _window && !glfwWindowShouldClose(_window) - ); + return SIGINT != _signal_status + && SIGTERM != _signal_status + && SIGABRT != _signal_status + && _window + && !glfwWindowShouldClose(_window); } void