1
0
mirror of synced 2024-11-12 02:00:52 +01:00

fix: Multiple issues causing visualizers to crash when used _slightly_ incorrectly

This commit is contained in:
WerWolv 2024-07-10 20:50:58 +02:00
parent 9e1c2d5a2c
commit 07c259c9c1
21 changed files with 121 additions and 100 deletions

@ -1 +1 @@
Subproject commit c7bca89b1aaf4bb942c53bc3561af687eca44667 Subproject commit 8909b964e24e63b37840d469db5746371e295a33

View File

@ -438,7 +438,7 @@ namespace hex {
namespace impl { namespace impl {
using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, pl::ptrn::IIterable&, bool, std::span<const pl::core::Token::Literal>)>; using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, bool, std::span<const pl::core::Token::Literal>)>;
struct FunctionDefinition { struct FunctionDefinition {
pl::api::Namespace ns; pl::api::Namespace ns;

View File

@ -172,17 +172,22 @@ namespace hex {
} }
void Window::fullFrame() { void Window::fullFrame() {
static u32 crashWatchdog = 0; [[maybe_unused]] static u32 crashWatchdog = 0;
if (auto g = ImGui::GetCurrentContext(); g == nullptr || g->WithinFrameScope) { if (auto g = ImGui::GetCurrentContext(); g == nullptr || g->WithinFrameScope) {
return; return;
} }
#if !defined(DEBUG)
try { try {
#endif
// Render an entire frame
this->frameBegin(); this->frameBegin();
this->frame(); this->frame();
this->frameEnd(); this->frameEnd();
#if !defined(DEBUG)
// Feed the watchdog // Feed the watchdog
crashWatchdog = 0; crashWatchdog = 0;
} catch (...) { } catch (...) {
@ -202,6 +207,7 @@ namespace hex {
// Handle the exception // Handle the exception
handleException(); handleException();
} }
#endif
} }
void Window::loop() { void Window::loop() {

View File

@ -5,8 +5,8 @@
namespace hex::plugin::builtin { namespace hex::plugin::builtin {
void drawHexVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawHexVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void drawChunkBasedEntropyVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawChunkBasedEntropyVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void registerPatternLanguageVisualizers() { void registerPatternLanguageVisualizers() {
using ParamCount = pl::api::FunctionParameterCount; using ParamCount = pl::api::FunctionParameterCount;

View File

@ -8,7 +8,7 @@
namespace hex::plugin::builtin { namespace hex::plugin::builtin {
void drawChunkBasedEntropyVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawChunkBasedEntropyVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
// Variable used to store the result to avoid having to recalculate the result at each frame // Variable used to store the result to avoid having to recalculate the result at each frame
static DiagramChunkBasedEntropyAnalysis analyzer; static DiagramChunkBasedEntropyAnalysis analyzer;

View File

@ -12,7 +12,7 @@
namespace hex::plugin::builtin { namespace hex::plugin::builtin {
void drawHexVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawHexVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
static ui::HexEditor editor; static ui::HexEditor editor;
static prv::MemoryProvider dataProvider; static prv::MemoryProvider dataProvider;

View File

@ -12,7 +12,7 @@
namespace hex::plugin::disasm { namespace hex::plugin::disasm {
void drawDisassemblyVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawDisassemblyVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
struct Disassembly { struct Disassembly {
u64 address; u64 address;
std::vector<u8> bytes; std::vector<u8> bytes;

View File

@ -14,7 +14,7 @@ using namespace hex::plugin::disasm;
namespace hex::plugin::disasm { namespace hex::plugin::disasm {
void drawDisassemblyVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawDisassemblyVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
} }

View File

@ -71,7 +71,7 @@ namespace hex::ui {
void makeSelectable(const pl::ptrn::Pattern &pattern); void makeSelectable(const pl::ptrn::Pattern &pattern);
void drawValueColumn(pl::ptrn::Pattern& pattern); void drawValueColumn(pl::ptrn::Pattern& pattern);
void drawVisualizer(const std::map<std::string, ContentRegistry::PatternLanguage::impl::Visualizer> &visualizers, const std::vector<pl::core::Token::Literal> &arguments, pl::ptrn::Pattern &pattern, pl::ptrn::IIterable &iterable, bool reset); void drawVisualizer(const std::map<std::string, ContentRegistry::PatternLanguage::impl::Visualizer> &visualizers, const std::vector<pl::core::Token::Literal> &arguments, pl::ptrn::Pattern &pattern, bool reset);
void drawFavoriteColumn(const pl::ptrn::Pattern& pattern); void drawFavoriteColumn(const pl::ptrn::Pattern& pattern);
bool drawNameColumn(const pl::ptrn::Pattern &pattern, bool leaf = false); bool drawNameColumn(const pl::ptrn::Pattern &pattern, bool leaf = false);
void drawColorColumn(const pl::ptrn::Pattern& pattern); void drawColorColumn(const pl::ptrn::Pattern& pattern);

View File

@ -50,7 +50,7 @@ namespace hex::ui {
if (!currSelection.has_value()) if (!currSelection.has_value())
return false; return false;
return Region{ address, size }.overlaps(*currSelection); return Region(address, size).overlaps(*currSelection);
} }
bool isPatternFullySelected(u64 address, u64 size) { bool isPatternFullySelected(u64 address, u64 size) {
@ -113,7 +113,7 @@ namespace hex::ui {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
const auto bitSize = (pattern.getBitOffsetForDisplay() + pattern.getBitSize() - (pattern.getSize() == 0 ? 0 : 1)); const auto bitSize = (pattern.getBitOffsetForDisplay() + pattern.getBitSize() - (pattern.getSize() == 0 ? 0 : 1));
ImGuiExt::TextFormatted("0x{0:08X}.{1}", pattern.getOffset() + bitSize / 8, bitSize % 8); ImGuiExt::TextFormatted("0x{0:08X}.{1}", pattern.getOffset() + (bitSize / 8), bitSize % 8);
} }
} }
@ -339,7 +339,7 @@ namespace hex::ui {
ImGui::TextUnformatted(pattern.getComment().c_str()); ImGui::TextUnformatted(pattern.getComment().c_str());
} }
void PatternDrawer::drawVisualizer(const std::map<std::string, ContentRegistry::PatternLanguage::impl::Visualizer> &visualizers, const std::vector<pl::core::Token::Literal> &arguments, pl::ptrn::Pattern &pattern, pl::ptrn::IIterable &iterable, bool reset) { void PatternDrawer::drawVisualizer(const std::map<std::string, ContentRegistry::PatternLanguage::impl::Visualizer> &visualizers, const std::vector<pl::core::Token::Literal> &arguments, pl::ptrn::Pattern &pattern, bool reset) {
auto visualizerName = arguments.front().toString(true); auto visualizerName = arguments.front().toString(true);
if (auto entry = visualizers.find(visualizerName); entry != visualizers.end()) { if (auto entry = visualizers.find(visualizerName); entry != visualizers.end()) {
@ -350,7 +350,7 @@ namespace hex::ui {
if (paramCount >= minParams && paramCount <= maxParams) { if (paramCount >= minParams && paramCount <= maxParams) {
try { try {
visualizer.callback(pattern, iterable, reset, { arguments.begin() + 1, arguments.end() }); visualizer.callback(pattern, reset, { arguments.begin() + 1, arguments.end() });
} catch (std::exception &e) { } catch (std::exception &e) {
m_lastVisualizerError = e.what(); m_lastVisualizerError = e.what();
} }
@ -383,13 +383,13 @@ namespace hex::ui {
bool shouldReset = false; bool shouldReset = false;
if (ImGui::Button(hex::format(" {} {}", ICON_VS_EYE_WATCH, value).c_str(), ImVec2(width, ImGui::GetTextLineHeight()))) { if (ImGui::Button(hex::format(" {} {}", ICON_VS_EYE_WATCH, value).c_str(), ImVec2(width, ImGui::GetTextLineHeight()))) {
auto previousPattern = m_currVisualizedPattern; auto previousPattern = m_currVisualizedPattern;
m_currVisualizedPattern = &pattern; m_currVisualizedPattern = &pattern;
m_lastVisualizerError.clear();
if (m_currVisualizedPattern != previousPattern) if (!m_lastVisualizerError.empty() || m_currVisualizedPattern != previousPattern)
shouldReset = true; shouldReset = true;
m_lastVisualizerError.clear();
ImGui::OpenPopup("Visualizer"); ImGui::OpenPopup("Visualizer");
} }
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2);
@ -398,14 +398,14 @@ namespace hex::ui {
if (ImGui::BeginPopup("Visualizer")) { if (ImGui::BeginPopup("Visualizer")) {
if (m_currVisualizedPattern == &pattern) { if (m_currVisualizedPattern == &pattern) {
drawVisualizer(ContentRegistry::PatternLanguage::impl::getVisualizers(), visualizeArgs, pattern, dynamic_cast<pl::ptrn::IIterable&>(pattern), !m_visualizedPatterns.contains(&pattern) || shouldReset); drawVisualizer(ContentRegistry::PatternLanguage::impl::getVisualizers(), visualizeArgs, pattern, !m_visualizedPatterns.contains(&pattern) || shouldReset);
m_visualizedPatterns.insert(&pattern); m_visualizedPatterns.insert(&pattern);
} }
ImGui::EndPopup(); ImGui::EndPopup();
} }
} else if (const auto &inlineVisualizeArgs = pattern.getAttributeArguments("hex::inline_visualize"); !inlineVisualizeArgs.empty()) { } else if (const auto &inlineVisualizeArgs = pattern.getAttributeArguments("hex::inline_visualize"); !inlineVisualizeArgs.empty()) {
drawVisualizer(ContentRegistry::PatternLanguage::impl::getInlineVisualizers(), inlineVisualizeArgs, pattern, dynamic_cast<pl::ptrn::IIterable&>(pattern), true); drawVisualizer(ContentRegistry::PatternLanguage::impl::getInlineVisualizers(), inlineVisualizeArgs, pattern, true);
} else { } else {
ImGuiExt::TextFormatted("{}", value); ImGuiExt::TextFormatted("{}", value);
} }
@ -1239,7 +1239,7 @@ namespace hex::ui {
this->resetEditing(); this->resetEditing();
} }
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeightWithSpacing() * 9.4F); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - (ImGui::GetTextLineHeightWithSpacing() * 9.4F));
if (ImGuiExt::InputTextIcon("##Search", ICON_VS_FILTER, m_filterText)) { if (ImGuiExt::InputTextIcon("##Search", ICON_VS_FILTER, m_filterText)) {
m_filter = parseRValueFilter(m_filterText).value_or(Filter{ }); m_filter = parseRValueFilter(m_filterText).value_or(Filter{ });
updateFilter(); updateFilter();
@ -1284,7 +1284,7 @@ namespace hex::ui {
const auto &extension = formatter->getFileExtension(); const auto &extension = formatter->getFileExtension();
if (ImGui::MenuItem(name.c_str())) { if (ImGui::MenuItem(name.c_str())) {
fs::openFileBrowser(fs::DialogMode::Save, { { name, extension } }, [&](const std::fs::path &path) { fs::openFileBrowser(fs::DialogMode::Save, { fs::ItemFilter(name, extension) }, [&](const std::fs::path &path) {
auto result = formatter->format(*runtime); auto result = formatter->format(*runtime);
wolv::io::File output(path, wolv::io::File::Mode::Create); wolv::io::File output(path, wolv::io::File::Mode::Create);

View File

@ -12,7 +12,7 @@ namespace hex::plugin::visualizers {
namespace { namespace {
void drawColorInlineVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments) { void drawColorInlineVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments) {
auto r = arguments[0].toFloatingPoint(); auto r = arguments[0].toFloatingPoint();
auto g = arguments[1].toFloatingPoint(); auto g = arguments[1].toFloatingPoint();
auto b = arguments[2].toFloatingPoint(); auto b = arguments[2].toFloatingPoint();
@ -21,7 +21,7 @@ namespace hex::plugin::visualizers {
ImGui::ColorButton("color", ImVec4(r / 255.0F, g / 255.0F, b / 255.0F, a / 255.0F), ImGuiColorEditFlags_NoTooltip, ImVec2(ImGui::GetColumnWidth(), ImGui::GetTextLineHeight())); ImGui::ColorButton("color", ImVec4(r / 255.0F, g / 255.0F, b / 255.0F, a / 255.0F), ImGuiColorEditFlags_NoTooltip, ImVec2(ImGui::GetColumnWidth(), ImGui::GetTextLineHeight()));
} }
void drawGaugeInlineVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments) { void drawGaugeInlineVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments) {
auto value = arguments[0].toFloatingPoint(); auto value = arguments[0].toFloatingPoint();
const auto color = ImGui::GetStyleColorVec4(ImGuiCol_Text); const auto color = ImGui::GetStyleColorVec4(ImGuiCol_Text);
@ -37,7 +37,7 @@ namespace hex::plugin::visualizers {
ImGui::PopStyleColor(3); ImGui::PopStyleColor(3);
} }
void drawButtonInlineVisualizer(pl::ptrn::Pattern &pattern, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments) { void drawButtonInlineVisualizer(pl::ptrn::Pattern &pattern, bool, std::span<const pl::core::Token::Literal> arguments) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0.5F)); ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0.5F));

View File

@ -5,16 +5,16 @@
namespace hex::plugin::visualizers { namespace hex::plugin::visualizers {
void drawLinePlotVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawLinePlotVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void drawScatterPlotVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawScatterPlotVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void drawImageVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawImageVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void drawBitmapVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawBitmapVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void draw3DVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void draw3DVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void drawSoundVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawSoundVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void drawCoordinateVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawCoordinateVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void drawTimestampVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawTimestampVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void drawTableVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawTableVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void drawDigitalSignalVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments); void drawDigitalSignalVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
void registerPatternLanguageVisualizers() { void registerPatternLanguageVisualizers() {
using ParamCount = pl::api::FunctionParameterCount; using ParamCount = pl::api::FunctionParameterCount;

View File

@ -1,3 +1,4 @@
#include <algorithm>
#include <hex/helpers/utils.hpp> #include <hex/helpers/utils.hpp>
#include <content/visualizer_helpers.hpp> #include <content/visualizer_helpers.hpp>
@ -9,7 +10,6 @@
#include <imgui_internal.h> #include <imgui_internal.h>
#include <hex/helpers/opengl.hpp> #include <hex/helpers/opengl.hpp>
#include <opengl_support.h> #include <opengl_support.h>
#include <GLFW/glfw3.h>
#include <numbers> #include <numbers>
@ -23,7 +23,7 @@ namespace hex::plugin::visualizers {
namespace { namespace {
enum class IndexType { enum class IndexType : u8 {
U8, U8,
U16, U16,
U32, U32,
@ -105,15 +105,15 @@ namespace hex::plugin::visualizers {
u32 vertexCount = vertexIndices.size() / 3; u32 vertexCount = vertexIndices.size() / 3;
indices.resize(vertexCount * 6); indices.resize(vertexCount * 6);
for (u32 i = 0; i < vertexCount; ++i) { for (u32 i = 0; i < vertexCount; i += 1) {
indices[i * 6] = vertexIndices[3 * i]; indices[i * 6] = vertexIndices[3 * i];
indices[i * 6 + 1] = vertexIndices[3 * i + 1]; indices[(i * 6) + 1] = vertexIndices[(3 * i) + 1];
indices[i * 6 + 2] = vertexIndices[3 * i + 1]; indices[(i * 6) + 2] = vertexIndices[(3 * i) + 1];
indices[i * 6 + 3] = vertexIndices[3 * i + 2]; indices[(i * 6) + 3] = vertexIndices[(3 * i) + 2];
indices[i * 6 + 4] = vertexIndices[3 * i + 2]; indices[(i * 6) + 4] = vertexIndices[(3 * i) + 2];
indices[i * 6 + 5] = vertexIndices[3 * i]; indices[(i * 6) + 5] = vertexIndices[3 * i];
} }
vertexIndices.resize(indices.size()); vertexIndices.resize(indices.size());
@ -125,13 +125,13 @@ namespace hex::plugin::visualizers {
float getBoundingBox(const std::vector<float> &vertices) { float getBoundingBox(const std::vector<float> &vertices) {
gl::Vector<float, 4> minWorld(std::numeric_limits<float>::infinity()), maxWorld(-std::numeric_limits<float>::infinity()); gl::Vector<float, 4> minWorld(std::numeric_limits<float>::infinity()), maxWorld(-std::numeric_limits<float>::infinity());
for (u32 i = 0; i < vertices.size(); i += 3) { for (u32 i = 0; i < vertices.size(); i += 3) {
if (vertices[i] < minWorld[0]) minWorld[0] = vertices[i]; minWorld[0] = std::min(vertices[i], minWorld[0]);
if (vertices[i + 1] < minWorld[1]) minWorld[1] = vertices[i + 1]; minWorld[1] = std::min(vertices[i + 1], minWorld[1]);
if (vertices[i + 2] < minWorld[2]) minWorld[2] = vertices[i + 2]; minWorld[2] = std::min(vertices[i + 2], minWorld[2]);
if (vertices[i] > maxWorld[0]) maxWorld[0] = vertices[i]; maxWorld[0] = std::max(vertices[i], maxWorld[0]);
if (vertices[i + 1] > maxWorld[1]) maxWorld[1] = vertices[i + 1]; maxWorld[1] = std::max(vertices[i + 1], maxWorld[1]);
if (vertices[i + 2] > maxWorld[2]) maxWorld[2] = vertices[i + 2]; maxWorld[2] = std::max(vertices[i + 2], maxWorld[2]);
} }
minWorld[3] = 1; minWorld[3] = 1;
@ -200,23 +200,23 @@ namespace hex::plugin::visualizers {
auto idx1 = indices[i + 1]; auto idx1 = indices[i + 1];
auto idx2 = indices[i + 2]; auto idx2 = indices[i + 2];
auto v1 = gl::Vector<float, 3>({vertices[3 * idx], vertices[3 * idx + 1], vertices[3 * idx + 2]}); auto v1 = gl::Vector<float, 3>({vertices[3 * idx], vertices[(3 * idx) + 1], vertices[(3 * idx) + 2]});
auto v2 = gl::Vector<float, 3>( auto v2 = gl::Vector<float, 3>(
{vertices[3 * idx1], vertices[3 * idx1 + 1], vertices[3 * idx1 + 2]}); {vertices[3 * idx1], vertices[(3 * idx1) + 1], vertices[(3 * idx1) + 2]});
auto v3 = gl::Vector<float, 3>( auto v3 = gl::Vector<float, 3>(
{vertices[3 * idx2], vertices[3 * idx2 + 1], vertices[3 * idx2 + 2]}); {vertices[3 * idx2], vertices[(3 * idx2) + 1], vertices[(3 * idx2) + 2]});
auto weighted = ((v2 - v1).cross(v3 - v1)); auto weighted = ((v2 - v1).cross(v3 - v1));
normals[3 * idx] += weighted[0]; normals[3 * idx] += weighted[0];
normals[3 * idx + 1] += weighted[1]; normals[(3 * idx) + 1] += weighted[1];
normals[3 * idx + 2] += weighted[2]; normals[(3 * idx) + 2] += weighted[2];
normals[3 * idx1] += weighted[0]; normals[(3 * idx1)] += weighted[0];
normals[3 * idx1 + 1] += weighted[1]; normals[(3 * idx1) + 1] += weighted[1];
normals[3 * idx1 + 2] += weighted[2]; normals[(3 * idx1) + 2] += weighted[2];
normals[3 * idx2] += weighted[0]; normals[(3 * idx2)] += weighted[0];
normals[3 * idx2 + 1] += weighted[1]; normals[(3 * idx2) + 1] += weighted[1];
normals[3 * idx2 + 2] += weighted[2]; normals[(3 * idx2) + 2] += weighted[2];
} }
for (u32 i = 0; i < normals.size(); i += 3) { for (u32 i = 0; i < normals.size(); i += 3) {
@ -271,6 +271,7 @@ namespace hex::plugin::visualizers {
} }
void loadLineVectors(LineVectors &lineVectors, IndexType indexType) { void loadLineVectors(LineVectors &lineVectors, IndexType indexType) {
const auto vertexCount = lineVectors.vertices.size();
s_max = getBoundingBox(lineVectors.vertices); s_max = getBoundingBox(lineVectors.vertices);
if (lineVectors.colors.empty()) if (lineVectors.colors.empty())
@ -283,11 +284,21 @@ namespace hex::plugin::visualizers {
indicesForLines(lineVectors.indices16); indicesForLines(lineVectors.indices16);
else else
indicesForLines(lineVectors.indices32); indicesForLines(lineVectors.indices32);
const auto isIndexInRange = [vertexCount](auto index) { return index >= vertexCount; };
if (
!std::ranges::all_of(lineVectors.indices8, isIndexInRange) ||
!std::ranges::all_of(lineVectors.indices16, isIndexInRange) ||
!std::ranges::all_of(lineVectors.indices32, isIndexInRange)
) {
throw std::logic_error("One or more indices point to out-of-range vertex");
}
} }
void processKeyEvent(ImGuiKey key, float &variable, float incr, float accel) { void processKeyEvent(ImGuiKey key, float &variable, float increment, float acceleration) {
if (ImGui::IsKeyPressed(key)) { if (ImGui::IsKeyPressed(key)) {
auto temp = variable + incr * accel; auto temp = variable + (increment * acceleration);
if (variable * temp < 0.0F) if (variable * temp < 0.0F)
variable = 0.0F; variable = 0.0F;
else else
@ -320,8 +331,7 @@ namespace hex::plugin::visualizers {
auto scrollDelta = ImGui::GetIO().MouseWheel; auto scrollDelta = ImGui::GetIO().MouseWheel;
scaling += scrollDelta * 0.1F * accel; scaling += scrollDelta * 0.1F * accel;
if (scaling < 0.01F) scaling = std::max(scaling, 0.01F);
scaling = 0.01F;
processKeyEvent(ImGuiKey_Keypad4, translation[0], -0.1F, accel); processKeyEvent(ImGuiKey_Keypad4, translation[0], -0.1F, accel);
processKeyEvent(ImGuiKey_Keypad6, translation[0], 0.1F, accel); processKeyEvent(ImGuiKey_Keypad6, translation[0], 0.1F, accel);
@ -339,7 +349,7 @@ namespace hex::plugin::visualizers {
processKeyEvent(ImGuiKey_KeypadAdd, rotation[2], -0.075F, accel); processKeyEvent(ImGuiKey_KeypadAdd, rotation[2], -0.075F, accel);
processKeyEvent(ImGuiKey_KeypadSubtract, rotation[2], 0.075F, accel); processKeyEvent(ImGuiKey_KeypadSubtract, rotation[2], 0.075F, accel);
rotation[2] = std::fmod(rotation[2], 2 * std::numbers::pi); rotation[2] = std::fmod(rotation[2], 2 * std::numbers::pi_v<float>);
} }
@ -577,7 +587,7 @@ namespace hex::plugin::visualizers {
} }
void draw3DVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void draw3DVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
static gl::LightSourceVectors sourceVectors(20); static gl::LightSourceVectors sourceVectors(20);
static gl::VertexArray sourceVertexArray = {}; static gl::VertexArray sourceVertexArray = {};
static gl::LightSourceBuffers sourceBuffers(sourceVertexArray, sourceVectors); static gl::LightSourceBuffers sourceBuffers(sourceVertexArray, sourceVectors);
@ -598,7 +608,7 @@ namespace hex::plugin::visualizers {
std::shared_ptr<pl::ptrn::Pattern> indicesPattern = arguments[1].toPattern(); std::shared_ptr<pl::ptrn::Pattern> indicesPattern = arguments[1].toPattern();
std::shared_ptr<pl::ptrn::Pattern> normalsPattern = nullptr; std::shared_ptr<pl::ptrn::Pattern> normalsPattern = nullptr;
std::shared_ptr<pl::ptrn::Pattern> colorsPattern = nullptr; std::shared_ptr<pl::ptrn::Pattern> colorsPattern = nullptr;
std::shared_ptr<pl::ptrn::Pattern> uvPattern1 = nullptr; std::shared_ptr<pl::ptrn::Pattern> uv1Pattern = nullptr;
std::string textureFile; std::string textureFile;
if (arguments.size() > 2) { if (arguments.size() > 2) {
@ -606,7 +616,7 @@ namespace hex::plugin::visualizers {
if (arguments.size() > 3) { if (arguments.size() > 3) {
colorsPattern = arguments[3].toPattern(); colorsPattern = arguments[3].toPattern();
if (arguments.size() > 4) { if (arguments.size() > 4) {
uvPattern1 = arguments[4].toPattern(); uv1Pattern = arguments[4].toPattern();
if (arguments.size() > 5) if (arguments.size() > 5)
textureFile = arguments[5].toString(); textureFile = arguments[5].toString();
} }
@ -618,7 +628,7 @@ namespace hex::plugin::visualizers {
const auto fontSize = ImGui::GetFontSize(); const auto fontSize = ImGui::GetFontSize();
const auto framePad = ImGui::GetStyle().FramePadding; const auto framePad = ImGui::GetStyle().FramePadding;
float minSize = fontSize * 8_scaled + framePad.x * 20_scaled; float minSize = (fontSize * 8_scaled) + (framePad.x * 20_scaled);
minSize = minSize > 200_scaled ? minSize : 200_scaled; minSize = minSize > 200_scaled ? minSize : 200_scaled;
if (s_renderingWindowSize.x <= 0 || s_renderingWindowSize.y <= 0) if (s_renderingWindowSize.x <= 0 || s_renderingWindowSize.y <= 0)
@ -629,10 +639,8 @@ namespace hex::plugin::visualizers {
else else
s_drawTexture = false; s_drawTexture = false;
if (s_renderingWindowSize.x < minSize) s_renderingWindowSize.x = std::max(s_renderingWindowSize.x, minSize);
s_renderingWindowSize.x = minSize; s_renderingWindowSize.y = std::max(s_renderingWindowSize.y, minSize);
if (s_renderingWindowSize.y < minSize)
s_renderingWindowSize.y = minSize;
gl::Matrix<float, 4, 4> mvp(0); gl::Matrix<float, 4, 4> mvp(0);
@ -670,8 +678,8 @@ namespace hex::plugin::visualizers {
vectors.colors = patternToArray<float>(colorsPattern.get()); vectors.colors = patternToArray<float>(colorsPattern.get());
if (normalsPattern != nullptr) if (normalsPattern != nullptr)
vectors.normals = patternToArray<float>(normalsPattern.get()); vectors.normals = patternToArray<float>(normalsPattern.get());
if (uvPattern1 != nullptr) if (uv1Pattern != nullptr)
vectors.uv1 = patternToArray<float>(uvPattern1.get()); vectors.uv1 = patternToArray<float>(uv1Pattern.get());
loadVectors(vectors, s_indexType); loadVectors(vectors, s_indexType);
@ -731,12 +739,12 @@ namespace hex::plugin::visualizers {
float viewHeight = s_renderingWindowSize.y / 500.0F; float viewHeight = s_renderingWindowSize.y / 500.0F;
glViewport(0,0 , GLsizei(renderTexture.getWidth()), GLsizei(renderTexture.getHeight())); glViewport(0,0 , GLsizei(renderTexture.getWidth()), GLsizei(renderTexture.getHeight()));
glDepthRangef(s_nearLimit, s_farLimit); glDepthRangef(s_nearLimit, s_farLimit);
glClearColor(0.00F, 0.00F, 0.00F, 0.00f); glClearColor(0.00F, 0.00F, 0.00F, 0.00F);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
if (s_isPerspective == 0) { if (!s_isPerspective) {
projection = gl::GetOrthographicMatrix(viewWidth, viewHeight, s_nearLimit, s_farLimit, false); projection = gl::GetOrthographicMatrix(viewWidth, viewHeight, s_nearLimit, s_farLimit, false);
totalScale = s_scaling / (std::fabs(s_translation[2])); totalScale = s_scaling / (std::fabs(s_translation[2]));
scale(0, 0) = totalScale; scale(0, 0) = totalScale;
@ -768,8 +776,11 @@ namespace hex::plugin::visualizers {
mvp = model * view * projection; mvp = model * view * projection;
if (s_drawMode == GL_TRIANGLES) { if (s_drawMode == GL_TRIANGLES) {
static gl::Shader shader = gl::Shader(romfs::get("shaders/default/vertex.glsl").string(), static gl::Shader shader = gl::Shader(
romfs::get("shaders/default/fragment.glsl").string()); romfs::get("shaders/default/vertex.glsl").string(),
romfs::get("shaders/default/fragment.glsl").string()
);
shader.bind(); shader.bind();
shader.setUniform("modelScale", scaledModel); shader.setUniform("modelScale", scaledModel);
@ -820,7 +831,9 @@ namespace hex::plugin::visualizers {
} else { } else {
static gl::Shader lineShader = gl::Shader( static gl::Shader lineShader = gl::Shader(
romfs::get("shaders/default/lineVertex.glsl").string(), romfs::get("shaders/default/lineVertex.glsl").string(),
romfs::get("shaders/default/lineFragment.glsl").string()); romfs::get("shaders/default/lineFragment.glsl").string()
);
lineShader.bind(); lineShader.bind();
lineShader.setUniform("modelMatrix", scaledModel); lineShader.setUniform("modelMatrix", scaledModel);
lineShader.setUniform("viewMatrix", view); lineShader.setUniform("viewMatrix", view);
@ -854,7 +867,9 @@ namespace hex::plugin::visualizers {
if (s_drawGrid || s_drawAxes) { if (s_drawGrid || s_drawAxes) {
static auto gridAxesShader = gl::Shader( static auto gridAxesShader = gl::Shader(
romfs::get("shaders/default/lineVertex.glsl").string(), romfs::get("shaders/default/lineVertex.glsl").string(),
romfs::get("shaders/default/lineFragment.glsl").string()); romfs::get("shaders/default/lineFragment.glsl").string()
);
gridAxesShader.bind(); gridAxesShader.bind();
gridAxesShader.setUniform("modelMatrix", model); gridAxesShader.setUniform("modelMatrix", model);
@ -881,7 +896,8 @@ namespace hex::plugin::visualizers {
if (s_drawLightSource) { if (s_drawLightSource) {
static auto sourceShader = gl::Shader( static auto sourceShader = gl::Shader(
romfs::get("shaders/default/lightVertex.glsl").string(), romfs::get("shaders/default/lightVertex.glsl").string(),
romfs::get("shaders/default/lightFragment.glsl").string()); romfs::get("shaders/default/lightFragment.glsl").string()
);
sourceShader.bind(); sourceShader.bind();
sourceShader.setUniform("modelMatrix", model); sourceShader.setUniform("modelMatrix", model);

View File

@ -13,7 +13,7 @@
namespace hex::plugin::visualizers { namespace hex::plugin::visualizers {
void drawCoordinateVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawCoordinateVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
static ImVec2 coordinate; static ImVec2 coordinate;
static double latitude, longitude; static double latitude, longitude;
static std::string address; static std::string address;

View File

@ -4,15 +4,14 @@
#include <implot.h> #include <implot.h>
#include <imgui.h> #include <imgui.h>
#include <hex/helpers/logger.hpp>
#include <hex/ui/imgui_imhex_extensions.h> #include <hex/ui/imgui_imhex_extensions.h>
#include <pl/patterns/pattern_bitfield.hpp> #include <pl/patterns/pattern_bitfield.hpp>
namespace hex::plugin::visualizers { namespace hex::plugin::visualizers {
void drawDigitalSignalVisualizer(pl::ptrn::Pattern &pattern, pl::ptrn::IIterable &iterable, bool shouldReset, std::span<const pl::core::Token::Literal>) { void drawDigitalSignalVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
auto *bitfield = dynamic_cast<pl::ptrn::PatternBitfield*>(&pattern); auto *bitfield = dynamic_cast<pl::ptrn::PatternBitfield*>(arguments[0].toPattern().get());
if (bitfield == nullptr) if (bitfield == nullptr)
throw std::logic_error("Digital signal visualizer only works with bitfields."); throw std::logic_error("Digital signal visualizer only works with bitfields.");
@ -30,8 +29,8 @@ namespace hex::plugin::visualizers {
dataPoints.clear(); dataPoints.clear();
lastPoint = { 0, 0 }; lastPoint = { 0, 0 };
iterable.forEachEntry(0, iterable.getEntryCount(), [&](u64, pl::ptrn::Pattern *entry) { bitfield->forEachEntry(0, bitfield->getEntryCount(), [&](u64, pl::ptrn::Pattern *entry) {
size_t bitSize = 0; size_t bitSize;
if (auto bitfieldField = dynamic_cast<pl::ptrn::PatternBitfieldField*>(entry); bitfieldField != nullptr) if (auto bitfieldField = dynamic_cast<pl::ptrn::PatternBitfieldField*>(entry); bitfieldField != nullptr)
bitSize = bitfieldField->getBitSize(); bitSize = bitfieldField->getBitSize();
else else
@ -47,7 +46,7 @@ namespace hex::plugin::visualizers {
); );
lastPoint = dataPoints.back().points[1]; lastPoint = dataPoints.back().points[1];
lastPoint.x += bitSize; lastPoint.x += float(bitSize);
}); });
dataPoints.push_back({ dataPoints.push_back({
@ -70,7 +69,7 @@ namespace hex::plugin::visualizers {
const auto &right = dataPoints[i + 1]; const auto &right = dataPoints[i + 1];
{ {
auto x = left.points[1].x + (right.points[0].x - left.points[1].x) / 2; auto x = left.points[1].x + ((right.points[0].x - left.points[1].x) / 2);
ImPlot::Annotation(x, 0.55F, left.color, {}, false, "%s", left.label.c_str()); ImPlot::Annotation(x, 0.55F, left.color, {}, false, "%s", left.label.c_str());
ImPlot::Annotation(x, 0.40F, left.color, {}, false, "%s", left.value.c_str()); ImPlot::Annotation(x, 0.40F, left.color, {}, false, "%s", left.value.c_str());
} }

View File

@ -8,7 +8,7 @@
namespace hex::plugin::visualizers { namespace hex::plugin::visualizers {
void drawImageVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawImageVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
static ImGuiExt::Texture texture; static ImGuiExt::Texture texture;
static float scale = 1.0F; static float scale = 1.0F;
@ -32,7 +32,7 @@ namespace hex::plugin::visualizers {
} }
} }
void drawBitmapVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawBitmapVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
static ImGuiExt::Texture texture; static ImGuiExt::Texture texture;
static float scale = 1.0F; static float scale = 1.0F;

View File

@ -9,7 +9,7 @@
namespace hex::plugin::visualizers { namespace hex::plugin::visualizers {
void drawLinePlotVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawLinePlotVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
static std::vector<float> values; static std::vector<float> values;
auto dataPattern = arguments[0].toPattern(); auto dataPattern = arguments[0].toPattern();

View File

@ -9,7 +9,7 @@
namespace hex::plugin::visualizers { namespace hex::plugin::visualizers {
void drawScatterPlotVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawScatterPlotVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
static std::vector<float> xValues, yValues; static std::vector<float> xValues, yValues;
auto xPattern = arguments[0].toPattern(); auto xPattern = arguments[0].toPattern();

View File

@ -12,7 +12,7 @@
namespace hex::plugin::visualizers { namespace hex::plugin::visualizers {
void drawSoundVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawSoundVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
auto wavePattern = arguments[0].toPattern(); auto wavePattern = arguments[0].toPattern();
auto channels = arguments[1].toUnsigned(); auto channels = arguments[1].toUnsigned();
auto sampleRate = arguments[2].toUnsigned(); auto sampleRate = arguments[2].toUnsigned();

View File

@ -13,7 +13,7 @@
namespace hex::plugin::visualizers { namespace hex::plugin::visualizers {
void drawTableVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) { void drawTableVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span<const pl::core::Token::Literal> arguments) {
static std::vector<std::string> tableContent; static std::vector<std::string> tableContent;
static u128 width = 0, height = 0; static u128 width = 0, height = 0;
@ -47,7 +47,7 @@ namespace hex::plugin::visualizers {
for (u128 j = 0; j < width; j += 1) { for (u128 j = 0; j < width; j += 1) {
ImGui::TableSetColumnIndex(j); ImGui::TableSetColumnIndex(j);
if (i * width + j < tableContent.size()) if (i * width + j < tableContent.size())
ImGui::TextUnformatted(tableContent[i * width + j].c_str()); ImGui::TextUnformatted(tableContent[(i * width) + j].c_str());
else else
ImGui::TextUnformatted("??"); ImGui::TextUnformatted("??");
} }

View File

@ -14,7 +14,7 @@
namespace hex::plugin::visualizers { namespace hex::plugin::visualizers {
void drawTimestampVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments) { void drawTimestampVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments) {
time_t timestamp = arguments[0].toUnsigned(); time_t timestamp = arguments[0].toUnsigned();
auto tm = fmt::gmtime(timestamp); auto tm = fmt::gmtime(timestamp);
auto date = std::chrono::year_month_day(std::chrono::year(tm.tm_year + 1900), std::chrono::month(tm.tm_mon + 1), std::chrono::day(tm.tm_mday)); auto date = std::chrono::year_month_day(std::chrono::year(tm.tm_year + 1900), std::chrono::month(tm.tm_mon + 1), std::chrono::day(tm.tm_mday));