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 | 273 | bool NAV::Pin::canCreateLink(const OutputPin& startPin, const InputPin& endPin) | |
30 | { | ||
31 | 273 | bool dataTypesMatch = true; | |
32 | |||
33 | 273 | if (startPin.type == Pin::Type::Flow | |
34 |
7/8✓ Branch 0 taken 263 times.
✓ Branch 1 taken 10 times.
✓ Branch 3 taken 263 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 261 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 271 times.
|
273 | && !NAV::NodeRegistry::NodeDataTypeAnyIsChildOf(startPin.dataIdentifier, endPin.dataIdentifier)) |
35 | { | ||
36 | 2 | dataTypesMatch = false; | |
37 | } | ||
38 | |||
39 | ✗ | if (startPin.type == Pin::Type::Delegate | |
40 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 273 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
273 | && (startPin.parentNode == nullptr |
41 |
2/12✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 273 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 273 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
273 | || std::ranges::find(endPin.dataIdentifier, startPin.parentNode->type()) == endPin.dataIdentifier.end())) |
42 | { | ||
43 | ✗ | dataTypesMatch = false; | |
44 | } | ||
45 | |||
46 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 263 times.
|
536 | if ((startPin.type == Pin::Type::Object || startPin.type == Pin::Type::Matrix) // NOLINT(misc-redundant-expression) - false positive warning |
47 |
5/8✓ Branch 0 taken 263 times.
✓ Branch 1 taken 10 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 273 times.
|
536 | && !dataIdentifierHaveCommon(startPin.dataIdentifier, endPin.dataIdentifier)) |
48 | { | ||
49 | ✗ | dataTypesMatch = false; | |
50 | } | ||
51 | |||
52 | 273 | return startPin.id != endPin.id // Different Pins | |
53 |
1/2✓ Branch 1 taken 273 times.
✗ Branch 2 not taken.
|
273 | && startPin.kind != endPin.kind // Input <=> Output |
54 |
1/2✓ Branch 1 taken 273 times.
✗ Branch 2 not taken.
|
273 | && startPin.type == endPin.type // Same Type (Flow, Object, ...) |
55 |
1/2✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
|
273 | && startPin.parentNode != endPin.parentNode // Different Nodes |
56 |
3/4✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 271 times.
✓ Branch 3 taken 2 times.
|
546 | && dataTypesMatch; // Data identifier match |
57 | } | ||
58 | |||
59 | 10 | bool NAV::Pin::dataIdentifierHaveCommon(const std::vector<std::string>& a, const std::vector<std::string>& b) | |
60 | { | ||
61 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
20 | return !a.empty() && !b.empty() |
62 |
4/8✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 10 times.
✗ Branch 12 not taken.
|
30 | && 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 | 539 | bool NAV::Pin::createLink(OutputPin& startPin, InputPin& endPin, ax::NodeEditor::LinkId linkId) | |
144 | { | ||
145 |
2/2✓ Branch 1 taken 267 times.
✓ Branch 2 taken 272 times.
|
539 | if (startPin.isPinLinked(endPin)) { return true; } // Pins are already linked |
146 | |||
147 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 270 times.
|
272 | if (!startPin.canCreateLink(endPin)) { return false; } // Types do not match |
148 | |||
149 |
2/4✓ Branch 0 taken 270 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 270 times.
|
270 | 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 270 times.
|
270 | 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 270 times.
|
270 | 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 270 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 270 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 270 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 270 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 270 times.
✗ Branch 16 not taken.
|
270 | 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 | 270 | startPin.connect(endPin, linkId); | |
170 | 270 | endPin.connect(startPin, linkId); | |
171 | |||
172 | 270 | nm::AddLink(linkId); | |
173 | |||
174 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 260 times.
|
270 | if (endPin.type != Pin::Type::Flow) |
175 | { | ||
176 |
4/8✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
|
10 | if (startPin.parentNode && endPin.parentNode && !startPin.parentNode->isInitialized()) |
177 | { | ||
178 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if (endPin.parentNode->isInitialized()) |
179 | { | ||
180 | ✗ | endPin.parentNode->doDeinitialize(true); | |
181 | } | ||
182 | } | ||
183 | } | ||
184 | |||
185 |
2/4✓ Branch 0 taken 270 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 270 times.
✗ Branch 3 not taken.
|
270 | if (startPin.parentNode && endPin.parentNode) |
186 | { | ||
187 | 270 | startPin.parentNode->afterCreateLink(startPin, endPin); | |
188 | 270 | endPin.parentNode->afterCreateLink(startPin, endPin); | |
189 | } | ||
190 | |||
191 | 270 | flow::ApplyChanges(); | |
192 | |||
193 | 270 | return true; | |
194 | } | ||
195 | |||
196 | 1 | bool NAV::Pin::recreateLink(OutputPin& startPin, InputPin& endPin) | |
197 | { | ||
198 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (startPin.isPinLinked(endPin)) |
199 | { | ||
200 | 1 | deleteLink(startPin, endPin); | |
201 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | return createLink(startPin, endPin); |
202 | } | ||
203 | ✗ | return false; | |
204 | } | ||
205 | |||
206 | 269 | void NAV::Pin::deleteLink(OutputPin& startPin, InputPin& endPin) | |
207 | { | ||
208 |
2/4✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 269 times.
|
269 | if (!startPin.parentNode || !endPin.parentNode) { return; } |
209 | |||
210 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
|
269 | 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 269 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 269 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 269 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 269 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 269 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 269 times.
✗ Branch 19 not taken.
|
269 | 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 | 269 | startPin.parentNode->onDeleteLink(startPin, endPin); | |
222 | 269 | endPin.parentNode->onDeleteLink(startPin, endPin); | |
223 | |||
224 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 259 times.
|
269 | if (endPin.type != Pin::Type::Flow) { endPin.parentNode->doDeinitialize(true); } |
225 | |||
226 | 269 | startPin.disconnect(endPin); | |
227 | 269 | endPin.disconnect(); | |
228 | |||
229 | 269 | startPin.parentNode->afterDeleteLink(startPin, endPin); | |
230 | 269 | endPin.parentNode->afterDeleteLink(startPin, endPin); | |
231 | |||
232 | 269 | flow::ApplyChanges(); | |
233 | } | ||
234 | |||
235 | // ########################################################################################################### | ||
236 | // OutputPin | ||
237 | // ########################################################################################################### | ||
238 | |||
239 | 273 | bool NAV::OutputPin::canCreateLink(const NAV::InputPin& other) const | |
240 | { | ||
241 | 273 | return Pin::canCreateLink(*this, other); | |
242 | } | ||
243 | |||
244 | 494 | bool NAV::OutputPin::isPinLinked() const | |
245 | { | ||
246 | 494 | return !links.empty(); | |
247 | } | ||
248 | |||
249 | 809 | bool NAV::OutputPin::isPinLinked(const NAV::InputPin& endPin) const | |
250 | { | ||
251 |
1/2✓ Branch 1 taken 809 times.
✗ Branch 2 not taken.
|
809 | auto iter = std::ranges::find_if(links, [&endPin](const OutgoingLink& link) { |
252 |
4/4✓ Branch 0 taken 588 times.
✓ Branch 1 taken 146 times.
✓ Branch 3 taken 537 times.
✓ Branch 4 taken 51 times.
|
734 | return link.connectedNode == endPin.parentNode && link.connectedPinId == endPin.id; |
253 | }); | ||
254 | 809 | return iter != links.cend(); | |
255 | } | ||
256 | |||
257 | 538 | bool NAV::OutputPin::createLink(InputPin& endPin, ax::NodeEditor::LinkId linkId) | |
258 | { | ||
259 | 538 | return Pin::createLink(*this, endPin, linkId); | |
260 | } | ||
261 | |||
262 | 1 | bool NAV::OutputPin::recreateLink(InputPin& endPin) | |
263 | { | ||
264 | 1 | return Pin::recreateLink(*this, endPin); | |
265 | } | ||
266 | |||
267 | ✗ | void NAV::OutputPin::deleteLink(InputPin& endPin) | |
268 | { | ||
269 | ✗ | Pin::deleteLink(*this, endPin); | |
270 | ✗ | } | |
271 | |||
272 | 73 | void NAV::OutputPin::deleteLinks() | |
273 | { | ||
274 |
2/2✓ Branch 1 taken 96 times.
✓ Branch 2 taken 73 times.
|
169 | while (!links.empty()) |
275 | { | ||
276 |
1/2✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
|
96 | if (auto* endPin = links.back().getConnectedPin()) |
277 | { | ||
278 | 96 | Pin::deleteLink(*this, *endPin); | |
279 | } | ||
280 | else | ||
281 | { | ||
282 | ✗ | links.pop_back(); | |
283 | } | ||
284 | } | ||
285 | 73 | } | |
286 | |||
287 | 270 | void NAV::OutputPin::connect(NAV::InputPin& endPin, ax::NodeEditor::LinkId linkId) | |
288 | { | ||
289 |
1/2✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
|
270 | auto iter = std::ranges::find_if(links, [&endPin](const OutgoingLink& link) { |
290 |
3/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 49 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
|
66 | return link.connectedNode == endPin.parentNode && link.connectedPinId == endPin.id; |
291 | }); | ||
292 |
1/2✓ Branch 2 taken 270 times.
✗ Branch 3 not taken.
|
270 | if (iter == links.end()) // Link does not yet exist |
293 | { | ||
294 |
3/4✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 269 times.
✓ Branch 4 taken 1 times.
|
270 | if (linkId) |
295 | { | ||
296 | // LinkId is given | ||
297 |
1/2✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
|
269 | links.emplace_back(linkId, endPin.parentNode, endPin.id); |
298 |
2/4✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 269 times.
✗ Branch 4 not taken.
|
269 | if (endPin.link.linkId != linkId) |
299 | { | ||
300 |
1/2✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
|
269 | endPin.disconnect(); |
301 |
1/2✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
|
269 | endPin.connect(*this, linkId); |
302 | } | ||
303 | } | ||
304 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
|
1 | 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 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | links.emplace_back(nm::GetNextLinkId(), endPin.parentNode, endPin.id); |
313 | // Also connect the endPin to this one | ||
314 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | endPin.connect(*this); |
315 | } | ||
316 | } | ||
317 | 270 | } | |
318 | |||
319 | 269 | void NAV::OutputPin::disconnect(InputPin& endPin) | |
320 | { | ||
321 |
1/2✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
|
269 | auto iter = std::ranges::find_if(links, [&endPin](const OutgoingLink& link) { |
322 |
4/4✓ Branch 0 taken 286 times.
✓ Branch 1 taken 48 times.
✓ Branch 3 taken 269 times.
✓ Branch 4 taken 17 times.
|
334 | return link.connectedNode == endPin.parentNode && link.connectedPinId == endPin.id; |
323 | }); | ||
324 |
1/2✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
|
269 | if (iter != links.end()) |
325 | { | ||
326 |
1/2✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
|
269 | links.erase(iter); |
327 |
4/8✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 269 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 269 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 269 times.
✗ Branch 8 not taken.
|
269 | if (endPin.link.connectedNode == parentNode && endPin.link.connectedPinId == id) |
328 | { | ||
329 |
1/2✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
|
269 | endPin.disconnect(); |
330 | } | ||
331 | } | ||
332 | 269 | } | |
333 | |||
334 | 543491 | NAV::InputPin* NAV::OutputPin::OutgoingLink::getConnectedPin() const | |
335 | { | ||
336 |
2/2✓ Branch 0 taken 543293 times.
✓ Branch 1 taken 198 times.
|
543491 | if (connectedNode) |
337 | { | ||
338 |
1/2✓ Branch 5 taken 1047172 times.
✗ Branch 6 not taken.
|
1047405 | for (auto& inputPin : connectedNode->inputPins) |
339 | { | ||
340 |
3/4✓ Branch 1 taken 1047634 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 543522 times.
✓ Branch 4 taken 504112 times.
|
1047143 | if (inputPin.id == connectedPinId) { return &inputPin; } |
341 | } | ||
342 | } | ||
343 | 198 | 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 | 656138 | bool NAV::InputPin::isPinLinked() const | |
356 | { | ||
357 |
4/6✓ Branch 1 taken 655730 times.
✓ Branch 2 taken 236 times.
✓ Branch 3 taken 655764 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 654810 times.
✗ Branch 7 not taken.
|
656138 | 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 | 172 | void NAV::InputPin::deleteLink() | |
371 | { | ||
372 |
1/2✓ Branch 1 taken 172 times.
✗ Branch 2 not taken.
|
172 | if (auto* startPin = link.getConnectedPin()) |
373 | { | ||
374 | 172 | Pin::deleteLink(*startPin, *this); | |
375 | } | ||
376 | 172 | } | |
377 | |||
378 | 540 | void NAV::InputPin::connect(NAV::OutputPin& startPin, ax::NodeEditor::LinkId linkId) | |
379 | { | ||
380 |
5/6✓ Branch 0 taken 270 times.
✓ Branch 1 taken 270 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 270 times.
✓ Branch 5 taken 270 times.
✓ Branch 6 taken 270 times.
|
540 | if (link.connectedNode != startPin.parentNode || link.connectedPinId != startPin.id) // Link does not yet exist |
381 | { | ||
382 | 270 | link.connectedNode = startPin.parentNode; | |
383 | 270 | link.connectedPinId = startPin.id; | |
384 | |||
385 |
1/2✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
|
270 | auto iter = std::ranges::find_if(startPin.links, [&, this](const OutputPin::OutgoingLink& link) { |
386 |
4/4✓ Branch 0 taken 287 times.
✓ Branch 1 taken 49 times.
✓ Branch 3 taken 270 times.
✓ Branch 4 taken 17 times.
|
336 | return link.connectedNode == parentNode && link.connectedPinId == id; |
387 | }); | ||
388 | |||
389 |
3/4✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 269 times.
✓ Branch 4 taken 1 times.
|
270 | if (linkId) |
390 | { | ||
391 | // LinkId is given | ||
392 | 269 | link.linkId = linkId; | |
393 |
4/8✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 269 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 269 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 269 times.
|
269 | 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 1 times.
✗ Branch 3 not taken.
|
1 | else if (iter != startPin.links.end()) |
400 | { | ||
401 | // Connected pin is already linked, so get linkId from the connected pin | ||
402 | 1 | 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 | 540 | } | |
413 | |||
414 | 807 | void NAV::InputPin::disconnect() | |
415 | { | ||
416 |
6/8✓ Branch 0 taken 538 times.
✓ Branch 1 taken 269 times.
✓ Branch 3 taken 538 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 538 times.
✓ Branch 8 taken 269 times.
✓ Branch 9 taken 538 times.
|
807 | if (link.connectedNode || link.connectedPinId || link.linkId) |
417 | { | ||
418 | 269 | auto* startPin = link.getConnectedPin(); | |
419 | |||
420 |
1/2✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
|
269 | link.linkId = 0; |
421 | 269 | link.connectedNode = nullptr; | |
422 |
1/2✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
|
269 | link.connectedPinId = 0; |
423 | |||
424 |
1/2✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
|
269 | if (startPin) |
425 | { | ||
426 |
1/2✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
|
269 | auto iter = std::ranges::find_if(startPin->links, [&, this](const OutputPin::OutgoingLink& link) { |
427 |
3/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 49 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
|
66 | return link.connectedNode == parentNode && link.connectedPinId == id; |
428 | }); | ||
429 | |||
430 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 269 times.
|
269 | if (iter != startPin->links.end()) |
431 | { | ||
432 | ✗ | startPin->disconnect(*this); | |
433 | } | ||
434 | } | ||
435 | } | ||
436 | 807 | } | |
437 | |||
438 | 1571889 | NAV::OutputPin* NAV::InputPin::IncomingLink::getConnectedPin() const | |
439 | { | ||
440 |
2/2✓ Branch 0 taken 1571598 times.
✓ Branch 1 taken 291 times.
|
1571889 | if (connectedNode) |
441 | { | ||
442 |
1/2✓ Branch 5 taken 2140431 times.
✗ Branch 6 not taken.
|
2140854 | for (auto& outputPin : connectedNode->outputPins) |
443 | { | ||
444 |
3/4✓ Branch 1 taken 2140699 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1571443 times.
✓ Branch 4 taken 569256 times.
|
2140406 | if (outputPin.id == connectedPinId) { return &outputPin; } |
445 | } | ||
446 | } | ||
447 | 291 | 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 | 1067 | void NAV::from_json(const json& j, OutputPin& pin) | |
460 | { | ||
461 |
3/6✓ Branch 1 taken 1067 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1067 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1067 times.
✗ Branch 8 not taken.
|
1067 | pin.id = j.at("id").get<size_t>(); |
462 |
1/2✓ Branch 1 taken 1067 times.
✗ Branch 2 not taken.
|
1067 | if (j.contains("name")) { j.at("name").get_to(pin.name); } |
463 | 1067 | } | |
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 | 1022 | void NAV::from_json(const json& j, InputPin& pin) | |
473 | { | ||
474 |
3/6✓ Branch 1 taken 1022 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1022 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1022 times.
✗ Branch 8 not taken.
|
1022 | pin.id = j.at("id").get<size_t>(); |
475 |
1/2✓ Branch 1 taken 1022 times.
✗ Branch 2 not taken.
|
1022 | if (j.contains("name")) { j.at("name").get_to(pin.name); } |
476 | 1022 | } | |
477 |