Skip to content

Commit 7895bfd

Browse files
authored
Add ResourceBrowser (#68)
* Add ResourceBrowser (stateful) - Keep all persistent popup state in `ResourceBrowser`. - Enable adding `StaticMesh`s through editor. * Complete Add StaticMesh - Upgrade Camera editor. - Minor fixes. - Focus keyboard on input on popup open. - main: Ignore engine input if ImGui is using keyboard. * Add editor::Combo - Use in `Inspector`. * Improve editor/common - Store close callback (and whether to force close) in `Openable`, call it in its destructor. - Have derived classes pass `ImGui::End*()` as the close callback.
1 parent e4a2180 commit 7895bfd

File tree

18 files changed

+376
-188
lines changed

18 files changed

+376
-188
lines changed

lib/engine/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ target_sources(${PROJECT_NAME} PRIVATE
4343
include/${target_prefix}/engine/editor/browse_file.hpp
4444
include/${target_prefix}/engine/editor/common.hpp
4545
include/${target_prefix}/engine/editor/drag_drop_id.hpp
46-
include/${target_prefix}/engine/editor/inspect_data.hpp
4746
include/${target_prefix}/engine/editor/inspector.hpp
4847
include/${target_prefix}/engine/editor/log.hpp
4948
include/${target_prefix}/engine/editor/reflector.hpp
49+
include/${target_prefix}/engine/editor/resource_browser.hpp
5050
include/${target_prefix}/engine/editor/scene_tree.hpp
5151

5252
src/scene_renderer.cpp
@@ -57,5 +57,6 @@ target_sources(${PROJECT_NAME} PRIVATE
5757
src/editor/inspector.cpp
5858
src/editor/log.cpp
5959
src/editor/reflector.cpp
60+
src/editor/resource_browser.cpp
6061
src/editor/scene_tree.cpp
6162
)

lib/engine/include/facade/engine/editor/common.hpp

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,53 @@ glm::vec2 max_size(std::span<char const* const> strings);
2525
///
2626
bool small_button_red(char const* label);
2727

28+
///
29+
/// \brief Create a selectable item.
30+
/// \param label Label on the selectable
31+
/// \param selected whether this selectable should be selected
32+
/// \param flags ImGuiSelectableFlags (passthrough)
33+
/// \param size Size (passthrough)
34+
/// \returns true if clicked
35+
///
36+
bool selectable(char const* label, Bool selected, int flags = {}, glm::vec2 size = {});
37+
38+
///
39+
/// \brief RAII Dear ImGui StyleVar stack
40+
///
41+
class StyleVar : public Pinned {
42+
public:
43+
explicit StyleVar(int index, glm::vec2 value) { push(index, value); }
44+
explicit StyleVar(int index, float value) { push(index, value); }
45+
~StyleVar();
46+
47+
void push(int index, glm::vec2 value);
48+
void push(int index, float value);
49+
50+
explicit operator bool() const { return true; }
51+
52+
private:
53+
int m_count{};
54+
};
55+
2856
///
2957
/// \brief Base class for RAII Dear ImGui wrappers whose widgets return a boolean on Begin()
3058
///
3159
class Openable : public Pinned {
3260
public:
61+
~Openable() noexcept;
62+
3363
bool is_open() const { return m_open; }
3464
explicit operator bool() const { return is_open(); }
3565

3666
protected:
37-
Openable(bool is_open = false);
38-
bool m_open;
67+
using Close = void (*)();
68+
69+
Openable() = default;
70+
Openable(bool is_open, Close close, Bool force_close = {}) : m_close(close), m_open(is_open), m_force_close(force_close) {}
71+
72+
Close m_close{};
73+
bool m_open{};
74+
bool m_force_close{};
3975
};
4076

4177
///
@@ -63,10 +99,6 @@ class Window : public Canvas {
6399

64100
explicit Window(char const* label, bool* open_if = {}, int flags = {});
65101
Window(NotClosed<Canvas> parent, char const* label, glm::vec2 size = {}, Bool border = {}, int flags = {});
66-
~Window();
67-
68-
private:
69-
bool m_child{};
70102
};
71103

72104
///
@@ -75,7 +107,6 @@ class Window : public Canvas {
75107
class TreeNode : public Openable {
76108
public:
77109
explicit TreeNode(char const* label, int flags = {});
78-
~TreeNode();
79110

80111
static bool leaf(char const* label, int flags = {});
81112
};
@@ -94,7 +125,6 @@ class MenuBar : public Openable {
94125
class Menu : public Openable {
95126
public:
96127
explicit Menu(NotClosed<MenuBar>, char const* label, Bool enabled = {true});
97-
~Menu();
98128
};
99129

100130
///
@@ -103,7 +133,6 @@ class Menu : public Openable {
103133
class Window::Menu : public MenuBar {
104134
public:
105135
explicit Menu(NotClosed<Canvas>);
106-
~Menu();
107136
};
108137

109138
///
@@ -112,7 +141,6 @@ class Window::Menu : public MenuBar {
112141
class MainMenu : public MenuBar {
113142
public:
114143
explicit MainMenu();
115-
~MainMenu();
116144
};
117145

118146
///
@@ -121,7 +149,6 @@ class MainMenu : public MenuBar {
121149
class Popup : public Canvas {
122150
public:
123151
explicit Popup(char const* id, Bool centered = {}, int flags = {}) : Popup(id, {}, {}, centered, flags) {}
124-
~Popup();
125152

126153
static void open(char const* id);
127154
static void close_current();
@@ -139,14 +166,27 @@ class Modal : public Popup {
139166
};
140167

141168
///
142-
/// \brief RAII Dear ImGui StyleVar stack
169+
/// \brief RAII Dear ImGui TabBar
143170
///
144-
class StyleVar : public Pinned {
171+
class TabBar : public Openable {
145172
public:
146-
explicit StyleVar(int index, glm::vec2 value);
147-
explicit StyleVar(int index, float value);
148-
~StyleVar();
173+
class Item;
149174

150-
explicit operator bool() const { return true; }
175+
explicit TabBar(char const* label, int flags = {});
176+
};
177+
178+
class TabBar::Item : public Openable {
179+
public:
180+
explicit Item(NotClosed<TabBar>, char const* label, bool* open = {}, int flags = {});
181+
};
182+
183+
///
184+
/// \brief RAII Dear ImGui Combo
185+
///
186+
class Combo : public Openable {
187+
public:
188+
explicit Combo(char const* label, char const* preview);
189+
190+
bool item(char const* label, Bool selected, int flags = {}, glm::vec2 size = {}) const { return selectable(label, selected, flags, size); }
151191
};
152192
} // namespace facade::editor

lib/engine/include/facade/engine/editor/inspect_data.hpp

Lines changed: 0 additions & 9 deletions
This file was deleted.

lib/engine/include/facade/engine/editor/inspector.hpp

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#pragma once
22
#include <facade/engine/editor/common.hpp>
3-
#include <facade/engine/editor/inspect_data.hpp>
43
#include <facade/scene/scene.hpp>
54

65
namespace facade::editor {
@@ -10,7 +9,7 @@ namespace facade::editor {
109
/// Inspectors are stateless ImGui helpers to view / edit various components, with drag-and-drop support.
1110
///
1211
class Inspector {
13-
protected:
12+
public:
1413
///
1514
/// \brief Construct an Inspector instance.
1615
///
@@ -19,6 +18,7 @@ class Inspector {
1918
///
2019
Inspector(NotClosed<Window> target, Scene& out_scene) : m_target(target), m_scene(out_scene), m_resources(out_scene.resources()) {}
2120

21+
protected:
2222
NotClosed<Window> m_target;
2323
Scene& m_scene;
2424
SceneResources& m_resources;
@@ -68,17 +68,8 @@ class ResourceInspector : public Inspector {
6868
///
6969
class SceneInspector : public Inspector {
7070
public:
71-
using Data = InspectData;
72-
73-
SceneInspector(NotClosed<Window> target, Scene& out_scene) : Inspector(target, out_scene) {}
71+
using Inspector::Inspector;
7472

75-
///
76-
/// \brief View/edit all resources.
77-
/// \param out_data Persistent data for popups
78-
///
79-
/// Uses ResourceInspector.
80-
///
81-
void resources(Data& out_data) const;
8273
///
8374
/// \brief Inspect the Scene's camera.
8475
///
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#pragma once
2+
#include <facade/engine/editor/common.hpp>
3+
#include <glm/vec3.hpp>
4+
5+
namespace facade {
6+
class Scene;
7+
8+
namespace editor {
9+
///
10+
/// \brief Stateful browser for resources in a scene.
11+
///
12+
/// Uses a framed TreeNode.
13+
///
14+
class ResourceBrowser {
15+
public:
16+
///
17+
/// \brief View/edit all resources.
18+
/// \param target editor Window to draw to
19+
/// \param out_scene Scene whose resources to view/edit
20+
///
21+
/// Uses ResourceInspector.
22+
///
23+
void display(NotClosed<Window> target, Scene& out_scene);
24+
25+
private:
26+
void add_mesh(bool trigger);
27+
void add_material(bool trigger);
28+
void add_static_mesh(bool trigger);
29+
30+
enum class SmType { eCube, eSphere, eCone, eCylinder, eArrow };
31+
32+
struct {
33+
struct {
34+
std::string buffer{};
35+
int type{};
36+
} mat{};
37+
struct {
38+
std::string buffer{};
39+
} mesh{};
40+
struct {
41+
SmType type{};
42+
std::string buffer{};
43+
struct {
44+
glm::vec3 vertex_rgb{1.0f};
45+
glm::vec3 size{1.0f};
46+
} cube{};
47+
struct {
48+
glm::vec3 vertex_rgb{1.0f};
49+
float diameter{1.0f};
50+
int quads_per_side{32};
51+
} sphere{};
52+
struct {
53+
glm::vec3 vertex_rgb{1.0f};
54+
float xz_diam{1.0f};
55+
int xz_points{128};
56+
float y_height{1.0f};
57+
} conic{};
58+
struct {
59+
glm::vec3 vertex_rgb{1.0f};
60+
float stalk_diam{0.5f};
61+
float stalk_height{1.0f};
62+
int xz_points{128};
63+
} arrow{};
64+
} static_mesh{};
65+
} m_data{};
66+
67+
Scene* m_scene{};
68+
NotClosed<Window>* m_target{};
69+
};
70+
} // namespace editor
71+
} // namespace facade

lib/engine/src/editor/common.cpp

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -23,46 +23,32 @@ bool small_button_red(char const* label) {
2323
return ret;
2424
}
2525

26-
Openable::Openable(bool is_open) : m_open(is_open) {}
26+
bool selectable(char const* label, Bool selected, int flags, glm::vec2 size) { return ImGui::Selectable(label, selected.value, flags, {size.x, size.y}); }
2727

28-
Window::Window(char const* label, bool* open_if, int flags) : Canvas(ImGui::Begin(label, open_if, flags)) {}
29-
30-
Window::Window(NotClosed<Canvas>, char const* label, glm::vec2 size, Bool border, int flags)
31-
: Canvas(ImGui::BeginChild(label, {size.x, size.y}, border.value, flags)), m_child(true) {}
32-
33-
// ImGui windows requires End() even if Begin() returned false
34-
Window::~Window() {
35-
if (m_child) {
36-
ImGui::EndChild();
37-
} else {
38-
ImGui::End();
28+
Openable::~Openable() noexcept {
29+
if (m_open || m_force_close) {
30+
assert(m_close);
31+
(*m_close)();
3932
}
4033
}
4134

42-
TreeNode::TreeNode(char const* label, int flags) : Openable(ImGui::TreeNodeEx(label, flags)) {}
35+
Window::Window(char const* label, bool* open_if, int flags) : Canvas(ImGui::Begin(label, open_if, flags), &ImGui::End, {true}) {}
4336

44-
TreeNode::~TreeNode() {
45-
if (m_open) { ImGui::TreePop(); }
46-
}
37+
Window::Window(NotClosed<Canvas>, char const* label, glm::vec2 size, Bool border, int flags)
38+
: Canvas(ImGui::BeginChild(label, {size.x, size.y}, border.value, flags), &ImGui::EndChild, {true}) {}
39+
40+
TreeNode::TreeNode(char const* label, int flags) : Openable(ImGui::TreeNodeEx(label, flags), &ImGui::TreePop) {}
4741

4842
bool TreeNode::leaf(char const* label, int flags) {
4943
auto tn = TreeNode{label, flags | ImGuiTreeNodeFlags_Leaf};
5044
return ImGui::IsItemClicked();
5145
}
5246

53-
Window::Menu::Menu(NotClosed<Canvas>) : MenuBar(ImGui::BeginMenuBar()) {}
54-
55-
Window::Menu::~Menu() {
56-
if (m_open) { ImGui::EndMenuBar(); }
57-
}
58-
59-
MainMenu::MainMenu() : MenuBar(ImGui::BeginMainMenuBar()) {}
47+
Window::Menu::Menu(NotClosed<Canvas>) : MenuBar(ImGui::BeginMenuBar(), &ImGui::EndMenuBar) {}
6048

61-
MainMenu::~MainMenu() {
62-
if (m_open) { ImGui::EndMainMenuBar(); }
63-
}
49+
MainMenu::MainMenu() : MenuBar(ImGui::BeginMainMenuBar(), &ImGui::EndMainMenuBar) {}
6450

65-
Popup::Popup(char const* id, Bool modal, Bool closeable, Bool centered, int flags) {
51+
Popup::Popup(char const* id, Bool modal, Bool closeable, Bool centered, int flags) : Canvas(false, &ImGui::EndPopup) {
6652
if (centered) {
6753
auto const center = ImGui::GetMainViewport()->GetCenter();
6854
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2{0.5f, 0.5f});
@@ -74,21 +60,27 @@ Popup::Popup(char const* id, Bool modal, Bool closeable, Bool centered, int flag
7460
}
7561
}
7662

77-
Popup::~Popup() {
78-
if (m_open) { ImGui::EndPopup(); }
79-
}
80-
8163
void Popup::open(char const* id) { ImGui::OpenPopup(id); }
8264

8365
void Popup::close_current() { ImGui::CloseCurrentPopup(); }
8466

85-
Menu::Menu(NotClosed<MenuBar>, char const* label, Bool enabled) : Openable(ImGui::BeginMenu(label, enabled.value)) {}
67+
Menu::Menu(NotClosed<MenuBar>, char const* label, Bool enabled) : Openable(ImGui::BeginMenu(label, enabled.value), &ImGui::EndMenu) {}
8668

87-
Menu::~Menu() {
88-
if (m_open) { ImGui::EndMenu(); }
69+
void StyleVar::push(int index, glm::vec2 value) {
70+
ImGui::PushStyleVar(index, {value.x, value.y});
71+
++m_count;
8972
}
9073

91-
StyleVar::StyleVar(int index, glm::vec2 value) { ImGui::PushStyleVar(index, {value.x, value.y}); }
92-
StyleVar::StyleVar(int index, float value) { ImGui::PushStyleVar(index, value); }
93-
StyleVar::~StyleVar() { ImGui::PopStyleVar(); }
74+
void StyleVar::push(int index, float value) {
75+
ImGui::PushStyleVar(index, value);
76+
++m_count;
77+
}
78+
79+
StyleVar::~StyleVar() { ImGui::PopStyleVar(m_count); }
80+
81+
TabBar::TabBar(char const* label, int flags) : Openable(ImGui::BeginTabBar(label, flags), &ImGui::EndTabBar) {}
82+
83+
TabBar::Item::Item(NotClosed<TabBar>, char const* label, bool* open, int flags) : Openable(ImGui::BeginTabItem(label, open, flags), &ImGui::EndTabItem) {}
84+
85+
Combo::Combo(char const* label, char const* preview) : Openable(ImGui::BeginCombo(label, preview), &ImGui::EndCombo) {}
9486
} // namespace facade::editor

0 commit comments

Comments
 (0)