diff options
author | rtk0c <[email protected]> | 2021-04-16 16:49:28 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2021-04-16 16:49:28 -0700 |
commit | 4e5730e1fcef150ce2f13f52a278890589ca96ad (patch) | |
tree | 0fe4002349047c7c770754e273d6a1d1ed666cbb /core/src/Model/Workflow.cpp | |
parent | 80d8ae5a6fef6c9a34e81e240539cb655dd99851 (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.cpp | 306 |
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) { } |