Skip to content

Commit 3f6e674

Browse files
authored
Better hierarchy (#691)
- Added icons for actors in hierarchy - Actors are now grayed out in the hierarchy when disabled - Improved search bar, and reused it in `ItemPicker` as well - `TreeNode` now support icons and label color override
1 parent e0d5a71 commit 3f6e674

File tree

11 files changed

+130
-6
lines changed

11 files changed

+130
-6
lines changed
423 Bytes
Loading
398 Bytes
Loading

Sources/OvCore/include/OvCore/Helpers/GUIDrawer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ namespace OvCore::Helpers
7272

7373
static OvUI::Widgets::InputFields::AssetField& DrawScene(OvUI::Internal::WidgetContainer& p_root, const std::string& p_name, std::function<std::string()> p_gatherer, std::function<void(std::string)> p_provider);
7474

75+
/**
76+
* Creates a full-width search bar with an optional search icon
77+
* @param p_root
78+
* @param p_searchIconTextureID
79+
*/
80+
static OvUI::Widgets::InputFields::InputText& DrawSearchBar(OvUI::Internal::WidgetContainer& p_root, uint32_t p_searchIconTextureID = 0);
81+
7582
template <typename T>
7683
static void DrawScalar(OvUI::Internal::WidgetContainer& p_root, const std::string& p_name, std::function<T(void)> p_gatherer, std::function<void(T)> p_provider, float p_step = 1.f, T p_min = std::numeric_limits<T>::min(), T p_max = std::numeric_limits<T>::max());
7784
static void DrawBoolean(OvUI::Internal::WidgetContainer& p_root, const std::string& p_name, std::function<bool(void)> p_gatherer, std::function<void(bool)> p_provider);

Sources/OvCore/src/OvCore/Helpers/GUIDrawer.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,3 +458,11 @@ void OvCore::Helpers::GUIDrawer::DrawColor(OvUI::Internal::WidgetContainer & p_r
458458
dispatcher.RegisterGatherer(p_gatherer);
459459
dispatcher.RegisterProvider(p_provider);
460460
}
461+
462+
OvUI::Widgets::InputFields::InputText& OvCore::Helpers::GUIDrawer::DrawSearchBar(OvUI::Internal::WidgetContainer& p_root, uint32_t p_searchIconTextureID)
463+
{
464+
auto& searchBar = p_root.CreateWidget<OvUI::Widgets::InputFields::InputText>();
465+
searchBar.fullWidth = true;
466+
searchBar.iconTextureID = p_searchIconTextureID;
467+
return searchBar;
468+
}

Sources/OvEditor/src/OvEditor/Core/EditorResources.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ OvEditor::Core::EditorResources::EditorResources(const std::string& p_editorAsse
131131
{"Directional_Light", CreateTexture<NEAREST>(texturesFolder / "Directional_Light.png")},
132132
{"Ambient_Box_Light", CreateTexture<NEAREST>(texturesFolder / "Ambient_Box_Light.png")},
133133
{"Ambient_Sphere_Light", CreateTexture<NEAREST>(texturesFolder / "Ambient_Sphere_Light.png")},
134-
{"Empty_Texture", CreateTexture<LINEAR>(texturesFolder / "Empty_Texture.png")}
134+
{"Empty_Texture", CreateTexture<LINEAR>(texturesFolder / "Empty_Texture.png")},
135+
{"Actor", CreateTexture<LINEAR>(texturesFolder / "Actor.png")},
136+
{"Search", CreateTexture<LINEAR>(texturesFolder / "Search.png")}
135137
};
136138

137139
m_models = {

Sources/OvEditor/src/OvEditor/Panels/Hierarchy.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <OvDebug/Logger.h>
1717

1818
#include <OvCore/Global/ServiceLocator.h>
19+
#include <OvCore/Helpers/GUIDrawer.h>
1920

2021
#include <OvCore/ECS/Components/CCamera.h>
2122
#include <OvCore/ECS/Components/CPointLight.h>
@@ -31,6 +32,7 @@
3132

3233
#include <OvUI/Plugins/ContextualMenu.h>
3334

35+
#include "OvEditor/Core/EditorResources.h"
3436
#include "OvEditor/Utils/ActorCreationMenu.h"
3537

3638
class ActorContextualMenu : public OvUI::Plugins::ContextualMenu
@@ -149,7 +151,13 @@ OvEditor::Panels::Hierarchy::Hierarchy
149151
m_actions(CreateWidget<OvUI::Widgets::Layout::Group>()),
150152
m_actors(CreateWidget<OvUI::Widgets::Layout::Group>())
151153
{
152-
auto& searchBar = m_actions.CreateWidget<OvUI::Widgets::InputFields::InputText>();
154+
const uint32_t searchIconID = []{
155+
if (auto* tex = EDITOR_CONTEXT(editorResources)->GetTexture("Search"))
156+
return tex->GetTexture().GetID();
157+
return 0u;
158+
}();
159+
160+
auto& searchBar = OvCore::Helpers::GUIDrawer::DrawSearchBar(m_actions, searchIconID);
153161
searchBar.ContentChangedEvent += [this](const std::string& p_content)
154162
{
155163
founds.clear();
@@ -334,6 +342,10 @@ void OvEditor::Panels::Hierarchy::AddActorByInstance(OvCore::ECS::Actor & p_acto
334342
{
335343
auto& textSelectable = m_actors.CreateWidget<OvUI::Widgets::Layout::TreeNode>(p_actor.GetName(), true);
336344
textSelectable.leaf = true;
345+
346+
if (auto* actorTexture = EDITOR_CONTEXT(editorResources)->GetTexture("Actor"))
347+
textSelectable.iconTextureID = actorTexture->GetTexture().GetID();
348+
337349
textSelectable.AddPlugin<ActorContextualMenu>(&p_actor, &textSelectable);
338350
textSelectable.AddPlugin<OvUI::Plugins::DDSource<std::pair<OvCore::ECS::Actor*, OvUI::Widgets::Layout::TreeNode*>>>("Actor", "Attach to...", std::make_pair(&p_actor, &textSelectable));
339351
textSelectable.AddPlugin<OvUI::Plugins::DDTarget<std::pair<OvCore::ECS::Actor*, OvUI::Widgets::Layout::TreeNode*>>>("Actor").DataReceivedEvent += [&p_actor, &textSelectable](std::pair<OvCore::ECS::Actor*, OvUI::Widgets::Layout::TreeNode*> p_element)
@@ -349,7 +361,15 @@ void OvEditor::Panels::Hierarchy::AddActorByInstance(OvCore::ECS::Actor & p_acto
349361
auto& dispatcher = textSelectable.AddPlugin<OvUI::Plugins::DataDispatcher<std::string>>();
350362

351363
OvCore::ECS::Actor* targetPtr = &p_actor;
352-
dispatcher.RegisterGatherer([targetPtr] { return targetPtr->GetName(); });
364+
dispatcher.RegisterGatherer([targetPtr, &textSelectable]
365+
{
366+
const bool isActive = targetPtr->IsSelfActive();
367+
textSelectable.overrideLabelColor = !isActive;
368+
if (!isActive)
369+
textSelectable.labelColor = {0.5f, 0.5f, 0.5f, 1.0f};
370+
371+
return targetPtr->GetName();
372+
});
353373

354374
m_widgetActorLink[targetPtr] = &textSelectable;
355375

Sources/OvEditor/src/OvEditor/Panels/ItemPicker.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <imgui.h>
1111

1212
#include <OvEditor/Panels/ItemPicker.h>
13+
#include <OvEditor/Core/EditorActions.h>
14+
15+
#include <OvCore/Helpers/GUIDrawer.h>
1316

1417
#include <OvUI/Widgets/InputFields/InputText.h>
1518
#include <OvUI/Widgets/Layout/Group.h>
@@ -44,7 +47,13 @@ ItemPicker::ItemPicker(
4447
{
4548
minSize = { 250.f, 250.f };
4649

47-
m_searchField = &CreateWidget<OvUI::Widgets::InputFields::InputText>("", "Search");
50+
const uint32_t searchIconID = []{
51+
if (auto* tex = EDITOR_CONTEXT(editorResources)->GetTexture("Search"))
52+
return tex->GetTexture().GetID();
53+
return 0u;
54+
}();
55+
56+
m_searchField = &OvCore::Helpers::GUIDrawer::DrawSearchBar(*this, searchIconID);
4857
m_searchField->ContentChangedEvent += [this](const std::string& p_text)
4958
{
5059
FilterList(p_text);

Sources/OvUI/include/OvUI/Widgets/InputFields/InputText.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ namespace OvUI::Widgets::InputFields
3333
std::string label;
3434
bool selectAllOnClick = false;
3535
bool focusOnNextDraw = false;
36+
bool fullWidth = false;
37+
uint32_t iconTextureID = 0;
38+
float iconSize = 16.f;
3639
OvTools::Eventing::Event<std::string> ContentChangedEvent;
3740
OvTools::Eventing::Event<std::string> EnterPressedEvent;
3841
};

Sources/OvUI/include/OvUI/Widgets/Layout/TreeNode.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <OvTools/Eventing/Event.h>
1212

1313
#include "OvUI/Internal/WidgetContainer.h"
14+
#include "OvUI/Types/Color.h"
1415
#include "OvUI/Widgets/DataWidget.h"
1516

1617
namespace OvUI::Widgets::Layout
@@ -51,6 +52,11 @@ namespace OvUI::Widgets::Layout
5152
bool selected = false;
5253
bool leaf = false;
5354

55+
uint32_t iconTextureID = 0;
56+
float iconSize = 16.f;
57+
bool overrideLabelColor = false;
58+
Types::Color labelColor{1.0f, 1.0f, 1.0f, 1.0f};
59+
5460
OvTools::Eventing::Event<> ClickedEvent;
5561
OvTools::Eventing::Event<> DoubleClickedEvent;
5662
OvTools::Eventing::Event<> OpenedEvent;

Sources/OvUI/src/OvUI/Widgets/InputFields/InputText.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,39 @@ void OvUI::Widgets::InputFields::InputText::_Draw_Impl()
2323
focusOnNextDraw = false;
2424
}
2525

26+
const bool hasIcon = iconTextureID != 0;
27+
28+
if (hasIcon)
29+
{
30+
const ImVec2 padding = ImGui::GetStyle().FramePadding;
31+
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding.x + iconSize + padding.x, padding.y));
32+
}
33+
34+
if (fullWidth)
35+
ImGui::SetNextItemWidth(-FLT_MIN);
36+
2637
content.resize(256, '\0');
2738
bool enterPressed = ImGui::InputText((label + m_widgetID).c_str(), &content[0], 256, ImGuiInputTextFlags_EnterReturnsTrue | (selectAllOnClick ? ImGuiInputTextFlags_AutoSelectAll : 0));
2839
content = content.c_str();
2940

41+
if (hasIcon)
42+
{
43+
ImGui::PopStyleVar();
44+
45+
ImDrawList* drawList = ImGui::GetWindowDrawList();
46+
const ImVec2 rectMin = ImGui::GetItemRectMin();
47+
const ImVec2 rectMax = ImGui::GetItemRectMax();
48+
const float frameHeight = rectMax.y - rectMin.y;
49+
const float padding = ImGui::GetStyle().FramePadding.y;
50+
const float fitSize = std::min(iconSize, frameHeight - padding * 2.0f);
51+
const float centerY = (rectMin.y + rectMax.y) * 0.5f;
52+
const float iconX = rectMin.x + ImGui::GetStyle().FramePadding.x;
53+
drawList->AddImage(iconTextureID,
54+
ImVec2(iconX, centerY - fitSize * 0.5f),
55+
ImVec2(iconX + fitSize, centerY + fitSize * 0.5f),
56+
ImVec2(0.f, 1.f), ImVec2(1.f, 0.f));
57+
}
58+
3059
if (content != previousContent)
3160
{
3261
ContentChangedEvent.Invoke(content);

0 commit comments

Comments
 (0)