1
1
#include < imgui.h>
2
2
#include < facade/engine/editor/inspector.hpp>
3
3
#include < facade/scene/scene.hpp>
4
+ #include < facade/util/enumerate.hpp>
4
5
#include < facade/util/fixed_string.hpp>
5
6
#include < cassert>
6
7
@@ -19,8 +20,6 @@ struct Modified {
19
20
};
20
21
} // namespace
21
22
22
- Inspector::Inspector ([[maybe_unused]] Window const & target) { assert (target.is_open ()); }
23
-
24
23
bool Inspector::inspect (char const * label, glm::vec2& out_vec2, float speed, float lo, float hi) const {
25
24
float arr[2 ] = {out_vec2.x , out_vec2.y };
26
25
ImGui::DragFloat2 (label, arr, speed, lo, hi);
@@ -51,6 +50,15 @@ bool Inspector::inspect(char const* label, glm::vec4& out_vec4, float speed, flo
51
50
return false ;
52
51
}
53
52
53
+ bool Inspector::inspect (char const * label, nvec3& out_vec3, float speed) const {
54
+ auto vec3 = out_vec3.value ();
55
+ if (inspect (label, vec3, speed, -1 .0f , 1 .0f )) {
56
+ out_vec3 = vec3;
57
+ return true ;
58
+ }
59
+ return false ;
60
+ }
61
+
54
62
bool Inspector::inspect (char const * label, glm::quat& out_quat) const {
55
63
auto euler = to_degree (glm::eulerAngles (out_quat));
56
64
auto const org = euler;
@@ -63,39 +71,124 @@ bool Inspector::inspect(char const* label, glm::quat& out_quat) const {
63
71
return false ;
64
72
}
65
73
74
+ bool Inspector::inspect_rgb (char const * label, glm::vec3& out_rgb) const {
75
+ float arr[3 ] = {out_rgb.x , out_rgb.y , out_rgb.z };
76
+ if (ImGui::ColorEdit3 (label, arr)) {
77
+ out_rgb = {arr[0 ], arr[1 ], arr[2 ]};
78
+ return true ;
79
+ }
80
+ return false ;
81
+ }
82
+
83
+ bool Inspector::inspect (char const * label, Rgb& out_rgb) const {
84
+ auto ret = Modified{};
85
+ if (auto tn = TreeNode{label}) {
86
+ auto vec3 = Rgb{.channels = out_rgb.channels , .intensity = 1 .0f }.to_vec3 ();
87
+ if (inspect_rgb (" RGB" , vec3)) {
88
+ out_rgb = Rgb::make (vec3, out_rgb.intensity );
89
+ ret.value = true ;
90
+ }
91
+ ret (ImGui::DragFloat (" Intensity" , &out_rgb.intensity , 0 .05f , 0 .1f , 1000 .0f ));
92
+ }
93
+ return ret.value ;
94
+ }
95
+
66
96
bool Inspector::inspect (Transform& out_transform, Bool& out_unified_scaling) const {
97
+ if (ImGui::CollapsingHeader (" Transform" , ImGuiTreeNodeFlags_DefaultOpen)) { return do_inspect (out_transform, out_unified_scaling, {true }); }
98
+ return false ;
99
+ }
100
+
101
+ bool Inspector::inspect (std::span<Transform> out_instances, Bool unified_scaling) const {
102
+ if (out_instances.empty ()) { return false ; }
103
+ auto ret = Modified{};
104
+ if (ImGui::CollapsingHeader (" Instances" )) {
105
+ for (auto [transform, index] : enumerate(out_instances)) {
106
+ if (auto tn = TreeNode{FixedString{" Instance [{}]" , index}.c_str ()}) { ret (do_inspect (transform, unified_scaling, {false })); }
107
+ }
108
+ }
109
+ return ret.value ;
110
+ }
111
+
112
+ bool Inspector::inspect (Lights& out_lights) const {
113
+ if (out_lights.dir_lights .empty ()) { return false ; }
67
114
auto ret = Modified{};
68
- if (ImGui::CollapsingHeader (" Transform" , ImGuiTreeNodeFlags_DefaultOpen)) {
69
- auto vec3 = out_transform.position ();
70
- if (ret (inspect (" Position" , vec3))) { out_transform.set_position (vec3); }
71
- auto quat = out_transform.orientation ();
72
- if (ret (inspect (" Orientation" , quat))) { out_transform.set_orientation (quat); }
73
- vec3 = out_transform.scale ();
74
- if (out_unified_scaling) {
75
- if (ret (ImGui::DragFloat (" Scale" , &vec3.x , 0 .1f ))) { out_transform.set_scale ({vec3.x , vec3.x , vec3.x }); }
76
- } else {
77
- if (ret (inspect (" Scale" , vec3, 0 .1f ))) { out_transform.set_scale (vec3); }
115
+ auto to_remove = std::optional<std::size_t >{};
116
+ bool allow_removal = out_lights.dir_lights .size () > 1 ;
117
+ auto inspect_dir_light = [&](DirLight& out_light, std::size_t index) {
118
+ auto tn = TreeNode{FixedString{" [{}]" , index}.c_str ()};
119
+ if (allow_removal) {
120
+ ImGui::SameLine (ImGui::GetWindowContentRegionWidth () - 10 .0f );
121
+ static constexpr auto colour_v = ImVec4{0 .8f , 0 .0f , 0 .1f , 1 .0f };
122
+ ImGui::PushStyleColor (ImGuiCol_Button, colour_v);
123
+ ImGui::PushStyleColor (ImGuiCol_ButtonHovered, colour_v);
124
+ ImGui::PushStyleColor (ImGuiCol_ButtonActive, colour_v);
125
+ if (ImGui::SmallButton (" x" )) { to_remove = index; }
126
+ ImGui::PopStyleColor (3 );
127
+ }
128
+ if (tn) {
129
+ ret (inspect (" Direction" , out_light.direction ));
130
+ ret (inspect (" Albedo" , out_light.rgb ));
131
+ }
132
+ };
133
+ if (ImGui::CollapsingHeader (" DirLights" )) {
134
+ for (auto [light, index] : enumerate(out_lights.dir_lights .span ())) { inspect_dir_light (light, index); }
135
+ }
136
+ if (to_remove) {
137
+ auto replace = decltype (out_lights.dir_lights ){};
138
+ for (auto const [light, index] : enumerate(out_lights.dir_lights .span ())) {
139
+ if (index == *to_remove) { continue ; }
140
+ replace.insert (light);
78
141
}
142
+ out_lights.dir_lights = std::move (replace);
143
+ }
144
+ if (out_lights.dir_lights .size () < Lights::max_lights_v && ImGui::Button (" [+]" )) { out_lights.dir_lights .insert (DirLight{}); }
145
+ return ret.value ;
146
+ }
147
+
148
+ bool Inspector::do_inspect (Transform& out_transform, Bool& out_unified_scaling, Bool scaling_toggle) const {
149
+ auto ret = Modified{};
150
+ auto vec3 = out_transform.position ();
151
+ if (ret (inspect (" Position" , vec3))) { out_transform.set_position (vec3); }
152
+ auto quat = out_transform.orientation ();
153
+ if (ret (inspect (" Orientation" , quat))) { out_transform.set_orientation (quat); }
154
+ vec3 = out_transform.scale ();
155
+ if (out_unified_scaling) {
156
+ if (ret (ImGui::DragFloat (" Scale" , &vec3.x , 0 .1f ))) { out_transform.set_scale ({vec3.x , vec3.x , vec3.x }); }
157
+ } else {
158
+ if (ret (inspect (" Scale" , vec3, 0 .1f ))) { out_transform.set_scale (vec3); }
159
+ }
160
+ if (scaling_toggle) {
79
161
ImGui::SameLine ();
80
162
ImGui::Checkbox (" Unified" , &out_unified_scaling.value );
81
163
}
82
164
return ret.value ;
83
165
}
84
166
85
- SceneInspector::SceneInspector ([[maybe_unused]] Window const & target, Scene& scene) : Inspector(target), m_scene(scene) { assert (target. is_open ()); }
167
+ SceneInspector::SceneInspector (NotClosed< Window> target, Scene& scene) : Inspector(target), m_scene(scene) {}
86
168
87
- bool SceneInspector::inspect ([[maybe_unused]] TreeNode const & node, UnlitMaterial& out_material) const {
88
- assert (node.is_open ());
169
+ bool SceneInspector::inspect (NotClosed<TreeNode>, UnlitMaterial& out_material) const {
89
170
auto ret = Modified{};
90
171
ret (inspect (" Tint" , out_material.tint , 0 .01f , 0 .0f , 1 .0f ));
91
172
return ret.value ;
92
173
}
93
174
94
- bool SceneInspector::inspect ([[maybe_unused]] TreeNode const & node, LitMaterial& out_material) const {
95
- assert (node.is_open ());
175
+ bool SceneInspector::inspect (NotClosed<TreeNode>, LitMaterial& out_material) const {
96
176
auto ret = Modified{};
97
177
ret (ImGui::SliderFloat (" Metallic" , &out_material.metallic , 0 .0f , 1 .0f ));
98
178
ret (ImGui::SliderFloat (" Roughness" , &out_material.roughness , 0 .0f , 1 .0f ));
179
+ ret (inspect_rgb (" Albedo" , out_material.albedo ));
180
+ if (out_material.base_colour || out_material.roughness_metallic ) {
181
+ if (auto tn = TreeNode{" Textures" }) {
182
+ if (out_material.base_colour ) {
183
+ auto const * tex = m_scene.find (*out_material.base_colour );
184
+ TreeNode::leaf (FixedString{" Albedo: {} ({})" , tex->name , *out_material.base_colour }.c_str ());
185
+ }
186
+ if (out_material.roughness_metallic ) {
187
+ auto const * tex = m_scene.find (*out_material.roughness_metallic );
188
+ TreeNode::leaf (FixedString{" Roughness-Metallic: {} ({})" , tex->name , *out_material.roughness_metallic }.c_str ());
189
+ }
190
+ }
191
+ }
99
192
return ret.value ;
100
193
}
101
194
@@ -112,28 +205,28 @@ bool SceneInspector::inspect(Id<Material> material_id) const {
112
205
return false ;
113
206
}
114
207
115
- bool SceneInspector::inspect (Id<Node> node_id, Bool& out_unified_scaling) const {
116
- auto ret = Modified{};
117
- auto * node = m_scene.find (node_id);
118
- if (!node) { return false ; }
119
- ret (inspect (node->transform , out_unified_scaling));
120
- if (auto const * mesh_id = node->find <Id<Mesh>>()) { ret (inspect (*mesh_id)); }
121
- return ret.value ;
122
- }
123
-
124
208
bool SceneInspector::inspect (Id<Mesh> mesh_id) const {
125
209
auto ret = Modified{};
126
210
auto * mesh = m_scene.find (mesh_id);
127
211
if (!mesh) { return ret.value ; }
128
212
if (ImGui::CollapsingHeader (FixedString{" Mesh ({})###Mesh" , mesh_id}.c_str ())) {
129
- for (std::size_t i = 0 ; i < mesh->primitives .size (); ++i) {
130
- if (auto tn = TreeNode{FixedString{" Primitive {}" , i}.c_str ()}) {
131
- auto const & primitive = mesh->primitives [i];
132
- ImGui::Text (" %s" , FixedString{" Static Mesh ({})" , primitive.static_mesh }.c_str ());
213
+ for (auto [primitive, index] : enumerate(mesh->primitives )) {
214
+ if (auto tn = TreeNode{FixedString{" Primitive [{}]" , index}.c_str ()}) {
215
+ TreeNode::leaf (FixedString{" Static Mesh ({})" , primitive.static_mesh }.c_str ());
133
216
if (primitive.material ) { ret (inspect (*primitive.material )); }
134
217
}
135
218
}
136
219
}
137
220
return ret.value ;
138
221
}
222
+
223
+ bool SceneInspector::inspect (Id<Node> node_id, Bool& out_unified_scaling) const {
224
+ auto ret = Modified{};
225
+ auto * node = m_scene.find (node_id);
226
+ if (!node) { return false ; }
227
+ ret (inspect (node->transform , out_unified_scaling));
228
+ ret (inspect (node->instances , out_unified_scaling));
229
+ if (auto const * mesh_id = node->find <Id<Mesh>>()) { ret (inspect (*mesh_id)); }
230
+ return ret.value ;
231
+ }
139
232
} // namespace facade::editor
0 commit comments