From 2757075a10cb9c6ac95ec83259859473765c4732 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Mon, 8 Jul 2024 21:34:27 +0200 Subject: [PATCH] impr: Make highlight hovering more efficient --- lib/libimhex/include/hex/api/imhex_api.hpp | 2 +- lib/libimhex/include/hex/helpers/types.hpp | 4 ++++ .../include/content/views/view_hex_editor.hpp | 1 + .../source/content/views/view_hex_editor.cpp | 18 +++++++-------- .../content/views/view_pattern_data.cpp | 4 ++-- .../content/views/view_pattern_editor.cpp | 23 +++++++++---------- plugins/ui/include/ui/hex_editor.hpp | 5 ++++ plugins/ui/source/ui/hex_editor.cpp | 18 ++++++++++++--- 8 files changed, 48 insertions(+), 27 deletions(-) diff --git a/lib/libimhex/include/hex/api/imhex_api.hpp b/lib/libimhex/include/hex/api/imhex_api.hpp index d98a0175aa5bc..2ecd25c1b0394 100644 --- a/lib/libimhex/include/hex/api/imhex_api.hpp +++ b/lib/libimhex/include/hex/api/imhex_api.hpp @@ -75,7 +75,7 @@ namespace hex { namespace impl { using HighlightingFunction = std::function(u64, const u8*, size_t, bool)>; - using HoveringFunction = std::function; + using HoveringFunction = std::function(const prv::Provider *, u64, size_t)>; const std::map& getBackgroundHighlights(); const std::map& getBackgroundHighlightingFunctions(); diff --git a/lib/libimhex/include/hex/helpers/types.hpp b/lib/libimhex/include/hex/helpers/types.hpp index 8e52d8c88d663..e8eed53990c41 100644 --- a/lib/libimhex/include/hex/helpers/types.hpp +++ b/lib/libimhex/include/hex/helpers/types.hpp @@ -61,6 +61,10 @@ namespace hex { constexpr static Region Invalid() { return { 0, 0 }; } + + constexpr bool operator<(const Region &other) const { + return this->address < other.address; + } }; diff --git a/plugins/builtin/include/content/views/view_hex_editor.hpp b/plugins/builtin/include/content/views/view_hex_editor.hpp index 21fbefdb98593..70ee16ef9c8cd 100644 --- a/plugins/builtin/include/content/views/view_hex_editor.hpp +++ b/plugins/builtin/include/content/views/view_hex_editor.hpp @@ -91,6 +91,7 @@ namespace hex::plugin::builtin { PerProvider> m_selectionStart, m_selectionEnd; PerProvider> m_foregroundHighlights, m_backgroundHighlights; + PerProvider> m_hoverHighlights; }; } \ No newline at end of file diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 78b63599ab4bc..a4f89752e2148 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -493,16 +493,8 @@ namespace hex::plugin::builtin { }); m_hexEditor.setBackgroundHighlightCallback([this](u64 address, const u8 *data, size_t size) -> std::optional { - bool hovered = false; - for (const auto &[id, hoverFunction] : ImHexApi::HexEditor::impl::getHoveringFunctions()) { - if (hoverFunction(m_hexEditor.getProvider(), address, data, size)) { - hovered = true; - break; - } - } - if (auto highlight = m_backgroundHighlights->find(address); highlight != m_backgroundHighlights->end()) { - if (hovered) + if (std::ranges::any_of(*m_hoverHighlights, [region = Region(address, size)](const Region &highlight) { return highlight.overlaps(region); })) return ImAlphaBlendColors(highlight->second, 0xA0FFFFFF); else return highlight->second; @@ -527,6 +519,14 @@ namespace hex::plugin::builtin { return result; }); + m_hexEditor.setHoverChangedCallback([this](u64 address, size_t size) { + m_hoverHighlights->clear(); + for (const auto &[id, hoverFunction] : ImHexApi::HexEditor::impl::getHoveringFunctions()) { + auto highlightedAddresses = hoverFunction(m_hexEditor.getProvider(), address, size); + m_hoverHighlights->merge(highlightedAddresses); + } + }); + m_hexEditor.setTooltipCallback([](u64 address, const u8 *data, size_t size) { for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getTooltipFunctions()) { callback(address, data, size); diff --git a/plugins/builtin/source/content/views/view_pattern_data.cpp b/plugins/builtin/source/content/views/view_pattern_data.cpp index 3d54dfbceebd8..901b9c2ac009f 100644 --- a/plugins/builtin/source/content/views/view_pattern_data.cpp +++ b/plugins/builtin/source/content/views/view_pattern_data.cpp @@ -37,8 +37,8 @@ namespace hex::plugin::builtin { (*m_patternDrawer)->jumpToPattern(pattern); }); - ImHexApi::HexEditor::addHoverHighlightProvider([this](const prv::Provider *, u64 address, const u8 *, size_t size) { - return m_hoveredPatternRegion.overlaps(Region { address, size }); + ImHexApi::HexEditor::addHoverHighlightProvider([this](const prv::Provider *, u64, size_t) -> std::set { + return { m_hoveredPatternRegion }; }); m_patternDrawer.setOnCreateCallback([this](const prv::Provider *provider, auto &drawer) { diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index 75dd6b607eab6..cf70e20d27549 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -1912,24 +1912,23 @@ namespace hex::plugin::builtin { return color; }); - ImHexApi::HexEditor::addHoverHighlightProvider([this](const prv::Provider *provider, u64 address, const u8 *, size_t) { - if (!m_parentHighlightingEnabled) return false; + ImHexApi::HexEditor::addHoverHighlightProvider([this](const prv::Provider *, u64 address, size_t size) { + std::set result; + if (!m_parentHighlightingEnabled) + return result; const auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); - if (auto hoveredRegion = ImHexApi::HexEditor::getHoveredRegion(provider)) { - for (const auto &pattern : runtime.getPatternsAtAddress(hoveredRegion->getStartAddress())) { - const pl::ptrn::Pattern * checkPattern = pattern; - if (auto parent = checkPattern->getParent(); parent != nullptr) - checkPattern = parent; + const auto hoveredRegion = Region { address, size }; + for (const auto &pattern : runtime.getPatternsAtAddress(hoveredRegion.getStartAddress())) { + const pl::ptrn::Pattern * checkPattern = pattern; + if (auto parent = checkPattern->getParent(); parent != nullptr) + checkPattern = parent; - if (checkPattern->getOffset() <= address && checkPattern->getOffset() + checkPattern->getSize() > address) { - return true; - } - } + result.emplace(checkPattern->getOffset(), checkPattern->getSize()); } - return false; + return result; }); ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) { diff --git a/plugins/ui/include/ui/hex_editor.hpp b/plugins/ui/include/ui/hex_editor.hpp index 6c90ea12ba674..94116413e21f6 100644 --- a/plugins/ui/include/ui/hex_editor.hpp +++ b/plugins/ui/include/ui/hex_editor.hpp @@ -270,6 +270,10 @@ namespace hex::ui { m_backgroundColorCallback = callback; } + void setHoverChangedCallback(const std::function &callback) { + m_hoverChangedCallback = callback; + } + void setTooltipCallback(const std::function &callback) { m_tooltipCallback = callback; } @@ -372,6 +376,7 @@ namespace hex::ui { static std::optional defaultColorCallback(u64, const u8 *, size_t) { return std::nullopt; } static void defaultTooltipCallback(u64, const u8 *, size_t) { } std::function(u64, const u8 *, size_t)> m_foregroundColorCallback = defaultColorCallback, m_backgroundColorCallback = defaultColorCallback; + std::function m_hoverChangedCallback = [](auto, auto){ }; std::function m_tooltipCallback = defaultTooltipCallback; Mode m_mode = Mode::Overwrite; diff --git a/plugins/ui/source/ui/hex_editor.cpp b/plugins/ui/source/ui/hex_editor.cpp index 38409d98ecac6..a9583913dd790 100644 --- a/plugins/ui/source/ui/hex_editor.cpp +++ b/plugins/ui/source/ui/hex_editor.cpp @@ -666,7 +666,11 @@ namespace hex::ui { ImGuiExt::TextFormatted("{:?>{}}", "", maxCharsPerCell); if (cellHovered) { - hoveredCell = { byteAddress, bytesPerCell }; + Region newHoveredCell = { byteAddress, bytesPerCell }; + if (hoveredCell != newHoveredCell) { + hoveredCell = newHoveredCell; + m_hoverChangedCallback(hoveredCell.address, hoveredCell.size); + } } ImGui::PopItemWidth(); @@ -725,7 +729,11 @@ namespace hex::ui { this->drawCell(byteAddress, &bytes[x], 1, cellHovered, CellType::ASCII); if (cellHovered) { - hoveredCell = { byteAddress, bytesPerCell }; + Region newHoveredCell = { byteAddress, bytesPerCell }; + if (hoveredCell != newHoveredCell) { + hoveredCell = newHoveredCell; + m_hoverChangedCallback(hoveredCell.address, hoveredCell.size); + } } ImGui::PopItemWidth(); @@ -813,7 +821,11 @@ namespace hex::ui { this->handleSelection(address, data.advance, &bytes[address % m_bytesPerRow], cellHovered); if (cellHovered) { - hoveredCell = { address, data.advance }; + Region newHoveredCell = { address, data.advance }; + if (hoveredCell != newHoveredCell) { + hoveredCell = newHoveredCell; + m_hoverChangedCallback(hoveredCell.address, hoveredCell.size); + } } } }