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/FlowManager.hpp" | ||
10 | |||
11 | #include "util/Json.hpp" | ||
12 | |||
13 | #include "internal/NodeManager.hpp" | ||
14 | namespace nm = NAV::NodeManager; | ||
15 | |||
16 | #include <implot.h> | ||
17 | #include <imgui_node_editor.h> | ||
18 | namespace ed = ax::NodeEditor; | ||
19 | |||
20 | #include "NodeRegistry.hpp" | ||
21 | |||
22 | #include "internal/Node/Node.hpp" | ||
23 | #include "internal/Node/Pin.hpp" | ||
24 | #include "internal/ConfigManager.hpp" | ||
25 | #include "internal/FlowExecutor.hpp" | ||
26 | |||
27 | #include "internal/gui/windows/ImPlotStyleEditor.hpp" | ||
28 | #include "internal/gui/NodeEditorApplication.hpp" | ||
29 | #include "internal/gui/windows/NodeEditorStyleEditor.hpp" | ||
30 | #include "util/Plot/Colormap.hpp" | ||
31 | #include "util/Logger/CommonLog.hpp" | ||
32 | |||
33 | #include <fstream> | ||
34 | #include <set> | ||
35 | #include <iomanip> | ||
36 | #include <string> | ||
37 | #include <memory> | ||
38 | |||
39 | #include <iostream> | ||
40 | |||
41 | namespace NAV::flow | ||
42 | { | ||
43 | namespace | ||
44 | { | ||
45 | |||
46 | bool unsavedChanges = false; | ||
47 | |||
48 | constexpr int loadingFramesToWait = 2; | ||
49 | |||
50 | std::string currentFilename; | ||
51 | std::filesystem::path programRootPath; | ||
52 | |||
53 | // The current number for the rotated parent folder | ||
54 | size_t currentRotatedParentFolderNumber; | ||
55 | |||
56 | } // namespace | ||
57 | |||
58 | bool saveLastActions = true; | ||
59 | int loadingFrameCount = 0; | ||
60 | |||
61 | } // namespace NAV::flow | ||
62 | |||
63 | ✗ | void NAV::flow::SaveFlow(GlobalActions& globalAction) | |
64 | { | ||
65 | ✗ | if (currentFilename.empty()) | |
66 | { | ||
67 | ✗ | globalAction = GlobalActions::SaveAs; | |
68 | } | ||
69 | else | ||
70 | { | ||
71 | ✗ | SaveFlowAs(currentFilename); | |
72 | } | ||
73 | ✗ | } | |
74 | |||
75 | ✗ | void NAV::flow::SaveFlowAs(const std::string& filepath) | |
76 | { | ||
77 | ✗ | std::ofstream filestream(filepath); | |
78 | |||
79 | ✗ | if (!filestream.good()) | |
80 | { | ||
81 | ✗ | std::cerr << "Save Flow error: Could not open file: " << filepath; | |
82 | ✗ | return; | |
83 | } | ||
84 | |||
85 | ✗ | json j; | |
86 | ✗ | for (const auto& node : nm::m_Nodes()) | |
87 | { | ||
88 | ✗ | j["nodes"]["node-" + std::to_string(size_t(node->id))] = *node; | |
89 | ✗ | j["nodes"]["node-" + std::to_string(size_t(node->id))]["data"] = node->save(); | |
90 | |||
91 | ✗ | for (const auto& outputPin : node->outputPins) | |
92 | { | ||
93 | ✗ | for (const auto& link : outputPin.links) | |
94 | { | ||
95 | ✗ | auto& jLink = j["links"]["link-" + std::to_string(size_t(link.linkId))]; | |
96 | ✗ | jLink["id"] = size_t(link.linkId); | |
97 | ✗ | jLink["startPinId"] = size_t(outputPin.id); | |
98 | ✗ | jLink["endPinId"] = size_t(link.connectedPinId); | |
99 | } | ||
100 | } | ||
101 | } | ||
102 | ✗ | if (gui::windows::saveConfigInFlow) | |
103 | { | ||
104 | ✗ | j["implot"]["style"] = ImPlot::GetStyle(); | |
105 | ✗ | j["implot"]["prefereFlowOverGlobal"] = gui::windows::prefereFlowOverGlobal; | |
106 | } | ||
107 | |||
108 | ✗ | j["fonts"]["useBigDefaultFont"] = gui::NodeEditorApplication::isUsingBigDefaultFont(); | |
109 | ✗ | j["fonts"]["useBigWindowFont"] = gui::NodeEditorApplication::isUsingBigWindowFont(); | |
110 | ✗ | j["fonts"]["useBigPanelFont"] = gui::NodeEditorApplication::isUsingBigPanelFont(); | |
111 | ✗ | j["fonts"]["useBigMonoFont"] = gui::NodeEditorApplication::isUsingBigMonoFont(); | |
112 | ✗ | j["leftPane"]["hide"] = gui::NodeEditorApplication::hideLeftPane; | |
113 | ✗ | j["leftPane"]["leftWidth"] = gui::NodeEditorApplication::leftPaneWidth; | |
114 | ✗ | j["leftPane"]["rightWidth"] = gui::NodeEditorApplication::rightPaneWidth; | |
115 | ✗ | j["bottomViewHeight"] = gui::NodeEditorApplication::bottomViewHeight; | |
116 | ✗ | j["hideFPS"] = gui::NodeEditorApplication::hideFPS; | |
117 | ✗ | j["lightMode"] = gui::windows::nodeEditorLightMode; | |
118 | ✗ | j["gridLinesEnabled"] = ed::GetStyle().Colors[ed::StyleColor_Grid].w; | |
119 | ✗ | j["transparentWindows"] = ImGui::GetStyle().Colors[ImGuiCol_WindowBg].w; | |
120 | |||
121 | // if (ImGui::Checkbox("Light mode", &nodeEditorLightMode)) | ||
122 | // { | ||
123 | // ApplyDarkLightMode(NodeEditorApplication::m_colors); | ||
124 | // flow::ApplyChanges(); | ||
125 | // } | ||
126 | |||
127 | ✗ | j["colormaps"] = ColormapsFlow; | |
128 | ✗ | j["commonLog"] = CommonLog::save(); | |
129 | |||
130 | ✗ | filestream << std::setw(4) << j << std::endl; // NOLINT(performance-avoid-endl) | |
131 | |||
132 | ✗ | unsavedChanges = false; | |
133 | ✗ | } | |
134 | |||
135 | 112 | bool NAV::flow::LoadFlow(const std::string& filepath) | |
136 | { | ||
137 | LOG_TRACE("called for path {}", filepath); | ||
138 | 112 | bool loadSuccessful = true; | |
139 | |||
140 | try | ||
141 | { | ||
142 |
1/2✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
|
112 | std::ifstream filestream(filepath); |
143 | |||
144 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
|
112 | if (!filestream.good()) |
145 | { | ||
146 | ✗ | LOG_ERROR("Load Flow error: Could not open file: {}", filepath); | |
147 | ✗ | return false; | |
148 | } | ||
149 | |||
150 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
112 | if (FlowExecutor::isRunning()) { FlowExecutor::stop(); } |
151 | |||
152 | 112 | json j; | |
153 |
1/2✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
|
112 | filestream >> j; |
154 | |||
155 | 112 | saveLastActions = false; | |
156 | |||
157 |
1/2✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
|
112 | nm::DeleteAllNodes(); |
158 | |||
159 |
3/6✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 112 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 112 times.
✗ Branch 8 not taken.
|
112 | if (!j.contains("commonLog")) { CommonLog::restore(json{}); } |
160 |
1/2✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
|
112 | LoadJson(j); |
161 | |||
162 | #ifdef TESTING | ||
163 |
1/2✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
|
112 | nm::CallPreInitCallback(); |
164 | #endif | ||
165 | |||
166 |
3/6✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 112 times.
✗ Branch 8 not taken.
|
224 | if (!ConfigManager::Get<bool>("noinit")) |
167 | { | ||
168 |
3/6✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 112 times.
✗ Branch 8 not taken.
|
224 | if (ConfigManager::Get<bool>("nogui")) |
169 | { | ||
170 |
3/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 111 times.
|
112 | if (!nm::InitializeAllNodes()) |
171 | { | ||
172 | 1 | loadSuccessful = false; | |
173 | } | ||
174 | } | ||
175 | else | ||
176 | { | ||
177 | ✗ | nm::InitializeAllNodesAsync(); | |
178 | } | ||
179 | } | ||
180 | |||
181 |
3/6✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 112 times.
|
224 | if (!ConfigManager::Get<bool>("nogui")) |
182 | { | ||
183 | ✗ | loadingFrameCount = ImGui::GetFrameCount(); | |
184 | } | ||
185 | 112 | unsavedChanges = false; | |
186 | 112 | saveLastActions = true; | |
187 |
1/2✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
|
112 | currentFilename = filepath; |
188 | |||
189 |
3/6✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 112 times.
|
224 | if (!ConfigManager::Get<bool>("nogui")) |
190 | { | ||
191 | ✗ | gui::clearLastActionList(); | |
192 | ✗ | gui::saveLastAction(); | |
193 | } | ||
194 | |||
195 |
1/2✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
|
112 | std::string path = filepath; |
196 |
3/6✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 112 times.
|
112 | if (path.find(GetProgramRootPath().string()) != std::string::npos) |
197 | { | ||
198 | ✗ | path = path.substr(GetProgramRootPath().string().size()); | |
199 | ✗ | if (path.starts_with('\\') || path.starts_with('/')) { path = path.substr(1); } | |
200 | } | ||
201 | |||
202 |
2/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 112 times.
✗ Branch 6 not taken.
|
112 | LOG_INFO("Loaded flow file: {}", path); |
203 | 112 | } | |
204 | ✗ | catch (const std::exception& e) | |
205 | { | ||
206 | ✗ | LOG_ERROR("Loading flow file failed with error: {}", e.what()); | |
207 | ✗ | loadSuccessful = false; | |
208 | ✗ | } | |
209 | |||
210 | 112 | return loadSuccessful; | |
211 | } | ||
212 | |||
213 | 112 | bool NAV::flow::LoadJson(const json& j, bool requestNewIds) | |
214 | { | ||
215 | 112 | bool loadSuccessful = true; | |
216 | |||
217 |
3/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 110 times.
|
112 | if (j.contains("implot")) |
218 | { | ||
219 | 2 | gui::windows::saveConfigInFlow = true; | |
220 | |||
221 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
2 | if (j.at("implot").contains("prefereFlowOverGlobal")) |
222 | { | ||
223 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | j.at("implot").at("prefereFlowOverGlobal").get_to(gui::windows::prefereFlowOverGlobal); |
224 | } | ||
225 | |||
226 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | std::filesystem::path filepath = flow::GetProgramRootPath(); |
227 |
4/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
4 | if (std::filesystem::path inputPath{ ConfigManager::Get<std::string>("implot-config") }; |
228 | 2 | inputPath.is_relative()) | |
229 | { | ||
230 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | filepath /= inputPath; |
231 | } | ||
232 | else | ||
233 | { | ||
234 | ✗ | filepath = inputPath; | |
235 | 2 | } | |
236 | |||
237 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | if (gui::windows::prefereFlowOverGlobal || !std::filesystem::exists(filepath)) |
238 | { | ||
239 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
|
4 | if (!ConfigManager::Get<bool>("nogui")) |
240 | { | ||
241 | ✗ | if (j.at("implot").contains("style")) | |
242 | { | ||
243 | ✗ | j.at("implot").at("style").get_to(ImPlot::GetStyle()); | |
244 | } | ||
245 | } | ||
246 | } | ||
247 | 2 | } | |
248 | else | ||
249 | { | ||
250 | 110 | gui::windows::saveConfigInFlow = false; | |
251 | } | ||
252 | |||
253 |
3/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
✓ Branch 4 taken 43 times.
|
112 | if (j.contains("colormaps")) |
254 | { | ||
255 |
2/4✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
|
69 | j.at("colormaps").get_to(ColormapsFlow); |
256 | } | ||
257 | else | ||
258 | { | ||
259 | 43 | ColormapsFlow.clear(); | |
260 | } | ||
261 |
2/8✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
112 | if (j.contains("commonLog")) { CommonLog::restore(j.at("commonLog")); } |
262 | |||
263 |
3/6✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 112 times.
|
224 | if (!ConfigManager::Get<bool>("nogui")) |
264 | { | ||
265 | ✗ | if (j.contains("fonts")) | |
266 | { | ||
267 | ✗ | if (j.at("fonts").contains("useBigDefaultFont")) | |
268 | { | ||
269 | ✗ | gui::NodeEditorApplication::swapDefaultFont(j.at("fonts").at("useBigDefaultFont").get<bool>()); | |
270 | } | ||
271 | ✗ | if (j.at("fonts").contains("useBigWindowFont")) | |
272 | { | ||
273 | ✗ | gui::NodeEditorApplication::swapWindowFont(j.at("fonts").at("useBigWindowFont").get<bool>()); | |
274 | } | ||
275 | ✗ | if (j.at("fonts").contains("useBigPanelFont")) | |
276 | { | ||
277 | ✗ | gui::NodeEditorApplication::swapPanelFont(j.at("fonts").at("useBigPanelFont").get<bool>()); | |
278 | } | ||
279 | ✗ | if (j.at("fonts").contains("useBigMonoFont")) | |
280 | { | ||
281 | ✗ | gui::NodeEditorApplication::swapMonoFont(j.at("fonts").at("useBigMonoFont").get<bool>()); | |
282 | } | ||
283 | } | ||
284 | ✗ | if (j.contains("leftPane")) | |
285 | { | ||
286 | ✗ | j.at("leftPane").at("hide").get_to(gui::NodeEditorApplication::hideLeftPane); | |
287 | ✗ | j.at("leftPane").at("leftWidth").get_to(gui::NodeEditorApplication::leftPaneWidth); | |
288 | ✗ | j.at("leftPane").at("rightWidth").get_to(gui::NodeEditorApplication::rightPaneWidth); | |
289 | } | ||
290 | ✗ | if (j.contains("bottomViewHeight")) { j.at("bottomViewHeight").get_to(gui::NodeEditorApplication::bottomViewHeight); } | |
291 | ✗ | if (j.contains("hideFPS")) { j.at("hideFPS").get_to(gui::NodeEditorApplication::hideFPS); } | |
292 | ✗ | if (j.contains("lightMode")) | |
293 | { | ||
294 | ✗ | j.at("lightMode").get_to(gui::windows::nodeEditorLightMode); | |
295 | ✗ | gui::windows::ApplyDarkLightMode(gui::NodeEditorApplication::m_colors); | |
296 | } | ||
297 | ✗ | if (j.contains("gridLinesEnabled")) { j.at("gridLinesEnabled").get_to(ed::GetStyle().Colors[ed::StyleColor_Grid].w); } | |
298 | ✗ | if (j.contains("transparentWindows")) { j.at("transparentWindows").get_to(ImGui::GetStyle().Colors[ImGuiCol_WindowBg].w); } | |
299 | } | ||
300 | |||
301 |
2/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 112 times.
✗ Branch 4 not taken.
|
112 | if (j.contains("nodes")) |
302 | { | ||
303 |
6/10✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 346 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 346 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 458 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 346 times.
✓ Branch 15 taken 112 times.
|
458 | for (const auto& nodeJson : j.at("nodes")) |
304 | { | ||
305 |
2/4✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 346 times.
|
346 | if (!nodeJson.contains("type")) |
306 | { | ||
307 | ✗ | LOG_ERROR("Node does not contain a type"); | |
308 | ✗ | continue; | |
309 | } | ||
310 | 346 | Node* node = nullptr; | |
311 |
2/4✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 1827 times.
✗ Branch 9 not taken.
|
1827 | for (const auto& registeredNode : NAV::NodeRegistry::RegisteredNodes()) |
312 | { | ||
313 |
2/2✓ Branch 5 taken 19074 times.
✓ Branch 6 taken 1481 times.
|
20555 | for (const auto& nodeInfo : registeredNode.second) |
314 | { | ||
315 |
4/6✓ Branch 1 taken 19074 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19074 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 346 times.
✓ Branch 9 taken 18728 times.
|
19074 | if (nodeInfo.type == nodeJson.at("type").get<std::string>()) |
316 | { | ||
317 |
1/2✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
|
346 | node = nodeInfo.constructor(); |
318 | 346 | break; | |
319 | } | ||
320 | } | ||
321 |
2/2✓ Branch 0 taken 346 times.
✓ Branch 1 taken 1481 times.
|
1827 | if (node != nullptr) |
322 | { | ||
323 | 346 | break; | |
324 | } | ||
325 | } | ||
326 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 346 times.
|
346 | if (node == nullptr) |
327 | { | ||
328 | ✗ | LOG_ERROR("Node type ({}) is not a valid type.", nodeJson.at("type").get<std::string>()); | |
329 | ✗ | loadSuccessful = false; | |
330 | ✗ | continue; | |
331 | } | ||
332 | |||
333 |
1/2✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
|
346 | nm::AddNode(node); |
334 | 346 | auto newNodeId = node->id; | |
335 | |||
336 |
1/2✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
|
346 | nodeJson.get_to<Node>(*node); |
337 |
2/4✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 346 times.
✗ Branch 4 not taken.
|
346 | if (nodeJson.contains("data")) |
338 | { | ||
339 |
2/4✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 346 times.
✗ Branch 5 not taken.
|
346 | node->restore(nodeJson.at("data")); |
340 | } | ||
341 | // Load second time in case restore changed the amount of pins | ||
342 |
1/2✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
|
346 | nodeJson.get_to<Node>(*node); |
343 | |||
344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 346 times.
|
346 | if (requestNewIds) |
345 | { | ||
346 | ✗ | node->id = newNodeId; | |
347 | ✗ | for (auto& pin : node->inputPins) | |
348 | { | ||
349 | ✗ | pin.id = nm::GetNextPinId(); | |
350 | } | ||
351 | ✗ | for (auto& pin : node->outputPins) | |
352 | { | ||
353 | ✗ | pin.id = nm::GetNextPinId(); | |
354 | } | ||
355 | } | ||
356 | |||
357 |
1/2✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
|
346 | nm::UpdateNode(node); |
358 | |||
359 |
3/6✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 346 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 346 times.
|
692 | if (!ConfigManager::Get<bool>("nogui")) |
360 | { | ||
361 | ✗ | ed::SetNodePosition(node->id, nodeJson.at("pos").get<ImVec2>()); | |
362 | |||
363 | ✗ | if (node->getSize().x > 0 && node->getSize().y > 0) | |
364 | { | ||
365 | ✗ | ed::SetGroupSize(node->id, node->getSize()); | |
366 | } | ||
367 | } | ||
368 | } | ||
369 | } | ||
370 | |||
371 | // Collect the node ids which get new links to call the restoreAfterLinks function on them | ||
372 | 112 | std::set<Node*> newlyLinkedNodes; | |
373 | |||
374 |
3/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 75 times.
✓ Branch 4 taken 37 times.
|
112 | if (j.contains("links")) |
375 | { | ||
376 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 75 times.
|
225 | for (size_t i = 0; i < 2; i++) // Run twice because pins can change type depending on other links |
377 | { | ||
378 |
6/10✓ Branch 1 taken 150 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 538 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 538 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 688 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 538 times.
✓ Branch 15 taken 150 times.
|
688 | for (const auto& linkJson : j.at("links")) |
379 | { | ||
380 |
2/4✓ Branch 1 taken 538 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 538 times.
✗ Branch 5 not taken.
|
538 | auto linkId = linkJson.at("id").get<size_t>(); |
381 |
2/4✓ Branch 1 taken 538 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 538 times.
✗ Branch 5 not taken.
|
538 | auto startPinId = linkJson.at("startPinId").get<size_t>(); |
382 |
2/4✓ Branch 1 taken 538 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 538 times.
✗ Branch 5 not taken.
|
538 | auto endPinId = linkJson.at("endPinId").get<size_t>(); |
383 | |||
384 | 538 | InputPin* endPin = nullptr; | |
385 | 538 | OutputPin* startPin = nullptr; | |
386 |
2/4✓ Branch 1 taken 538 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 2466 times.
✗ Branch 9 not taken.
|
2466 | for (auto* node : nm::m_Nodes()) |
387 | { | ||
388 |
2/2✓ Branch 0 taken 1896 times.
✓ Branch 1 taken 570 times.
|
2466 | if (!endPin) |
389 | { | ||
390 |
2/2✓ Branch 5 taken 2396 times.
✓ Branch 6 taken 1896 times.
|
4292 | for (auto& inputPin : node->inputPins) |
391 | { | ||
392 |
3/4✓ Branch 1 taken 2396 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 538 times.
✓ Branch 4 taken 1858 times.
|
2396 | if (endPinId == size_t(inputPin.id)) { endPin = &inputPin; } |
393 | } | ||
394 | } | ||
395 |
2/2✓ Branch 0 taken 1754 times.
✓ Branch 1 taken 712 times.
|
2466 | if (!startPin) |
396 | { | ||
397 |
2/2✓ Branch 5 taken 1846 times.
✓ Branch 6 taken 1754 times.
|
3600 | for (auto& outputPin : node->outputPins) |
398 | { | ||
399 |
3/4✓ Branch 1 taken 1846 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 538 times.
✓ Branch 4 taken 1308 times.
|
1846 | if (startPinId == size_t(outputPin.id)) { startPin = &outputPin; } |
400 | } | ||
401 | } | ||
402 |
4/4✓ Branch 0 taken 1250 times.
✓ Branch 1 taken 1216 times.
✓ Branch 2 taken 538 times.
✓ Branch 3 taken 712 times.
|
2466 | if (startPin && endPin) { break; } |
403 | } | ||
404 |
2/4✓ Branch 0 taken 538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 538 times.
✗ Branch 3 not taken.
|
538 | if (startPin && endPin) |
405 | { | ||
406 |
4/6✓ Branch 1 taken 538 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 538 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 536 times.
|
538 | if (!startPin->createLink(*endPin, linkId)) |
407 | { | ||
408 | 2 | loadSuccessful = false; | |
409 | 2 | continue; | |
410 | } | ||
411 |
1/2✓ Branch 1 taken 536 times.
✗ Branch 2 not taken.
|
536 | newlyLinkedNodes.insert(startPin->parentNode); |
412 |
1/2✓ Branch 1 taken 536 times.
✗ Branch 2 not taken.
|
536 | newlyLinkedNodes.insert(endPin->parentNode); |
413 | } | ||
414 | } | ||
415 | } | ||
416 | } | ||
417 |
2/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 112 times.
✗ Branch 4 not taken.
|
112 | if (j.contains("nodes")) |
418 | { | ||
419 |
2/2✓ Branch 5 taken 305 times.
✓ Branch 6 taken 112 times.
|
417 | for (auto* node : newlyLinkedNodes) |
420 | { | ||
421 |
6/12✓ Branch 1 taken 305 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 305 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 305 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 305 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 305 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 305 times.
✗ Branch 18 not taken.
|
305 | if (j.at("nodes").contains("node-" + std::to_string(size_t(node->id)))) |
422 | { | ||
423 |
3/6✓ Branch 1 taken 305 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 305 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 305 times.
✗ Branch 9 not taken.
|
305 | LOG_DEBUG("Calling restoreAtferLink() for new node '{}'", node->nameId()); |
424 | |||
425 |
5/10✓ Branch 1 taken 305 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 305 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 305 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 305 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 305 times.
✗ Branch 14 not taken.
|
305 | const auto& nodeJson = j.at("nodes").at("node-" + std::to_string(size_t(node->id))); |
426 |
2/4✓ Branch 1 taken 305 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 305 times.
✗ Branch 4 not taken.
|
305 | if (nodeJson.contains("data")) |
427 | { | ||
428 |
2/4✓ Branch 1 taken 305 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 305 times.
✗ Branch 5 not taken.
|
305 | node->restoreAtferLink(nodeJson.at("data")); |
429 | } | ||
430 | } | ||
431 | } | ||
432 | } | ||
433 | |||
434 | 112 | return loadSuccessful; | |
435 | 112 | } | |
436 | |||
437 | ✗ | bool NAV::flow::HasUnsavedChanges() | |
438 | { | ||
439 | ✗ | return unsavedChanges; | |
440 | } | ||
441 | |||
442 | 14088 | void NAV::flow::ApplyChanges() | |
443 | { | ||
444 | // This prevents the newly loaded gui elements from triggering the unsaved changes | ||
445 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 14088 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 14088 times.
|
14088 | if (ImGui::GetCurrentContext() && ImGui::GetFrameCount() - loadingFrameCount >= loadingFramesToWait) |
446 | { | ||
447 | ✗ | unsavedChanges = true; | |
448 | ✗ | if (saveLastActions) | |
449 | { | ||
450 | ✗ | gui::saveLastAction(); | |
451 | } | ||
452 | } | ||
453 | 14088 | } | |
454 | |||
455 | ✗ | void NAV::flow::DiscardChanges() | |
456 | { | ||
457 | ✗ | unsavedChanges = false; | |
458 | ✗ | } | |
459 | |||
460 | ✗ | std::string NAV::flow::GetCurrentFilename() | |
461 | { | ||
462 | ✗ | return currentFilename; | |
463 | } | ||
464 | |||
465 | ✗ | void NAV::flow::SetCurrentFilename(const std::string& newFilename) | |
466 | { | ||
467 | ✗ | currentFilename = newFilename; | |
468 | ✗ | } | |
469 | |||
470 | 813 | std::filesystem::path NAV::flow::GetProgramRootPath() | |
471 | { | ||
472 | 813 | return programRootPath; | |
473 | } | ||
474 | |||
475 | 116 | void NAV::flow::SetProgramRootPath(const std::filesystem::path& newRootPath) | |
476 | { | ||
477 |
1/2✓ Branch 3 taken 116 times.
✗ Branch 4 not taken.
|
116 | LOG_DEBUG("Program root path set to {}", newRootPath); |
478 | 116 | programRootPath = newRootPath; | |
479 | 116 | } | |
480 | |||
481 | 260 | std::filesystem::path NAV::flow::GetOutputPath() | |
482 | { | ||
483 | 260 | std::filesystem::path filepath = flow::GetProgramRootPath(); | |
484 | |||
485 |
4/8✓ Branch 1 taken 260 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 259 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 259 times.
✗ Branch 11 not taken.
|
519 | if (std::filesystem::path outputPath{ ConfigManager::Get<std::string>("output-path") }; |
486 | 260 | outputPath.is_relative()) | |
487 | { | ||
488 |
1/2✓ Branch 1 taken 259 times.
✗ Branch 2 not taken.
|
259 | filepath /= outputPath; |
489 | } | ||
490 | else | ||
491 | { | ||
492 | ✗ | filepath = outputPath; | |
493 | 259 | } | |
494 | |||
495 |
4/6✓ Branch 1 taken 260 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 260 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 30 times.
✓ Branch 8 taken 229 times.
|
518 | if (ConfigManager::Get<bool>("rotate-output")) |
496 | { | ||
497 |
1/2✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
|
60 | filepath /= fmt::format("{:04d}", currentRotatedParentFolderNumber); |
498 | } | ||
499 | |||
500 | 259 | return filepath; | |
501 | ✗ | } | |
502 | |||
503 | 125 | void NAV::flow::SetOutputPath() | |
504 | { | ||
505 | 125 | currentRotatedParentFolderNumber = 0; | |
506 |
2/2✓ Branch 0 taken 1250080 times.
✓ Branch 1 taken 115 times.
|
1250195 | for (int i = 10000; i >= 0; --i) |
507 | { | ||
508 |
1/2✓ Branch 1 taken 1250080 times.
✗ Branch 2 not taken.
|
1250080 | std::filesystem::path outputDir{ programRootPath }; |
509 | |||
510 |
4/8✓ Branch 1 taken 1250080 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1250080 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1250080 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1250080 times.
✗ Branch 11 not taken.
|
2500160 | if (std::filesystem::path outputPath{ ConfigManager::Get<std::string>("output-path") }; |
511 | 1250080 | outputPath.is_relative()) | |
512 | { | ||
513 |
1/2✓ Branch 1 taken 1250080 times.
✗ Branch 2 not taken.
|
1250080 | outputDir /= outputPath; |
514 | } | ||
515 | else | ||
516 | { | ||
517 | ✗ | outputDir = outputPath; | |
518 | 1250080 | } | |
519 |
1/2✓ Branch 2 taken 1250080 times.
✗ Branch 3 not taken.
|
2500160 | outputDir /= fmt::format("{:04d}", i); |
520 |
3/4✓ Branch 1 taken 1250080 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1250070 times.
|
1250080 | if (std::filesystem::exists(outputDir)) |
521 | { | ||
522 | 10 | currentRotatedParentFolderNumber = static_cast<size_t>(i + 1); // NOLINT(bugprone-misplaced-widening-cast) | |
523 | 10 | break; | |
524 | } | ||
525 | 1250080 | } | |
526 |
2/4✓ Branch 2 taken 125 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 125 times.
✗ Branch 7 not taken.
|
125 | LOG_DEBUG("Output directory set to {}", GetOutputPath()); |
527 | 125 | } | |
528 | |||
529 | 321 | std::filesystem::path NAV::flow::GetInputPath() | |
530 | { | ||
531 | 321 | std::filesystem::path filepath = flow::GetProgramRootPath(); | |
532 | |||
533 |
4/8✓ Branch 1 taken 321 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 321 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 322 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 320 times.
✗ Branch 11 not taken.
|
641 | if (std::filesystem::path inputPath{ ConfigManager::Get<std::string>("input-path") }; |
534 | 320 | inputPath.is_relative()) | |
535 | { | ||
536 |
1/2✓ Branch 1 taken 322 times.
✗ Branch 2 not taken.
|
320 | filepath /= inputPath; |
537 | } | ||
538 | else | ||
539 | { | ||
540 | ✗ | filepath = inputPath; | |
541 | 322 | } | |
542 | |||
543 | 320 | return filepath; | |
544 | ✗ | } | |
545 | |||
546 | 3 | std::filesystem::path NAV::flow::GetFlowPath() | |
547 | { | ||
548 | 3 | std::filesystem::path filepath = flow::GetProgramRootPath(); | |
549 | |||
550 |
4/8✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
|
6 | if (std::filesystem::path inputPath{ ConfigManager::Get<std::string>("flow-path") }; |
551 | 3 | inputPath.is_relative()) | |
552 | { | ||
553 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | filepath /= inputPath; |
554 | } | ||
555 | else | ||
556 | { | ||
557 | ✗ | filepath = inputPath; | |
558 | 3 | } | |
559 | |||
560 | 3 | return filepath; | |
561 | ✗ | } | |
562 | |||
563 | ✗ | std::filesystem::path NAV::flow::GetConfigPath() | |
564 | { | ||
565 | ✗ | return flow::GetProgramRootPath() / "config"; | |
566 | } | ||
567 |