| 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 | #include "internal/Node/Pin.hpp" | ||
| 10 | |||
| 11 | #include "internal/Node/Node.hpp" | ||
| 12 | #include "internal/gui/widgets/PinIcon.hpp" | ||
| 13 | #include "internal/gui/NodeEditorApplication.hpp" | ||
| 14 | #include "internal/NodeManager.hpp" | ||
| 15 | namespace nm = NAV::NodeManager; | ||
| 16 | #include "internal/FlowManager.hpp" | ||
| 17 | |||
| 18 | #include "util/Assert.h" | ||
| 19 | |||
| 20 | #include "NodeRegistry.hpp" | ||
| 21 | |||
| 22 | #include <imgui_node_editor.h> | ||
| 23 | #include <algorithm> | ||
| 24 | |||
| 25 | // ########################################################################################################### | ||
| 26 | // Pin | ||
| 27 | // ########################################################################################################### | ||
| 28 | |||
| 29 | 296 | bool NAV::Pin::canCreateLink(const OutputPin& startPin, const InputPin& endPin) | |
| 30 | { | ||
| 31 | 296 | bool dataTypesMatch = true; | |
| 32 | |||
| 33 | 296 | if (startPin.type == Pin::Type::Flow | |
| 34 |
7/8✓ Branch 0 taken 274 times.
✓ Branch 1 taken 22 times.
✓ Branch 3 taken 274 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 272 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 294 times.
|
296 | && !NAV::NodeRegistry::NodeDataTypeAnyIsChildOf(startPin.dataIdentifier, endPin.dataIdentifier)) |
| 35 | { | ||
| 36 | 2 | dataTypesMatch = false; | |
| 37 | } | ||
| 38 | |||
| 39 | ✗ | if (startPin.type == Pin::Type::Delegate | |
| 40 |
3/4✓ Branch 1 taken 1 times.
✓ Branch 2 taken 295 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
297 | && (startPin.parentNode == nullptr |
| 41 |
6/12✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 295 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 296 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
297 | || std::ranges::find(endPin.dataIdentifier, startPin.parentNode->type()) == endPin.dataIdentifier.end())) |
| 42 | { | ||
| 43 | ✗ | dataTypesMatch = false; | |
| 44 | } | ||
| 45 | |||
| 46 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 281 times.
|
578 | if ((startPin.type == Pin::Type::Object || startPin.type == Pin::Type::Matrix) // NOLINT(misc-redundant-expression) - false positive warning |
| 47 |
5/8✓ Branch 0 taken 282 times.
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 296 times.
|
578 | && !dataIdentifierHaveCommon(startPin.dataIdentifier, endPin.dataIdentifier)) |
| 48 | { | ||
| 49 | ✗ | dataTypesMatch = false; | |
| 50 | } | ||
| 51 | |||
| 52 | 296 | return startPin.id != endPin.id // Different Pins | |
| 53 |
1/2✓ Branch 1 taken 296 times.
✗ Branch 2 not taken.
|
296 | && startPin.kind != endPin.kind // Input <=> Output |
| 54 |
1/2✓ Branch 1 taken 296 times.
✗ Branch 2 not taken.
|
296 | && startPin.type == endPin.type // Same Type (Flow, Object, ...) |
| 55 |
1/2✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
|
296 | && startPin.parentNode != endPin.parentNode // Different Nodes |
| 56 |
3/4✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 294 times.
✓ Branch 3 taken 2 times.
|
592 | && dataTypesMatch; // Data identifier match |
| 57 | } | ||
| 58 | |||
| 59 | 15 | bool NAV::Pin::dataIdentifierHaveCommon(const std::vector<std::string>& a, const std::vector<std::string>& b) | |
| 60 | { | ||
| 61 |
1/2✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
30 | return !a.empty() && !b.empty() |
| 62 |
4/8✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 15 times.
✗ Branch 12 not taken.
|
45 | && std::ranges::find_if(a, [&b](const std::string& str) { return std::ranges::find(b, str) != b.end(); }) != a.end(); |
| 63 | } | ||
| 64 | |||
| 65 | ✗ | ImColor NAV::Pin::getIconColor() const | |
| 66 | { | ||
| 67 | ✗ | switch (Type::Value(type)) | |
| 68 | { | ||
| 69 | ✗ | case Type::None: | |
| 70 | ✗ | return { 0, 0, 0 }; | |
| 71 | ✗ | case Type::Flow: | |
| 72 | ✗ | if (ax::NodeEditor::GetStyle().Colors[ax::NodeEditor::StyleColor_NodeBg].x | |
| 73 | ✗ | + ax::NodeEditor::GetStyle().Colors[ax::NodeEditor::StyleColor_NodeBg].y | |
| 74 | ✗ | + ax::NodeEditor::GetStyle().Colors[ax::NodeEditor::StyleColor_NodeBg].z | |
| 75 | ✗ | > 2.0F) | |
| 76 | { | ||
| 77 | ✗ | return { 0, 0, 0 }; | |
| 78 | } | ||
| 79 | ✗ | return { 255, 255, 255 }; | |
| 80 | ✗ | case Type::Bool: | |
| 81 | ✗ | return { 220, 48, 48 }; | |
| 82 | ✗ | case Type::Int: | |
| 83 | ✗ | return { 68, 201, 156 }; | |
| 84 | ✗ | case Type::Float: | |
| 85 | ✗ | return { 147, 226, 74 }; | |
| 86 | ✗ | case Type::String: | |
| 87 | ✗ | return { 124, 21, 153 }; | |
| 88 | ✗ | case Type::Object: | |
| 89 | ✗ | return { 51, 150, 215 }; | |
| 90 | ✗ | case Type::Matrix: | |
| 91 | ✗ | return { 255, 165, 0 }; | |
| 92 | ✗ | case Type::Delegate: | |
| 93 | ✗ | return { 255, 48, 48 }; | |
| 94 | } | ||
| 95 | ✗ | return { 0, 0, 0 }; | |
| 96 | } | ||
| 97 | |||
| 98 | ✗ | void NAV::Pin::drawPinIcon(bool connected, int alpha) const | |
| 99 | { | ||
| 100 | namespace PinIcon = gui::widgets::PinIcon; | ||
| 101 | |||
| 102 | ✗ | PinIcon::Type iconType = PinIcon::Type::Flow; | |
| 103 | ✗ | ImColor color = getIconColor(); | |
| 104 | ✗ | color.Value.w = static_cast<float>(alpha) / 255.0F; | |
| 105 | ✗ | switch (Type::Value(type)) | |
| 106 | { | ||
| 107 | ✗ | case Type::None: | |
| 108 | ✗ | iconType = PinIcon::Type::Grid; | |
| 109 | ✗ | break; | |
| 110 | ✗ | case Type::Flow: | |
| 111 | ✗ | iconType = PinIcon::Type::Flow; | |
| 112 | ✗ | break; | |
| 113 | ✗ | case Type::Bool: | |
| 114 | // iconType = PinIcon::Type::Circle; | ||
| 115 | // break; | ||
| 116 | case Type::Int: | ||
| 117 | // iconType = PinIcon::Type::Circle; | ||
| 118 | // break; | ||
| 119 | case Type::Float: | ||
| 120 | ✗ | iconType = PinIcon::Type::Circle; | |
| 121 | ✗ | break; | |
| 122 | ✗ | case Type::String: | |
| 123 | ✗ | iconType = PinIcon::Type::RoundSquare; | |
| 124 | ✗ | break; | |
| 125 | ✗ | case Type::Object: | |
| 126 | // iconType = PinIcon::Type::Diamond; | ||
| 127 | // break; | ||
| 128 | case Type::Matrix: | ||
| 129 | ✗ | iconType = PinIcon::Type::Diamond; | |
| 130 | ✗ | break; | |
| 131 | ✗ | case Type::Delegate: | |
| 132 | ✗ | iconType = PinIcon::Type::Square; | |
| 133 | ✗ | break; | |
| 134 | ✗ | default: | |
| 135 | ✗ | return; | |
| 136 | } | ||
| 137 | |||
| 138 | ✗ | gui::widgets::PinIcon::Draw(ImVec2(static_cast<float>(m_PinIconSize) * gui::NodeEditorApplication::defaultFontRatio(), | |
| 139 | ✗ | static_cast<float>(m_PinIconSize) * gui::NodeEditorApplication::defaultFontRatio()), | |
| 140 | ✗ | iconType, connected, color, ImColor(32, 32, 32, alpha)); | |
| 141 | } | ||
| 142 | |||
| 143 | 583 | bool NAV::Pin::createLink(OutputPin& startPin, InputPin& endPin, ax::NodeEditor::LinkId linkId) | |
| 144 | { | ||
| 145 |
2/2✓ Branch 1 taken 288 times.
✓ Branch 2 taken 295 times.
|
583 | if (startPin.isPinLinked(endPin)) { return true; } // Pins are already linked |
| 146 | |||
| 147 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 293 times.
|
295 | if (!startPin.canCreateLink(endPin)) { return false; } // Types do not match |
| 148 | |||
| 149 |
2/4✓ Branch 0 taken 293 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 293 times.
|
293 | if (!startPin.parentNode || !endPin.parentNode) { return false; } |
| 150 | LOG_TRACE("called: {} of [{}] ==> {} of [{}]", size_t(startPin.id), startPin.parentNode->nameId(), size_t(endPin.id), endPin.parentNode->nameId()); | ||
| 151 | |||
| 152 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 293 times.
|
293 | if (!startPin.parentNode->onCreateLink(startPin, endPin)) |
| 153 | { | ||
| 154 | ✗ | LOG_ERROR("The new Link between node '{}' and '{}' was refused by its start node.", | |
| 155 | startPin.parentNode->nameId(), endPin.parentNode->nameId()); | ||
| 156 | ✗ | return false; | |
| 157 | } | ||
| 158 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 293 times.
|
293 | if (!endPin.parentNode->onCreateLink(startPin, endPin)) |
| 159 | { | ||
| 160 | ✗ | LOG_ERROR("The new Link between node '{}' and '{}' was refused by its end node.", | |
| 161 | startPin.parentNode->nameId(), endPin.parentNode->nameId()); | ||
| 162 | ✗ | return false; | |
| 163 | } | ||
| 164 | |||
| 165 |
5/10✓ Branch 2 taken 293 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 293 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 293 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 293 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 293 times.
✗ Branch 16 not taken.
|
293 | LOG_DEBUG("Creating link from pin {} of [{}] ==> {} of [{}]", |
| 166 | size_t(startPin.id), startPin.parentNode->nameId(), | ||
| 167 | size_t(endPin.id), endPin.parentNode->nameId()); | ||
| 168 | |||
| 169 | 293 | startPin.connect(endPin, linkId); | |
| 170 | 293 | endPin.connect(startPin, linkId); | |
| 171 | |||
| 172 | 293 | nm::AddLink(linkId); | |
| 173 | |||
| 174 |
2/2✓ Branch 1 taken 22 times.
✓ Branch 2 taken 271 times.
|
293 | if (endPin.type != Pin::Type::Flow) |
| 175 | { | ||
| 176 |
4/8✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 22 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 22 times.
✗ Branch 8 not taken.
|
22 | if (startPin.parentNode && endPin.parentNode && !startPin.parentNode->isInitialized()) |
| 177 | { | ||
| 178 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
|
22 | if (endPin.parentNode->isInitialized()) |
| 179 | { | ||
| 180 | ✗ | endPin.parentNode->doDeinitialize(true); | |
| 181 | } | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 |
2/4✓ Branch 0 taken 293 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 293 times.
✗ Branch 3 not taken.
|
293 | if (startPin.parentNode && endPin.parentNode) |
| 186 | { | ||
| 187 | 293 | startPin.parentNode->afterCreateLink(startPin, endPin); | |
| 188 | 293 | endPin.parentNode->afterCreateLink(startPin, endPin); | |
| 189 | } | ||
| 190 | |||
| 191 | 293 | flow::ApplyChanges(); | |
| 192 | |||
| 193 | 293 | return true; | |
| 194 | } | ||
| 195 | |||
| 196 | 3 | bool NAV::Pin::recreateLink(OutputPin& startPin, InputPin& endPin) | |
| 197 | { | ||
| 198 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (startPin.isPinLinked(endPin)) |
| 199 | { | ||
| 200 | 3 | deleteLink(startPin, endPin); | |
| 201 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | return createLink(startPin, endPin); |
| 202 | } | ||
| 203 | ✗ | return false; | |
| 204 | } | ||
| 205 | |||
| 206 | 292 | void NAV::Pin::deleteLink(OutputPin& startPin, InputPin& endPin) | |
| 207 | { | ||
| 208 |
2/4✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 292 times.
|
292 | if (!startPin.parentNode || !endPin.parentNode) { return; } |
| 209 | |||
| 210 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 292 times.
|
292 | if (!startPin.isPinLinked(endPin)) |
| 211 | { | ||
| 212 | ✗ | LOG_ERROR("Cannot delete the link, because the nodes '{}' and '{}' are not linked over pins '{}' => '{}'.", | |
| 213 | startPin.parentNode->nameId(), endPin.parentNode->nameId(), | ||
| 214 | size_t(startPin.id), size_t(endPin.id)); | ||
| 215 | ✗ | return; | |
| 216 | } | ||
| 217 | |||
| 218 |
6/12✓ Branch 2 taken 292 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 292 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 292 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 292 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 292 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 292 times.
✗ Branch 19 not taken.
|
292 | LOG_DEBUG("Deleting link {} from pin {} of [{}] ==> pin {} of [{}]", size_t(endPin.link.linkId), |
| 219 | size_t(startPin.id), startPin.parentNode->nameId(), size_t(endPin.id), endPin.parentNode->nameId()); | ||
| 220 | |||
| 221 | 292 | startPin.parentNode->onDeleteLink(startPin, endPin); | |
| 222 | 292 | endPin.parentNode->onDeleteLink(startPin, endPin); | |
| 223 | |||
| 224 |
2/2✓ Branch 1 taken 22 times.
✓ Branch 2 taken 270 times.
|
292 | if (endPin.type != Pin::Type::Flow) { endPin.parentNode->doDeinitialize(true); } |
| 225 | |||
| 226 | 292 | startPin.disconnect(endPin); | |
| 227 | 292 | endPin.disconnect(); | |
| 228 | |||
| 229 | 292 | startPin.parentNode->afterDeleteLink(startPin, endPin); | |
| 230 | 292 | endPin.parentNode->afterDeleteLink(startPin, endPin); | |
| 231 | |||
| 232 | 292 | flow::ApplyChanges(); | |
| 233 | } | ||
| 234 | |||
| 235 | // ########################################################################################################### | ||
| 236 | // OutputPin | ||
| 237 | // ########################################################################################################### | ||
| 238 | |||
| 239 | 296 | bool NAV::OutputPin::canCreateLink(const NAV::InputPin& other) const | |
| 240 | { | ||
| 241 | 296 | return Pin::canCreateLink(*this, other); | |
| 242 | } | ||
| 243 | |||
| 244 | 615 | bool NAV::OutputPin::isPinLinked() const | |
| 245 | { | ||
| 246 | 615 | return !links.empty(); | |
| 247 | } | ||
| 248 | |||
| 249 | 878 | bool NAV::OutputPin::isPinLinked(const NAV::InputPin& endPin) const | |
| 250 | { | ||
| 251 |
1/2✓ Branch 1 taken 878 times.
✗ Branch 2 not taken.
|
878 | auto iter = std::ranges::find_if(links, [&endPin](const OutgoingLink& link) { |
| 252 |
4/4✓ Branch 0 taken 631 times.
✓ Branch 1 taken 150 times.
✓ Branch 3 taken 583 times.
✓ Branch 4 taken 48 times.
|
781 | return link.connectedNode == endPin.parentNode && link.connectedPinId == endPin.id; |
| 253 | }); | ||
| 254 | 878 | return iter != links.cend(); | |
| 255 | } | ||
| 256 | |||
| 257 | 580 | bool NAV::OutputPin::createLink(InputPin& endPin, ax::NodeEditor::LinkId linkId) | |
| 258 | { | ||
| 259 | 580 | return Pin::createLink(*this, endPin, linkId); | |
| 260 | } | ||
| 261 | |||
| 262 | 3 | bool NAV::OutputPin::recreateLink(InputPin& endPin) | |
| 263 | { | ||
| 264 | 3 | return Pin::recreateLink(*this, endPin); | |
| 265 | } | ||
| 266 | |||
| 267 | ✗ | void NAV::OutputPin::deleteLink(InputPin& endPin) | |
| 268 | { | ||
| 269 | ✗ | Pin::deleteLink(*this, endPin); | |
| 270 | ✗ | } | |
| 271 | |||
| 272 | 82 | void NAV::OutputPin::deleteLinks() | |
| 273 | { | ||
| 274 |
2/2✓ Branch 1 taken 101 times.
✓ Branch 2 taken 82 times.
|
183 | while (!links.empty()) |
| 275 | { | ||
| 276 |
1/2✓ Branch 2 taken 101 times.
✗ Branch 3 not taken.
|
101 | if (auto* endPin = links.back().getConnectedPin()) |
| 277 | { | ||
| 278 | 101 | Pin::deleteLink(*this, *endPin); | |
| 279 | } | ||
| 280 | else | ||
| 281 | { | ||
| 282 | ✗ | links.pop_back(); | |
| 283 | } | ||
| 284 | } | ||
| 285 | 82 | } | |
| 286 | |||
| 287 | 293 | void NAV::OutputPin::connect(NAV::InputPin& endPin, ax::NodeEditor::LinkId linkId) | |
| 288 | { | ||
| 289 |
1/2✓ Branch 1 taken 293 times.
✗ Branch 2 not taken.
|
293 | auto iter = std::ranges::find_if(links, [&endPin](const OutgoingLink& link) { |
| 290 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 63 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
79 | return link.connectedNode == endPin.parentNode && link.connectedPinId == endPin.id; |
| 291 | }); | ||
| 292 |
1/2✓ Branch 2 taken 293 times.
✗ Branch 3 not taken.
|
293 | if (iter == links.end()) // Link does not yet exist |
| 293 | { | ||
| 294 |
3/4✓ Branch 1 taken 293 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 290 times.
✓ Branch 4 taken 3 times.
|
293 | if (linkId) |
| 295 | { | ||
| 296 | // LinkId is given | ||
| 297 |
1/2✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
|
290 | links.emplace_back(linkId, endPin.parentNode, endPin.id); |
| 298 |
2/4✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 290 times.
✗ Branch 4 not taken.
|
290 | if (endPin.link.linkId != linkId) |
| 299 | { | ||
| 300 |
1/2✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
|
290 | endPin.disconnect(); |
| 301 |
1/2✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
|
290 | endPin.connect(*this, linkId); |
| 302 | } | ||
| 303 | } | ||
| 304 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
|
3 | else if (endPin.link.connectedNode == parentNode && endPin.link.connectedPinId == id) |
| 305 | { | ||
| 306 | // Connected pin is already linked, so get linkId from the connected pin | ||
| 307 | ✗ | links.emplace_back(endPin.link.linkId, endPin.parentNode, endPin.id); | |
| 308 | } | ||
| 309 | else | ||
| 310 | { | ||
| 311 | // Connected pin is not linked, so get new linkId | ||
| 312 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | links.emplace_back(nm::GetNextLinkId(), endPin.parentNode, endPin.id); |
| 313 | // Also connect the endPin to this one | ||
| 314 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | endPin.connect(*this); |
| 315 | } | ||
| 316 | } | ||
| 317 | 293 | } | |
| 318 | |||
| 319 | 292 | void NAV::OutputPin::disconnect(InputPin& endPin) | |
| 320 | { | ||
| 321 |
1/2✓ Branch 1 taken 292 times.
✗ Branch 2 not taken.
|
292 | auto iter = std::ranges::find_if(links, [&endPin](const OutgoingLink& link) { |
| 322 |
4/4✓ Branch 0 taken 308 times.
✓ Branch 1 taken 25 times.
✓ Branch 3 taken 292 times.
✓ Branch 4 taken 16 times.
|
333 | return link.connectedNode == endPin.parentNode && link.connectedPinId == endPin.id; |
| 323 | }); | ||
| 324 |
1/2✓ Branch 2 taken 292 times.
✗ Branch 3 not taken.
|
292 | if (iter != links.end()) |
| 325 | { | ||
| 326 |
1/2✓ Branch 2 taken 292 times.
✗ Branch 3 not taken.
|
292 | links.erase(iter); |
| 327 |
4/8✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 292 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 292 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 292 times.
✗ Branch 8 not taken.
|
292 | if (endPin.link.connectedNode == parentNode && endPin.link.connectedPinId == id) |
| 328 | { | ||
| 329 |
1/2✓ Branch 1 taken 292 times.
✗ Branch 2 not taken.
|
292 | endPin.disconnect(); |
| 330 | } | ||
| 331 | } | ||
| 332 | 292 | } | |
| 333 | |||
| 334 | 556388 | NAV::InputPin* NAV::OutputPin::OutgoingLink::getConnectedPin() const | |
| 335 | { | ||
| 336 |
2/2✓ Branch 0 taken 556322 times.
✓ Branch 1 taken 66 times.
|
556388 | if (connectedNode) |
| 337 | { | ||
| 338 |
1/2✓ Branch 5 taken 1098662 times.
✗ Branch 6 not taken.
|
1098955 | for (auto& inputPin : connectedNode->inputPins) |
| 339 | { | ||
| 340 |
3/4✓ Branch 1 taken 1099200 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 556567 times.
✓ Branch 4 taken 542633 times.
|
1098580 | if (inputPin.id == connectedPinId) { return &inputPin; } |
| 341 | } | ||
| 342 | } | ||
| 343 | 66 | return nullptr; | |
| 344 | } | ||
| 345 | |||
| 346 | // ########################################################################################################### | ||
| 347 | // InputPin | ||
| 348 | // ########################################################################################################### | ||
| 349 | |||
| 350 | ✗ | bool NAV::InputPin::canCreateLink(const OutputPin& other) const | |
| 351 | { | ||
| 352 | ✗ | return Pin::canCreateLink(other, *this); | |
| 353 | } | ||
| 354 | |||
| 355 | 708757 | bool NAV::InputPin::isPinLinked() const | |
| 356 | { | ||
| 357 |
4/6✓ Branch 1 taken 708013 times.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 708055 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 707770 times.
✗ Branch 7 not taken.
|
708757 | return link.linkId && link.connectedNode && link.connectedPinId; |
| 358 | } | ||
| 359 | |||
| 360 | ✗ | bool NAV::InputPin::createLink(OutputPin& startPin, ax::NodeEditor::LinkId linkId) | |
| 361 | { | ||
| 362 | ✗ | return Pin::createLink(startPin, *this, linkId); | |
| 363 | } | ||
| 364 | |||
| 365 | ✗ | bool NAV::InputPin::recreateLink(OutputPin& startPin) | |
| 366 | { | ||
| 367 | ✗ | return Pin::recreateLink(startPin, *this); | |
| 368 | } | ||
| 369 | |||
| 370 | 191 | void NAV::InputPin::deleteLink() | |
| 371 | { | ||
| 372 |
2/2✓ Branch 1 taken 188 times.
✓ Branch 2 taken 3 times.
|
191 | if (auto* startPin = link.getConnectedPin()) |
| 373 | { | ||
| 374 | 188 | Pin::deleteLink(*startPin, *this); | |
| 375 | } | ||
| 376 | 191 | } | |
| 377 | |||
| 378 | 586 | void NAV::InputPin::connect(NAV::OutputPin& startPin, ax::NodeEditor::LinkId linkId) | |
| 379 | { | ||
| 380 |
5/6✓ Branch 0 taken 293 times.
✓ Branch 1 taken 293 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 293 times.
✓ Branch 5 taken 293 times.
✓ Branch 6 taken 293 times.
|
586 | if (link.connectedNode != startPin.parentNode || link.connectedPinId != startPin.id) // Link does not yet exist |
| 381 | { | ||
| 382 | 293 | link.connectedNode = startPin.parentNode; | |
| 383 | 293 | link.connectedPinId = startPin.id; | |
| 384 | |||
| 385 |
1/2✓ Branch 1 taken 293 times.
✗ Branch 2 not taken.
|
293 | auto iter = std::ranges::find_if(startPin.links, [&, this](const OutputPin::OutgoingLink& link) { |
| 386 |
4/4✓ Branch 0 taken 309 times.
✓ Branch 1 taken 63 times.
✓ Branch 3 taken 293 times.
✓ Branch 4 taken 16 times.
|
372 | return link.connectedNode == parentNode && link.connectedPinId == id; |
| 387 | }); | ||
| 388 | |||
| 389 |
3/4✓ Branch 1 taken 293 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 290 times.
✓ Branch 4 taken 3 times.
|
293 | if (linkId) |
| 390 | { | ||
| 391 | // LinkId is given | ||
| 392 | 290 | link.linkId = linkId; | |
| 393 |
4/8✓ Branch 2 taken 290 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 290 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 290 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 290 times.
|
290 | if (iter != startPin.links.end() && iter->linkId != linkId) |
| 394 | { | ||
| 395 | ✗ | startPin.disconnect(*this); | |
| 396 | ✗ | startPin.connect(*this, linkId); | |
| 397 | } | ||
| 398 | } | ||
| 399 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | else if (iter != startPin.links.end()) |
| 400 | { | ||
| 401 | // Connected pin is already linked, so get linkId from the connected pin | ||
| 402 | 3 | link.linkId = iter->linkId; | |
| 403 | } | ||
| 404 | else | ||
| 405 | { | ||
| 406 | // Connected pin is not linked, so get new linkId | ||
| 407 | ✗ | link.linkId = nm::GetNextLinkId(); | |
| 408 | // Also connect the startPin to this one | ||
| 409 | ✗ | startPin.connect(*this); | |
| 410 | } | ||
| 411 | } | ||
| 412 | 586 | } | |
| 413 | |||
| 414 | 874 | void NAV::InputPin::disconnect() | |
| 415 | { | ||
| 416 |
6/8✓ Branch 0 taken 582 times.
✓ Branch 1 taken 292 times.
✓ Branch 3 taken 582 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 582 times.
✓ Branch 8 taken 292 times.
✓ Branch 9 taken 582 times.
|
874 | if (link.connectedNode || link.connectedPinId || link.linkId) |
| 417 | { | ||
| 418 | 292 | auto* startPin = link.getConnectedPin(); | |
| 419 | |||
| 420 |
1/2✓ Branch 1 taken 292 times.
✗ Branch 2 not taken.
|
292 | link.linkId = 0; |
| 421 | 292 | link.connectedNode = nullptr; | |
| 422 |
1/2✓ Branch 1 taken 292 times.
✗ Branch 2 not taken.
|
292 | link.connectedPinId = 0; |
| 423 | |||
| 424 |
1/2✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
|
292 | if (startPin) |
| 425 | { | ||
| 426 |
1/2✓ Branch 1 taken 292 times.
✗ Branch 2 not taken.
|
292 | auto iter = std::ranges::find_if(startPin->links, [&, this](const OutputPin::OutgoingLink& link) { |
| 427 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 63 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
79 | return link.connectedNode == parentNode && link.connectedPinId == id; |
| 428 | }); | ||
| 429 | |||
| 430 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 292 times.
|
292 | if (iter != startPin->links.end()) |
| 431 | { | ||
| 432 | ✗ | startPin->disconnect(*this); | |
| 433 | } | ||
| 434 | } | ||
| 435 | } | ||
| 436 | 874 | } | |
| 437 | |||
| 438 | 1702486 | NAV::OutputPin* NAV::InputPin::IncomingLink::getConnectedPin() const | |
| 439 | { | ||
| 440 |
2/2✓ Branch 0 taken 1702284 times.
✓ Branch 1 taken 202 times.
|
1702486 | if (connectedNode) |
| 441 | { | ||
| 442 |
1/2✓ Branch 5 taken 2282061 times.
✗ Branch 6 not taken.
|
2282402 | for (auto& outputPin : connectedNode->outputPins) |
| 443 | { | ||
| 444 |
3/4✓ Branch 1 taken 2282269 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1702151 times.
✓ Branch 4 taken 580118 times.
|
2282007 | if (outputPin.id == connectedPinId) { return &outputPin; } |
| 445 | } | ||
| 446 | } | ||
| 447 | 202 | return nullptr; | |
| 448 | } | ||
| 449 | |||
| 450 | // ########################################################################################################### | ||
| 451 | |||
| 452 | ✗ | void NAV::to_json(json& j, const OutputPin& pin) | |
| 453 | { | ||
| 454 | ✗ | j = json{ | |
| 455 | ✗ | { "id", size_t(pin.id) }, | |
| 456 | ✗ | { "name", pin.name }, | |
| 457 | ✗ | }; | |
| 458 | ✗ | } | |
| 459 | 1155 | void NAV::from_json(const json& j, OutputPin& pin) | |
| 460 | { | ||
| 461 |
3/6✓ Branch 1 taken 1155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1155 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1155 times.
✗ Branch 8 not taken.
|
1155 | pin.id = j.at("id").get<size_t>(); |
| 462 |
1/2✓ Branch 1 taken 1155 times.
✗ Branch 2 not taken.
|
1155 | if (j.contains("name")) { j.at("name").get_to(pin.name); } |
| 463 | 1155 | } | |
| 464 | |||
| 465 | ✗ | void NAV::to_json(json& j, const InputPin& pin) | |
| 466 | { | ||
| 467 | ✗ | j = json{ | |
| 468 | ✗ | { "id", size_t(pin.id) }, | |
| 469 | ✗ | { "name", pin.name }, | |
| 470 | ✗ | }; | |
| 471 | ✗ | } | |
| 472 | 1120 | void NAV::from_json(const json& j, InputPin& pin) | |
| 473 | { | ||
| 474 |
3/6✓ Branch 1 taken 1120 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1120 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1120 times.
✗ Branch 8 not taken.
|
1120 | pin.id = j.at("id").get<size_t>(); |
| 475 |
1/2✓ Branch 1 taken 1120 times.
✗ Branch 2 not taken.
|
1120 | if (j.contains("name")) { j.at("name").get_to(pin.name); } |
| 476 | 1120 | } | |
| 477 |