Line | Branch | Exec | Source |
---|---|---|---|
1 | // This file is part of INSTINCT, the INS Toolkit for Integrated | ||
2 | // Navigation Concepts and Training by the Institute of Navigation of | ||
3 | // the University of Stuttgart, Germany. | ||
4 | // | ||
5 | // This Source Code Form is subject to the terms of the Mozilla Public | ||
6 | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
7 | // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
8 | |||
9 | /// @file NodeManager.hpp | ||
10 | /// @brief Manages all Nodes | ||
11 | /// @author T. Topp (topp@ins.uni-stuttgart.de) | ||
12 | /// @date 2020-12-14 | ||
13 | |||
14 | #pragma once | ||
15 | |||
16 | #include <imgui_node_editor.h> | ||
17 | |||
18 | #include "internal/Node/Node.hpp" | ||
19 | #include "internal/Node/Pin.hpp" | ||
20 | #include "util/Assert.h" | ||
21 | |||
22 | #include "NodeData/NodeData.hpp" | ||
23 | |||
24 | #include <vector> | ||
25 | #include <functional> | ||
26 | |||
27 | namespace NAV::NodeManager | ||
28 | { | ||
29 | /// Flag if invokeCallbacks triggers a GUI Flow event | ||
30 | extern bool showFlowWhenInvokingCallbacks; | ||
31 | |||
32 | /// Flag if notifyOutputValueChanged & notifyInputValueChanged triggers a GUI Flow event | ||
33 | extern bool showFlowWhenNotifyingValueChange; | ||
34 | |||
35 | /// @brief List of all registered Nodes | ||
36 | const std::vector<Node*>& m_Nodes(); | ||
37 | |||
38 | /// @brief Add the provided node object to the list of nodes | ||
39 | /// @param[in] node Node object to add to the list | ||
40 | void AddNode(Node* node); | ||
41 | |||
42 | /// @brief Update the provided node object | ||
43 | /// @param[in] node Node object to add to the list | ||
44 | void UpdateNode(Node* node); | ||
45 | |||
46 | /// @brief Delete the node provided by id | ||
47 | /// @param[in] nodeId Unique Id of the Node to delete | ||
48 | /// @return True if delete was successful, false if NodeId does not exist | ||
49 | bool DeleteNode(ax::NodeEditor::NodeId nodeId); | ||
50 | |||
51 | /// @brief Delete all nodes | ||
52 | void DeleteAllNodes(); | ||
53 | |||
54 | /// @brief Adds the link | ||
55 | /// @param[in] linkId Unique Id of the link | ||
56 | void AddLink(ax::NodeEditor::LinkId linkId); | ||
57 | |||
58 | /// @brief Create an Input Pin object | ||
59 | /// @param[in] node Node to register the Pin for | ||
60 | /// @param[in] name Display name of the Pin | ||
61 | /// @param[in] pinType Type of the pin | ||
62 | /// @param[in] dataIdentifier Identifier of the data which is represented by the pin | ||
63 | /// @param[in] callback Callback to register with the pin | ||
64 | /// @param[in] firable Function to check whether the callback is firable | ||
65 | /// @param[in] priority Priority when checking firable condition related to other pins (higher priority gets triggered first) | ||
66 | /// @param[in] idx Index where to put the new pin (-1 means at the end) | ||
67 | /// @return Pointer to the created pin | ||
68 | InputPin* CreateInputPin(Node* node, const char* name, Pin::Type pinType, const std::vector<std::string>& dataIdentifier = {}, | ||
69 | InputPin::Callback callback = static_cast<InputPin::FlowFirableCallbackFunc>(nullptr), | ||
70 | InputPin::FlowFirableCheckFunc firable = nullptr, | ||
71 | int priority = 0, int idx = -1); | ||
72 | |||
73 | /// @brief Create an Input Pin object | ||
74 | /// @tparam T Node Class where the function is member of | ||
75 | /// @param[in] node Node to register the Pin for | ||
76 | /// @param[in] name Display name of the Pin | ||
77 | /// @param[in] pinType Type of the pin | ||
78 | /// @param[in] dataIdentifier Identifier of the data which is represented by the pin | ||
79 | /// @param[in] callback Flow firable callback function to register with the pin | ||
80 | /// @param[in] firable Function to check whether the callback is firable | ||
81 | /// @param[in] priority Priority when checking firable condition related to other pins (higher priority gets triggered first) | ||
82 | /// @param[in] idx Index where to put the new pin (-1 means at the end) | ||
83 | /// @return Pointer to the created pin | ||
84 | template<std::derived_from<Node> T> | ||
85 | 4182 | InputPin* CreateInputPin(Node* node, const char* name, Pin::Type pinType, const std::vector<std::string>& dataIdentifier = {}, | |
86 | void (T::*callback)(InputPin::NodeDataQueue&, size_t) = nullptr, | ||
87 | InputPin::FlowFirableCheckFunc firable = nullptr, | ||
88 | int priority = 0, int idx = -1) | ||
89 | { | ||
90 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4182 times.
|
4182 | assert(pinType == Pin::Type::Flow); |
91 | |||
92 |
1/2✓ Branch 2 taken 4182 times.
✗ Branch 3 not taken.
|
4182 | return CreateInputPin(node, name, pinType, dataIdentifier, InputPin::Callback(static_cast<InputPin::FlowFirableCallbackFunc>(callback)), firable, priority, idx); |
93 | } | ||
94 | |||
95 | /// @brief Create an Input Pin object | ||
96 | /// @tparam T Node Class where the function is member of | ||
97 | /// @param[in] node Node to register the Pin for | ||
98 | /// @param[in] name Display name of the Pin | ||
99 | /// @param[in] pinType Type of the pin | ||
100 | /// @param[in] dataIdentifier Identifier of the data which is represented by the pin | ||
101 | /// @param[in] notifyFunc Function to call when the data is updated | ||
102 | /// @param[in] idx Index where to put the new pin (-1 means at the end) | ||
103 | /// @return Pointer to the created pin | ||
104 | template<std::derived_from<Node> T> | ||
105 | 224 | InputPin* CreateInputPin(Node* node, const char* name, Pin::Type pinType, const std::vector<std::string>& dataIdentifier, | |
106 | void (T::*notifyFunc)(const InsTime&, size_t), int idx = -1) | ||
107 | { | ||
108 |
2/4✓ Branch 1 taken 224 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 224 times.
✗ Branch 5 not taken.
|
224 | assert(pinType != Pin::Type::Flow && pinType != Pin::Type::Delegate); |
109 | |||
110 |
1/2✓ Branch 2 taken 224 times.
✗ Branch 3 not taken.
|
224 | return CreateInputPin(node, name, pinType, dataIdentifier, InputPin::Callback(static_cast<InputPin::DataChangedNotifyFunc>(notifyFunc)), nullptr, 0, idx); |
111 | } | ||
112 | |||
113 | /// @brief Create an Output Pin object | ||
114 | /// @param[in] node Node to register the Pin for | ||
115 | /// @param[in] name Display name of the Pin | ||
116 | /// @param[in] pinType Type of the pin | ||
117 | /// @param[in] dataIdentifier Identifier of the data which is represented by the pin | ||
118 | /// @param[in] data Pointer to data which is represented by the pin | ||
119 | /// @param[in] idx Index where to put the new pin (-1 means at the end) | ||
120 | /// @return Pointer to the created pin | ||
121 | OutputPin* CreateOutputPin(Node* node, const char* name, Pin::Type pinType, const std::vector<std::string>& dataIdentifier, OutputPin::PinData data = static_cast<void*>(nullptr), int idx = -1); | ||
122 | |||
123 | /// @brief Create an Output Pin object for Flow Pins | ||
124 | /// @tparam T Class where the function is member of | ||
125 | /// @param[in] node Node to register the Pin for | ||
126 | /// @param[in] name Display name of the Pin | ||
127 | /// @param[in] pinType Type of the pin | ||
128 | /// @param[in] dataIdentifier Identifier of the data which is represented by the pin | ||
129 | /// @param[in] peekPollDataFunc Function to poll for data on this pin | ||
130 | /// @param[in] idx Index where to put the new pin (-1 means at the end) | ||
131 | /// @return Pointer to the created pin | ||
132 | template<std::derived_from<Node> T> | ||
133 | 810 | OutputPin* CreateOutputPin(Node* node, const char* name, Pin::Type pinType, const std::vector<std::string>& dataIdentifier, | |
134 | std::shared_ptr<const NAV::NodeData> (T::*peekPollDataFunc)(size_t, bool) = nullptr, int idx = -1) | ||
135 | { | ||
136 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 810 times.
|
810 | assert(pinType == Pin::Type::Flow); |
137 |
1/2✓ Branch 3 taken 810 times.
✗ Branch 4 not taken.
|
2070 | INS_ASSERT_USER_ERROR(std::none_of(node->outputPins.begin(), node->outputPins.end(), |
138 | [](const OutputPin& outputPin) { return std::holds_alternative<OutputPin::PollDataFunc>(outputPin.data); }), | ||
139 | "You cannot mix PollDataFunc and PeekPollDataFunc output pins. Use only PeekPollDataFunc pins if multiple pins are needed."); | ||
140 | |||
141 |
1/2✓ Branch 2 taken 810 times.
✗ Branch 3 not taken.
|
810 | return CreateOutputPin(node, name, pinType, dataIdentifier, OutputPin::PinData(static_cast<OutputPin::PeekPollDataFunc>(peekPollDataFunc)), idx); |
142 | } | ||
143 | |||
144 | /// @brief Create an Output Pin object for Flow Pins | ||
145 | /// @tparam T Class where the function is member of | ||
146 | /// @param[in] node Node to register the Pin for | ||
147 | /// @param[in] name Display name of the Pin | ||
148 | /// @param[in] pinType Type of the pin | ||
149 | /// @param[in] dataIdentifier Identifier of the data which is represented by the pin | ||
150 | /// @param[in] pollDataFunc Function to poll for data on this pin | ||
151 | /// @param[in] idx Index where to put the new pin (-1 means at the end) | ||
152 | /// @return Pointer to the created pin | ||
153 | template<std::derived_from<Node> T> | ||
154 | 1343 | OutputPin* CreateOutputPin(Node* node, const char* name, Pin::Type pinType, const std::vector<std::string>& dataIdentifier, | |
155 | std::shared_ptr<const NAV::NodeData> (T::*pollDataFunc)() = nullptr, int idx = -1) | ||
156 | { | ||
157 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1343 times.
|
1343 | assert(pinType == Pin::Type::Flow); |
158 |
1/6✓ Branch 3 taken 1343 times.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
1343 | INS_ASSERT_USER_ERROR(std::none_of(node->outputPins.begin(), node->outputPins.end(), |
159 | [](const OutputPin& outputPin) { return std::holds_alternative<OutputPin::PeekPollDataFunc>(outputPin.data) | ||
160 | || std::holds_alternative<OutputPin::PollDataFunc>(outputPin.data); }), | ||
161 | "There can only be one poll pin if the poll only data function is chosen. If multiple are needed, create PeekPollDataFunc pins."); | ||
162 | |||
163 |
1/2✓ Branch 2 taken 1343 times.
✗ Branch 3 not taken.
|
1343 | return CreateOutputPin(node, name, pinType, dataIdentifier, OutputPin::PinData(static_cast<OutputPin::PollDataFunc>(pollDataFunc)), idx); |
164 | } | ||
165 | |||
166 | /// @brief Deletes the output pin. Invalidates the pin reference given. | ||
167 | /// @param[in, out] pin Output Pin to delete | ||
168 | /// @return True if the pin was delete | ||
169 | bool DeleteOutputPin(OutputPin& pin); | ||
170 | |||
171 | /// @brief Deletes the input pin. Invalidates the pin reference given. | ||
172 | /// @param[in, out] pin Input Pin to delete | ||
173 | /// @return True if the pin was delete | ||
174 | bool DeleteInputPin(InputPin& pin); | ||
175 | |||
176 | /// @brief Finds the Node for the NodeId | ||
177 | /// @param[in] id Unique Id of the Node to search for | ||
178 | /// @return Pointer to the node or nullptr if the NodeId does not exist | ||
179 | Node* FindNode(ax::NodeEditor::NodeId id); | ||
180 | |||
181 | /// @brief Finds the Pin for the PinId | ||
182 | /// @param[in] id Unique Id of the Pin to search for | ||
183 | /// @return Pointer to the pin or nullptr if the PinId does not exist | ||
184 | OutputPin* FindOutputPin(ax::NodeEditor::PinId id); | ||
185 | |||
186 | /// @brief Finds the Pin for the PinId | ||
187 | /// @param[in] id Unique Id of the Pin to search for | ||
188 | /// @return Pointer to the pin or nullptr if the PinId does not exist | ||
189 | InputPin* FindInputPin(ax::NodeEditor::PinId id); | ||
190 | |||
191 | /// @brief Enables all Node callbacks | ||
192 | void EnableAllCallbacks(); | ||
193 | |||
194 | /// @brief Disables all Node callbacks | ||
195 | void DisableAllCallbacks(); | ||
196 | |||
197 | /// @brief Clears all nodes queues | ||
198 | void ClearAllNodeQueues(); | ||
199 | |||
200 | /// @brief Initializes all nodes. | ||
201 | /// @return Returns false if one of the nodes could not initialize | ||
202 | bool InitializeAllNodes(); | ||
203 | |||
204 | /// @brief Initializes all nodes in a separate thread | ||
205 | void InitializeAllNodesAsync(); | ||
206 | |||
207 | /// @brief Generates a new node id | ||
208 | ax::NodeEditor::NodeId GetNextNodeId(); | ||
209 | |||
210 | /// @brief Generates a new link id | ||
211 | ax::NodeEditor::LinkId GetNextLinkId(); | ||
212 | |||
213 | /// @brief Generates a new pin id | ||
214 | ax::NodeEditor::PinId GetNextPinId(); | ||
215 | |||
216 | #ifdef TESTING | ||
217 | |||
218 | /// @brief Registers the callback function to the watcher list | ||
219 | /// @param[in] id Output pin id to add the callback to | ||
220 | /// @param[in] callback Callback function | ||
221 | /// @attention ApplyWatcherCallbacks() needs to be called after loading the flow to apply the list to the pins. | ||
222 | void RegisterWatcherCallbackToInputPin(ax::NodeEditor::PinId id, const InputPin::WatcherCallback& callback); | ||
223 | |||
224 | /// @brief Registers the callback function to the watcher list | ||
225 | /// @param[in] id Link id to add the callback to | ||
226 | /// @param[in] callback Callback function | ||
227 | /// @attention ApplyWatcherCallbacks() needs to be called after loading the flow to apply the list to the pins. | ||
228 | void RegisterWatcherCallbackToLink(ax::NodeEditor::LinkId id, const InputPin::WatcherCallback& callback); | ||
229 | |||
230 | /// @brief Applies the watcher lists to the node pins | ||
231 | void ApplyWatcherCallbacks(); | ||
232 | |||
233 | /// @brief Registers a callback function which gets called before the nodes are initialized. Used to change node settings. | ||
234 | /// @param[in] callback Callback function | ||
235 | void RegisterPreInitCallback(std::function<void()> callback); | ||
236 | |||
237 | /// @brief Calls the pre-init callback | ||
238 | void CallPreInitCallback(); | ||
239 | |||
240 | /// @brief Registers a callback which gets called after flow execution before cleanup | ||
241 | /// @param[in] callback Callback function | ||
242 | void RegisterCleanupCallback(std::function<void()> callback); | ||
243 | |||
244 | /// @brief Calls the cleanup callback | ||
245 | void CallCleanupCallback(); | ||
246 | |||
247 | /// @brief Clears the watcher list | ||
248 | void ClearRegisteredCallbacks(); | ||
249 | |||
250 | #endif | ||
251 | |||
252 | } // namespace NAV::NodeManager | ||
253 |