feat: Added new pattern inline visualizers
This commit is contained in:
parent
33566137c2
commit
86c4c8fa96
@ -258,6 +258,7 @@ namespace hex {
|
||||
};
|
||||
|
||||
std::map<std::string, Visualizer> &getVisualizers();
|
||||
std::map<std::string, Visualizer> &getInlineVisualizers();
|
||||
std::map<std::string, pl::api::PragmaHandler> &getPragmas();
|
||||
std::vector<impl::FunctionDefinition> &getFunctions();
|
||||
|
||||
@ -317,6 +318,15 @@ namespace hex {
|
||||
*/
|
||||
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, u32 parameterCount);
|
||||
|
||||
/**
|
||||
* @brief Adds a new inline visualizer to the pattern language
|
||||
* @note Inline visualizers are extensions to the [[hex::inline_visualize]] attribute, used to visualize data
|
||||
* @param name The name of the visualizer
|
||||
* @param func The function callback
|
||||
* @param parameterCount The amount of parameters the function takes
|
||||
*/
|
||||
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, u32 parameterCount);
|
||||
|
||||
}
|
||||
|
||||
/* View Registry. Allows adding of new windows */
|
||||
|
@ -336,6 +336,11 @@ namespace hex {
|
||||
impl::getVisualizers()[name] = impl::Visualizer { parameterCount, function };
|
||||
}
|
||||
|
||||
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, u32 parameterCount) {
|
||||
log::debug("Registered new inline pattern visualizer function: {}", name);
|
||||
impl::getInlineVisualizers()[name] = impl::Visualizer { parameterCount, function };
|
||||
}
|
||||
|
||||
|
||||
namespace impl {
|
||||
|
||||
@ -345,6 +350,12 @@ namespace hex {
|
||||
return visualizers;
|
||||
}
|
||||
|
||||
std::map<std::string, impl::Visualizer> &getInlineVisualizers() {
|
||||
static std::map<std::string, impl::Visualizer> visualizers;
|
||||
|
||||
return visualizers;
|
||||
}
|
||||
|
||||
std::map<std::string, pl::api::PragmaHandler> &getPragmas() {
|
||||
static std::map<std::string, pl::api::PragmaHandler> pragmas;
|
||||
|
||||
|
@ -367,6 +367,7 @@ namespace hex::init {
|
||||
ContentRegistry::PatternLanguage::impl::getFunctions().clear();
|
||||
ContentRegistry::PatternLanguage::impl::getPragmas().clear();
|
||||
ContentRegistry::PatternLanguage::impl::getVisualizers().clear();
|
||||
ContentRegistry::PatternLanguage::impl::getInlineVisualizers().clear();
|
||||
|
||||
ContentRegistry::Views::impl::getEntries().clear();
|
||||
impl::PopupBase::getOpenPopups().clear();
|
||||
|
@ -13,6 +13,7 @@ add_library(${PROJECT_NAME} SHARED
|
||||
source/content/pl_builtin_functions.cpp
|
||||
source/content/pl_pragmas.cpp
|
||||
source/content/pl_visualizers.cpp
|
||||
source/content/pl_inline_visualizers.cpp
|
||||
source/content/settings_entries.cpp
|
||||
source/content/tools_entries.cpp
|
||||
source/content/data_processor_nodes.cpp
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/task.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <pl/patterns/pattern.hpp>
|
||||
#include <pl/pattern_visitor.hpp>
|
||||
@ -61,7 +62,7 @@ namespace hex::plugin::builtin::ui {
|
||||
void makeSelectable(const pl::ptrn::Pattern &pattern);
|
||||
|
||||
void drawValueColumn(pl::ptrn::Pattern& pattern);
|
||||
void drawVisualizer(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, pl::ptrn::IIterable &iterable, bool reset);
|
||||
void drawFavoriteColumn(const pl::ptrn::Pattern& pattern);
|
||||
|
||||
bool createTreeNode(const pl::ptrn::Pattern& pattern, bool leaf = false);
|
||||
|
68
plugins/builtin/source/content/pl_inline_visualizers.cpp
Normal file
68
plugins/builtin/source/content/pl_inline_visualizers.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <pl/patterns/pattern.hpp>
|
||||
#include <pl/patterns/pattern_padding.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
#include <fonts/codicons_font.h>
|
||||
|
||||
|
||||
#include <romfs/romfs.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace {
|
||||
|
||||
void drawColorInlineVisualizer(pl::ptrn::Pattern &, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments) {
|
||||
auto r = arguments[0].toFloatingPoint();
|
||||
auto g = arguments[1].toFloatingPoint();
|
||||
auto b = arguments[2].toFloatingPoint();
|
||||
auto a = arguments[3].toFloatingPoint();
|
||||
|
||||
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) {
|
||||
auto value = arguments[0].toFloatingPoint();
|
||||
|
||||
const auto color = ImGui::GetStyleColorVec4(ImGuiCol_Text);
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(color.x, color.y, color.z, 0.2F));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0F, 0.0F, 0.0F, 0.0F));
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(color.x, color.y, color.z, 0.5F));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0F);
|
||||
|
||||
ImGui::ProgressBar(value / 100.0F, ImVec2(ImGui::GetColumnWidth(), ImGui::GetTextLineHeight()), "");
|
||||
|
||||
ImGui::PopStyleVar(1);
|
||||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
|
||||
void drawButtonInlineVisualizer(pl::ptrn::Pattern &pattern, pl::ptrn::IIterable &, bool, std::span<const pl::core::Token::Literal> arguments) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0.5F));
|
||||
|
||||
if (ImGui::Button(hex::format(" {} {}", ICON_VS_PLAY, pattern.getFormattedValue()).c_str(), ImVec2(ImGui::GetColumnWidth(), ImGui::GetTextLineHeight()))) {
|
||||
auto *evaluator = pattern.getEvaluator();
|
||||
const auto functionName = arguments[0].toString(false);
|
||||
const auto &function = evaluator->findFunction(functionName);
|
||||
|
||||
if (function.has_value())
|
||||
function->func(evaluator, { pattern.clone() });
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void registerPatternLanguageInlineVisualizers() {
|
||||
ContentRegistry::PatternLanguage::addInlineVisualizer("color", drawColorInlineVisualizer, 4);
|
||||
ContentRegistry::PatternLanguage::addInlineVisualizer("gauge", drawGaugeInlineVisualizer, 1);
|
||||
ContentRegistry::PatternLanguage::addInlineVisualizer("button", drawButtonInlineVisualizer, 1);
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,7 @@ namespace hex::plugin::builtin {
|
||||
void registerPatternLanguageFunctions();
|
||||
void registerPatternLanguagePragmas();
|
||||
void registerPatternLanguageVisualizers();
|
||||
void registerPatternLanguageInlineVisualizers();
|
||||
void registerCommandPaletteCommands();
|
||||
void registerSettings();
|
||||
void loadSettings();
|
||||
@ -57,6 +58,7 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {
|
||||
registerPatternLanguageFunctions();
|
||||
registerPatternLanguagePragmas();
|
||||
registerPatternLanguageVisualizers();
|
||||
registerPatternLanguageInlineVisualizers();
|
||||
registerCommandPaletteCommands();
|
||||
registerSettings();
|
||||
loadSettings();
|
||||
|
@ -219,11 +219,9 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
|
||||
void PatternDrawer::drawVisualizer(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, pl::ptrn::IIterable &iterable, bool reset) {
|
||||
auto visualizerName = arguments.front().toString(true);
|
||||
|
||||
const auto &visualizers = ContentRegistry::PatternLanguage::impl::getVisualizers();
|
||||
|
||||
if (auto entry = visualizers.find(visualizerName); entry != visualizers.end()) {
|
||||
const auto &[name, visualizer] = *entry;
|
||||
if (visualizer.parameterCount != arguments.size() - 1) {
|
||||
@ -248,12 +246,12 @@ namespace hex::plugin::builtin::ui {
|
||||
const auto value = pattern.getFormattedValue();
|
||||
|
||||
const auto width = ImGui::GetColumnWidth();
|
||||
if (const auto &arguments = pattern.getAttributeArguments("hex::visualize"); !arguments.empty()) {
|
||||
if (const auto &visualizeArgs = pattern.getAttributeArguments("hex::visualize"); !visualizeArgs.empty()) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0.5F));
|
||||
|
||||
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 = this->m_currVisualizedPattern;
|
||||
|
||||
this->m_currVisualizedPattern = &pattern;
|
||||
@ -270,12 +268,14 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
if (ImGui::BeginPopup("Visualizer")) {
|
||||
if (this->m_currVisualizedPattern == &pattern) {
|
||||
drawVisualizer(arguments, pattern, dynamic_cast<pl::ptrn::IIterable&>(pattern), !this->m_visualizedPatterns.contains(&pattern) || shouldReset);
|
||||
drawVisualizer(ContentRegistry::PatternLanguage::impl::getVisualizers(), visualizeArgs, pattern, dynamic_cast<pl::ptrn::IIterable&>(pattern), !this->m_visualizedPatterns.contains(&pattern) || shouldReset);
|
||||
this->m_visualizedPatterns.insert(&pattern);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
} 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);
|
||||
} else {
|
||||
ImGui::TextFormatted("{}", value);
|
||||
}
|
||||
@ -660,20 +660,16 @@ namespace hex::plugin::builtin::ui {
|
||||
drawSizeColumn(pattern);
|
||||
drawTypenameColumn(pattern, "struct");
|
||||
|
||||
if (this->isEditingPattern(pattern)) {
|
||||
if (pattern.getWriteFormatterFunction().empty())
|
||||
ImGui::TextFormatted("{}", pattern.getFormattedValue());
|
||||
else {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
auto value = pattern.toString();
|
||||
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
pattern.setValue(value);
|
||||
this->resetEditing();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PopStyleVar();
|
||||
if (this->isEditingPattern(pattern) && !pattern.getWriteFormatterFunction().empty()) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
auto value = pattern.toString();
|
||||
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
pattern.setValue(value);
|
||||
this->resetEditing();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PopStyleVar();
|
||||
} else {
|
||||
drawValueColumn(pattern);
|
||||
}
|
||||
@ -712,20 +708,16 @@ namespace hex::plugin::builtin::ui {
|
||||
drawSizeColumn(pattern);
|
||||
drawTypenameColumn(pattern, "union");
|
||||
|
||||
if (this->isEditingPattern(pattern)) {
|
||||
if (pattern.getWriteFormatterFunction().empty())
|
||||
ImGui::TextFormatted("{}", pattern.getFormattedValue());
|
||||
else {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
auto value = pattern.toString();
|
||||
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
pattern.setValue(value);
|
||||
this->resetEditing();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PopStyleVar();
|
||||
if (this->isEditingPattern(pattern) && !pattern.getWriteFormatterFunction().empty()) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
auto value = pattern.toString();
|
||||
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
pattern.setValue(value);
|
||||
this->resetEditing();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PopStyleVar();
|
||||
} else {
|
||||
drawValueColumn(pattern);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user