From f4753a5bd80aa1a37c51f46a9e641274cde30b3b Mon Sep 17 00:00:00 2001 From: WerWolv Date: Mon, 1 Dec 2025 19:37:36 +0100 Subject: [PATCH] feat: Added hex editor minimap option to shade cells based on the byte's value --- .../source/content/views/view_hex_editor.cpp | 2 +- plugins/ui/include/ui/hex_editor.hpp | 2 + plugins/ui/romfs/lang/en_US.json | 1 + plugins/ui/source/ui/hex_editor.cpp | 53 +++++++++++++------ 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 69ddef36f..42ca3017f 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -802,7 +802,7 @@ namespace hex::plugin::builtin { ImGui::PopStyleVar(); // Right click menu - if (ImGui::IsMouseDown(ImGuiMouseButton_Right) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows) && !ImGui::IsAnyItemHovered() && !ImGui::IsMouseDragging(ImGuiMouseButton_Right)) { + if (ImGui::IsMouseClicked(ImGuiMouseButton_Right) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows) && !ImGui::IsAnyItemHovered() && !ImGui::IsMouseDragging(ImGuiMouseButton_Right)) { RequestOpenPopup::post("hex.builtin.menu.edit"); ImGui::SetWindowFocus(); } diff --git a/plugins/ui/include/ui/hex_editor.hpp b/plugins/ui/include/ui/hex_editor.hpp index 875d3ae37..1082e48ef 100644 --- a/plugins/ui/include/ui/hex_editor.hpp +++ b/plugins/ui/include/ui/hex_editor.hpp @@ -111,6 +111,7 @@ namespace hex::ui { void drawTooltip(u64 address, const u8 *data, size_t size) const; void drawScrollbar(ImVec2 characterSize); void drawMinimap(ImVec2 characterSize); + void drawMinimapPopup(); void handleSelection(u64 address, u32 bytesPerCell, const u8 *data, bool cellHovered); std::optional applySelectionColor(u64 byteAddress, std::optional color); @@ -440,6 +441,7 @@ namespace hex::ui { bool m_showMiniMap = false; bool m_showSelectionInFooter = false; int m_miniMapWidth = 5; + bool m_minimapValueBrightness = true; u32 m_byteCellPadding = 0, m_characterCellPadding = 0; bool m_footerCollapsed = true; diff --git a/plugins/ui/romfs/lang/en_US.json b/plugins/ui/romfs/lang/en_US.json index 0dbcd86ee..ebad11c37 100644 --- a/plugins/ui/romfs/lang/en_US.json +++ b/plugins/ui/romfs/lang/en_US.json @@ -100,6 +100,7 @@ "hex.ui.hex_editor.no_separator": "No Segment Separators", "hex.ui.hex_editor.uppercase_hex": "Upper case Hex characters", "hex.ui.hex_editor.visualizer": "Data visualizer", + "hex.ui.hex_editor.minimap.value_brightness": "Shade cells based on value", "hex.ui.pattern_drawer.color": "Color", "hex.ui.pattern_drawer.comment": "Comment", "hex.ui.pattern_drawer.double_click": "Double-click to see more items", diff --git a/plugins/ui/source/ui/hex_editor.cpp b/plugins/ui/source/ui/hex_editor.cpp index df5c53119..c4743365d 100644 --- a/plugins/ui/source/ui/hex_editor.cpp +++ b/plugins/ui/source/ui/hex_editor.cpp @@ -318,6 +318,13 @@ namespace hex::ui { (std::ceil(innerRect.Max.y - innerRect.Min.y) / characterSize.y), std::nextafterf((numRows - m_visibleRowCount) + ImGui::GetWindowSize().y / characterSize.y, std::numeric_limits::max()), roundingCorners); + + if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) { + ImGui::OpenPopup("MiniMapOptions"); + } + + drawMinimapPopup(); + ImGui::PopStyleVar(2); ImGui::PopStyleColor(3); ImGui::PopID(); @@ -339,7 +346,13 @@ namespace hex::ui { const auto cellSize = rowSize / ImVec2(rowColors.size(), 1); ImVec2 cellPos = rowStart; - for (const auto &rowColor : rowColors) { + const auto stride = bytesPerRow / rowColors.size(); + for (u32 i = 0; i < rowColors.size(); i += 1) { + auto rowColor = rowColors[i]; + if (m_minimapValueBrightness) { + rowColor = ImColor(rowColor.Value + ImVec4(0.3F, 0.3F, 0.3F, 0.0F) * ((float(rowData[i * stride]) - 0x7F) / 0xFF)); + } + drawList->AddRectFilled(cellPos, cellPos + cellSize, rowColor); cellPos.x += cellSize.x; } @@ -1087,6 +1100,27 @@ namespace hex::ui { m_shouldScrollToSelection = false; } + void HexEditor::drawMinimapPopup() { + if (ImGui::BeginPopup("MiniMapOptions")) { + ImGui::SliderInt("hex.ui.hex_editor.minimap.width"_lang, &m_miniMapWidth, 1, 25, "%d", ImGuiSliderFlags_AlwaysClamp); + + if (ImGui::BeginCombo("##minimap_visualizer", Lang(m_miniMapVisualizer->unlocalizedName))) { + + for (const auto &visualizer : ContentRegistry::HexEditor::impl::getMiniMapVisualizers()) { + if (ImGui::Selectable(Lang(visualizer->unlocalizedName))) { + m_miniMapVisualizer = visualizer; + } + } + + ImGui::EndCombo(); + } + + ImGui::Checkbox("hex.ui.hex_editor.minimap.value_brightness"_lang, &m_minimapValueBrightness); + + ImGui::EndPopup(); + } + } + void HexEditor::drawFooter(const ImVec2 &size) { const auto windowEndPos = ImGui::GetWindowPos() + size - ImGui::GetStyle().WindowPadding; ImGui::GetWindowDrawList()->AddLine(windowEndPos - ImVec2(0, size.y - 1_scaled), windowEndPos - size + ImVec2(0, 1_scaled), ImGui::GetColorU32(ImGuiCol_Separator), 2.0_scaled); @@ -1152,22 +1186,7 @@ namespace hex::ui { if (ImGui::IsItemClicked(ImGuiMouseButton_Right) && m_miniMapVisualizer != nullptr) ImGui::OpenPopup("MiniMapOptions"); - if (ImGui::BeginPopup("MiniMapOptions")) { - ImGui::SliderInt("hex.ui.hex_editor.minimap.width"_lang, &m_miniMapWidth, 1, 25, "%d", ImGuiSliderFlags_AlwaysClamp); - - if (ImGui::BeginCombo("##minimap_visualizer", Lang(m_miniMapVisualizer->unlocalizedName))) { - - for (const auto &visualizer : ContentRegistry::HexEditor::impl::getMiniMapVisualizers()) { - if (ImGui::Selectable(Lang(visualizer->unlocalizedName))) { - m_miniMapVisualizer = visualizer; - } - } - - ImGui::EndCombo(); - } - - ImGui::EndPopup(); - } + drawMinimapPopup(); ImGui::SameLine(0, 1_scaled);