Skip to content

Commit a9273fb

Browse files
authored
Refactor MainMenu (#57)
- Create `main_menu/main_menu.[hc]cpp` - Remove `editor::Log`, move state storage into `WindowMenu` - Have `FileMenu` return a `Command` instead of executing (incomplete) logic itself
1 parent 7569239 commit a9273fb

File tree

8 files changed

+260
-151
lines changed

8 files changed

+260
-151
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ if(FACADE_BUILD_EXE)
5353
add_executable(${PROJECT_NAME})
5454

5555
target_sources(${PROJECT_NAME} PRIVATE
56+
src/main_menu/main_menu.cpp
57+
src/main_menu/main_menu.hpp
58+
5659
src/main.cpp
5760

5861
src/bin/shaders.cpp

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
#include <glm/vec2.hpp>
55
#include <cassert>
66
#include <concepts>
7+
#include <span>
8+
9+
namespace facade {
10+
class Engine;
11+
}
712

813
namespace facade::editor {
914
///
@@ -25,6 +30,9 @@ class Openable : public Pinned {
2530
template <typename T>
2631
struct NotClosed {
2732
NotClosed([[maybe_unused]] T const& t) { assert(t.is_open()); }
33+
34+
template <std::derived_from<T> Derived>
35+
NotClosed(NotClosed<Derived>) {}
2836
};
2937

3038
///

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

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55
#include <vector>
66

77
namespace facade::editor {
8-
class Log : public logger::Accessor {
9-
public:
10-
void render(NotClosed<Window> window);
8+
struct LogState {
9+
EnumArray<logger::Level, bool> level_filter{true, true, true, debug_v};
10+
int display_count{50};
11+
bool auto_scroll{true};
1112

12-
private:
13-
void operator()(std::span<logger::Entry const> entries) final;
14-
15-
std::vector<logger::Entry const*> m_list{};
16-
EnumArray<logger::Level, bool> m_level_filter{true, true, true, debug_v};
17-
int m_display_count{50};
18-
bool m_auto_scroll{true};
13+
std::vector<logger::Entry const*> list{};
1914
};
15+
16+
void display_log(NotClosed<Window> window, LogState& out_state);
2017
} // namespace facade::editor

lib/engine/src/editor/inspector.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ bool Inspector::inspect(std::span<Transform> out_instances, Bool unified_scaling
110110
}
111111

112112
bool Inspector::inspect(Lights& out_lights) const {
113-
if (out_lights.dir_lights.empty()) { return false; }
114113
auto ret = Modified{};
115114
auto to_remove = std::optional<std::size_t>{};
116115
bool allow_removal = out_lights.dir_lights.size() > 1;

lib/engine/src/editor/log.cpp

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,30 @@
33
#include <facade/engine/editor/log.hpp>
44
#include <facade/util/fixed_string.hpp>
55

6-
namespace facade::editor {
7-
void Log::render(NotClosed<Window> window) {
8-
ImGui::Text("%s", FixedString{"Count: {}", m_display_count}.c_str());
6+
namespace facade {
7+
void editor::display_log(NotClosed<Window> window, LogState& out_state) {
8+
ImGui::Text("%s", FixedString{"Count: {}", out_state.display_count}.c_str());
99
ImGui::SameLine();
1010
float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
1111
ImGui::PushButtonRepeat(true);
1212
auto const max_logs = static_cast<int>(logger::buffer_size().total());
13-
if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { m_display_count = std::clamp(m_display_count - 10, 0, max_logs); }
13+
if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { out_state.display_count = std::clamp(out_state.display_count - 10, 0, max_logs); }
1414
ImGui::SameLine(0.0f, spacing);
15-
if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { m_display_count = std::clamp(m_display_count + 10, 0, max_logs); }
15+
if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { out_state.display_count = std::clamp(out_state.display_count + 10, 0, max_logs); }
1616
ImGui::PopButtonRepeat();
1717

1818
static constexpr std::string_view levels_v[] = {"Error", "Warn", "Info", "Debug"};
1919
static constexpr auto max_log_level_v = debug_v ? logger::Level::eDebug : logger::Level::eInfo;
2020
for (logger::Level l = logger::Level::eError; l <= max_log_level_v; l = static_cast<logger::Level>(static_cast<int>(l) + 1)) {
2121
ImGui::SameLine();
22-
ImGui::Checkbox(levels_v[static_cast<std::size_t>(l)].data(), &m_level_filter[l]);
22+
ImGui::Checkbox(levels_v[static_cast<std::size_t>(l)].data(), &out_state.level_filter[l]);
2323
}
2424
ImGui::SameLine();
2525
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
2626
ImGui::SameLine();
27-
ImGui::Checkbox("Auto-scroll", &m_auto_scroll);
27+
ImGui::Checkbox("Auto-scroll", &out_state.auto_scroll);
2828

2929
ImGui::Separator();
30-
logger::access_buffer(*this);
3130
auto child = editor::Window{window, "scroll", {}, {}, ImGuiWindowFlags_HorizontalScrollbar};
3231
static constexpr auto im_colour = [](logger::Level const l) {
3332
switch (l) {
@@ -38,21 +37,13 @@ void Log::render(NotClosed<Window> window) {
3837
case logger::Level::eDebug: return ImVec4{0.5f, 0.5f, 0.5f, 1.0f};
3938
}
4039
};
41-
auto span = std::span{m_list};
42-
auto const max_size = static_cast<std::size_t>(m_display_count);
40+
auto span = std::span{out_state.list};
41+
auto const max_size = static_cast<std::size_t>(out_state.display_count);
4342
if (span.size() > max_size) { span = span.subspan(span.size() - max_size); }
4443
if (auto style = editor::StyleVar{ImGuiStyleVar_ItemSpacing, glm::vec2{}}) {
4544
for (auto const* entry : span) ImGui::TextColored(im_colour(entry->level), "%s", entry->message.c_str());
4645
}
4746

48-
if (m_auto_scroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) { ImGui::SetScrollHereY(1.0f); }
47+
if (out_state.auto_scroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) { ImGui::SetScrollHereY(1.0f); }
4948
}
50-
51-
void Log::operator()(std::span<logger::Entry const> entries) {
52-
m_list.clear();
53-
for (auto const& entry : entries) {
54-
if (!m_level_filter[entry.level]) { continue; }
55-
m_list.push_back(&entry);
56-
}
57-
}
58-
} // namespace facade::editor
49+
} // namespace facade

src/main.cpp

Lines changed: 27 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
1-
21
#include <facade/defines.hpp>
32

43
#include <facade/util/data_provider.hpp>
54
#include <facade/util/error.hpp>
6-
#include <facade/util/fixed_string.hpp>
75
#include <facade/util/logger.hpp>
86
#include <facade/vk/geometry.hpp>
97

10-
#include <djson/json.hpp>
11-
12-
#include <facade/render/renderer.hpp>
138
#include <facade/scene/fly_cam.hpp>
149

15-
#include <facade/engine/editor/inspector.hpp>
16-
#include <facade/engine/editor/log.hpp>
17-
#include <facade/engine/editor/scene_tree.hpp>
1810
#include <facade/engine/engine.hpp>
1911

2012
#include <bin/shaders.hpp>
13+
#include <main_menu/main_menu.hpp>
2114

22-
#include <filesystem>
23-
#include <iostream>
15+
#include <djson/json.hpp>
2416

2517
#include <imgui.h>
2618

19+
#include <filesystem>
20+
#include <iostream>
21+
2722
using namespace facade;
2823

2924
namespace {
@@ -112,111 +107,6 @@ static constexpr auto test_json_v = R"(
112107
}
113108
)";
114109

115-
struct MainMenu {
116-
struct {
117-
bool stats{};
118-
bool tree{};
119-
bool lights{};
120-
bool log{};
121-
bool imgui_demo{};
122-
} windows{};
123-
124-
struct {
125-
editor::Log log{};
126-
editor::InspectNode inspect{};
127-
Bool unified_scaling{true};
128-
} data{};
129-
130-
void change_vsync(Engine const& engine) const {
131-
static constexpr vk::PresentModeKHR modes[] = {vk::PresentModeKHR::eFifo, vk::PresentModeKHR::eFifoRelaxed, vk::PresentModeKHR::eMailbox,
132-
vk::PresentModeKHR::eImmediate};
133-
static std::size_t index{0};
134-
auto const next_mode = [&] {
135-
while (true) {
136-
index = (index + 1) % std::size(modes);
137-
auto const ret = modes[index];
138-
if (!engine.renderer().is_supported(ret)) { continue; }
139-
return ret;
140-
}
141-
throw Error{"Invariant violated"};
142-
}();
143-
engine.renderer().request_mode(next_mode);
144-
logger::info("Requesting present mode: [{}]", present_mode_str(next_mode));
145-
}
146-
147-
void inspector(Scene& scene) {
148-
bool show = true;
149-
ImGui::SetNextWindowSize({400.0f, 400.0f}, ImGuiCond_FirstUseEver);
150-
if (auto window = editor::Window{data.inspect.name.c_str(), &show}) {
151-
editor::SceneInspector{window, scene}.inspect(data.inspect.id, data.unified_scaling);
152-
}
153-
if (!show) { data.inspect = {}; }
154-
}
155-
156-
void stats(Engine const& engine, float const dt) {
157-
ImGui::SetNextWindowSize({250.0f, 200.0f}, ImGuiCond_FirstUseEver);
158-
if (auto window = editor::Window{"Frame Stats", &windows.stats}) {
159-
auto const& stats = engine.renderer().frame_stats();
160-
ImGui::Text("%s", FixedString{"Counter: {}", stats.frame_counter}.c_str());
161-
ImGui::Text("%s", FixedString{"Triangles: {}", stats.triangles}.c_str());
162-
ImGui::Text("%s", FixedString{"Draw calls: {}", stats.draw_calls}.c_str());
163-
ImGui::Text("%s", FixedString{"FPS: {}", (stats.fps == 0 ? static_cast<std::uint32_t>(stats.frame_counter) : stats.fps)}.c_str());
164-
ImGui::Text("%s", FixedString{"Frame time: {:.2f}ms", dt * 1000.0f}.c_str());
165-
ImGui::Text("%s", FixedString{"GPU: {}", stats.gpu_name}.c_str());
166-
ImGui::Text("%s", FixedString{"MSAA: {}x", to_int(stats.msaa)}.c_str());
167-
if (ImGui::SmallButton("Vsync")) { change_vsync(engine); }
168-
ImGui::SameLine();
169-
ImGui::Text("%s", vsync_status(stats.mode).data());
170-
}
171-
}
172-
173-
void tree(Scene& scene) {
174-
ImGui::SetNextWindowSize({250.0f, 350.0f}, ImGuiCond_FirstUseEver);
175-
if (auto window = editor::Window{"Scene", &windows.tree}) {
176-
if (ImGui::Button("Lights")) { windows.lights = true; }
177-
ImGui::Separator();
178-
editor::SceneTree{scene}.render(window, data.inspect);
179-
}
180-
}
181-
182-
void lights(Lights& lights) {
183-
ImGui::SetNextWindowSize({400.0f, 400.0f}, ImGuiCond_FirstUseEver);
184-
if (auto window = editor::Window{"Lights", &windows.lights}) { editor::Inspector{window}.inspect(lights); }
185-
}
186-
187-
void log() {
188-
ImGui::SetNextWindowSize({600.0f, 200.0f}, ImGuiCond_FirstUseEver);
189-
if (auto window = editor::Window{"Log", &windows.log}) { data.log.render(window); }
190-
}
191-
192-
void display(Engine& engine, float const dt) {
193-
if (auto main = editor::MainMenu{}) {
194-
if (auto file = editor::Menu{main, "File"}) {
195-
ImGui::Separator();
196-
if (ImGui::MenuItem("Exit")) { engine.request_stop(); }
197-
}
198-
if (auto window = editor::Menu{main, "Window"}) {
199-
if (ImGui::MenuItem("Tree")) { windows.tree = true; }
200-
if (ImGui::MenuItem("Lights")) { windows.lights = true; }
201-
if (ImGui::MenuItem("Stats")) { windows.stats = true; }
202-
if (ImGui::MenuItem("Log")) { windows.log = true; }
203-
if constexpr (debug_v) {
204-
if (ImGui::MenuItem("ImGui demo")) { windows.imgui_demo = true; }
205-
}
206-
ImGui::Separator();
207-
if (ImGui::MenuItem("Close All")) { windows = {}; }
208-
}
209-
}
210-
211-
if (windows.tree) { tree(engine.scene()); }
212-
if (windows.lights) { lights(engine.scene().lights); }
213-
if (data.inspect) { inspector(engine.scene()); }
214-
if (windows.stats) { stats(engine, dt); }
215-
if (windows.log) { log(); }
216-
if (windows.imgui_demo) { ImGui::ShowDemoWindow(&windows.imgui_demo); }
217-
}
218-
};
219-
220110
void log_prologue() {
221111
auto const now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
222112
char buf[32]{};
@@ -245,14 +135,16 @@ void run() {
245135

246136
auto material_id = Id<Material>{};
247137
auto node_id = Id<Node>{};
248-
auto post_scene_load = [&](Scene& scene) {
138+
auto post_scene_load = [&]() {
139+
auto& scene = engine->scene();
249140
scene.lights.dir_lights.insert(DirLight{.direction = glm::normalize(glm::vec3{-1.0f, -1.0f, -1.0f}), .rgb = {.intensity = 5.0f}});
250141
scene.camera().transform.set_position({0.0f, 0.0f, 5.0f});
251142

252143
auto material = std::make_unique<LitMaterial>();
253144
material->albedo = {1.0f, 0.0f, 0.0f};
254145
material_id = scene.add(std::move(material));
255146
auto static_mesh_id = scene.add(make_cubed_sphere(1.0f, 32));
147+
// auto static_mesh_id = scene.add(make_manipulator(0.125f, 1.0f, 16));
256148
auto mesh_id = scene.add(Mesh{.primitives = {Mesh::Primitive{static_mesh_id, material_id}}});
257149

258150
auto node = Node{};
@@ -273,15 +165,16 @@ void run() {
273165

274166
auto& scene = engine->scene();
275167
scene.load_gltf(dj::Json::parse(test_json_v), DummyDataProvider{});
276-
post_scene_load(engine->scene());
168+
post_scene_load();
277169
engine->show(true);
278170
};
279171

280172
init();
281173

282174
float const drot_z[] = {100.0f, -150.0f};
283175

284-
auto main_menu = MainMenu{};
176+
auto file_menu = FileMenu{};
177+
auto window_menu = WindowMenu{};
285178

286179
struct {
287180
LoadStatus status{};
@@ -302,8 +195,9 @@ void run() {
302195
if (!fs::is_regular_file(path)) {
303196
logger::error("Failed to locate .gltf in path: [{}]", state.file_drops.front());
304197
} else {
305-
if (engine->load_async(path.generic_string(), [&] { post_scene_load(engine->scene()); })) {
198+
if (engine->load_async(path.generic_string(), post_scene_load)) {
306199
loading.title = fmt::format("Loading {}...", path.filename().generic_string());
200+
file_menu.add_recent(path.generic_string());
307201
}
308202
}
309203
}
@@ -343,7 +237,20 @@ void run() {
343237
node->instances[1].rotate(glm::radians(drot_z[1]) * dt, {1.0f, 0.0f, 0.0f});
344238
}
345239

346-
main_menu.display(*engine, dt);
240+
if (auto menu = editor::MainMenu{}) {
241+
auto file_command = file_menu.display(menu);
242+
window_menu.display_menu(menu);
243+
window_menu.display_windows(*engine);
244+
auto const visitor = Visitor{
245+
[&engine](FileMenu::Shutdown) { engine->request_stop(); },
246+
[&engine, &post_scene_load, &file_menu](FileMenu::OpenRecent open_recent) {
247+
engine->load_async(open_recent.path, post_scene_load);
248+
file_menu.add_recent(std::move(open_recent.path));
249+
},
250+
[](std::monostate) {},
251+
};
252+
std::visit(visitor, file_command);
253+
}
347254
// TEMP CODE
348255

349256
engine->render();

0 commit comments

Comments
 (0)