INSTINCT Code Coverage Report


Directory: src/
File: internal/NodeManager.hpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 14 14 100.0%
Functions: 46 61 75.4%
Branches: 11 26 42.3%

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