| 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 | 114 | bool NAV::flow::LoadFlow(const std::string& filepath) | |
| 136 | { | ||
| 137 | LOG_TRACE("called for path {}", filepath); | ||
| 138 | 114 | bool loadSuccessful = true; | |
| 139 | |||
| 140 | try | ||
| 141 | { | ||
| 142 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
114 | std::ifstream filestream(filepath); |
| 143 | |||
| 144 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 114 times.
|
114 | 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 114 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
114 | if (FlowExecutor::isRunning()) { FlowExecutor::stop(); } |
| 151 | |||
| 152 | 114 | json j; | |
| 153 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
114 | filestream >> j; |
| 154 | |||
| 155 | 114 | saveLastActions = false; | |
| 156 | |||
| 157 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
114 | nm::DeleteAllNodes(); |
| 158 | |||
| 159 |
4/6✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 93 times.
✓ Branch 4 taken 21 times.
✓ Branch 7 taken 93 times.
✗ Branch 8 not taken.
|
114 | if (!j.contains("commonLog")) { CommonLog::restore(json{}); } |
| 160 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
114 | LoadJson(j); |
| 161 | |||
| 162 | #ifdef TESTING | ||
| 163 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
114 | nm::CallPreInitCallback(); |
| 164 | #endif | ||
| 165 | |||
| 166 |
3/6✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 114 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 114 times.
✗ Branch 8 not taken.
|
228 | if (!ConfigManager::Get<bool>("noinit")) |
| 167 | { | ||
| 168 |
3/6✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 114 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 114 times.
✗ Branch 8 not taken.
|
228 | if (ConfigManager::Get<bool>("nogui")) |
| 169 | { | ||
| 170 |
3/4✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 113 times.
|
114 | 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 114 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 114 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 114 times.
|
228 | if (!ConfigManager::Get<bool>("nogui")) |
| 182 | { | ||
| 183 | ✗ | loadingFrameCount = ImGui::GetFrameCount(); | |
| 184 | } | ||
| 185 | 114 | unsavedChanges = false; | |
| 186 | 114 | saveLastActions = true; | |
| 187 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
114 | currentFilename = filepath; |
| 188 | |||
| 189 |
3/6✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 114 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 114 times.
|
228 | if (!ConfigManager::Get<bool>("nogui")) |
| 190 | { | ||
| 191 | ✗ | gui::clearLastActionList(); | |
| 192 | ✗ | gui::saveLastAction(); | |
| 193 | } | ||
| 194 | |||
| 195 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
114 | std::string path = filepath; |
| 196 |
3/6✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 114 times.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 114 times.
|
114 | 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 114 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 114 times.
✗ Branch 6 not taken.
|
114 | LOG_INFO("Loaded flow file: {}", path); |
| 203 | 114 | } | |
| 204 | ✗ | catch (const std::exception& e) | |
| 205 | { | ||
| 206 | ✗ | LOG_ERROR("Loading flow file failed with error: {}", e.what()); | |
| 207 | ✗ | loadSuccessful = false; | |
| 208 | ✗ | } | |
| 209 | |||
| 210 | 114 | return loadSuccessful; | |
| 211 | } | ||
| 212 | |||
| 213 | 114 | bool NAV::flow::LoadJson(const json& j, bool requestNewIds) | |
| 214 | { | ||
| 215 | 114 | bool loadSuccessful = true; | |
| 216 | |||
| 217 |
3/4✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 113 times.
|
114 | if (j.contains("implot")) |
| 218 | { | ||
| 219 | 1 | gui::windows::saveConfigInFlow = true; | |
| 220 | |||
| 221 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
1 | if (j.at("implot").contains("prefereFlowOverGlobal")) |
| 222 | { | ||
| 223 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | j.at("implot").at("prefereFlowOverGlobal").get_to(gui::windows::prefereFlowOverGlobal); |
| 224 | } | ||
| 225 | |||
| 226 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::filesystem::path filepath = flow::GetProgramRootPath(); |
| 227 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
2 | if (std::filesystem::path inputPath{ ConfigManager::Get<std::string>("implot-config") }; |
| 228 | 1 | inputPath.is_relative()) | |
| 229 | { | ||
| 230 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | filepath /= inputPath; |
| 231 | } | ||
| 232 | else | ||
| 233 | { | ||
| 234 | ✗ | filepath = inputPath; | |
| 235 | 1 | } | |
| 236 | |||
| 237 |
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 taken 1 times.
✗ Branch 8 not taken.
|
1 | if (gui::windows::prefereFlowOverGlobal || !std::filesystem::exists(filepath)) |
| 238 | { | ||
| 239 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
|
2 | 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 | 1 | } | |
| 248 | else | ||
| 249 | { | ||
| 250 | 113 | gui::windows::saveConfigInFlow = false; | |
| 251 | } | ||
| 252 | |||
| 253 |
3/4✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
✓ Branch 4 taken 44 times.
|
114 | if (j.contains("colormaps")) |
| 254 | { | ||
| 255 |
2/4✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
|
70 | j.at("colormaps").get_to(ColormapsFlow); |
| 256 | } | ||
| 257 | else | ||
| 258 | { | ||
| 259 | 44 | ColormapsFlow.clear(); | |
| 260 | } | ||
| 261 |
5/8✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 93 times.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
|
114 | if (j.contains("commonLog")) { CommonLog::restore(j.at("commonLog")); } |
| 262 | |||
| 263 |
3/6✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 114 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 114 times.
|
228 | 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 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 114 times.
✗ Branch 4 not taken.
|
114 | if (j.contains("nodes")) |
| 302 | { | ||
| 303 |
6/10✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 357 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 357 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 471 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 357 times.
✓ Branch 15 taken 114 times.
|
471 | for (const auto& nodeJson : j.at("nodes")) |
| 304 | { | ||
| 305 |
2/4✓ Branch 1 taken 357 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 357 times.
|
357 | if (!nodeJson.contains("type")) |
| 306 | { | ||
| 307 | ✗ | LOG_ERROR("Node does not contain a type"); | |
| 308 | ✗ | continue; | |
| 309 | } | ||
| 310 | 357 | Node* node = nullptr; | |
| 311 |
2/4✓ Branch 1 taken 357 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 1918 times.
✗ Branch 9 not taken.
|
1918 | for (const auto& registeredNode : NAV::NodeRegistry::RegisteredNodes()) |
| 312 | { | ||
| 313 |
2/2✓ Branch 5 taken 20805 times.
✓ Branch 6 taken 1561 times.
|
22366 | for (const auto& nodeInfo : registeredNode.second) |
| 314 | { | ||
| 315 |
4/6✓ Branch 1 taken 20805 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20805 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 357 times.
✓ Branch 9 taken 20448 times.
|
20805 | if (nodeInfo.type == nodeJson.at("type").get<std::string>()) |
| 316 | { | ||
| 317 |
1/2✓ Branch 1 taken 357 times.
✗ Branch 2 not taken.
|
357 | node = nodeInfo.constructor(); |
| 318 | 357 | break; | |
| 319 | } | ||
| 320 | } | ||
| 321 |
2/2✓ Branch 0 taken 357 times.
✓ Branch 1 taken 1561 times.
|
1918 | if (node != nullptr) |
| 322 | { | ||
| 323 | 357 | break; | |
| 324 | } | ||
| 325 | } | ||
| 326 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 357 times.
|
357 | 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 357 times.
✗ Branch 2 not taken.
|
357 | nm::AddNode(node); |
| 334 | 357 | auto newNodeId = node->id; | |
| 335 | |||
| 336 |
1/2✓ Branch 1 taken 357 times.
✗ Branch 2 not taken.
|
357 | nodeJson.get_to<Node>(*node); |
| 337 |
2/4✓ Branch 1 taken 357 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 357 times.
✗ Branch 4 not taken.
|
357 | if (nodeJson.contains("data")) |
| 338 | { | ||
| 339 |
2/4✓ Branch 1 taken 357 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 357 times.
✗ Branch 5 not taken.
|
357 | node->restore(nodeJson.at("data")); |
| 340 | } | ||
| 341 | // Load second time in case restore changed the amount of pins | ||
| 342 |
1/2✓ Branch 1 taken 357 times.
✗ Branch 2 not taken.
|
357 | nodeJson.get_to<Node>(*node); |
| 343 | |||
| 344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 357 times.
|
357 | 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 357 times.
✗ Branch 2 not taken.
|
357 | nm::UpdateNode(node); |
| 358 | |||
| 359 |
3/6✓ Branch 1 taken 357 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 357 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 357 times.
|
714 | 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 | 114 | std::set<Node*> newlyLinkedNodes; | |
| 373 | |||
| 374 |
3/4✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
✓ Branch 4 taken 37 times.
|
114 | if (j.contains("links")) |
| 375 | { | ||
| 376 |
2/2✓ Branch 0 taken 154 times.
✓ Branch 1 taken 77 times.
|
231 | 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 154 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 580 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 580 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 734 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 580 times.
✓ Branch 15 taken 154 times.
|
734 | for (const auto& linkJson : j.at("links")) |
| 379 | { | ||
| 380 |
2/4✓ Branch 1 taken 580 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 580 times.
✗ Branch 5 not taken.
|
580 | auto linkId = linkJson.at("id").get<size_t>(); |
| 381 |
2/4✓ Branch 1 taken 580 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 580 times.
✗ Branch 5 not taken.
|
580 | auto startPinId = linkJson.at("startPinId").get<size_t>(); |
| 382 |
2/4✓ Branch 1 taken 580 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 580 times.
✗ Branch 5 not taken.
|
580 | auto endPinId = linkJson.at("endPinId").get<size_t>(); |
| 383 | |||
| 384 | 580 | InputPin* endPin = nullptr; | |
| 385 | 580 | OutputPin* startPin = nullptr; | |
| 386 |
2/4✓ Branch 1 taken 580 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 2776 times.
✗ Branch 9 not taken.
|
2776 | for (auto* node : nm::m_Nodes()) |
| 387 | { | ||
| 388 |
2/2✓ Branch 0 taken 2150 times.
✓ Branch 1 taken 626 times.
|
2776 | if (!endPin) |
| 389 | { | ||
| 390 |
2/2✓ Branch 5 taken 3124 times.
✓ Branch 6 taken 2150 times.
|
5274 | for (auto& inputPin : node->inputPins) |
| 391 | { | ||
| 392 |
3/4✓ Branch 1 taken 3124 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 580 times.
✓ Branch 4 taken 2544 times.
|
3124 | if (endPinId == size_t(inputPin.id)) { endPin = &inputPin; } |
| 393 | } | ||
| 394 | } | ||
| 395 |
2/2✓ Branch 0 taken 1934 times.
✓ Branch 1 taken 842 times.
|
2776 | if (!startPin) |
| 396 | { | ||
| 397 |
2/2✓ Branch 5 taken 2208 times.
✓ Branch 6 taken 1934 times.
|
4142 | for (auto& outputPin : node->outputPins) |
| 398 | { | ||
| 399 |
3/4✓ Branch 1 taken 2208 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 580 times.
✓ Branch 4 taken 1628 times.
|
2208 | if (startPinId == size_t(outputPin.id)) { startPin = &outputPin; } |
| 400 | } | ||
| 401 | } | ||
| 402 |
4/4✓ Branch 0 taken 1422 times.
✓ Branch 1 taken 1354 times.
✓ Branch 2 taken 580 times.
✓ Branch 3 taken 842 times.
|
2776 | if (startPin && endPin) { break; } |
| 403 | } | ||
| 404 |
2/4✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 580 times.
✗ Branch 3 not taken.
|
580 | if (startPin && endPin) |
| 405 | { | ||
| 406 |
4/6✓ Branch 1 taken 580 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 580 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 578 times.
|
580 | if (!startPin->createLink(*endPin, linkId)) |
| 407 | { | ||
| 408 | 2 | loadSuccessful = false; | |
| 409 | 2 | continue; | |
| 410 | } | ||
| 411 |
1/2✓ Branch 1 taken 578 times.
✗ Branch 2 not taken.
|
578 | newlyLinkedNodes.insert(startPin->parentNode); |
| 412 |
1/2✓ Branch 1 taken 578 times.
✗ Branch 2 not taken.
|
578 | newlyLinkedNodes.insert(endPin->parentNode); |
| 413 | } | ||
| 414 | } | ||
| 415 | } | ||
| 416 | } | ||
| 417 |
2/4✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 114 times.
✗ Branch 4 not taken.
|
114 | if (j.contains("nodes")) |
| 418 | { | ||
| 419 |
2/2✓ Branch 5 taken 315 times.
✓ Branch 6 taken 114 times.
|
429 | for (auto* node : newlyLinkedNodes) |
| 420 | { | ||
| 421 |
6/12✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 315 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 315 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 315 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 315 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 315 times.
✗ Branch 18 not taken.
|
315 | if (j.at("nodes").contains("node-" + std::to_string(size_t(node->id)))) |
| 422 | { | ||
| 423 |
3/6✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 315 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 315 times.
✗ Branch 9 not taken.
|
315 | LOG_DEBUG("Calling restoreAtferLink() for new node '{}'", node->nameId()); |
| 424 | |||
| 425 |
5/10✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 315 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 315 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 315 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 315 times.
✗ Branch 14 not taken.
|
315 | const auto& nodeJson = j.at("nodes").at("node-" + std::to_string(size_t(node->id))); |
| 426 |
2/4✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 315 times.
✗ Branch 4 not taken.
|
315 | if (nodeJson.contains("data")) |
| 427 | { | ||
| 428 |
2/4✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 315 times.
✗ Branch 5 not taken.
|
315 | node->restoreAtferLink(nodeJson.at("data")); |
| 429 | } | ||
| 430 | } | ||
| 431 | } | ||
| 432 | } | ||
| 433 | |||
| 434 | 114 | return loadSuccessful; | |
| 435 | 114 | } | |
| 436 | |||
| 437 | ✗ | bool NAV::flow::HasUnsavedChanges() | |
| 438 | { | ||
| 439 | ✗ | return unsavedChanges; | |
| 440 | } | ||
| 441 | |||
| 442 | 13644 | 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 13644 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 13644 times.
|
13644 | if (ImGui::GetCurrentContext() && ImGui::GetFrameCount() - loadingFrameCount >= loadingFramesToWait) |
| 446 | { | ||
| 447 | ✗ | unsavedChanges = true; | |
| 448 | ✗ | if (saveLastActions) | |
| 449 | { | ||
| 450 | ✗ | gui::saveLastAction(); | |
| 451 | } | ||
| 452 | } | ||
| 453 | 13644 | } | |
| 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 | 828 | std::filesystem::path NAV::flow::GetProgramRootPath() | |
| 471 | { | ||
| 472 | 828 | return programRootPath; | |
| 473 | } | ||
| 474 | |||
| 475 | 118 | void NAV::flow::SetProgramRootPath(const std::filesystem::path& newRootPath) | |
| 476 | { | ||
| 477 |
1/2✓ Branch 3 taken 118 times.
✗ Branch 4 not taken.
|
118 | LOG_DEBUG("Program root path set to {}", newRootPath); |
| 478 | 118 | programRootPath = newRootPath; | |
| 479 | 118 | } | |
| 480 | |||
| 481 | 261 | std::filesystem::path NAV::flow::GetOutputPath() | |
| 482 | { | ||
| 483 | 261 | std::filesystem::path filepath = flow::GetProgramRootPath(); | |
| 484 | |||
| 485 |
4/8✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 262 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 262 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 262 times.
✗ Branch 11 not taken.
|
524 | if (std::filesystem::path outputPath{ ConfigManager::Get<std::string>("output-path") }; |
| 486 | 262 | outputPath.is_relative()) | |
| 487 | { | ||
| 488 |
1/2✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
|
262 | filepath /= outputPath; |
| 489 | } | ||
| 490 | else | ||
| 491 | { | ||
| 492 | ✗ | filepath = outputPath; | |
| 493 | 262 | } | |
| 494 | |||
| 495 |
4/6✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 262 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 30 times.
✓ Branch 8 taken 232 times.
|
524 | if (ConfigManager::Get<bool>("rotate-output")) |
| 496 | { | ||
| 497 |
2/4✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
30 | filepath /= fmt::format("{:04d}", currentRotatedParentFolderNumber); |
| 498 | } | ||
| 499 | |||
| 500 | 262 | return filepath; | |
| 501 | ✗ | } | |
| 502 | |||
| 503 | 127 | void NAV::flow::SetOutputPath() | |
| 504 | { | ||
| 505 | 127 | currentRotatedParentFolderNumber = 0; | |
| 506 |
2/2✓ Branch 0 taken 1270082 times.
✓ Branch 1 taken 117 times.
|
1270199 | for (int i = 10000; i >= 0; --i) |
| 507 | { | ||
| 508 |
1/2✓ Branch 1 taken 1270082 times.
✗ Branch 2 not taken.
|
1270082 | std::filesystem::path outputDir{ programRootPath }; |
| 509 | |||
| 510 |
4/8✓ Branch 1 taken 1270082 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1270082 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1270082 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1270082 times.
✗ Branch 11 not taken.
|
2540164 | if (std::filesystem::path outputPath{ ConfigManager::Get<std::string>("output-path") }; |
| 511 | 1270082 | outputPath.is_relative()) | |
| 512 | { | ||
| 513 |
1/2✓ Branch 1 taken 1270082 times.
✗ Branch 2 not taken.
|
1270082 | outputDir /= outputPath; |
| 514 | } | ||
| 515 | else | ||
| 516 | { | ||
| 517 | ✗ | outputDir = outputPath; | |
| 518 | 1270082 | } | |
| 519 |
2/4✓ Branch 1 taken 1270082 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1270082 times.
✗ Branch 5 not taken.
|
1270082 | outputDir /= fmt::format("{:04d}", i); |
| 520 |
3/4✓ Branch 1 taken 1270082 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1270072 times.
|
1270082 | 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 | 1270082 | } | |
| 526 |
2/4✓ Branch 2 taken 127 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 127 times.
✗ Branch 7 not taken.
|
127 | LOG_DEBUG("Output directory set to {}", GetOutputPath()); |
| 527 | 127 | } | |
| 528 | |||
| 529 | 332 | std::filesystem::path NAV::flow::GetInputPath() | |
| 530 | { | ||
| 531 | 332 | std::filesystem::path filepath = flow::GetProgramRootPath(); | |
| 532 | |||
| 533 |
4/8✓ Branch 1 taken 331 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 331 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 330 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 330 times.
✗ Branch 11 not taken.
|
662 | if (std::filesystem::path inputPath{ ConfigManager::Get<std::string>("input-path") }; |
| 534 | 330 | inputPath.is_relative()) | |
| 535 | { | ||
| 536 |
1/2✓ Branch 1 taken 331 times.
✗ Branch 2 not taken.
|
330 | filepath /= inputPath; |
| 537 | } | ||
| 538 | else | ||
| 539 | { | ||
| 540 | ✗ | filepath = inputPath; | |
| 541 | 331 | } | |
| 542 | |||
| 543 | 331 | 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 |