INSTINCT Code Coverage Report


Directory: src/
File: internal/gui/panels/LeftPane.cpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 0 107 0.0%
Functions: 0 1 0.0%
Branches: 0 282 0.0%

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 "LeftPane.hpp"
10
11 #include <imgui_node_editor.h>
12 #include <imgui_internal.h>
13
14 #include "internal/NodeManager.hpp"
15 namespace nm = NAV::NodeManager;
16
17 #include "internal/gui/TouchTracker.hpp"
18 #include "internal/gui/NodeEditorApplication.hpp"
19
20 #include "util/StringUtil.hpp"
21
22 #include <string>
23 #include <algorithm>
24
25 namespace ed = ax::NodeEditor;
26
27 bool NAV::gui::panels::ShowLeftPane(float paneWidth)
28 {
29 auto& io = ImGui::GetIO();
30
31 bool paneActive = false;
32
33 float insLogoWidth = paneWidth < 150 ? paneWidth : 150;
34
35 float insLogoHeight = insLogoWidth * 2967.0F / 4073.0F;
36 float childHeight = ImGui::GetContentRegionAvail().y - insLogoHeight;
37
38 ImGui::BeginGroup();
39
40 ImGui::BeginChild("Selection", ImVec2(paneWidth, childHeight));
41
42 paneWidth = ImGui::GetContentRegionAvail().x;
43
44 float colSum = ImGui::GetStyle().Colors[ImGuiCol_WindowBg].x + ImGui::GetStyle().Colors[ImGuiCol_WindowBg].y + ImGui::GetStyle().Colors[ImGuiCol_WindowBg].z;
45 ImTextureID instinctLogo = NodeEditorApplication::m_InstinctLogo.at(colSum > 2.0F ? 1 : 0);
46 ImTextureID insLogo = NodeEditorApplication::m_InsLogo.at(colSum > 2.0F ? 1 : 0);
47
48 ImGui::Image(instinctLogo, ImVec2(paneWidth, paneWidth * 3000.0F / 13070.0F));
49 ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5.0F);
50
51 { // Control Buttons
52 ImGui::BeginHorizontal("Control Buttons", ImVec2(paneWidth, 0));
53 ImGui::Spring(0.0F, 0.0F);
54 if (ImGui::Button("Zoom to Content"))
55 {
56 ed::NavigateToContent();
57 }
58 if (ImGui::IsItemHovered())
59 {
60 ImGui::SetTooltip("Shortcut: F");
61 }
62 ImGui::Spring();
63 ImGui::EndHorizontal();
64 }
65
66 std::vector<ed::NodeId> selectedNodes;
67 std::vector<ed::LinkId> selectedLinks;
68 selectedNodes.resize(static_cast<size_t>(ed::GetSelectedObjectCount()));
69 selectedLinks.resize(static_cast<size_t>(ed::GetSelectedObjectCount()));
70
71 auto nodeCount = static_cast<size_t>(ed::GetSelectedNodes(selectedNodes.data(), static_cast<int>(selectedNodes.size())));
72 auto linkCount = static_cast<size_t>(ed::GetSelectedLinks(selectedLinks.data(), static_cast<int>(selectedLinks.size())));
73
74 selectedNodes.resize(nodeCount);
75 selectedLinks.resize(linkCount);
76
77 { // Node List
78 ImGui::GetWindowDrawList()->AddRectFilled(
79 ImGui::GetCursorScreenPos(),
80 ImGui::GetCursorScreenPos() + ImVec2(paneWidth, ImGui::GetTextLineHeight()),
81 ImColor(ImGui::GetStyle().Colors[ImGuiCol_HeaderActive]), ImGui::GetTextLineHeight() * 0.25F);
82 ImGui::Spacing();
83 ImGui::SameLine();
84 ImGui::TextUnformatted("Nodes");
85 ImGui::Indent();
86 for (const auto* node : nm::m_Nodes())
87 {
88 ImGui::PushID(node->id.AsPointer());
89 auto start = ImGui::GetCursorScreenPos();
90
91 if (const auto progress = gui::GetTouchProgress(node->id); progress != 0.0F)
92 {
93 ImGui::GetWindowDrawList()->AddLine(
94 start + ImVec2(-18, 0),
95 start + ImVec2(-18, ImGui::GetTextLineHeight()),
96 IM_COL32(255, 0, 0, 255 - static_cast<int>(255 * progress)), 4.0F);
97 }
98
99 if (node->kind == Node::Kind::GroupBox)
100 {
101 ImGui::PopID();
102 continue;
103 }
104
105 // Circle to show init status
106 ImU32 circleCol = 0;
107 if (node->isDisabled())
108 {
109 circleCol = IM_COL32(192, 192, 192, 255);
110 }
111 else if (node->getState() == Node::State::DoInitialize)
112 {
113 circleCol = IM_COL32(144, 202, 238, 255);
114 }
115 else if (node->getState() == Node::State::Initializing)
116 {
117 circleCol = IM_COL32(143, 188, 143, 255);
118 }
119 else if (node->getState() == Node::State::DoDeinitialize)
120 {
121 circleCol = IM_COL32(255, 222, 122, 255);
122 }
123 else if (node->getState() == Node::State::Deinitializing)
124 {
125 circleCol = IM_COL32(240, 128, 128, 255);
126 }
127 else if (node->getState() == Node::State::Initialized)
128 {
129 circleCol = IM_COL32(0, 255, 0, 255);
130 }
131 else // if (!node->getState() == Node::State::Deinitialized)
132 {
133 circleCol = IM_COL32(255, 0, 0, 255);
134 }
135 ImGui::GetWindowDrawList()->AddCircleFilled(start + ImVec2(-8 + (NodeEditorApplication::panelFontRatio() - 1.F) * 5.F, ImGui::GetTextLineHeight() / 2.0F + 1.0F),
136 5.0F * NodeEditorApplication::panelFontRatio(), circleCol);
137
138 bool isSelected = std::ranges::find(selectedNodes, node->id) != selectedNodes.end();
139 if (NodeEditorApplication::panelFontRatio() != 1.F) { ImGui::Indent((NodeEditorApplication::panelFontRatio() - 1.F) * 15.F); }
140 if (ImGui::Selectable((str::replaceAll_copy(node->name, "\n", "") + "##" + std::to_string(size_t(node->id))).c_str(), &isSelected))
141 {
142 if (io.KeyCtrl)
143 {
144 if (isSelected)
145 {
146 ed::SelectNode(node->id, true);
147 }
148 else
149 {
150 ed::DeselectNode(node->id);
151 }
152 }
153 else
154 {
155 ed::SelectNode(node->id, false);
156 }
157
158 ed::NavigateToSelection();
159 }
160 if (ImGui::IsItemHovered())
161 {
162 ImGui::SetTooltip("Type: %s", node->type().c_str());
163 }
164 if (NodeEditorApplication::panelFontRatio() != 1.F) { ImGui::Unindent((NodeEditorApplication::panelFontRatio() - 1.F) * 15.F); }
165
166 // auto id = fmt::format("({})", size_t(node->id));
167 // auto textSize = ImGui::CalcTextSize(id.c_str(), nullptr);
168 // auto iconPanelPos = start + ImVec2(std::max(paneWidth, 150.F) - ImGui::GetStyle().FramePadding.x - ImGui::GetStyle().IndentSpacing - ImGui::GetStyle().ItemInnerSpacing.x * 1, ImGui::GetTextLineHeight() / 2);
169 // ImGui::GetWindowDrawList()->AddText(
170 // ImVec2(iconPanelPos.x - textSize.x - ImGui::GetStyle().ItemInnerSpacing.x, start.y),
171 // colSum > 2.0F ? IM_COL32(0, 0, 0, 255) : IM_COL32(255, 255, 255, 255), id.c_str(), nullptr);
172
173 ImGui::PopID();
174 }
175 ImGui::Unindent();
176 }
177
178 { // Selection List
179 ImGui::GetWindowDrawList()->AddRectFilled(
180 ImGui::GetCursorScreenPos(),
181 ImGui::GetCursorScreenPos() + ImVec2(paneWidth, ImGui::GetTextLineHeight()),
182 ImColor(ImGui::GetStyle().Colors[ImGuiCol_HeaderActive]), ImGui::GetTextLineHeight() * 0.25F);
183 ImGui::Spacing();
184 ImGui::SameLine();
185 ImGui::TextUnformatted("Selection");
186
187 ImGui::BeginHorizontal("Selection Stats", ImVec2(paneWidth, 0));
188 size_t selectedCount = selectedNodes.size() + selectedLinks.size();
189 ImGui::Text("%lu item%s selected", selectedCount, (selectedCount > 1 || selectedCount == 0) ? "s" : "");
190 ImGui::Spring();
191 if (ImGui::Button("Deselect"))
192 {
193 ed::ClearSelection();
194 }
195 ImGui::EndHorizontal();
196 ImGui::Indent();
197 for (size_t i = 0; i < nodeCount; ++i)
198 {
199 auto* node = nm::FindNode(selectedNodes[i]);
200 ImGui::Text("%s (%lu)", node != nullptr ? node->name.c_str() : "", size_t(selectedNodes[i]));
201 }
202 for (size_t i = 0; i < linkCount; ++i)
203 {
204 ImGui::Text("Link (%lu)", size_t(selectedLinks[i]));
205 }
206 ImGui::Unindent();
207 }
208
209 if (ImGui::IsWindowFocused())
210 {
211 paneActive = true;
212 }
213
214 ImGui::EndChild();
215
216 ImGui::Image(insLogo, ImVec2(insLogoWidth, insLogoHeight));
217
218 ImGui::EndGroup();
219
220 return paneActive;
221 }
222