feat: Added digital signal pattern visualizer
This commit is contained in:
parent
c5f5973a9d
commit
2e3f523f32
@ -26,6 +26,7 @@ add_imhex_plugin(
|
||||
source/content/pl_visualizers/coordinates.cpp
|
||||
source/content/pl_visualizers/timestamp.cpp
|
||||
source/content/pl_visualizers/table.cpp
|
||||
source/content/pl_visualizers/digital_signal.cpp
|
||||
INCLUDES
|
||||
include
|
||||
${MINIAUDIO_INCLUDE_DIRS}
|
||||
|
@ -14,6 +14,7 @@ namespace hex::plugin::visualizers {
|
||||
void drawCoordinateVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, 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 drawTableVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, 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 registerPatternLanguageVisualizers() {
|
||||
using ParamCount = pl::api::FunctionParameterCount;
|
||||
@ -27,6 +28,7 @@ namespace hex::plugin::visualizers {
|
||||
ContentRegistry::PatternLanguage::addVisualizer("coordinates", drawCoordinateVisualizer, ParamCount::exactly(2));
|
||||
ContentRegistry::PatternLanguage::addVisualizer("timestamp", drawTimestampVisualizer, ParamCount::exactly(1));
|
||||
ContentRegistry::PatternLanguage::addVisualizer("table", drawTableVisualizer, ParamCount::exactly(3));
|
||||
ContentRegistry::PatternLanguage::addVisualizer("digital_signal", drawDigitalSignalVisualizer, ParamCount::exactly(1));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,100 @@
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <content/visualizer_helpers.hpp>
|
||||
|
||||
#include <implot.h>
|
||||
#include <imgui.h>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
#include <pl/patterns/pattern_bitfield.hpp>
|
||||
|
||||
namespace hex::plugin::visualizers {
|
||||
|
||||
void drawDigitalSignalVisualizer(pl::ptrn::Pattern &pattern, pl::ptrn::IIterable &iterable, bool shouldReset, std::span<const pl::core::Token::Literal>) {
|
||||
auto *bitfield = dynamic_cast<pl::ptrn::PatternBitfield*>(&pattern);
|
||||
if (bitfield == nullptr)
|
||||
throw std::logic_error("Digital signal visualizer only works with bitfields.");
|
||||
|
||||
|
||||
struct DataPoint {
|
||||
std::array<ImVec2, 2> points;
|
||||
std::string label;
|
||||
std::string value;
|
||||
ImColor color;
|
||||
};
|
||||
static std::vector<DataPoint> dataPoints;
|
||||
static ImVec2 lastPoint;
|
||||
|
||||
if (shouldReset) {
|
||||
dataPoints.clear();
|
||||
lastPoint = { 0, 0 };
|
||||
|
||||
iterable.forEachEntry(0, iterable.getEntryCount(), [&](u64, pl::ptrn::Pattern *entry) {
|
||||
size_t bitSize = 0;
|
||||
if (auto bitfieldField = dynamic_cast<pl::ptrn::PatternBitfieldField*>(entry); bitfieldField != nullptr)
|
||||
bitSize = bitfieldField->getBitSize();
|
||||
else
|
||||
bitSize = entry->getSize() * 8;
|
||||
|
||||
auto value = entry->getValue();
|
||||
bool high = value.toUnsigned() > 0;
|
||||
dataPoints.emplace_back(
|
||||
std::array<ImVec2, 2> { lastPoint, { lastPoint.x, high ? 1.0F : 0.0F } },
|
||||
entry->getDisplayName(),
|
||||
entry->getFormattedValue(),
|
||||
entry->getColor()
|
||||
);
|
||||
|
||||
lastPoint = dataPoints.back().points[1];
|
||||
lastPoint.x += bitSize;
|
||||
});
|
||||
|
||||
dataPoints.push_back({
|
||||
.points = { lastPoint, { lastPoint.x, 0 } },
|
||||
.label = "",
|
||||
.value = "",
|
||||
.color = ImColor(0x00)
|
||||
});
|
||||
}
|
||||
|
||||
if (ImPlot::BeginPlot("##Signal", ImVec2(600_scaled, 200_scaled), ImPlotFlags_NoLegend | ImPlotFlags_NoFrame | ImPlotFlags_NoMenus | ImPlotFlags_NoMouseText)) {
|
||||
ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, 0, lastPoint.x);
|
||||
|
||||
ImPlot::SetupAxis(ImAxis_Y1, "", ImPlotAxisFlags_LockMin | ImPlotAxisFlags_LockMax);
|
||||
ImPlot::SetupAxisFormat(ImAxis_Y1, "");
|
||||
ImPlot::SetupAxisLimits(ImAxis_Y1, -0.1F, 1.1F);
|
||||
|
||||
for (size_t i = 0; i < dataPoints.size() - 1; i += 1) {
|
||||
const auto &left = dataPoints[i];
|
||||
const auto &right = dataPoints[i + 1];
|
||||
|
||||
{
|
||||
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.40F, left.color, {}, false, "%s", left.value.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
ImVec2 min = ImPlot::PlotToPixels(ImPlotPoint(left.points[0].x, 0));
|
||||
ImVec2 max = ImPlot::PlotToPixels(ImPlotPoint(right.points[1].x, 1));
|
||||
|
||||
ImPlot::PushPlotClipRect();
|
||||
auto transparentColor = left.color;
|
||||
transparentColor.Value.w = 0.4F;
|
||||
ImPlot::GetPlotDrawList()->AddRectFilled(min, max, transparentColor);
|
||||
ImPlot::PopPlotClipRect();
|
||||
}
|
||||
}
|
||||
|
||||
ImPlot::PushStyleVar(ImPlotStyleVar_LineWeight, 2_scaled);
|
||||
ImPlot::PlotLineG("Signal", [](int idx, void*) -> ImPlotPoint {
|
||||
return dataPoints[idx / 2].points[idx % 2];
|
||||
}, nullptr, dataPoints.size() * 2);
|
||||
ImPlot::PopStyleVar();
|
||||
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user