mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-30 00:40:02 -05:00
impr: Replace horrible pattern extra data class with a more modular system
This commit is contained in:
@@ -7,9 +7,6 @@
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <content/views/view_data_processor.hpp>
|
||||
|
||||
#include <content/helpers/provider_extra_data.hpp>
|
||||
#include <content/helpers/diagrams.hpp>
|
||||
|
||||
#include <cctype>
|
||||
@@ -22,7 +19,6 @@
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
#include <wolv/utils/core.hpp>
|
||||
#include <wolv/utils/guards.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
@@ -1166,10 +1162,10 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void process() override {
|
||||
auto &pl = ProviderExtraData::getCurrent().patternLanguage;
|
||||
auto lock = ContentRegistry::PatternLanguage::getRuntimeLock();
|
||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
|
||||
std::scoped_lock lock(pl.runtimeMutex);
|
||||
const auto &outVars = pl.runtime->getOutVariables();
|
||||
const auto &outVars = runtime.getOutVariables();
|
||||
|
||||
if (outVars.contains(this->m_name)) {
|
||||
std::visit(wolv::util::overloaded {
|
||||
@@ -1201,303 +1197,6 @@ namespace hex::plugin::builtin {
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
class NodeCustomInput : public dp::Node {
|
||||
public:
|
||||
NodeCustomInput() : Node("hex.builtin.nodes.custom.input.header", { dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "hex.builtin.nodes.common.input") }) { }
|
||||
~NodeCustomInput() override = default;
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
if (ImGui::Combo("##type", &this->m_type, "Integer\0Float\0Buffer\0")) {
|
||||
this->setAttributes({
|
||||
{ dp::Attribute(dp::Attribute::IOType::Out, this->getType(), "hex.builtin.nodes.common.input") }
|
||||
});
|
||||
}
|
||||
|
||||
if (ImGui::InputText("##name", this->m_name)) {
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void setValue(auto value) { this->m_value = std::move(value); }
|
||||
|
||||
const std::string &getName() const { return this->m_name; }
|
||||
dp::Attribute::Type getType() const {
|
||||
switch (this->m_type) {
|
||||
default:
|
||||
case 0: return dp::Attribute::Type::Integer;
|
||||
case 1: return dp::Attribute::Type::Float;
|
||||
case 2: return dp::Attribute::Type::Buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void process() override {
|
||||
std::visit(wolv::util::overloaded {
|
||||
[this](i128 value) { this->setIntegerOnOutput(0, value); },
|
||||
[this](long double value) { this->setFloatOnOutput(0, value); },
|
||||
[this](const std::vector<u8> &value) { this->setBufferOnOutput(0, value); }
|
||||
}, this->m_value);
|
||||
}
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["name"] = this->m_name;
|
||||
j["type"] = this->m_type;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_name = j["name"].get<std::string>();
|
||||
this->m_type = j["type"];
|
||||
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
this->setAttributes({
|
||||
{ dp::Attribute(dp::Attribute::IOType::Out, this->getType(), "hex.builtin.nodes.common.input") }
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_name = LangEntry(this->getUnlocalizedName());
|
||||
int m_type = 0;
|
||||
|
||||
std::variant<i128, long double, std::vector<u8>> m_value;
|
||||
};
|
||||
|
||||
class NodeCustomOutput : public dp::Node {
|
||||
public:
|
||||
NodeCustomOutput() : Node("hex.builtin.nodes.custom.output.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "hex.builtin.nodes.common.output") }) { }
|
||||
~NodeCustomOutput() override = default;
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
if (ImGui::Combo("##type", &this->m_type, "Integer\0Float\0Buffer\0")) {
|
||||
this->setAttributes({
|
||||
{ dp::Attribute(dp::Attribute::IOType::In, this->getType(), "hex.builtin.nodes.common.output") }
|
||||
});
|
||||
}
|
||||
|
||||
if (ImGui::InputText("##name", this->m_name)) {
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
const std::string &getName() const { return this->m_name; }
|
||||
dp::Attribute::Type getType() const {
|
||||
switch (this->m_type) {
|
||||
case 0: return dp::Attribute::Type::Integer;
|
||||
case 1: return dp::Attribute::Type::Float;
|
||||
case 2: return dp::Attribute::Type::Buffer;
|
||||
default: return dp::Attribute::Type::Integer;
|
||||
}
|
||||
}
|
||||
|
||||
void process() override {
|
||||
switch (this->getType()) {
|
||||
case dp::Attribute::Type::Integer: this->m_value = this->getIntegerOnInput(0); break;
|
||||
case dp::Attribute::Type::Float: this->m_value = this->getFloatOnInput(0); break;
|
||||
case dp::Attribute::Type::Buffer: this->m_value = this->getBufferOnInput(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto& getValue() const { return this->m_value; }
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["name"] = this->m_name;
|
||||
j["type"] = this->m_type;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_name = j["name"].get<std::string>();
|
||||
this->m_type = j["type"];
|
||||
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
this->setAttributes({
|
||||
{ dp::Attribute(dp::Attribute::IOType::In, this->getType(), "hex.builtin.nodes.common.output") }
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_name = LangEntry(this->getUnlocalizedName());
|
||||
int m_type = 0;
|
||||
|
||||
std::variant<i128, long double, std::vector<u8>> m_value;
|
||||
};
|
||||
|
||||
class NodeCustom : public dp::Node {
|
||||
public:
|
||||
NodeCustom() : Node("hex.builtin.nodes.custom.custom.header", {}) { }
|
||||
~NodeCustom() override = default;
|
||||
|
||||
void drawNode() override {
|
||||
if (this->m_requiresAttributeUpdate) {
|
||||
this->m_requiresAttributeUpdate = false;
|
||||
this->setAttributes(this->findAttributes());
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(200_scaled);
|
||||
|
||||
bool editing = false;
|
||||
if (this->m_editable) {
|
||||
ImGui::InputTextIcon("##name", ICON_VS_SYMBOL_KEY, this->m_name);
|
||||
editing = ImGui::IsItemActive();
|
||||
|
||||
if (ImGui::Button("hex.builtin.nodes.custom.custom.edit"_lang, ImVec2(200_scaled, ImGui::GetTextLineHeightWithSpacing()))) {
|
||||
auto &data = ProviderExtraData::getCurrent().dataProcessor;
|
||||
data.workspaceStack.push_back(&this->m_workspace);
|
||||
|
||||
this->m_requiresAttributeUpdate = true;
|
||||
}
|
||||
} else {
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
|
||||
if (this->getAttributes().empty()) {
|
||||
ImGui::TextUnformatted("hex.builtin.nodes.custom.custom.edit_hint"_lang);
|
||||
}
|
||||
}
|
||||
|
||||
this->m_editable = ImGui::GetIO().KeyShift || editing;
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void process() override {
|
||||
auto indexFromId = [this](u32 id) -> std::optional<u32> {
|
||||
const auto &attributes = this->getAttributes();
|
||||
for (u32 i = 0; i < attributes.size(); i++)
|
||||
if (u32(attributes[i].getId()) == id)
|
||||
return i;
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
auto prevContext = ImNodes::GetCurrentContext();
|
||||
ImNodes::SetCurrentContext(this->m_workspace.context.get());
|
||||
ON_SCOPE_EXIT { ImNodes::SetCurrentContext(prevContext); };
|
||||
|
||||
// Forward inputs to input nodes values
|
||||
for (auto &attribute : this->getAttributes()) {
|
||||
auto index = indexFromId(attribute.getId());
|
||||
if (!index.has_value())
|
||||
continue;
|
||||
|
||||
if (auto input = this->findInput(attribute.getUnlocalizedName()); input != nullptr) {
|
||||
switch (attribute.getType()) {
|
||||
case dp::Attribute::Type::Integer: {
|
||||
const auto &value = this->getIntegerOnInput(*index);
|
||||
input->setValue(value);
|
||||
break;
|
||||
}
|
||||
case dp::Attribute::Type::Float: {
|
||||
const auto &value = this->getFloatOnInput(*index);
|
||||
input->setValue(value);
|
||||
break;
|
||||
}
|
||||
case dp::Attribute::Type::Buffer: {
|
||||
const auto &value = this->getBufferOnInput(*index);
|
||||
input->setValue(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process all nodes in our workspace
|
||||
for (auto &endNode : this->m_workspace.endNodes) {
|
||||
endNode->resetOutputData();
|
||||
|
||||
for (auto &node : this->m_workspace.nodes)
|
||||
node->resetProcessedInputs();
|
||||
|
||||
endNode->process();
|
||||
}
|
||||
|
||||
// Forward output node values to outputs
|
||||
for (auto &attribute : this->getAttributes()) {
|
||||
auto index = indexFromId(attribute.getId());
|
||||
if (!index.has_value())
|
||||
continue;
|
||||
|
||||
if (auto output = this->findOutput(attribute.getUnlocalizedName()); output != nullptr) {
|
||||
switch (attribute.getType()) {
|
||||
case dp::Attribute::Type::Integer: {
|
||||
auto value = std::get<i128>(output->getValue());
|
||||
this->setIntegerOnOutput(*index, value);
|
||||
break;
|
||||
}
|
||||
case dp::Attribute::Type::Float: {
|
||||
auto value = std::get<long double>(output->getValue());
|
||||
this->setFloatOnOutput(*index, value);
|
||||
break;
|
||||
}
|
||||
case dp::Attribute::Type::Buffer: {
|
||||
auto value = std::get<std::vector<u8>>(output->getValue());
|
||||
this->setBufferOnOutput(*index, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["nodes"] = ViewDataProcessor::saveNodes(this->m_workspace);
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
ViewDataProcessor::loadNodes(this->m_workspace, j["nodes"]);
|
||||
|
||||
this->m_name = LangEntry(this->getUnlocalizedTitle()).get();
|
||||
this->m_requiresAttributeUpdate = true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<dp::Attribute> findAttributes() {
|
||||
std::vector<dp::Attribute> result;
|
||||
|
||||
for (auto &node : this->m_workspace.nodes) {
|
||||
if (auto *inputNode = dynamic_cast<NodeCustomInput*>(node.get()); inputNode != nullptr)
|
||||
result.emplace_back(dp::Attribute::IOType::In, inputNode->getType(), inputNode->getName());
|
||||
else if (auto *outputNode = dynamic_cast<NodeCustomOutput*>(node.get()); outputNode != nullptr)
|
||||
result.emplace_back(dp::Attribute::IOType::Out, outputNode->getType(), outputNode->getName());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NodeCustomInput* findInput(const std::string &name) {
|
||||
for (auto &node : this->m_workspace.nodes) {
|
||||
if (auto *inputNode = dynamic_cast<NodeCustomInput*>(node.get()); inputNode != nullptr && inputNode->getName() == name)
|
||||
return inputNode;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodeCustomOutput* findOutput(const std::string &name) {
|
||||
for (auto &node : this->m_workspace.nodes) {
|
||||
if (auto *outputNode = dynamic_cast<NodeCustomOutput*>(node.get()); outputNode != nullptr && outputNode->getName() == name)
|
||||
return outputNode;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_name = "hex.builtin.nodes.custom.custom.header"_lang;
|
||||
|
||||
bool m_editable = false;
|
||||
|
||||
bool m_requiresAttributeUpdate = false;
|
||||
ProviderExtraData::Data::DataProcessor::Workspace m_workspace;
|
||||
};
|
||||
|
||||
void registerDataProcessorNodes() {
|
||||
ContentRegistry::DataProcessorNode::add<NodeInteger>("hex.builtin.nodes.constants", "hex.builtin.nodes.constants.int");
|
||||
ContentRegistry::DataProcessorNode::add<NodeFloat>("hex.builtin.nodes.constants", "hex.builtin.nodes.constants.float");
|
||||
@@ -1565,10 +1264,6 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::DataProcessorNode::add<NodeVisualizerByteDistribution>("hex.builtin.nodes.visualizer", "hex.builtin.nodes.visualizer.byte_distribution");
|
||||
|
||||
ContentRegistry::DataProcessorNode::add<NodePatternLanguageOutVariable>("hex.builtin.nodes.pattern_language", "hex.builtin.nodes.pattern_language.out_var");
|
||||
|
||||
ContentRegistry::DataProcessorNode::add<NodeCustom>("hex.builtin.nodes.custom", "hex.builtin.nodes.custom.custom");
|
||||
ContentRegistry::DataProcessorNode::add<NodeCustomInput>("hex.builtin.nodes.custom", "hex.builtin.nodes.custom.input");
|
||||
ContentRegistry::DataProcessorNode::add<NodeCustomOutput>("hex.builtin.nodes.custom", "hex.builtin.nodes.custom.output");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user