diff --git a/framework/imgui/CMakeLists.txt b/framework/imgui/CMakeLists.txt index c2a7a3e..ce725df 100644 --- a/framework/imgui/CMakeLists.txt +++ b/framework/imgui/CMakeLists.txt @@ -7,6 +7,10 @@ project(imgui_lib CXX) add_library(imgui_service ./src/mm/services/imgui_s.hpp ./src/mm/services/imgui_s.cpp + + # sneak + ./src/mm/services/imgui_menu_bar.hpp + ./src/mm/services/imgui_menu_bar.cpp ) target_include_directories(imgui_service PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src") diff --git a/framework/imgui/src/mm/services/imgui_menu_bar.cpp b/framework/imgui/src/mm/services/imgui_menu_bar.cpp new file mode 100644 index 0000000..6061d97 --- /dev/null +++ b/framework/imgui/src/mm/services/imgui_menu_bar.cpp @@ -0,0 +1,98 @@ +#include "./imgui_menu_bar.hpp" + +#include +#include + +#include + +#include + +#include +#define LOG_CRIT(...) __LOG_CRIT( "ImGuiMenuBar", __VA_ARGS__) +#define LOG_ERROR(...) __LOG_ERROR("ImGuiMenuBar", __VA_ARGS__) +#define LOG_WARN(...) __LOG_WARN( "ImGuiMenuBar", __VA_ARGS__) +#define LOG_INFO(...) __LOG_INFO( "ImGuiMenuBar", __VA_ARGS__) +#define LOG_DEBUG(...) __LOG_DEBUG("ImGuiMenuBar", __VA_ARGS__) +#define LOG_TRACE(...) __LOG_TRACE("ImGuiMenuBar", __VA_ARGS__) + +namespace MM::Services { + + bool ImGuiMenuBar::enable(Engine& engine) { + MM::Logger::initSectionLogger("ImGuiMenuBar"); + + auto* sdl_ss = engine.tryService(); + if (sdl_ss) { + _event_handle = sdl_ss->addEventHandler([this](const SDL_Event& e) -> bool { + if (e.type == SDL_KEYDOWN && !e.key.repeat && e.key.keysym.sym == toggle_key) { + show_menu_bar = !show_menu_bar; + } + return false; // invis + }); + } else { + LOG_WARN("no SDLService, skipping toggle hotkey"); + } + + return true; + } + + void ImGuiMenuBar::disable(Engine& engine) { + if (_event_handle) { + auto* sdl_ss = engine.tryService(); + sdl_ss->removeEventHandler(_event_handle); + _event_handle = nullptr; + } + } + + std::vector ImGuiMenuBar::registerUpdates(void) { + using namespace entt::literals; + return { + { + "ImGuiMenuBar::render"_hs, + "ImGuiMenuBar::render", + [this](Engine& e){ renderImGui(e); } + } + }; + } + + void ImGuiMenuBar::renderImGui(Engine& engine) { + if (show_menu_bar && ImGui::BeginMainMenuBar()) { + + // TODO: better solution? + std::unordered_set done; + + // we dont check for errors in section_order + for (const auto& section_key : section_order) { + if (menu_tree.count(section_key)) { + renderSection(engine, section_key, menu_tree[section_key]); + + done.emplace(section_key); + } + } + + for (auto& [section_key, section_data] : menu_tree) { + if (done.count(section_key)) { + continue; + } + + renderSection(engine, section_key, section_data); + + done.emplace(section_key); // we dont need this + } + + + ImGui::Text("%.1fFPS", ImGui::GetIO().Framerate); + ImGui::EndMainMenuBar(); + } + } + + void ImGuiMenuBar::renderSection(Engine& engine, const std::string& section_key, section_t& section) { + if (ImGui::BeginMenu(section_key.c_str())) { + for (auto& item : section) { + item.second(engine); + } + ImGui::EndMenu(); + } + } + +} // namespace MM::Services + diff --git a/framework/imgui/src/mm/services/imgui_menu_bar.hpp b/framework/imgui/src/mm/services/imgui_menu_bar.hpp new file mode 100644 index 0000000..e0efa61 --- /dev/null +++ b/framework/imgui/src/mm/services/imgui_menu_bar.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include +#include +#include + +namespace MM::Services { + + class ImGuiMenuBar : public Service { + public: + const char* name(void) override { return "ImGuiMenuBar"; } + + bool enable(Engine& engine) override; + void disable(Engine& engine) override; + + std::vector registerUpdates(void) override; + + public: + bool show_menu_bar = true; + + SDL_Keycode toggle_key = SDLK_F2; + + using menu_item_callback_t = std::function; + + using section_t = std::map; + + // menu tree + // section -> section_t -> menu_item_t + // section is stable id key + // menus contain stable id keys + std::map menu_tree; + + std::vector section_order { + "Engine", + }; + + private: + MM::Services::SDLService::EventHandlerHandle _event_handle = nullptr; + + private: + void renderImGui(Engine& engine); + + void renderSection(Engine& engine, const std::string& section_key, section_t& section); + }; + +} // namespace MM::Services +