Elevate Engine 1
Loading...
Searching...
No Matches
AnalyserPanel.cpp
Go to the documentation of this file.
1#include "eepch.h"
2
3#include "./AnalyserPanel.h"
4
5#ifdef EE_EDITOR_BUILD
6
7#include "imgui.h"
8
9#include <glm/glm.hpp>
10#include <glm/gtc/type_ptr.hpp>
11
14
18
19void Elevate::Editor::AnalyserPanel::OnImGuiRender()
20{
21 ImGui::Begin("Analyse");
22
23 std::weak_ptr<GameObject> selected = EditorLayer::Get().GetSelectedObject();
24 if (selected.lock())
25 {
26 std::shared_ptr<GameObject> obj = selected.lock();
27 Elevate::UI::InputField("Name: ", obj->GetName());
28
29 // Serialisation of the tranform and all other components
30 glm::vec4 color = EECategory("Transform").GetCategoryColor() * 0.6f;
31
32 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
33 ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(color.r + 0.3f, color.g + 0.3f, color.b + 0.3f, 1.0f));
34 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(color.r, color.g, color.b, 1.0f));
35 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(color.r + 0.1f, color.g + 0.1f, color.b + 0.1f, 1.0f));
36 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(color.r + 0.2f, color.g + 0.2f, color.b + 0.2f, 1.0f));
37
38 RenderComponentLayout(obj->GetTransform().GetLayout());
39
40 ImGui::PopStyleVar();
41
42 // TODO REMOVE AND / OR CHECK IF THE GAMEOBJECT IS DIFFERENT, THIS IS A COSTLY OPERATION FOR EACH FRAME
43 m_alredyAddedComponents.clear();
44
45 std::map<EECategory, std::vector<Component*>> m_sortedComponents;
46 for (Component* comp : obj->GetComponents())
47 {
48 m_sortedComponents[comp->GetCategory()].push_back(comp);
49 m_alredyAddedComponents.push_back(comp->GetTypeIndex());
50 }
51
52 for (std::pair<EECategory, std::vector<Component*>> entry : m_sortedComponents)
53 {
54 const std::string& categoryName = entry.first.GetName();
55
56 glm::vec4 color = entry.first.GetCategoryColor();
57 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
58 ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(color.r + 0.3f, color.g + 0.3f, color.b + 0.3f, 1.0f));
59 ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(color.r, color.g, color.b, 1.0f));
60 ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(color.r + 0.1f, color.g + 0.1f, color.b + 0.1f, 1.0f));
61 ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(color.r + 0.2f, color.g + 0.2f, color.b + 0.2f, 1.0f));
62 if (ImGui::CollapsingHeader(categoryName.c_str(), ImGuiTreeNodeFlags_DefaultOpen))
63 {
64 ImGui::PopStyleColor(4);
65 ImGui::PopStyleVar();
66
67 for (Component* comp : entry.second)
68 {
69 if (comp)
70 {
71 RenderComponent(comp);
72 }
73 }
74 }
75 else
76 {
77 ImGui::PopStyleColor(4);
78 ImGui::PopStyleVar();
79 }
80 }
81
82 if (ImGui::Button("Add Component", ImVec2(ImGui::GetContentRegionAvail().x, 0)))
83 {
84 ImGui::OpenPopup("AddComponentPopup");
85 }
86
87 if (ImGui::BeginPopup("AddComponentPopup"))
88 {
89 ImGui::Text("Add component :");
90 ImGui::Separator();
91
92 CategoryMenu root;
93 for (auto& pair : ComponentRegistry::GetEntries())
94 {
95 InsertCategory(root, pair.second);
96 }
97 std::weak_ptr<GameObject> obj = EditorLayer::Get().GetSelectedObject();
98 for (auto& cat : root.childs)
99 {
100 DrawCategoryMenu(cat, obj);
101 }
102 DrawCategoryChildren(root, obj);
103
104 ImGui::EndPopup();
105 }
106 }
107
108 ImGui::End();
109}
110
111void Elevate::Editor::AnalyserPanel::RenderComponent(Component* comp)
112{
113 const ComponentLayout layout = comp->GetLayout();
114
115 EECategory category = comp->GetCategory();
116
117 glm::vec4 color = category.GetCategoryColor() * 0.5f;
118
119 ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(color.r + 0.3f, color.g + 0.3f, color.b + 0.3f, 1.0f));
120 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(color.r, color.g, color.b, 1.0f));
121 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(color.r + 0.1f, color.g + 0.1f, color.b + 0.1f, 1.0f));
122 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(color.r + 0.2f, color.g + 0.2f, color.b + 0.2f, 1.0f));
123
124 RenderComponentLayout(layout, comp);
125}
126
127void Elevate::Editor::AnalyserPanel::RenderComponentLayout(const ComponentLayout& layout, Component* component)
128{
129 const void* texHandle = nullptr;
130 if (component)
131 {
132 if (!m_textureCache.count(component))
133 {
134 m_textureCache.insert({ component, component->GetEditorIconHandle() });
135 }
136 texHandle = m_textureCache.at(component);
137 }
138
139 if (UI::EECollapsingHeader((layout.GetName()).c_str(),
140 layout.GetFieldCount() > 0,
141 texHandle,
142 [&layout, &component]()
143 {
144 float menu_width = 0;
145
146 if (component)
147 {
148 ImGuiStyle& style = ImGui::GetStyle();
149
150 float customButtonWidth = 25.0f;
151 float customButtonHeight = ImGui::GetFontSize() + style.FramePadding.y * 2.0f;
152 menu_width = customButtonWidth + style.FramePadding.x;
153
154 ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - customButtonWidth, ImGui::GetCursorPosY()));
155 ImGui::PushID(layout.GetName().c_str());
156 if (ImGui::Button("...", ImVec2(customButtonWidth, customButtonHeight)))
157 ImGui::OpenPopup("HeaderMenu");
158
159 if (ImGui::BeginPopup("HeaderMenu"))
160 {
161 if (ImGui::MenuItem("Remove Component"))
162 {
163 EditorLayer::Get().PushCommand(std::make_unique<RemoveComponentCommand>(component));
164 }
165 ImGui::EndPopup();
166 }
167 ImGui::PopID();
168 }
169
170 return menu_width;
171 }))
172 {
173 ImGui::PopStyleColor(4);
174
175 for (const ComponentField& field : layout)
176 {
177 RenderField(field);
178 }
179 }
180 else
181 {
182 ImGui::PopStyleColor(4);
183 }
184}
185
186void Elevate::Editor::AnalyserPanel::RenderField(const ComponentField& field) const
187{
188 ImGui::BeginDisabled(field.readOnly);
189
190 switch (field.type)
191 {
192 case ComponentDataType::Float:
193 ImGui::InputFloat(field.GetDisplayName().c_str(), (float*)(field.data));
194 break;
195
196 case ComponentDataType::Float2:
197 ImGui::InputFloat2(field.GetDisplayName().c_str(), (float*)(field.data));
198 break;
199
200 case ComponentDataType::Float3:
201 if (field.isColor)
202 ImGui::ColorEdit3(field.GetDisplayName().c_str(), (float*)(field.data));
203 else
204 ImGui::InputFloat3(field.GetDisplayName().c_str(), (float*)(field.data));
205 break;
206
207 case ComponentDataType::Float4:
208 if (field.isColor)
209 ImGui::ColorEdit4(field.GetDisplayName().c_str(), (float*)(field.data));
210 else
211 ImGui::InputFloat4(field.GetDisplayName().c_str(), (float*)(field.data));
212 break;
213
214 case ComponentDataType::Bool:
215 ImGui::Checkbox(field.GetDisplayName().c_str(), (bool*)(field.data));
216 break;
217
218 case ComponentDataType::Custom:
219 if (!field.flatten)
220 {
221 if (ImGui::TreeNodeEx(field.GetDisplayName().c_str(), ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_FramePadding))
222 {
223 for (const auto& child : field.children)
224 RenderField(child);
225 ImGui::TreePop();
226 }
227 }
228 else
229 {
230 for (const auto& child : field.children)
231 RenderField(child);
232 }
233 break;
234
235 default:
236 ImGui::TextColored(ImVec4(1, 0, 0, 1), "Unsupported data type: %s", field.name.c_str());
237 break;
238 }
239
240 ImGui::EndDisabled();
241
242 if (!field.tooltip.empty())
243 {
244 ImGui::SetItemTooltip("%s", field.tooltip.c_str());
245 }
246}
247
248void Elevate::Editor::AnalyserPanel::InsertCategory(CategoryMenu& root, const ComponentRegistry::Entry& entry)
249{
250 if (!entry.visible)
251 {
252 return;
253 }
254
255 std::string path = entry.category.GetPath();
256
257 if (path.empty()) {
258 root.items.push_back(entry);
259 return;
260 }
261
262 CategoryMenu* current = &root;
263 size_t start = 0;
264
265 while (true)
266 {
267 size_t pos = path.find('/', start);
268 std::string part = (pos == std::string::npos)
269 ? path.substr(start)
270 : path.substr(start, pos - start);
271
272 std::string accumulated = path.substr(0, (pos == std::string::npos ? path.size() : pos));
273
274 auto it = std::find_if(current->childs.begin(), current->childs.end(),
275 [&](const CategoryMenu& child) {
276 return child.category.GetPath() == accumulated;
277 });
278
279 if (it == current->childs.end())
280 {
281 CategoryMenu child;
282 child.category = EECategory(accumulated);
283 current->childs.push_back(std::move(child));
284 it = std::prev(current->childs.end());
285 }
286
287 current = &(*it);
288
289 if (pos == std::string::npos)
290 {
291 current->items.push_back(entry);
292 break;
293 }
294
295 start = pos + 1;
296 }
297}
298
299void Elevate::Editor::AnalyserPanel::DrawCategoryChildren(const CategoryMenu& category, std::weak_ptr<GameObject> obj)
300{
301 // Grey out the item if it is already added to the current GameObject
302 for (auto& entry : category.items)
303 {
304 bool alreadyAdded = false;
305 for (auto& type : m_alredyAddedComponents)
306 {
307 if (type == entry.type)
308 {
309 alreadyAdded = true;
310 break;
311 }
312 }
313
314 ImGui::BeginDisabled(alreadyAdded);
315 if (ImGui::Selectable(entry.name.c_str()))
316 {
317 if (auto go = obj.lock())
318 {
319 EditorLayer::Get().PushCommand(std::make_unique<AddComponentCommand>(go, entry.factory, entry.destructor));
320 }
321 }
322 ImGui::EndDisabled();
323 }
324}
325
326void Elevate::Editor::AnalyserPanel::DrawCategoryMenu(const CategoryMenu& menu, std::weak_ptr<GameObject> obj)
327{
328 if (!menu.category.GetName().empty())
329 {
330 if (ImGui::BeginMenu(menu.category.GetName().c_str()))
331 {
332 for (auto& child : menu.childs)
333 {
334 DrawCategoryMenu(child, obj);
335 }
336
337 DrawCategoryChildren(menu, obj);
338
339 ImGui::EndMenu();
340 }
341 }
342 else
343 {
344 for (auto& child : menu.childs)
345 {
346 DrawCategoryMenu(child, obj);
347 }
348 }
349}
350
351#endif // EE_EDITOR_BUILD
glm::vec4 GetCategoryColor()
Definition EEObject.h:41
void InputField(const char *label, std::string &data)