aboutsummaryrefslogtreecommitdiff
path: root/core/src/Model/Workflow.cpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2021-04-16 16:49:28 -0700
committerrtk0c <[email protected]>2021-04-16 16:49:28 -0700
commit4e5730e1fcef150ce2f13f52a278890589ca96ad (patch)
tree0fe4002349047c7c770754e273d6a1d1ed666cbb /core/src/Model/Workflow.cpp
parent80d8ae5a6fef6c9a34e81e240539cb655dd99851 (diff)
More work on workflows
- WorkflowStep -> WorkflowNode - Added initial kinds of WorkflowNode's
Diffstat (limited to 'core/src/Model/Workflow.cpp')
-rw-r--r--core/src/Model/Workflow.cpp306
1 files changed, 253 insertions, 53 deletions
diff --git a/core/src/Model/Workflow.cpp b/core/src/Model/Workflow.cpp
index 96031c1..385544e 100644
--- a/core/src/Model/Workflow.cpp
+++ b/core/src/Model/Workflow.cpp
@@ -1,98 +1,298 @@
#include "Workflow.hpp"
-bool WorkflowStep::InputNode::IsConnected() const {
- return ConnectedNodeIndex != -1;
+#include <cassert>
+#include <utility>
+
+WorkflowConnection::WorkflowConnection()
+ : Source{ WorkflowNode::kInvalidId }
+ , Destination{ WorkflowNode::kInvalidId }
+ , SourcePin{ -1 }
+ , DestinationPin{ -1 } {
+}
+
+bool WorkflowConnection::IsValid() const {
+ return Source != WorkflowNode::kInvalidId;
+}
+
+bool WorkflowNode::InputPin::IsConstantConnection() const {
+ return ConnectionToConst;
}
-bool WorkflowStep::OutputNode::IsConnected() const {
- return ConnectedNodeIndex != -1;
+bool WorkflowNode::InputPin::IsConnected() const {
+ return Connection != WorkflowConnection::kInvalidId;
}
-size_t WorkflowStep::GetId() const {
+bool WorkflowNode::OutputPin::IsConnected() const {
+ return Connection != WorkflowConnection::kInvalidId;
+}
+
+WorkflowNode::WorkflowNode(Type type, Kind kind)
+ : mType{ type }
+ , mKind{ kind } {
+}
+
+size_t WorkflowNode::GetId() const {
return mId;
}
-void WorkflowStep::ConnectInput(int nodeId, size_t outputId, int outputNodeId) {
- mWorkflow->Connect(mId, nodeId, outputId, outputNodeId);
+WorkflowNode::Type WorkflowNode::GetType() const {
+ return mType;
+}
+
+WorkflowNode::Kind WorkflowNode::GetKind() const {
+ return mKind;
+}
+
+void WorkflowNode::ConnectInput(int nodeId, WorkflowNode& output, int outputNodeId) {
+ mWorkflow->Connect(*this, nodeId, output, outputNodeId);
}
-void WorkflowStep::DisconnectInput(int nodeId) {
- mWorkflow->DisconnectByDestination(mId, nodeId);
+void WorkflowNode::DisconnectInput(int nodeId) {
+ mWorkflow->DisconnectByDestination(*this, nodeId);
}
-bool WorkflowStep::IsInputConnected(int nodeId) const {
+bool WorkflowNode::IsInputConnected(int nodeId) const {
return mInputs[nodeId].IsConnected();
}
-void WorkflowStep::ConnectOutput(int nodeId, size_t inputId, int inputNodeId) {
- mWorkflow->Connect(inputId, inputNodeId, mId, nodeId);
+void WorkflowNode::ConnectOutput(int nodeId, WorkflowNode& input, int inputNodeId) {
+ mWorkflow->Connect(input, inputNodeId, *this, nodeId);
}
-void WorkflowStep::DisconnectOutput(int nodeId) {
- mWorkflow->DisconnectBySource(mId, nodeId);
+void WorkflowNode::DisconnectOutput(int nodeId) {
+ mWorkflow->DisconnectBySource(*this, nodeId);
}
-bool WorkflowStep::IsOutputConnected(int nodeId) const {
+bool WorkflowNode::IsOutputConnected(int nodeId) const {
return mOutputs[nodeId].IsConnected();
}
+WorkflowNode::InputPin& WorkflowNode::InsertInputPin(int atIdx) {
+ assert(atIdx >= 0 && atIdx < mInputs.size());
+
+ mInputs.push_back(InputPin{});
+ for (int i = (int)mInputs.size() - 1, end = atIdx + 1; i >= end; --i) {
+ SwapInputPin(i, i + 1);
+ }
+
+ return mInputs[atIdx];
+}
+
+void WorkflowNode::RemoveInputPin(int pin) {
+ DisconnectInput(pin);
+ for (int i = 0, end = (int)mInputs.size() - 1; i < end; ++i) {
+ SwapInputPin(i, i + 1);
+ }
+ mInputs.resize(mInputs.size() - 1);
+}
+
+void WorkflowNode::SwapInputPin(int a, int b) {
+ auto& pinA = mInputs[a];
+ auto& pinB = mInputs[b];
+
+ if (mWorkflow) {
+ if (pinA.IsConnected() && !pinA.IsConstantConnection()) {
+ auto& conn = *mWorkflow->GetConnectionById(pinA.Connection);
+ conn.DestinationPin = b;
+ }
+ if (pinB.IsConnected() && !pinB.IsConstantConnection()) {
+ auto& conn = *mWorkflow->GetConnectionById(pinB.Connection);
+ conn.DestinationPin = a;
+ }
+ }
+
+ std::swap(pinA, pinB);
+}
+
+WorkflowNode::OutputPin& WorkflowNode::InsertOutputPin(int atIdx) {
+ assert(atIdx >= 0 && atIdx < mOutputs.size());
+
+ mOutputs.push_back(OutputPin{});
+ for (int i = (int)mOutputs.size() - 1, end = atIdx + 1; i >= end; --i) {
+ SwapOutputPin(i, i + 1);
+ }
+
+ return mOutputs[atIdx];
+}
+
+void WorkflowNode::RemoveOutputPin(int pin) {
+ DisconnectOutput(pin);
+ for (int i = 0, end = (int)mOutputs.size() - 1; i < end; ++i) {
+ SwapInputPin(i, i + 1);
+ }
+ mOutputs.resize(mOutputs.size() - 1);
+}
+
+void WorkflowNode::SwapOutputPin(int a, int b) {
+ auto& pinA = mOutputs[a];
+ auto& pinB = mOutputs[b];
+
+ if (mWorkflow) {
+ if (pinA.IsConnected()) {
+ auto& conn = *mWorkflow->GetConnectionById(pinA.Connection);
+ conn.SourcePin = b;
+ }
+ if (pinB.IsConnected()) {
+ auto& conn = *mWorkflow->GetConnectionById(pinB.Connection);
+ conn.SourcePin = a;
+ }
+ }
+
+ std::swap(pinA, pinB);
+}
+
WorkflowConnection* Workflow::GetConnectionById(size_t id) {
return &mConnections[id];
}
-WorkflowStep* Workflow::GetStepById(size_t id) {
- return mSteps[id].get();
+WorkflowNode* Workflow::GetStepById(size_t id) {
+ return mNodes[id].get();
+}
+
+BaseValue* Workflow::GetConstantById(size_t id) {
+ return mConstants[id].get();
+}
+
+void Workflow::AddStep(std::unique_ptr<WorkflowNode> step) {
+ auto [storage, id] = AllocWorkflowStep();
+ storage = std::move(step);
+ storage->OnAttach(*this, id);
+ storage->mWorkflow = this;
+ storage->mId = id;
+}
+
+void Workflow::RemoveStep(size_t id) {
+ auto& step = mNodes[id];
+ if (step == nullptr) return;
+
+ step->OnDetach();
+ step->mWorkflow = nullptr;
+ step->mId = WorkflowNode::kInvalidId;
+}
+
+void Workflow::Connect(WorkflowNode& source, int sourceNode, WorkflowNode& destination, int destinationNode) {
+ if (source.mInputs[sourceNode].IsConnected()) {
+ DisconnectBySource(source, sourceNode);
+ }
+
+ auto [conn, id] = AllocWorkflowConnection();
+ conn.Source = source.GetId();
+ conn.SourcePin = sourceNode;
+ conn.Destination = destination.GetId();
+ conn.DestinationPin = destinationNode;
+
+ source.mInputs[sourceNode].Connection = id;
+ destination.mInputs[destinationNode].Connection = id;
+}
+
+void Workflow::DisconnectBySource(WorkflowNode& source, int sourceNode) {
+ auto& sn = source.mOutputs[sourceNode];
+ if (!sn.IsConnected()) return;
+
+ auto& conn = mConnections[sn.Connection];
+ auto& dn = mNodes[conn.Destination]->mInputs[conn.DestinationPin];
+
+ sn.Connection = WorkflowConnection::kInvalidId;
+ dn.Connection = WorkflowConnection::kInvalidId;
+ conn = {};
+}
+
+void Workflow::DisconnectByDestination(WorkflowNode& destination, int destinationNode) {
+ auto& dn = destination.mOutputs[destinationNode];
+ if (!dn.IsConnected()) return;
+
+ auto& conn = mConnections[dn.Connection];
+ auto& sn = mNodes[conn.Source]->mInputs[conn.SourcePin];
+
+ sn.Connection = WorkflowConnection::kInvalidId;
+ dn.Connection = WorkflowConnection::kInvalidId;
+ conn = {};
+}
+
+std::pair<WorkflowConnection&, size_t> Workflow::AllocWorkflowConnection() {
+ for (size_t idx = 0; idx < mConnections.size(); ++idx) {
+ auto& elm = mConnections[idx];
+ if (!elm.IsValid()) {
+ return { elm, idx };
+ }
+ }
+
+ auto id = mConnections.size();
+ return { mConnections.emplace_back(WorkflowConnection{}), id };
+}
+
+std::pair<std::unique_ptr<WorkflowNode>&, size_t> Workflow::AllocWorkflowStep() {
+ for (size_t idx = 0; idx < mNodes.size(); ++idx) {
+ auto& elm = mNodes[idx];
+ if (elm == nullptr) {
+ return { elm, idx };
+ }
+ }
+
+ auto id = mNodes.size();
+ return { mNodes.emplace_back(std::unique_ptr<WorkflowNode>()), id };
}
-void WorkflowStep::OnIOAboutToChange() {
- // TODO more robust solution that handles changes incrementally
- for (size_t i = 0; i < mInputs.size(); ++i) {
- DisconnectInput(i);
+struct WorkflowEvaluationContext::RuntimeNode {
+ WorkflowNode* Node;
+};
+
+struct WorkflowEvaluationContext::RuntimeConnection {
+ WorkflowConnection* Connection;
+ std::unique_ptr<BaseValue> Value;
+};
+
+WorkflowEvaluationContext::WorkflowEvaluationContext(Workflow& workflow)
+ : mWorkflow{ &workflow } {
+ mNodes.resize(workflow.mNodes.size());
+ for (size_t i = 0; i < workflow.mNodes.size(); ++i) {
+ mNodes[i].Node = workflow.mNodes[i].get();
}
- for (size_t i = 0; i < mOutputs.size(); ++i) {
- DisconnectOutput(i);
+
+ mConnections.resize(workflow.mConnections.size());
+ for (size_t i = 0; i < workflow.mConnections.size(); ++i) {
+ mConnections[i].Connection = &workflow.mConnections[i];
}
}
-void WorkflowStep::OnIOChanged() {
+BaseValue* WorkflowEvaluationContext::GetConnectionValue(size_t id, bool constant) {
+ if (constant) {
+ return mWorkflow->GetConstantById(id);
+ } else {
+ return mConnections[id].Value.get();
+ }
}
-void Workflow::Connect(size_t source, int sourceNode, size_t destination, int destinationNode) {
- auto& src = *mSteps[source];
- auto& o = src.mInputs[sourceNode];
- if (o.IsConnected()) {
- DisconnectBySource(source, sourceNode);
+BaseValue* WorkflowEvaluationContext::GetConnectionValue(const WorkflowNode::InputPin& inputPin) {
+ if (inputPin.IsConnected()) {
+ return GetConnectionValue(inputPin.Connection, inputPin.IsConstantConnection());
+ } else {
+ return nullptr;
}
+}
+
+void WorkflowEvaluationContext::SetConnectionValue(size_t id, std::unique_ptr<BaseValue> value) {
+ mConnections[id].Value = std::move(value);
+}
- o.ConnectedStep = destination;
- o.ConnectedNodeIndex = destinationNode;
+void WorkflowEvaluationContext::SetConnectionValue(const WorkflowNode::OutputPin& outputPin, std::unique_ptr<BaseValue> value) {
+ if (outputPin.IsConnected()) {
+ SetConnectionValue(outputPin.Connection, std::move(value));
+ }
+}
- auto& dst = *mSteps[destination];
- auto& i = dst.mInputs[destinationNode];
- i.ConnectedStep = source;
- i.ConnectedNodeIndex = sourceNode;
+void WorkflowEvaluationContext::Run() {
+ // TODO
}
-void Workflow::DisconnectBySource(size_t source, int sourceNode) {
- auto& src = *mSteps[source];
- auto& o = src.mOutputs[sourceNode];
- if (!o.IsConnected()) return;
+void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node, int pinId, bool inputPin) {
+}
- auto& i = mSteps[o.ConnectedStep]->mInputs[o.ConnectedNodeIndex];
- i.ConnectedStep = WorkflowStep::kInvalidId;
- i.ConnectedNodeIndex = -1;
- o.ConnectedStep = WorkflowStep::kInvalidId;
- o.ConnectedNodeIndex = -1;
+void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node) {
}
-void Workflow::DisconnectByDestination(size_t destination, int destinationNode) {
- auto& dst = *mSteps[destination];
- auto& i = dst.mInputs[destinationNode];
- if (!i.IsConnected()) return;
+void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node, int pinId, bool inputPin) {
+}
- auto& o = mSteps[i.ConnectedStep]->mOutputs[i.ConnectedNodeIndex];
- i.ConnectedStep = WorkflowStep::kInvalidId;
- i.ConnectedNodeIndex = -1;
- o.ConnectedStep = WorkflowStep::kInvalidId;
- o.ConnectedNodeIndex = -1;
+void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node) {
}