From 9be9eb90f609b43011449d3e246d12c77b812542 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 28 Nov 2024 21:26:55 +0100 Subject: [PATCH] feat: Added hex editor segment separators --- plugins/ui/include/ui/hex_editor.hpp | 2 ++ plugins/ui/romfs/lang/en_US.json | 3 ++ plugins/ui/source/ui/hex_editor.cpp | 46 +++++++++++++++++++++++++--- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/plugins/ui/include/ui/hex_editor.hpp b/plugins/ui/include/ui/hex_editor.hpp index 5e9e966cd..322dd28a6 100644 --- a/plugins/ui/include/ui/hex_editor.hpp +++ b/plugins/ui/include/ui/hex_editor.hpp @@ -96,6 +96,7 @@ namespace hex::ui { enum class CellType : u8 { None, Hex, ASCII }; void drawCell(u64 address, const u8 *data, size_t size, bool hovered, CellType cellType); + void drawSeparatorLine(u64 address, bool drawVerticalConnector); void drawSelectionFrame(u32 x, u32 y, Region selection, u64 byteAddress, u16 bytesPerCell, const ImVec2 &cellPos, const ImVec2 &cellSize, const ImColor &backgroundColor) const; void drawEditor(const ImVec2 &size); void drawFooter(const ImVec2 &size); @@ -339,6 +340,7 @@ namespace hex::ui { std::endian m_dataVisualizerEndianness = std::endian::little; std::shared_ptr m_currDataVisualizer; char m_unknownDataCharacter = '?'; + u64 m_separatorStride = 0; bool m_shouldJumpToSelection = false; float m_jumpPivot = 0.0F; diff --git a/plugins/ui/romfs/lang/en_US.json b/plugins/ui/romfs/lang/en_US.json index e5c71ad56..88fe434ab 100644 --- a/plugins/ui/romfs/lang/en_US.json +++ b/plugins/ui/romfs/lang/en_US.json @@ -63,6 +63,7 @@ "hex.ui.common.region": "Region", "hex.ui.common.remove": "Remove", "hex.ui.common.reset": "Reset", + "hex.ui.common.segment": "Segment", "hex.ui.common.set": "Set", "hex.ui.common.settings": "Settings", "hex.ui.common.size": "Size", @@ -97,6 +98,8 @@ "hex.ui.hex_editor.region": "Region", "hex.ui.hex_editor.selection": "Selection", "hex.ui.hex_editor.selection.none": "None", + "hex.ui.hex_editor.separator_stride": "Segment Size: 0x{0:02X}", + "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.pattern_drawer.color": "Color", diff --git a/plugins/ui/source/ui/hex_editor.cpp b/plugins/ui/source/ui/hex_editor.cpp index a5f3e5c4a..7db86f03b 100644 --- a/plugins/ui/source/ui/hex_editor.cpp +++ b/plugins/ui/source/ui/hex_editor.cpp @@ -300,6 +300,7 @@ namespace hex::ui { std::reverse(buffer.begin(), buffer.begin() + size); m_currDataVisualizer->draw(address, buffer.data(), size, m_upperCaseHex); + } else { asciiVisualizer.draw(address, data, size, m_upperCaseHex); } @@ -408,6 +409,26 @@ namespace hex::ui { } } + void HexEditor::drawSeparatorLine(u64 address, bool drawVerticalConnector) { + if (m_separatorStride == 0) return; + + const u64 regionProgress = address % m_separatorStride; + const u64 cellsPerRow = m_bytesPerRow / m_currDataVisualizer->getBytesPerCell(); + const auto table = ImGui::GetCurrentTable(); + if (regionProgress < cellsPerRow) { + const auto rect = ImGui::TableGetCellBgRect(table, table->CurrentColumn); + + const auto drawList = ImGui::GetWindowDrawList(); + + const auto lineColor = ImGui::GetColorU32(ImGuiCol_SeparatorActive); + drawList->AddLine(rect.Min, ImVec2(rect.Max.x, rect.Min.y), lineColor); + if (regionProgress == 0 && drawVerticalConnector) { + drawList->AddLine(ImFloor(rect.Min), ImFloor(ImVec2(rect.Min.x, rect.Max.y)), lineColor); + } + } + } + + void HexEditor::drawSelectionFrame(u32 x, u32 y, Region selection, u64 byteAddress, u16 bytesPerCell, const ImVec2 &cellPos, const ImVec2 &cellSize, const ImColor &backgroundColor) const { auto drawList = ImGui::GetWindowDrawList(); @@ -565,7 +586,14 @@ namespace hex::ui { // Draw address column ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGuiExt::TextFormatted(m_upperCaseHex ? "{:08X}: " : "{:08x}: ", y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress()); + + const auto rowAddress = y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(); + + if (m_separatorStride > 0 && rowAddress % m_separatorStride < m_bytesPerRow) + ImGuiExt::TextFormattedColored(ImGui::GetStyleColorVec4(ImGuiCol_SeparatorActive), "{} {}", "hex.ui.common.segment"_lang, rowAddress / m_separatorStride); + else + ImGuiExt::TextFormatted(m_upperCaseHex ? "{:08X}: " : "{:08x}: ", rowAddress); + ImGui::TableNextColumn(); const u8 validBytes = std::min(m_bytesPerRow, m_provider->getSize() - y * m_bytesPerRow); @@ -616,8 +644,11 @@ namespace hex::ui { const u64 byteAddress = y * m_bytesPerRow + x * bytesPerCell + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(); ImGui::TableNextColumn(); - if (isColumnSeparatorColumn(x, columnCount)) + if (y != 0) drawSeparatorLine(byteAddress, x != 0); + if (isColumnSeparatorColumn(x, columnCount)) { ImGui::TableNextColumn(); + if (y != 0) drawSeparatorLine(byteAddress, false); + } if (x < std::ceil(float(validBytes) / bytesPerCell)) { auto cellStartPos = getCellPosition(); @@ -679,6 +710,7 @@ namespace hex::ui { ImGui::PopStyleVar(); ImGui::TableNextColumn(); + if (y != 0) drawSeparatorLine(y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(), false); ImGui::TableNextColumn(); // Draw ASCII column @@ -691,10 +723,11 @@ namespace hex::ui { ImGui::TableNextRow(); for (u64 x = 0; x < m_bytesPerRow; x++) { - ImGui::TableNextColumn(); - const u64 byteAddress = y * m_bytesPerRow + x + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(); + ImGui::TableNextColumn(); + if (y != 0) drawSeparatorLine(byteAddress, true); + const auto cellStartPos = getCellPosition(); const auto cellSize = CharacterSize + scaled(ImVec2(m_characterCellPadding, 0)); @@ -1029,6 +1062,11 @@ namespace hex::ui { m_bytesPerRow = bytesPerRow * this->getBytesPerCell(); m_encodingLineStartAddresses.clear(); } + { + const auto min = 0; + const auto max = m_provider->getActualSize(); + ImGui::SliderScalar("##separator_stride", ImGuiDataType_U64, &m_separatorStride, &min, &max, m_separatorStride == 0 ? "hex.ui.hex_editor.no_separator"_lang : hex::format("hex.ui.hex_editor.separator_stride"_lang, m_separatorStride).c_str()); + } ImGui::EndPopup(); } }