From 98369600c3b80ae2d8922ee01bdbf9dd2a228fc5 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Wed, 17 Sep 2025 20:46:15 +0200 Subject: [PATCH] impr: Various rendering performance improvements --- .../include/hex/api/imhex_api/system.hpp | 2 +- .../include/hex/api/localization_manager.hpp | 1 - lib/libimhex/source/api/imhex_api.cpp | 9 ++-- .../source/api/localization_manager.cpp | 26 ++++++++--- .../source/ui/imgui_imhex_extensions.cpp | 6 ++- plugins/builtin/source/content/recent.cpp | 10 +++-- .../source/content/window_decoration.cpp | 43 +++++++++++-------- 7 files changed, 62 insertions(+), 35 deletions(-) diff --git a/lib/libimhex/include/hex/api/imhex_api/system.hpp b/lib/libimhex/include/hex/api/imhex_api/system.hpp index ac8012f6d..fc103eb0f 100644 --- a/lib/libimhex/include/hex/api/imhex_api/system.hpp +++ b/lib/libimhex/include/hex/api/imhex_api/system.hpp @@ -276,7 +276,7 @@ EXPORT_MODULE namespace hex { * @brief Gets the current ImHex version * @return ImHex version */ - SemanticVersion getImHexVersion(); + const SemanticVersion& getImHexVersion(); /** * @brief Gets the current git commit hash diff --git a/lib/libimhex/include/hex/api/localization_manager.hpp b/lib/libimhex/include/hex/api/localization_manager.hpp index e4a3b5cf8..98431be66 100644 --- a/lib/libimhex/include/hex/api/localization_manager.hpp +++ b/lib/libimhex/include/hex/api/localization_manager.hpp @@ -59,7 +59,6 @@ EXPORT_MODULE namespace hex { private: std::size_t m_entryHash; - std::string m_unlocalizedString; }; class LangConst { diff --git a/lib/libimhex/source/api/imhex_api.cpp b/lib/libimhex/source/api/imhex_api.cpp index 203b7ecd4..e56875545 100644 --- a/lib/libimhex/source/api/imhex_api.cpp +++ b/lib/libimhex/source/api/imhex_api.cpp @@ -899,12 +899,13 @@ namespace hex { return { { name, version } }; } - SemanticVersion getImHexVersion() { + const SemanticVersion& getImHexVersion() { #if defined(IMHEX_VERSION) static auto version = SemanticVersion(IMHEX_VERSION); return version; #else - return {}; + static auto version = SemanticVersion(); + return version; #endif } @@ -946,7 +947,9 @@ namespace hex { } bool isNightlyBuild() { - return getImHexVersion().nightly(); + const static bool isNightly = getImHexVersion().nightly(); + + return isNightly; } std::optional checkForUpdate() { diff --git a/lib/libimhex/source/api/localization_manager.cpp b/lib/libimhex/source/api/localization_manager.cpp index 58176feca..bc93f3a7e 100644 --- a/lib/libimhex/source/api/localization_manager.cpp +++ b/lib/libimhex/source/api/localization_manager.cpp @@ -171,11 +171,21 @@ namespace hex { } - Lang::Lang(const char *unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { } - Lang::Lang(const std::string &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { } - Lang::Lang(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash), m_unlocalizedString(localizedString.m_unlocalizedString) { } - Lang::Lang(const UnlocalizedString &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString.get())), m_unlocalizedString(unlocalizedString.get()) { } - Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { } + static AutoReset> s_unlocalizedNames; + + Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)) { + if (!s_unlocalizedNames->contains(m_entryHash)) [[unlikely]] { + s_unlocalizedNames->emplace(m_entryHash, unlocalizedString); + } + } + Lang::Lang(const char *unlocalizedString) : Lang(std::string_view(unlocalizedString)) { } + Lang::Lang(const std::string &unlocalizedString) : Lang(std::string_view(unlocalizedString)) { } + Lang::Lang(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash) { + if (!s_unlocalizedNames->contains(m_entryHash)) [[unlikely]] { + s_unlocalizedNames->emplace(m_entryHash, localizedString.m_unlocalizedString); + } + } + Lang::Lang(const UnlocalizedString &unlocalizedString) : Lang(unlocalizedString.get()) { } Lang::operator std::string() const { return get(); @@ -194,7 +204,11 @@ namespace hex { const auto it = lang.find(m_entryHash); if (it == lang.end()) { - return m_unlocalizedString.c_str(); + if (auto unlocalizedIt = s_unlocalizedNames->find(m_entryHash); unlocalizedIt != s_unlocalizedNames->end()) { + return unlocalizedIt->second.c_str(); + } else { + return ""; + } } else { return it->second.c_str(); } diff --git a/lib/libimhex/source/ui/imgui_imhex_extensions.cpp b/lib/libimhex/source/ui/imgui_imhex_extensions.cpp index 561bdd4a8..23f781eea 100644 --- a/lib/libimhex/source/ui/imgui_imhex_extensions.cpp +++ b/lib/libimhex/source/ui/imgui_imhex_extensions.cpp @@ -494,7 +494,7 @@ namespace ImGuiExt { ImGuiContext &g = *GImGui; const ImGuiStyle &style = g.Style; const ImGuiID id = window->GetID(label); - const ImVec2 text_size = CalcTextSize((std::string(label) + "\n " + std::string(description)).c_str(), nullptr, true); + const ImVec2 text_size = CalcTextSize(fmt::format("{}\n{}", label, description).c_str(), nullptr, true); const ImVec2 label_size = CalcTextSize(label, nullptr, true); ImVec2 pos = window->DC.CursorPos; @@ -1296,7 +1296,8 @@ namespace ImGuiExt { bool result = false; ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0F); - if (ImGui::BeginChild(fmt::format("{}##SubWindow", label).c_str(), size, ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeY | flags, hasMenuBar ? ImGuiWindowFlags_MenuBar : ImGuiWindowFlags_None)) { + ImGui::PushID("SubWindow"); + if (ImGui::BeginChild(label, size, ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeY | flags, hasMenuBar ? ImGuiWindowFlags_MenuBar : ImGuiWindowFlags_None)) { result = true; if (hasMenuBar && ImGui::BeginMenuBar()) { @@ -1329,6 +1330,7 @@ namespace ImGuiExt { void EndSubWindow() { ImGui::EndChild(); + ImGui::PopID(); } bool VSliderAngle(const char* label, const ImVec2& size, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags) { diff --git a/plugins/builtin/source/content/recent.cpp b/plugins/builtin/source/content/recent.cpp index d0d2e37b7..66c9441bd 100644 --- a/plugins/builtin/source/content/recent.cpp +++ b/plugins/builtin/source/content/recent.cpp @@ -320,19 +320,23 @@ namespace hex::plugin::builtin::recent { } } + ImGui::PushID(recentEntry.getHash()); + // Detect right click on recent provider - std::string popupID = fmt::format("RecentEntryMenu.{}", recentEntry.getHash()); + constexpr static auto PopupID = "RecentEntryMenu"; if (ImGui::IsMouseReleased(1) && ImGui::IsItemHovered()) { - ImGui::OpenPopup(popupID.c_str()); + ImGui::OpenPopup(PopupID); } - if (ImGui::BeginPopup(popupID.c_str())) { + if (ImGui::BeginPopup(PopupID)) { if (ImGui::MenuItemEx("hex.ui.common.remove"_lang, ICON_VS_REMOVE)) { shouldRemove = true; } ImGui::EndPopup(); } + ImGui::PopID(); + // Handle deletion from vector and on disk if (shouldRemove) { wolv::io::fs::remove(recentEntry.entryFilePath); diff --git a/plugins/builtin/source/content/window_decoration.cpp b/plugins/builtin/source/content/window_decoration.cpp index 61837e889..479cb33fb 100644 --- a/plugins/builtin/source/content/window_decoration.cpp +++ b/plugins/builtin/source/content/window_decoration.cpp @@ -26,6 +26,7 @@ #include #include +#include namespace hex::plugin::builtin { @@ -311,40 +312,44 @@ namespace hex::plugin::builtin { } } - bool isMenuItemVisible(const ContentRegistry::UserInterface::impl::MenuItem &menuItem) { - const auto lastFocusedView = View::getLastFocusedView(); - if (lastFocusedView == nullptr && menuItem.view != nullptr) { + bool isMenuItemVisible(const View *lastFocusedView, const ContentRegistry::UserInterface::impl::MenuItem &menuItem) { + if (!menuItem.view) + return true; + if (!lastFocusedView) return menuItem.shortcut.has(ShowOnWelcomeScreen); - } - - if (lastFocusedView != nullptr && menuItem.view != nullptr) { - if (menuItem.view != lastFocusedView && menuItem.view != lastFocusedView->getMenuItemInheritView()) { - return false; - } - } - - return true; + return menuItem.view == lastFocusedView || menuItem.view == lastFocusedView->getMenuItemInheritView(); } std::set getVisibleMainMenus() { - std::set result; - for (auto &[priority, menuItem] : ContentRegistry::UserInterface::impl::getMenuItems()) { - if (isMenuItemVisible(menuItem)) { - result.emplace(menuItem.unlocalizedNames.front()); - } - } + static std::set result; + const auto lastFocusedView = View::getLastFocusedView(); + static std::optional prevLastFocusedView; + if (lastFocusedView == prevLastFocusedView) + return result; + + prevLastFocusedView = lastFocusedView; + result.clear(); + + for (const auto &[priority, menuItem] : ContentRegistry::UserInterface::impl::getMenuItems()) { + if (result.contains(menuItem.unlocalizedNames.front())) [[likely]] + continue; + + if (isMenuItemVisible(lastFocusedView, menuItem)) + result.insert(menuItem.unlocalizedNames.front()); + } return result; } void populateMenu(const UnlocalizedString &menuName) { + const auto lastFocusedView = View::getLastFocusedView(); for (auto &[priority, menuItem] : ContentRegistry::UserInterface::impl::getMenuItems()) { if (!menuName.empty()) { if (menuItem.unlocalizedNames[0] != menuName) continue; } - if (!isMenuItemVisible(menuItem)) { + if (!isMenuItemVisible(lastFocusedView, menuItem)) { continue; }