diff options
author | rtk0c <[email protected]> | 2021-05-12 13:23:56 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2021-05-12 13:34:43 -0700 |
commit | 765df313e065f8401319c68ba70cd41b0bc34c9d (patch) | |
tree | 44e0c781ed9f5ea0f98ac906e96c677d04befa27 /core/src/Model/Workflow | |
parent | 6ec8cc216282396ece535941ea6ca4a63d924e8f (diff) |
Start to work on actually rendering the node graph
Diffstat (limited to 'core/src/Model/Workflow')
-rw-r--r-- | core/src/Model/Workflow/Value.hpp | 12 | ||||
-rw-r--r-- | core/src/Model/Workflow/Value_RTTI.cpp | 29 | ||||
-rw-r--r-- | core/src/Model/Workflow/Workflow.hpp | 100 | ||||
-rw-r--r-- | core/src/Model/Workflow/Workflow_Main.cpp | 193 |
4 files changed, 220 insertions, 114 deletions
diff --git a/core/src/Model/Workflow/Value.hpp b/core/src/Model/Workflow/Value.hpp index 6cd42f3..8b3e63a 100644 --- a/core/src/Model/Workflow/Value.hpp +++ b/core/src/Model/Workflow/Value.hpp @@ -1,5 +1,8 @@ #pragma once +#include "cplt_fwd.hpp" +#include "Utils/Color.hpp" + #include <iosfwd> #include <memory> @@ -17,11 +20,18 @@ public: KindCount = InvalidKind, }; + struct KindInfo + { + ImGui::IconType PinIcon; + RgbaColor PinColor; + }; + private: Kind mKind; public: - static const char* FormatKind(Kind kind); + static const KindInfo& QueryInfo(Kind kind); + static const char* Format(Kind kind); static std::unique_ptr<BaseValue> CreateByKind(Kind kind); BaseValue(Kind kind); diff --git a/core/src/Model/Workflow/Value_RTTI.cpp b/core/src/Model/Workflow/Value_RTTI.cpp index a0c3213..5e24ed7 100644 --- a/core/src/Model/Workflow/Value_RTTI.cpp +++ b/core/src/Model/Workflow/Value_RTTI.cpp @@ -1,9 +1,34 @@ #include "Value.hpp" #include "Model/Workflow/Values/BasicValues.hpp" -#include "Utils/Macros.hpp" +#include "UI/UI.hpp" -const char* BaseValue::FormatKind(Kind kind) +constexpr BaseValue::KindInfo kNumericInfo{ + .PinIcon = ImGui::IconType::Circle, + .PinColor = RgbaColor(147, 226, 74), +}; + +constexpr BaseValue::KindInfo kTextInfo{ + .PinIcon = ImGui::IconType::Circle, + .PinColor = RgbaColor(124, 21, 153), +}; + +constexpr BaseValue::KindInfo kDateTimeInfo{ + .PinIcon = ImGui::IconType::Diamond, + .PinColor = RgbaColor(147, 226, 74), +}; + +const BaseValue::KindInfo& BaseValue::QueryInfo(BaseValue::Kind kind) +{ + switch (kind) { + case KD_Numeric: return kNumericInfo; + case KD_Text: break; + case KD_DateTime: break; + case InvalidKind: break; + } +} + +const char* BaseValue::Format(Kind kind) { switch (kind) { case KD_Numeric: return "Numeric"; diff --git a/core/src/Model/Workflow/Workflow.hpp b/core/src/Model/Workflow/Workflow.hpp index 7bcd349..79c2b2f 100644 --- a/core/src/Model/Workflow/Workflow.hpp +++ b/core/src/Model/Workflow/Workflow.hpp @@ -17,20 +17,22 @@ class WorkflowConnection { public: - static constexpr auto kInvalidId = std::numeric_limits<size_t>::max(); + static constexpr auto kInvalidId = std::numeric_limits<uint32_t>::max(); - /// Used for `LinkId` when interfacing with imgui node editor. Runtime only (not saved to disk and generated when loading). - size_t UniqueId; - size_t SourceNode; - size_t DestinationNode; - int SourcePin; - int DestinationPin; + uint32_t Id; + uint32_t SourceNode; + uint32_t SourcePin; + uint32_t DestinationNode; + uint32_t DestinationPin; public: WorkflowConnection(); bool IsValid() const; + /// Used for `LinkId` when interfacing with imgui node editor. Runtime only (not saved to disk and generated when loading). + size_t GetLinkId() const; + void DrawDebugInfo() const; void ReadFrom(std::istream& stream); void WriteTo(std::ostream& stream); @@ -39,7 +41,8 @@ public: class WorkflowNode { public: - static constexpr auto kInvalidId = std::numeric_limits<size_t>::max(); + static constexpr auto kInvalidId = std::numeric_limits<uint32_t>::max(); + static constexpr auto kInvalidPinId = std::numeric_limits<uint32_t>::max(); enum Type { @@ -64,16 +67,13 @@ public: KindCount = InvalidKind, }; -protected: struct InputPin { - /// Equivalent of `PinId` when interfacing with imgui node editor. Runtime only (not saved to disk and generated when loading). - size_t UniqueId; - size_t Connection = WorkflowConnection::kInvalidId; + uint32_t Connection = WorkflowConnection::kInvalidId; BaseValue::Kind MatchingType = BaseValue::InvalidKind; bool ConnectionToConst = false; - /// A constant connection connects from a user-specified constant value, feeding to a valid \c Destination and \c DestinationPin (i.e. input pins). + /// A constant connection connects from a user-specified constant value, feeding to a valid \c DestinationNode and \c DestinationPin (i.e. input pins). bool IsConstantConnection() const; bool IsConnected() const; BaseValue::Kind GetMatchingType() const; @@ -81,26 +81,22 @@ protected: struct OutputPin { - /// Equivalent of `PinId` when interfacing with imgui node editor. Runtime only (not saved to disk and generated when loading). - size_t UniqueId; - size_t Connection = WorkflowConnection::kInvalidId; + uint32_t Connection = WorkflowConnection::kInvalidId; BaseValue::Kind MatchingType = BaseValue::InvalidKind; - bool AllowsMultipleConnections = false; bool IsConnected() const; BaseValue::Kind GetMatchingType() const; }; +protected: friend class Workflow; friend class WorkflowEvaluationContext; Workflow* mWorkflow; - /// Equivalent of `NodeId` when interfacing with imgui node editor. Runtime only (not saved to disk and generated when loading). - size_t mUniqueId; - size_t mId; std::vector<InputPin> mInputs; std::vector<OutputPin> mOutputs; Vec2i mPosition; + uint32_t mId; Kind mKind; int mDepth; @@ -120,7 +116,9 @@ public: void SetPosition(const Vec2i& position); Vec2i GetPosition() const; - size_t GetId() const; + uint32_t GetId() const; + /// Used for `NodeId` when interfacing with imgui node editor. Runtime only (not saved to disk and generated when loading). + size_t GetNodeId() const; Kind GetKind() const; int GetDepth() const; @@ -128,13 +126,15 @@ public: bool IsInputNode() const; bool IsOutputNode() const; - void ConnectInput(int nodeId, WorkflowNode& output, int outputNodeId); - void DisconnectInput(int nodeId); - bool IsInputConnected(int nodeId) const; + void ConnectInput(uint32_t pinId, WorkflowNode& output, uint32_t outputNodeId); + void DisconnectInput(uint32_t pinId); + const InputPin& GetInputPin(uint32_t pinId)const ; + size_t GetInputPinUniqueId(uint32_t pinId) const; - void ConnectOutput(int nodeId, WorkflowNode& input, int inputNodeId); - void DisconnectOutput(int nodeId); - bool IsOutputConnected(int nodeId) const; + void ConnectOutput(uint32_t pinId, WorkflowNode& input, uint32_t inputNodeId); + void DisconnectOutput(uint32_t pinId); + const OutputPin& GetOutputPin(uint32_t pinId)const ; + size_t GetOutputPinUniqueId(uint32_t pinId) const; virtual void Evaluate(WorkflowEvaluationContext& ctx) = 0; @@ -157,20 +157,20 @@ protected: /* For \c Workflow to invoke, override by implementations */ - void OnAttach(Workflow& workflow, size_t newId) {} - void OnDetach() {} + void OnAttach(Workflow& workflow, uint32_t newId); + void OnDetach(); }; class Workflow { private: + friend class WorkflowNode; friend class WorkflowEvaluationContext; - size_t mUniqueId = 0; std::vector<WorkflowConnection> mConnections; std::vector<std::unique_ptr<WorkflowNode>> mNodes; std::vector<std::unique_ptr<BaseValue>> mConstants; - std::vector<std::vector<size_t>> mDepthGroups; + std::vector<std::vector<uint32_t>> mDepthGroups; int mConnectionCount; int mNodeCount; int mConstantCount; @@ -186,23 +186,36 @@ public: const std::vector<std::unique_ptr<BaseValue>>& GetConstants() const; std::vector<std::unique_ptr<BaseValue>>& GetConstants(); - WorkflowConnection* GetConnectionById(size_t id); - WorkflowNode* GetStepById(size_t id); - BaseValue* GetConstantById(size_t id); + WorkflowConnection* GetConnectionById(uint32_t id); + WorkflowNode* GetNodeById(uint32_t id); + BaseValue* GetConstantById(uint32_t id); + + struct GlobalPinId + { + WorkflowNode* Node; + uint32_t PinId; + /// true => input pin + /// false => output pin + bool IsOutput; + }; + + /// `pinId` should be the `UniqueId` of a pin from a node that's within this workflow. + GlobalPinId DisassembleGlobalPinId(size_t id); + size_t FabricateGlobalPinId(const WorkflowNode& node, uint32_t pinId, bool isOutput) const; - const std::vector<std::vector<size_t>>& GetDepthGroups() const; + const std::vector<std::vector<uint32_t>>& GetDepthGroups() const; bool DoesDepthNeedsUpdate() const; /* Graph mutation */ - void AddStep(std::unique_ptr<WorkflowNode> step); - void RemoveStep(size_t id); + void AddNode(std::unique_ptr<WorkflowNode> step); + void RemoveNode(uint32_t id); - void RemoveConnection(size_t id); + void RemoveConnection(uint32_t id); - bool Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& destinationNode, int destinationPin); - bool DisconnectBySource(WorkflowNode& sourceNode, int sourcePin); - bool DisconnectByDestination(WorkflowNode& destinationNode, int destinationPin); + bool Connect(WorkflowNode& sourceNode, uint32_t sourcePin, WorkflowNode& destinationNode, uint32_t destinationPin); + bool DisconnectBySource(WorkflowNode& sourceNode, uint32_t sourcePin); + bool DisconnectByDestination(WorkflowNode& destinationNode, uint32_t destinationPin); /* Graph rebuild */ @@ -218,12 +231,12 @@ public: struct UnsatisfiedDependencies { - std::vector<size_t> UnsatisfiedNodes; + std::vector<uint32_t> UnsatisfiedNodes; }; struct UnreachableNodes { - std::vector<size_t> UnreachableNodes; + std::vector<uint32_t> UnreachableNodes; }; using T = std::variant< @@ -246,7 +259,6 @@ public: void WriteTo(std::ostream& stream); private: - size_t AllocUniqueId(); std::pair<WorkflowConnection&, size_t> AllocWorkflowConnection(); std::pair<std::unique_ptr<WorkflowNode>&, size_t> AllocWorkflowStep(); }; diff --git a/core/src/Model/Workflow/Workflow_Main.cpp b/core/src/Model/Workflow/Workflow_Main.cpp index cfa7cea..678b4b8 100644 --- a/core/src/Model/Workflow/Workflow_Main.cpp +++ b/core/src/Model/Workflow/Workflow_Main.cpp @@ -3,7 +3,6 @@ #include <imgui.h> #include <imgui_node_editor.h> #include <tsl/robin_set.h> -#include <algorithm> #include <cassert> #include <iostream> #include <queue> @@ -12,38 +11,46 @@ namespace ImNodes = ax::NodeEditor; WorkflowConnection::WorkflowConnection() - : SourceNode{ WorkflowNode::kInvalidId } + : Id{ 0 } + , SourceNode{ WorkflowNode::kInvalidId } , DestinationNode{ WorkflowNode::kInvalidId } - , SourcePin{ -1 } - , DestinationPin{ -1 } + , SourcePin{ WorkflowNode::kInvalidPinId } + , DestinationPin{ WorkflowNode::kInvalidPinId } { } bool WorkflowConnection::IsValid() const { - return SourceNode != WorkflowNode::kInvalidId; + return Id != 0; +} + +size_t WorkflowConnection::GetLinkId() const +{ + // Our id is 0-based (represents an index directly) + // but imgui-node-editor uses the value 0 to represent a null id, so we need to offset by 1 + return Id + 1; } void WorkflowConnection::DrawDebugInfo() const { ImGui::BeginTooltip(); ImGui::Text("Source (node with output pin):"); - ImGui::Text("{ Node = %llu, Pin = %d }", SourceNode, SourcePin); + ImGui::Text("{ Node = %u, Pin = %u }", SourceNode, SourcePin); ImGui::Text("Destination (node with input pin):"); - ImGui::Text("{ Node = %llu, Pin = %d }", DestinationNode, DestinationPin); + ImGui::Text("{ Node = %u, Pin = %u }", DestinationNode, DestinationPin); ImGui::EndTooltip(); } void WorkflowConnection::ReadFrom(std::istream& stream) { - stream >> SourceNode >> DestinationNode; - stream >> SourcePin >> DestinationPin; + stream >> SourceNode >> SourcePin; + stream >> DestinationNode >> DestinationPin; } void WorkflowConnection::WriteTo(std::ostream& stream) { - stream << SourceNode << DestinationNode; - stream << SourcePin << DestinationPin; + stream << SourceNode << SourcePin; + stream << DestinationNode << DestinationPin; } bool WorkflowNode::InputPin::IsConstantConnection() const @@ -87,11 +94,17 @@ void WorkflowNode::SetPosition(const Vec2i& position) mPosition = position; } -size_t WorkflowNode::GetId() const +uint32_t WorkflowNode::GetId() const { return mId; } +size_t WorkflowNode::GetNodeId() const +{ + // See WorkflowConnection::GetLinkId for the rationale + return mId + 1; +} + WorkflowNode::Kind WorkflowNode::GetKind() const { return mKind; @@ -123,47 +136,57 @@ bool WorkflowNode::IsOutputNode() const return mOutputs.size() == 0; } -void WorkflowNode::ConnectInput(int nodeId, WorkflowNode& output, int outputNodeId) +void WorkflowNode::ConnectInput(uint32_t pinId, WorkflowNode& output, uint32_t outputNodeId) +{ + mWorkflow->Connect(*this, pinId, output, outputNodeId); +} + +void WorkflowNode::DisconnectInput(uint32_t pinId) +{ + mWorkflow->DisconnectByDestination(*this, pinId); +} + +const WorkflowNode::InputPin& WorkflowNode::GetInputPin(uint32_t pinId) const { - mWorkflow->Connect(*this, nodeId, output, outputNodeId); + return mInputs[pinId]; } -void WorkflowNode::DisconnectInput(int nodeId) +size_t WorkflowNode::GetInputPinUniqueId(uint32_t pinId) const { - mWorkflow->DisconnectByDestination(*this, nodeId); + return mWorkflow->FabricateGlobalPinId(*this, pinId, false); } -bool WorkflowNode::IsInputConnected(int nodeId) const +void WorkflowNode::ConnectOutput(uint32_t pinId, WorkflowNode& input, uint32_t inputNodeId) { - return mInputs[nodeId].IsConnected(); + mWorkflow->Connect(input, inputNodeId, *this, pinId); } -void WorkflowNode::ConnectOutput(int nodeId, WorkflowNode& input, int inputNodeId) +void WorkflowNode::DisconnectOutput(uint32_t pinId) { - mWorkflow->Connect(input, inputNodeId, *this, nodeId); + mWorkflow->DisconnectBySource(*this, pinId); } -void WorkflowNode::DisconnectOutput(int nodeId) +const WorkflowNode::OutputPin& WorkflowNode::GetOutputPin(uint32_t pinId) const { - mWorkflow->DisconnectBySource(*this, nodeId); + return mOutputs[pinId]; } -bool WorkflowNode::IsOutputConnected(int nodeId) const +size_t WorkflowNode::GetOutputPinUniqueId(uint32_t pinId) const { - return mOutputs[nodeId].IsConnected(); + return mWorkflow->FabricateGlobalPinId(*this, pinId, true); } void WorkflowNode::Draw() { - for (size_t i = 0; i < mInputs.size(); ++i) { + for (uint32_t i = 0; i < mInputs.size(); ++i) { auto& pin = mInputs[i]; - ImNodes::BeginPin(i, ImNodes::PinKind::Input); + ImNodes::BeginPin(GetInputPinUniqueId(i), ImNodes::PinKind::Input); // TODO ImNodes::EndPin(); } - for (size_t i = 0; i < mOutputs.size(); ++i) { + for (uint32_t i = 0; i < mOutputs.size(); ++i) { auto& pin = mOutputs[i]; - ImNodes::BeginPin(i + mInputs.size(), ImNodes::PinKind::Output); + ImNodes::BeginPin(GetOutputPinUniqueId(i), ImNodes::PinKind::Output); // TODO ImNodes::EndPin(); } @@ -174,7 +197,7 @@ void WorkflowNode::DrawDebugInfo() const ImGui::BeginTooltip(); ImGui::Text("Node kind: %s", FormatKind(mKind)); ImGui::Text("Node type: %s", FormatType(GetType())); - ImGui::Text("Node ID: %llu", mId); + ImGui::Text("Node ID: %u", mId); ImGui::Text("Depth: %d", mDepth); DrawExtraDebugInfo(); ImGui::EndTooltip(); @@ -272,6 +295,14 @@ void WorkflowNode::SwapOutputPin(int a, int b) std::swap(pinA, pinB); } +void WorkflowNode::OnAttach(Workflow& workflow, uint32_t newId) +{ +} + +void WorkflowNode::OnDetach() +{ +} + const std::vector<WorkflowConnection>& Workflow::GetConnections() const { return mConnections; @@ -302,22 +333,57 @@ std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() return mConstants; } -WorkflowConnection* Workflow::GetConnectionById(size_t id) +WorkflowConnection* Workflow::GetConnectionById(uint32_t id) { return &mConnections[id]; } -WorkflowNode* Workflow::GetStepById(size_t id) +WorkflowNode* Workflow::GetNodeById(uint32_t id) { return mNodes[id].get(); } -BaseValue* Workflow::GetConstantById(size_t id) +BaseValue* Workflow::GetConstantById(uint32_t id) { return mConstants[id].get(); } -const std::vector<std::vector<size_t>>& Workflow::GetDepthGroups() const +Workflow::GlobalPinId Workflow::DisassembleGlobalPinId(size_t id) +{ + // imgui-node-editor requires all pins to have a global, unique id + // but in our model the pin are typed (input vs output) and associated with a node: there is no built-in global id + // Therefore we encode one ourselves + + // Global pin id format + // nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn Tppppppp pppppppp pppppppp pppppppp + // <------- (32 bits) node id -------> ^<------ (31 bits) pin id --------> + // | (1 bit) input (false) vs output (true) + + // 1 is added to pin id to prevent the 0th node's 0th input pin resulting in a 0 global pin id + // (this is problematic because imgui-node-editor use 0 to represent null) + + GlobalPinId result; + + result.Node = mNodes[id >> 32].get(); + result.PinId = (uint32_t)(id & 0x000000001FFFFFFF) - 1; + result.IsOutput = id >> 31; + + return result; +} + +size_t Workflow::FabricateGlobalPinId(const WorkflowNode& node, uint32_t pinId, bool isOutput) const +{ + // See this->DisassembleGlobalPinId for format details and rationale + + uint64_t id = 0; + id |= ((uint64_t)node.GetId() << 32); + id |= (isOutput << 31); + id |= ((pinId + 1) & 0x1FFFFFFF); + + return id; +} + +const std::vector<std::vector<uint32_t>>& Workflow::GetDepthGroups() const { return mDepthGroups; } @@ -327,7 +393,7 @@ bool Workflow::DoesDepthNeedsUpdate() const return mDepthsDirty; } -void Workflow::AddStep(std::unique_ptr<WorkflowNode> step) +void Workflow::AddNode(std::unique_ptr<WorkflowNode> step) { auto [storage, id] = AllocWorkflowStep(); storage = std::move(step); @@ -336,7 +402,7 @@ void Workflow::AddStep(std::unique_ptr<WorkflowNode> step) storage->mId = id; } -void Workflow::RemoveStep(size_t id) +void Workflow::RemoveNode(uint32_t id) { auto& step = mNodes[id]; if (step == nullptr) return; @@ -346,7 +412,7 @@ void Workflow::RemoveStep(size_t id) step->mId = WorkflowNode::kInvalidId; } -void Workflow::RemoveConnection(size_t id) +void Workflow::RemoveConnection(uint32_t id) { auto& conn = mConnections[id]; if (!conn.IsValid()) return; @@ -358,7 +424,7 @@ void Workflow::RemoveConnection(size_t id) mDepthsDirty = true; } -bool Workflow::Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& destinationNode, int destinationPin) +bool Workflow::Connect(WorkflowNode& sourceNode, uint32_t sourcePin, WorkflowNode& destinationNode, uint32_t destinationPin) { auto& src = sourceNode.mOutputs[sourcePin]; auto& dst = destinationNode.mInputs[destinationPin]; @@ -385,7 +451,7 @@ bool Workflow::Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& de return true; } -bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, int sourcePin) +bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, uint32_t sourcePin) { auto& sn = sourceNode.mOutputs[sourcePin]; if (!sn.IsConnected()) return false; @@ -401,7 +467,7 @@ bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, int sourcePin) return true; } -bool Workflow::DisconnectByDestination(WorkflowNode& destinationNode, int destinationPin) +bool Workflow::DisconnectByDestination(WorkflowNode& destinationNode, uint32_t destinationPin) { auto& dn = destinationNode.mOutputs[destinationPin]; if (!dn.IsConnected()) return false; @@ -436,7 +502,7 @@ Workflow::GraphUpdateResult::T Workflow::UpdateGraph() }; std::vector<WorkingNode> workingNodes; - std::queue<size_t> q; + std::queue<uint32_t> q; // Check if all dependencies of this node is satisfied auto CheckNodeDependencies = [&](WorkflowNode& node) -> bool { @@ -450,8 +516,8 @@ Workflow::GraphUpdateResult::T Workflow::UpdateGraph() workingNodes.reserve(mNodes.size()); { - std::vector<size_t> unsatisfiedNodes; - for (size_t i = 0; i < mNodes.size(); ++i) { + std::vector<uint32_t> unsatisfiedNodes; + for (uint32_t i = 0; i < mNodes.size(); ++i) { auto& node = mNodes[i]; workingNodes.push_back(WorkingNode{}); @@ -506,8 +572,8 @@ Workflow::GraphUpdateResult::T Workflow::UpdateGraph() if (processedNodes < mNodes.size()) { // There is unreachable nodes, collect them and report to the caller - std::vector<size_t> unreachableNodes; - for (size_t i = 0; i < mNodes.size(); ++i) { + std::vector<uint32_t> unreachableNodes; + for (uint32_t i = 0; i < mNodes.size(); ++i) { auto& wn = workingNodes[i]; auto& n = *mNodes[i]; @@ -526,41 +592,32 @@ Workflow::GraphUpdateResult::T Workflow::UpdateGraph() Workflow::ReadResult Workflow::ReadFrom(std::istream& stream) { auto DeserializeV0 = [&]() { - size_t connectionsStorage, nodesStorage, constantsStorage; - stream >> connectionsStorage >> nodesStorage >> constantsStorage; - uint32_t connectionCount, nodeCount, constantCount; stream >> connectionCount >> nodeCount >> constantCount; + mConnections.reserve(connectionCount); for (uint32_t i = 0; i < connectionCount; ++i) { - size_t idx; - stream >> idx; - - mConnections[idx].ReadFrom(stream); + mConnections.emplace_back().ReadFrom(stream); } + mNodes.reserve(connectionCount); for (uint32_t i = 0; i < nodeCount; ++i) { - size_t idx; - stream >> idx; - uint32_t nKind; stream >> nKind; auto kind = (WorkflowNode::Kind)nKind; - mNodes[idx] = WorkflowNode::CreateByKind(kind); - mNodes[idx]->ReadFrom(stream); + mNodes.push_back(WorkflowNode::CreateByKind(kind)); + mNodes.back()->ReadFrom(stream); } + mConstants.reserve(connectionCount); for (uint32_t i = 0; i < constantCount; ++i) { - size_t idx; - stream >> idx; - uint32_t nKind; stream >> nKind; auto kind = (BaseValue::Kind)nKind; - mConstants[idx] = BaseValue::CreateByKind(kind); - mConstants[idx]->ReadFrom(stream); + mConstants.push_back(BaseValue::CreateByKind(kind)); + mConstants.back()->ReadFrom(stream); } }; @@ -579,6 +636,8 @@ void Workflow::WriteTo(std::ostream& stream) // Version stream << (uint64_t)0; + // TODO id compacting + stream << (size_t)mConnections.size(); stream << (size_t)mNodes.size(); stream << (size_t)mConstants.size(); @@ -621,7 +680,10 @@ std::pair<WorkflowConnection&, size_t> Workflow::AllocWorkflowConnection() } auto id = mConnections.size(); - return { mConnections.emplace_back(WorkflowConnection{}), id }; + auto& conn = mConnections.emplace_back(WorkflowConnection{}); + conn.Id = id; + + return { conn, id }; } std::pair<std::unique_ptr<WorkflowNode>&, size_t> Workflow::AllocWorkflowStep() @@ -634,10 +696,7 @@ std::pair<std::unique_ptr<WorkflowNode>&, size_t> Workflow::AllocWorkflowStep() } auto id = mNodes.size(); - return { mNodes.emplace_back(std::unique_ptr<WorkflowNode>()), id }; -} + auto& node = mNodes.emplace_back(std::unique_ptr<WorkflowNode>()); -size_t Workflow::AllocUniqueId() -{ - return mUniqueId++; + return { node, id }; } |