impr: Run data processor in a worker task

This commit is contained in:
WerWolv
2024-07-11 23:30:54 +02:00
parent 7975edade4
commit 8422965d0b
6 changed files with 136 additions and 75 deletions
@@ -8,6 +8,7 @@
#include <imnodes_internal.h>
#include <string>
#include <hex/api/task_manager.hpp>
#include <nlohmann/json.hpp>
namespace hex::plugin::builtin {
@@ -17,6 +18,8 @@ namespace hex::plugin::builtin {
struct Workspace {
Workspace() = default;
std::unique_ptr<ImNodesContext, void(*)(ImNodesContext*)> context = { []{
ImNodesContext *ctx = ImNodes::CreateContext();
ctx->Style = ImNodes::GetStyle();
@@ -47,7 +50,7 @@ namespace hex::plugin::builtin {
static void eraseLink(Workspace &workspace, int id);
static void eraseNodes(Workspace &workspace, const std::vector<int> &ids);
static void processNodes(Workspace &workspace);
void processNodes(Workspace &workspace);
void reloadCustomNodes();
void updateNodePositions();
@@ -74,6 +77,7 @@ namespace hex::plugin::builtin {
PerProvider<Workspace> m_mainWorkspace;
PerProvider<std::vector<Workspace*>> m_workspaceStack;
TaskHolder m_evaluationTask;
};
}
@@ -138,6 +138,10 @@ namespace hex::plugin::builtin {
this->setIntegerOnOutput(4, m_value);
}
void reset() override {
m_started = false;
}
private:
bool m_started = false;
i128 m_value = 0;
@@ -28,10 +28,7 @@ namespace hex::plugin::builtin {
}
void process() override {
m_value.reset();
const auto &input = this->getIntegerOnInput(0);
m_value = input;
m_value = this->getIntegerOnInput(0);
}
private:
@@ -390,10 +390,6 @@ namespace hex::plugin::builtin {
m_updateNodePositions = true;
});
EventDataChanged::subscribe(this, [this](prv::Provider *provider) {
ViewDataProcessor::processNodes(*m_workspaceStack.get(provider).back());
});
/* Import Nodes */
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.import", "hex.builtin.menu.file.import.data_processor" }, ICON_VS_CHIP, 4050, Shortcut::None, [this]{
fs::openFileBrowser(fs::DialogMode::Open, { {"hex.builtin.view.data_processor.name"_lang, "hexnode" } },
@@ -532,36 +528,49 @@ namespace hex::plugin::builtin {
// Reset any potential node errors
workspace.currNodeError.reset();
// Process all nodes in the workspace
try {
for (auto &endNode : workspace.endNodes) {
// Reset the output data of the end node
endNode->resetOutputData();
m_evaluationTask = TaskManager::createTask("Evaluating Nodes...", 0, [this, workspace = &workspace](Task& task) {
task.setInterruptCallback([]{
dp::Node::interrupt();
});
do {
// Reset processed inputs of all nodes
for (auto &node : workspace.nodes)
node->resetProcessedInputs();
// Process all nodes in the workspace
try {
for (auto &endNode : workspace->endNodes) {
// Reset the output data of the end node
endNode->resetOutputData();
// Process the end node
endNode->process();
}
} catch (const dp::Node::NodeError &e) {
// Handle user errors
// Reset processed inputs of all nodes
for (auto &node : workspace->nodes) {
node->reset();
node->resetProcessedInputs();
}
// Add the node error to the current workspace, so it can be displayed
workspace.currNodeError = e;
// Process the end node
endNode->process();
}
} catch (const dp::Node::NodeError &e) {
// Handle user errors
// Add the node error to the current workspace, so it can be displayed
workspace->currNodeError = e;
// Delete all overlays
for (auto overlay : workspace->dataOverlays)
ImHexApi::Provider::get()->deleteOverlay(overlay);
workspace->dataOverlays.clear();
} catch (const std::runtime_error &e) {
// Handle internal errors
log::fatal("Data processor node implementation bug! {}", e.what());
} catch (const std::exception &e) {
// Handle other fatal errors
log::fatal("Unhandled exception thrown in data processor node! {}", e.what());
}
task.update();
} while (m_continuousEvaluation);
});
// Delete all overlays
for (auto overlay : workspace.dataOverlays)
ImHexApi::Provider::get()->deleteOverlay(overlay);
workspace.dataOverlays.clear();
} catch (const std::runtime_error &e) {
// Handle internal errors
log::fatal("Data processor node implementation bug! {}", e.what());
} catch (const std::exception &e) {
// Handle other fatal errors
log::fatal("Unhandled exception thrown in data processor node! {}", e.what());
}
}
void ViewDataProcessor::reloadCustomNodes() {
@@ -774,7 +783,9 @@ namespace hex::plugin::builtin {
// Draw the node's body
ImGui::PopStyleVar();
node.drawNode();
if (!m_evaluationTask.isRunning()) {
node.draw();
}
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1.0F, 1.0F));
// Draw all attributes of the node
@@ -851,6 +862,8 @@ namespace hex::plugin::builtin {
void ViewDataProcessor::drawContent() {
auto &workspace = *m_workspaceStack->back();
ImGui::BeginDisabled(m_evaluationTask.isRunning());
bool popWorkspace = false;
// Set the ImNodes context to the current workspace context
ImNodes::SetCurrentContext(workspace.context.get());
@@ -873,6 +886,9 @@ namespace hex::plugin::builtin {
if (ImGui::BeginChild("##node_editor", ImGui::GetContentRegionAvail() - ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 1.3F))) {
ImNodes::BeginNodeEditor();
if (m_evaluationTask.isRunning())
ImNodes::GetCurrentContext()->MousePos = { FLT_MAX, FLT_MAX };
// Loop over all nodes that have been placed in the workspace
bool stillUpdating = m_updateNodePositions;
for (auto &node : workspace.nodes) {
@@ -933,10 +949,19 @@ namespace hex::plugin::builtin {
}
ImGui::EndChild();
ImGui::EndDisabled();
// Draw the control bar at the bottom
{
if (ImGuiExt::IconButton(ICON_VS_DEBUG_START, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen)) || m_continuousEvaluation)
this->processNodes(workspace);
if (!m_evaluationTask.isRunning()) {
if (ImGuiExt::IconButton(ICON_VS_DEBUG_START, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen))) {
this->processNodes(workspace);
}
} else {
if (ImGuiExt::IconButton(ICON_VS_DEBUG_STOP, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) {
m_evaluationTask.interrupt();
}
}
ImGui::SameLine();
@@ -944,7 +969,7 @@ namespace hex::plugin::builtin {
}
// Erase links that have been distroyed
// Erase links that have been destroyed
{
int linkId;
if (ImNodes::IsLinkDestroyed(&linkId)) {