| 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 Node.hpp | ||
| 10 | /// @brief Node Class | ||
| 11 | /// @author T. Topp (topp@ins.uni-stuttgart.de) | ||
| 12 | /// @date 2020-12-14 | ||
| 13 | |||
| 14 | #pragma once | ||
| 15 | |||
| 16 | // <boost/asio.hpp> needs to be included before <winsock.h> (even though not used in this file) | ||
| 17 | // https://stackoverflow.com/questions/9750344/boostasio-winsock-and-winsock-2-compatibility-issue | ||
| 18 | #ifdef _WIN32 | ||
| 19 | // Set the proper SDK version before including boost/Asio | ||
| 20 | #include <SDKDDKVer.h> | ||
| 21 | // Note boost/ASIO includes Windows.h. | ||
| 22 | #include <boost/asio.hpp> | ||
| 23 | #endif //_WIN32 | ||
| 24 | |||
| 25 | #include <imgui.h> | ||
| 26 | #include <imgui_node_editor.h> | ||
| 27 | #include <imgui_stdlib.h> | ||
| 28 | |||
| 29 | #include "internal/Node/Pin.hpp" | ||
| 30 | #include "Navigation/Time/InsTime.hpp" | ||
| 31 | |||
| 32 | #include <string> | ||
| 33 | #include <vector> | ||
| 34 | #include <thread> | ||
| 35 | #include <mutex> | ||
| 36 | #include <condition_variable> | ||
| 37 | #include <atomic> | ||
| 38 | #include <chrono> | ||
| 39 | #include <map> | ||
| 40 | |||
| 41 | #include <nlohmann/json.hpp> | ||
| 42 | using json = nlohmann::json; ///< json namespace | ||
| 43 | |||
| 44 | namespace NAV | ||
| 45 | { | ||
| 46 | class Node; | ||
| 47 | class NodeData; | ||
| 48 | class GroupBox; | ||
| 49 | |||
| 50 | namespace NodeRegistry | ||
| 51 | { | ||
| 52 | |||
| 53 | void RegisterNodeTypes(); // NOLINT(readability-redundant-declaration) - false warning. This is needed for the friend declaration below | ||
| 54 | |||
| 55 | } // namespace NodeRegistry | ||
| 56 | |||
| 57 | namespace FlowExecutor | ||
| 58 | { | ||
| 59 | |||
| 60 | /// @brief Main task of the FlowExecutor thread | ||
| 61 | void execute(); // NOLINT(readability-redundant-declaration) - false warning. This is needed for the friend declaration below | ||
| 62 | |||
| 63 | /// @brief Deinitialize all Nodes | ||
| 64 | void deinitialize(); // NOLINT(readability-redundant-declaration) - false warning. This is needed for the friend declaration below | ||
| 65 | |||
| 66 | } // namespace FlowExecutor | ||
| 67 | |||
| 68 | namespace gui | ||
| 69 | { | ||
| 70 | class NodeEditorApplication; | ||
| 71 | |||
| 72 | namespace menus | ||
| 73 | { | ||
| 74 | |||
| 75 | void ShowRunMenu(); | ||
| 76 | |||
| 77 | } // namespace menus | ||
| 78 | |||
| 79 | } // namespace gui | ||
| 80 | |||
| 81 | /// @brief Converts the provided node into a json object | ||
| 82 | /// @param[out] j Json object which gets filled with the info | ||
| 83 | /// @param[in] node Node to convert into json | ||
| 84 | void to_json(json& j, const Node& node); | ||
| 85 | /// @brief Converts the provided json object into a node object | ||
| 86 | /// @param[in] j Json object with the needed values | ||
| 87 | /// @param[out] node Object to fill from the json | ||
| 88 | void from_json(const json& j, Node& node); | ||
| 89 | |||
| 90 | /// @brief Abstract parent class for all nodes | ||
| 91 | class Node | ||
| 92 | { | ||
| 93 | public: | ||
| 94 | /// Kind information class | ||
| 95 | struct Kind | ||
| 96 | { | ||
| 97 | /// Possible kinds of Nodes | ||
| 98 | enum Value : uint8_t | ||
| 99 | { | ||
| 100 | Blueprint, ///< Node with header | ||
| 101 | Simple, ///< Node without header, which displays its name in the center of the content | ||
| 102 | GroupBox, ///< Group box which can group other nodes and drag them together | ||
| 103 | }; | ||
| 104 | |||
| 105 | /// @brief Default Constructor | ||
| 106 | Kind() = default; | ||
| 107 | |||
| 108 | /// @brief Implicit Constructor from Value type | ||
| 109 | /// @param[in] kind Value type to construct from | ||
| 110 | 6855 | constexpr Kind(Value kind) // NOLINT(hicpp-explicit-conversions, google-explicit-constructor) | |
| 111 | 6855 | : value(kind) | |
| 112 | 6855 | {} | |
| 113 | |||
| 114 | /// @brief Constructor from std::string | ||
| 115 | /// @param[in] string String representation of the type | ||
| 116 | 714 | explicit Kind(const std::string& string) | |
| 117 | 714 | { | |
| 118 |
2/2✓ Branch 1 taken 606 times.
✓ Branch 2 taken 108 times.
|
714 | if (string == "Blueprint") |
| 119 | { | ||
| 120 | 606 | value = Kind::Blueprint; | |
| 121 | } | ||
| 122 |
2/2✓ Branch 1 taken 100 times.
✓ Branch 2 taken 8 times.
|
108 | else if (string == "Simple") |
| 123 | { | ||
| 124 | 100 | value = Kind::Simple; | |
| 125 | } | ||
| 126 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | else if (string == "GroupBox") |
| 127 | { | ||
| 128 | 8 | value = Kind::GroupBox; | |
| 129 | } | ||
| 130 | 714 | } | |
| 131 | |||
| 132 | /// @brief Allow switch(Node::Value(kind)) and comparisons | ||
| 133 | explicit operator Value() const { return value; } | ||
| 134 | /// @brief Prevent usage: if(node) | ||
| 135 | explicit operator bool() = delete; | ||
| 136 | /// @brief Assignment operator from Value type | ||
| 137 | /// @param[in] v Value type to construct from | ||
| 138 | /// @return The Kind type from the value type | ||
| 139 | 397 | Kind& operator=(Value v) | |
| 140 | { | ||
| 141 | 397 | value = v; | |
| 142 | 397 | return *this; | |
| 143 | } | ||
| 144 | |||
| 145 | friend constexpr bool operator==(const Node::Kind& lhs, const Node::Kind& rhs); | ||
| 146 | friend constexpr bool operator!=(const Node::Kind& lhs, const Node::Kind& rhs); | ||
| 147 | |||
| 148 | friend constexpr bool operator==(const Node::Kind& lhs, const Node::Kind::Value& rhs); | ||
| 149 | friend constexpr bool operator==(const Node::Kind::Value& lhs, const Node::Kind& rhs); | ||
| 150 | friend constexpr bool operator!=(const Node::Kind& lhs, const Node::Kind::Value& rhs); | ||
| 151 | friend constexpr bool operator!=(const Node::Kind::Value& lhs, const Node::Kind& rhs); | ||
| 152 | |||
| 153 | /// @brief std::string conversion operator | ||
| 154 | /// @return A std::string representation of the node kind | ||
| 155 | ✗ | explicit operator std::string() const | |
| 156 | { | ||
| 157 | ✗ | switch (value) | |
| 158 | { | ||
| 159 | ✗ | case Kind::Blueprint: | |
| 160 | ✗ | return "Blueprint"; | |
| 161 | ✗ | case Kind::Simple: | |
| 162 | ✗ | return "Simple"; | |
| 163 | ✗ | case Kind::GroupBox: | |
| 164 | ✗ | return "GroupBox"; | |
| 165 | } | ||
| 166 | ✗ | return ""; | |
| 167 | } | ||
| 168 | |||
| 169 | private: | ||
| 170 | /// @brief Value of the node kind | ||
| 171 | Value value; | ||
| 172 | }; | ||
| 173 | |||
| 174 | /// @brief Possible states of the node | ||
| 175 | enum class State : uint8_t | ||
| 176 | { | ||
| 177 | Disabled, ///< Node is disabled and won't be initialized | ||
| 178 | Deinitialized, ///< Node is deinitialized (red) | ||
| 179 | DoInitialize, ///< Node should be initialized | ||
| 180 | Initializing, ///< Node is currently initializing | ||
| 181 | Initialized, ///< Node is initialized (green) | ||
| 182 | DoDeinitialize, ///< Node should be deinitialized | ||
| 183 | Deinitializing, ///< Node is currently deinitializing | ||
| 184 | DoShutdown, ///< Node should shut down | ||
| 185 | Shutdown, ///< Node is shutting down | ||
| 186 | }; | ||
| 187 | |||
| 188 | /// @brief Different Modes the Node can work in | ||
| 189 | enum class Mode : uint8_t | ||
| 190 | { | ||
| 191 | REAL_TIME, ///< Node running in real-time mode | ||
| 192 | POST_PROCESSING, ///< Node running in post-processing mode | ||
| 193 | }; | ||
| 194 | |||
| 195 | /// @brief Constructor | ||
| 196 | /// @param[in] name Name of the node | ||
| 197 | explicit Node(std::string name); | ||
| 198 | /// @brief Destructor | ||
| 199 | virtual ~Node(); | ||
| 200 | /// @brief Copy constructor | ||
| 201 | Node(const Node&) = delete; | ||
| 202 | /// @brief Move constructor | ||
| 203 | Node(Node&&) = delete; | ||
| 204 | /// @brief Copy assignment operator | ||
| 205 | Node& operator=(const Node&) = delete; | ||
| 206 | /// @brief Move assignment operator | ||
| 207 | Node& operator=(Node&&) = delete; | ||
| 208 | |||
| 209 | /* -------------------------------------------------------------------------------------------------------- */ | ||
| 210 | /* Interface */ | ||
| 211 | /* -------------------------------------------------------------------------------------------------------- */ | ||
| 212 | |||
| 213 | /// @brief String representation of the Class Type | ||
| 214 | [[nodiscard]] virtual std::string type() const = 0; | ||
| 215 | |||
| 216 | /// @brief ImGui config window which is shown on double click | ||
| 217 | /// @attention Don't forget to set hasConfig to true | ||
| 218 | virtual void guiConfig(); | ||
| 219 | |||
| 220 | /// @brief Saves the node into a json object | ||
| 221 | [[nodiscard]] virtual json save() const; | ||
| 222 | |||
| 223 | /// @brief Restores the node from a json object | ||
| 224 | /// @param[in] j Json object with the node state | ||
| 225 | virtual void restore(const json& j); | ||
| 226 | |||
| 227 | /// @brief Restores link related properties of the node from a json object | ||
| 228 | /// @param[in] j Json object with the node state | ||
| 229 | virtual void restoreAtferLink(const json& j); | ||
| 230 | |||
| 231 | /// @brief Initialize the Node | ||
| 232 | /// | ||
| 233 | /// Here a node can do things like | ||
| 234 | /// - connecting to a sensor | ||
| 235 | /// - read a static data file which needs to be read completely (e.g. RINEX nav files) | ||
| 236 | /// - reset variables in case the NAV::Node::resetNode() is not used | ||
| 237 | /// @attention This function is called in the default implementation of the NAV::Node::resetNode() function. | ||
| 238 | /// If the initialize function should not be called more than once, make sure to override the NAV::Node::resetNode() function. | ||
| 239 | virtual bool initialize(); | ||
| 240 | |||
| 241 | /// @brief Deinitialize the Node | ||
| 242 | virtual void deinitialize(); | ||
| 243 | |||
| 244 | /// @brief Resets the node. It is guaranteed that the node is initialized when this is called. | ||
| 245 | virtual bool resetNode(); | ||
| 246 | |||
| 247 | /// @brief Called when a new link is to be established | ||
| 248 | /// @param[in] startPin Pin where the link starts | ||
| 249 | /// @param[in] endPin Pin where the link ends | ||
| 250 | /// @return True if link is allowed, false if link is rejected | ||
| 251 | virtual bool onCreateLink(OutputPin& startPin, InputPin& endPin); | ||
| 252 | |||
| 253 | /// @brief Called when a link is to be deleted | ||
| 254 | /// @param[in] startPin Pin where the link starts | ||
| 255 | /// @param[in] endPin Pin where the link ends | ||
| 256 | virtual void onDeleteLink(OutputPin& startPin, InputPin& endPin); | ||
| 257 | |||
| 258 | /// @brief Called when a new link was established | ||
| 259 | /// @param[in] startPin Pin where the link starts | ||
| 260 | /// @param[in] endPin Pin where the link ends | ||
| 261 | virtual void afterCreateLink(OutputPin& startPin, InputPin& endPin); | ||
| 262 | |||
| 263 | /// @brief Called when a link was deleted | ||
| 264 | /// @param[in] startPin Pin where the link starts | ||
| 265 | /// @param[in] endPin Pin where the link ends | ||
| 266 | virtual void afterDeleteLink(OutputPin& startPin, InputPin& endPin); | ||
| 267 | |||
| 268 | /// @brief Function called by the flow executer after finishing to flush out remaining data | ||
| 269 | virtual void flush(); | ||
| 270 | |||
| 271 | /* -------------------------------------------------------------------------------------------------------- */ | ||
| 272 | /* Member functions */ | ||
| 273 | /* -------------------------------------------------------------------------------------------------------- */ | ||
| 274 | |||
| 275 | /// @brief Notifies connected nodes about the change | ||
| 276 | /// @param[in] pinIdx Output Port index where to set the value | ||
| 277 | /// @param[in] insTime Time the value was generated | ||
| 278 | /// @param[in] guard Lock guard of the output data | ||
| 279 | void notifyOutputValueChanged(size_t pinIdx, const InsTime& insTime, const std::scoped_lock<std::mutex>&& guard); | ||
| 280 | |||
| 281 | /// @brief Blocks the thread till the output values was read by all connected nodes | ||
| 282 | /// @param[in] pinIdx Output Pin index where to request the lock | ||
| 283 | [[nodiscard]] std::scoped_lock<std::mutex> requestOutputValueLock(size_t pinIdx); | ||
| 284 | |||
| 285 | /// @brief Get Input Value connected on the pin. Only const data types. | ||
| 286 | /// @tparam T Type of the connected object | ||
| 287 | /// @param[in] portIndex Input port where to retrieve the data from | ||
| 288 | /// @return Pointer to the object | ||
| 289 | template<typename T> | ||
| 290 | 3041 | [[nodiscard]] std::optional<InputPin::IncomingLink::ValueWrapper<T>> getInputValue(size_t portIndex) const | |
| 291 | { | ||
| 292 | 3041 | return inputPins.at(portIndex).link.getValue<T>(); | |
| 293 | } | ||
| 294 | |||
| 295 | /// @brief Unblocks the connected node. Has to be called when the input value should be released and getInputValue was not called. | ||
| 296 | /// @param[in] portIndex Input port where the data should be released | ||
| 297 | void releaseInputValue(size_t portIndex); | ||
| 298 | |||
| 299 | /// @brief Checks wether there is an input pin with the same time | ||
| 300 | /// @param[in] insTime Time to check | ||
| 301 | bool hasInputPinWithSameTime(const InsTime& insTime) const; | ||
| 302 | |||
| 303 | /// @brief Calls all registered callbacks on the specified output port | ||
| 304 | /// @param[in] portIndex Output port where to call the callbacks | ||
| 305 | /// @param[in] data The data to pass to the callback targets | ||
| 306 | void invokeCallbacks(size_t portIndex, const std::shared_ptr<const NodeData>& data); | ||
| 307 | |||
| 308 | /// @brief Returns the pin with the given id | ||
| 309 | /// @param[in] pinId Id of the Pin | ||
| 310 | /// @return The input pin | ||
| 311 | [[nodiscard]] InputPin& inputPinFromId(ax::NodeEditor::PinId pinId); | ||
| 312 | |||
| 313 | /// @brief Returns the pin with the given id | ||
| 314 | /// @param[in] pinId Id of the Pin | ||
| 315 | /// @return The output pin | ||
| 316 | [[nodiscard]] OutputPin& outputPinFromId(ax::NodeEditor::PinId pinId); | ||
| 317 | |||
| 318 | /// @brief Returns the index of the pin | ||
| 319 | /// @param[in] pinId Id of the Pin | ||
| 320 | /// @return The index of the pin | ||
| 321 | [[nodiscard]] size_t inputPinIndexFromId(ax::NodeEditor::PinId pinId) const; | ||
| 322 | |||
| 323 | /// @brief Returns the index of the pin | ||
| 324 | /// @param[in] pinId Id of the Pin | ||
| 325 | /// @return The index of the pin | ||
| 326 | [[nodiscard]] size_t outputPinIndexFromId(ax::NodeEditor::PinId pinId) const; | ||
| 327 | |||
| 328 | /// @brief Node name and id | ||
| 329 | [[nodiscard]] std::string nameId() const; | ||
| 330 | |||
| 331 | /// @brief Get the size of the node | ||
| 332 | [[nodiscard]] const ImVec2& getSize() const; | ||
| 333 | |||
| 334 | // ------------------------------------------ State handling --------------------------------------------- | ||
| 335 | |||
| 336 | /// @brief Converts the state into a printable text | ||
| 337 | /// @param[in] state State to convert | ||
| 338 | /// @return String representation of the state | ||
| 339 | static std::string toString(State state); | ||
| 340 | |||
| 341 | /// @brief Get the current state of the node | ||
| 342 | [[nodiscard]] State getState() const; | ||
| 343 | |||
| 344 | /// @brief Get the current mode of the node | ||
| 345 | [[nodiscard]] Mode getMode() const; | ||
| 346 | |||
| 347 | /// @brief Asks the node worker to initialize the node | ||
| 348 | /// @param[in] wait Wait for the worker to complete the request | ||
| 349 | /// @return True if not waiting and the worker accepted the request otherwise if waiting only true if the node initialized correctly | ||
| 350 | bool doInitialize(bool wait = false); | ||
| 351 | |||
| 352 | /// @brief Asks the node worker to reinitialize the node | ||
| 353 | /// @param[in] wait Wait for the worker to complete the request | ||
| 354 | /// @return True if not waiting and the worker accepted the request otherwise if waiting only true if the node initialized correctly | ||
| 355 | bool doReinitialize(bool wait = false); | ||
| 356 | |||
| 357 | /// @brief Asks the node worker to deinitialize the node | ||
| 358 | /// @param[in] wait Wait for the worker to complete the request | ||
| 359 | /// @return True if the worker accepted the request | ||
| 360 | bool doDeinitialize(bool wait = false); | ||
| 361 | |||
| 362 | /// @brief Asks the node worker to disable the node | ||
| 363 | /// @param[in] wait Wait for the worker to complete the request | ||
| 364 | /// @return True if the worker accepted the request | ||
| 365 | bool doDisable(bool wait = false); | ||
| 366 | |||
| 367 | /// @brief Enable the node | ||
| 368 | /// @return True if enabling was successful | ||
| 369 | bool doEnable(); | ||
| 370 | |||
| 371 | /// Wakes the worker thread | ||
| 372 | void wakeWorker(); | ||
| 373 | |||
| 374 | /// @brief Checks if the node is disabled | ||
| 375 | [[nodiscard]] bool isDisabled() const; | ||
| 376 | |||
| 377 | /// @brief Checks if the node is initialized | ||
| 378 | [[nodiscard]] bool isInitialized() const; | ||
| 379 | |||
| 380 | /// @brief Checks if the node is changing its state currently | ||
| 381 | [[nodiscard]] bool isTransient() const; | ||
| 382 | |||
| 383 | /// @brief Checks if the node is only working in real time (sensors, network interfaces, ...) | ||
| 384 | [[nodiscard]] bool isOnlyRealtime() const; | ||
| 385 | |||
| 386 | /* -------------------------------------------------------------------------------------------------------- */ | ||
| 387 | /* Member variables */ | ||
| 388 | /* -------------------------------------------------------------------------------------------------------- */ | ||
| 389 | |||
| 390 | /// Unique Id of the Node | ||
| 391 | ax::NodeEditor::NodeId id = 0; | ||
| 392 | /// Kind of the Node | ||
| 393 | Kind kind = Kind::Blueprint; | ||
| 394 | /// Name of the Node | ||
| 395 | std::string name; | ||
| 396 | /// List of input pins | ||
| 397 | std::vector<InputPin> inputPins; | ||
| 398 | /// List of output pins | ||
| 399 | std::vector<OutputPin> outputPins; | ||
| 400 | |||
| 401 | /// Enables the callbacks | ||
| 402 | bool callbacksEnabled = false; | ||
| 403 | |||
| 404 | /// Map with callback events (sorted by time) | ||
| 405 | std::multimap<InsTime, std::pair<OutputPin*, size_t>> pollEvents; | ||
| 406 | |||
| 407 | protected: | ||
| 408 | /// The Default Window size for new config windows. | ||
| 409 | /// Only set the variable if the object/window has no persistently saved data (no entry in .ini file) | ||
| 410 | ImVec2 _guiConfigDefaultWindowSize{ 500.0F, 400.0F }; | ||
| 411 | |||
| 412 | /// Flag if the config window should be shown | ||
| 413 | bool _hasConfig = false; | ||
| 414 | |||
| 415 | /// Lock the config when executing post-processing | ||
| 416 | bool _lockConfigDuringRun = true; | ||
| 417 | |||
| 418 | /// Whether the node can run in post-processing or only real-time | ||
| 419 | bool _onlyRealTime = false; | ||
| 420 | |||
| 421 | private: | ||
| 422 | State _state = State::Deinitialized; ///< Current state of the node | ||
| 423 | mutable std::mutex _stateMutex; ///< Mutex to interact with the worker state variable | ||
| 424 | |||
| 425 | /// Mode the node is currently running in | ||
| 426 | std::atomic<Mode> _mode = Mode::REAL_TIME; | ||
| 427 | |||
| 428 | /// Flag if the node should be reinitialize after deinitializing | ||
| 429 | bool _reinitialize = false; | ||
| 430 | |||
| 431 | /// Flag if the node should be disabled after deinitializing | ||
| 432 | bool _disable = false; | ||
| 433 | |||
| 434 | /// Flag if the config window is shown | ||
| 435 | bool _showConfig = false; | ||
| 436 | |||
| 437 | /// Mutex to show the config window (prevents initialization to modify values within the config window) | ||
| 438 | std::mutex _configWindowMutex; | ||
| 439 | /// Flag if the config window should be forced collapsed | ||
| 440 | bool _configWindowForceCollapse = false; | ||
| 441 | /// Flag if the config window is collapsed | ||
| 442 | bool _configWindowIsCollapsed = false; | ||
| 443 | |||
| 444 | /// Flag if the config window should be focused | ||
| 445 | bool _configWindowFocus = false; | ||
| 446 | |||
| 447 | /// Size of the node in pixels | ||
| 448 | ImVec2 _size{ 0, 0 }; | ||
| 449 | |||
| 450 | /// Flag which prevents the worker to be autostarted if false | ||
| 451 | static inline bool _autostartWorker = true; | ||
| 452 | |||
| 453 | 6855 | std::chrono::duration<int64_t> _workerTimeout = std::chrono::minutes(1); ///< Periodic timeout of the worker to check if new data available | |
| 454 | std::thread _worker; ///< Worker handling initialization and processing of data | ||
| 455 | std::mutex _workerMutex; ///< Mutex to interact with the worker condition variable | ||
| 456 | std::condition_variable _workerConditionVariable; ///< Condition variable to signal the worker thread to do something | ||
| 457 | bool _workerWakeup = false; ///< Variable to prevent the worker from sleeping | ||
| 458 | |||
| 459 | /// @brief Worker thread | ||
| 460 | /// @param[in, out] node The node where the thread belongs to | ||
| 461 | static void workerThread(Node* node); | ||
| 462 | |||
| 463 | /// Handler which gets triggered if the worker runs into a periodic timeout | ||
| 464 | virtual void workerTimeoutHandler(); | ||
| 465 | |||
| 466 | /// @brief Called by the worker to initialize the node | ||
| 467 | /// @return True if the initialization was successful | ||
| 468 | bool workerInitializeNode(); | ||
| 469 | |||
| 470 | /// @brief Called by the worker to deinitialize the node | ||
| 471 | /// @return True if the deinitialization was successful | ||
| 472 | bool workerDeinitializeNode(); | ||
| 473 | |||
| 474 | friend class gui::NodeEditorApplication; | ||
| 475 | friend class NAV::GroupBox; | ||
| 476 | |||
| 477 | /// @brief Main task of the FlowExecutor thread | ||
| 478 | friend void NAV::FlowExecutor::execute(); | ||
| 479 | /// @brief Deinitialize all Nodes | ||
| 480 | friend void NAV::FlowExecutor::deinitialize(); | ||
| 481 | /// @brief Register all available Node types for the program | ||
| 482 | friend void NAV::NodeRegistry::RegisterNodeTypes(); | ||
| 483 | |||
| 484 | /// @brief Converts the provided node into a json object | ||
| 485 | /// @param[out] j Json object which gets filled with the info | ||
| 486 | /// @param[in] node Node to convert into json | ||
| 487 | friend void NAV::to_json(json& j, const Node& node); | ||
| 488 | /// @brief Converts the provided json object into a node object | ||
| 489 | /// @param[in] j Json object with the needed values | ||
| 490 | /// @param[out] node Object to fill from the json | ||
| 491 | friend void NAV::from_json(const json& j, Node& node); | ||
| 492 | |||
| 493 | /// @brief Show the run menu dropdown | ||
| 494 | friend void gui::menus::ShowRunMenu(); | ||
| 495 | }; | ||
| 496 | |||
| 497 | /// @brief Equal compares Node::Kind values | ||
| 498 | /// @param[in] lhs Left-hand side of the operator | ||
| 499 | /// @param[in] rhs Right-hand side of the operator | ||
| 500 | /// @return Whether the comparison was successful | ||
| 501 | constexpr bool operator==(const Node::Kind& lhs, const Node::Kind& rhs) { return lhs.value == rhs.value; } | ||
| 502 | /// @brief Inequal compares Node::Kind values | ||
| 503 | /// @param[in] lhs Left-hand side of the operator | ||
| 504 | /// @param[in] rhs Right-hand side of the operator | ||
| 505 | /// @return Whether the comparison was successful | ||
| 506 | constexpr bool operator!=(const Node::Kind& lhs, const Node::Kind& rhs) { return !(lhs == rhs); } | ||
| 507 | |||
| 508 | /// @brief Equal compares Node::Kind values | ||
| 509 | /// @param[in] lhs Left-hand side of the operator | ||
| 510 | /// @param[in] rhs Right-hand side of the operator | ||
| 511 | /// @return Whether the comparison was successful | ||
| 512 | 3599 | constexpr bool operator==(const Node::Kind& lhs, const Node::Kind::Value& rhs) { return lhs.value == rhs; } | |
| 513 | /// @brief Equal compares Node::Kind values | ||
| 514 | /// @param[in] lhs Left-hand side of the operator | ||
| 515 | /// @param[in] rhs Right-hand side of the operator | ||
| 516 | /// @return Whether the comparison was successful | ||
| 517 | constexpr bool operator==(const Node::Kind::Value& lhs, const Node::Kind& rhs) { return lhs == rhs.value; } | ||
| 518 | /// @brief Inequal compares Node::Kind values | ||
| 519 | /// @param[in] lhs Left-hand side of the operator | ||
| 520 | /// @param[in] rhs Right-hand side of the operator | ||
| 521 | /// @return Whether the comparison was successful | ||
| 522 | 2133 | constexpr bool operator!=(const Node::Kind& lhs, const Node::Kind::Value& rhs) { return !(lhs == rhs); } | |
| 523 | /// @brief Inequal compares Node::Kind values | ||
| 524 | /// @param[in] lhs Left-hand side of the operator | ||
| 525 | /// @param[in] rhs Right-hand side of the operator | ||
| 526 | /// @return Whether the comparison was successful | ||
| 527 | constexpr bool operator!=(const Node::Kind::Value& lhs, const Node::Kind& rhs) { return !(lhs == rhs); } | ||
| 528 | |||
| 529 | } // namespace NAV | ||
| 530 |