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> &getVisualizers();
|
||||||
|
std::map<std::string, Visualizer> &getInlineVisualizers();
|
||||||
std::map<std::string, pl::api::PragmaHandler> &getPragmas();
|
std::map<std::string, pl::api::PragmaHandler> &getPragmas();
|
||||||
std::vector<impl::FunctionDefinition> &getFunctions();
|
std::vector<impl::FunctionDefinition> &getFunctions();
|
||||||
|
|
||||||
@ -317,6 +318,15 @@ namespace hex {
|
|||||||
*/
|
*/
|
||||||
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, u32 parameterCount);
|
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 */
|
/* View Registry. Allows adding of new windows */
|
||||||
|
@ -336,6 +336,11 @@ namespace hex {
|
|||||||
impl::getVisualizers()[name] = impl::Visualizer { parameterCount, function };
|
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 {
|
namespace impl {
|
||||||
|
|
||||||
@ -345,6 +350,12 @@ namespace hex {
|
|||||||
return visualizers;
|
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() {
|
std::map<std::string, pl::api::PragmaHandler> &getPragmas() {
|
||||||
static std::map<std::string, pl::api::PragmaHandler> pragmas;
|
static std::map<std::string, pl::api::PragmaHandler> pragmas;
|
||||||
|
|
||||||
|
@ -367,6 +367,7 @@ namespace hex::init {
|
|||||||
ContentRegistry::PatternLanguage::impl::getFunctions().clear();
|
ContentRegistry::PatternLanguage::impl::getFunctions().clear();
|
||||||
ContentRegistry::PatternLanguage::impl::getPragmas().clear();
|
ContentRegistry::PatternLanguage::impl::getPragmas().clear();
|
||||||
ContentRegistry::PatternLanguage::impl::getVisualizers().clear();
|
ContentRegistry::PatternLanguage::impl::getVisualizers().clear();
|
||||||
|
ContentRegistry::PatternLanguage::impl::getInlineVisualizers().clear();
|
||||||
|
|
||||||
ContentRegistry::Views::impl::getEntries().clear();
|
ContentRegistry::Views::impl::getEntries().clear();
|
||||||
impl::PopupBase::getOpenPopups().clear();
|
impl::PopupBase::getOpenPopups().clear();
|
||||||
|
@ -13,6 +13,7 @@ add_library(${PROJECT_NAME} SHARED
|
|||||||
source/content/pl_builtin_functions.cpp
|
source/content/pl_builtin_functions.cpp
|
||||||
source/content/pl_pragmas.cpp
|
source/content/pl_pragmas.cpp
|
||||||
source/content/pl_visualizers.cpp
|
source/content/pl_visualizers.cpp
|
||||||
|
source/content/pl_inline_visualizers.cpp
|
||||||
source/content/settings_entries.cpp
|
source/content/settings_entries.cpp
|
||||||
source/content/tools_entries.cpp
|
source/content/tools_entries.cpp
|
||||||
source/content/data_processor_nodes.cpp
|
source/content/data_processor_nodes.cpp
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <hex/api/task.hpp>
|
#include <hex/api/task.hpp>
|
||||||
|
#include <hex/api/content_registry.hpp>
|
||||||
|
|
||||||
#include <pl/patterns/pattern.hpp>
|
#include <pl/patterns/pattern.hpp>
|
||||||
#include <pl/pattern_visitor.hpp>
|
#include <pl/pattern_visitor.hpp>
|
||||||
@ -61,7 +62,7 @@ namespace hex::plugin::builtin::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::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);
|
void drawFavoriteColumn(const pl::ptrn::Pattern& pattern);
|
||||||
|
|
||||||
bool createTreeNode(const pl::ptrn::Pattern& pattern, bool leaf = false);
|
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 registerPatternLanguageFunctions();
|
||||||
void registerPatternLanguagePragmas();
|
void registerPatternLanguagePragmas();
|
||||||
void registerPatternLanguageVisualizers();
|
void registerPatternLanguageVisualizers();
|
||||||
|
void registerPatternLanguageInlineVisualizers();
|
||||||
void registerCommandPaletteCommands();
|
void registerCommandPaletteCommands();
|
||||||
void registerSettings();
|
void registerSettings();
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
@ -57,6 +58,7 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {
|
|||||||
registerPatternLanguageFunctions();
|
registerPatternLanguageFunctions();
|
||||||
registerPatternLanguagePragmas();
|
registerPatternLanguagePragmas();
|
||||||
registerPatternLanguageVisualizers();
|
registerPatternLanguageVisualizers();
|
||||||
|
registerPatternLanguageInlineVisualizers();
|
||||||
registerCommandPaletteCommands();
|
registerCommandPaletteCommands();
|
||||||
registerSettings();
|
registerSettings();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
@ -219,11 +219,9 @@ namespace hex::plugin::builtin::ui {
|
|||||||
ImGui::TableNextColumn();
|
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);
|
auto visualizerName = arguments.front().toString(true);
|
||||||
|
|
||||||
const auto &visualizers = ContentRegistry::PatternLanguage::impl::getVisualizers();
|
|
||||||
|
|
||||||
if (auto entry = visualizers.find(visualizerName); entry != visualizers.end()) {
|
if (auto entry = visualizers.find(visualizerName); entry != visualizers.end()) {
|
||||||
const auto &[name, visualizer] = *entry;
|
const auto &[name, visualizer] = *entry;
|
||||||
if (visualizer.parameterCount != arguments.size() - 1) {
|
if (visualizer.parameterCount != arguments.size() - 1) {
|
||||||
@ -248,12 +246,12 @@ namespace hex::plugin::builtin::ui {
|
|||||||
const auto value = pattern.getFormattedValue();
|
const auto value = pattern.getFormattedValue();
|
||||||
|
|
||||||
const auto width = ImGui::GetColumnWidth();
|
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_FramePadding, ImVec2(0, 0));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0.5F));
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0.5F));
|
||||||
|
|
||||||
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 = this->m_currVisualizedPattern;
|
auto previousPattern = this->m_currVisualizedPattern;
|
||||||
|
|
||||||
this->m_currVisualizedPattern = &pattern;
|
this->m_currVisualizedPattern = &pattern;
|
||||||
@ -270,12 +268,14 @@ namespace hex::plugin::builtin::ui {
|
|||||||
|
|
||||||
if (ImGui::BeginPopup("Visualizer")) {
|
if (ImGui::BeginPopup("Visualizer")) {
|
||||||
if (this->m_currVisualizedPattern == &pattern) {
|
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);
|
this->m_visualizedPatterns.insert(&pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndPopup();
|
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 {
|
} else {
|
||||||
ImGui::TextFormatted("{}", value);
|
ImGui::TextFormatted("{}", value);
|
||||||
}
|
}
|
||||||
@ -660,20 +660,16 @@ namespace hex::plugin::builtin::ui {
|
|||||||
drawSizeColumn(pattern);
|
drawSizeColumn(pattern);
|
||||||
drawTypenameColumn(pattern, "struct");
|
drawTypenameColumn(pattern, "struct");
|
||||||
|
|
||||||
if (this->isEditingPattern(pattern)) {
|
if (this->isEditingPattern(pattern) && !pattern.getWriteFormatterFunction().empty()) {
|
||||||
if (pattern.getWriteFormatterFunction().empty())
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||||
ImGui::TextFormatted("{}", pattern.getFormattedValue());
|
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
else {
|
auto value = pattern.toString();
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
pattern.setValue(value);
|
||||||
auto value = pattern.toString();
|
this->resetEditing();
|
||||||
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
|
|
||||||
pattern.setValue(value);
|
|
||||||
this->resetEditing();
|
|
||||||
}
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::PopStyleVar();
|
|
||||||
}
|
}
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
} else {
|
} else {
|
||||||
drawValueColumn(pattern);
|
drawValueColumn(pattern);
|
||||||
}
|
}
|
||||||
@ -712,20 +708,16 @@ namespace hex::plugin::builtin::ui {
|
|||||||
drawSizeColumn(pattern);
|
drawSizeColumn(pattern);
|
||||||
drawTypenameColumn(pattern, "union");
|
drawTypenameColumn(pattern, "union");
|
||||||
|
|
||||||
if (this->isEditingPattern(pattern)) {
|
if (this->isEditingPattern(pattern) && !pattern.getWriteFormatterFunction().empty()) {
|
||||||
if (pattern.getWriteFormatterFunction().empty())
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||||
ImGui::TextFormatted("{}", pattern.getFormattedValue());
|
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
else {
|
auto value = pattern.toString();
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
pattern.setValue(value);
|
||||||
auto value = pattern.toString();
|
this->resetEditing();
|
||||||
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
|
|
||||||
pattern.setValue(value);
|
|
||||||
this->resetEditing();
|
|
||||||
}
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::PopStyleVar();
|
|
||||||
}
|
}
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
} else {
|
} else {
|
||||||
drawValueColumn(pattern);
|
drawValueColumn(pattern);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user