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