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 |
|
|
|