Created a UIStack component that handles multiple screens.

This commit is contained in:
Zed A. Shaw 2026-04-08 11:13:56 -04:00
parent d393cf91ab
commit 543928eb36
7 changed files with 121 additions and 18 deletions

View file

@ -65,7 +65,7 @@ debug: build
gdb --nx -x .gdbinit --ex run --args builddir/runtests gdb --nx -x .gdbinit --ex run --args builddir/runtests
debug_run: build debug_run: build
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/under_the_dome gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/multiscreen
debug_walk: build test debug_walk: build test
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/under_the_dome t gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/under_the_dome t

View file

@ -140,3 +140,11 @@ executable('fragviewer',
include_directories: inc_dirs, include_directories: inc_dirs,
override_options: exe_defaults, override_options: exe_defaults,
dependencies: dependencies) dependencies: dependencies)
executable('multiscreen',
[ 'tools/multiscreen.cpp' ],
cpp_args: cpp_args,
link_args: link_args,
include_directories: inc_dirs,
override_options: exe_defaults,
dependencies: dependencies)

View file

@ -58,8 +58,6 @@ namespace scene {
} }
void Engine::init() { void Engine::init() {
dbc::log($F("initialized scene with background {}", $scene.background));
$gui.position(SCENE_VIEW_X, SCENE_VIEW_Y, SCENE_VIEW_WIDTH, SCENE_VIEW_HEIGHT); $gui.position(SCENE_VIEW_X, SCENE_VIEW_Y, SCENE_VIEW_WIDTH, SCENE_VIEW_HEIGHT);
$gui.set<guecs::Background>($gui.MAIN, {$gui.$parser, guecs::THEME.TRANSPARENT}); $gui.set<guecs::Background>($gui.MAIN, {$gui.$parser, guecs::THEME.TRANSPARENT});
auto& background = $gui.get<guecs::Background>($gui.MAIN); auto& background = $gui.get<guecs::Background>($gui.MAIN);

View file

@ -49,8 +49,8 @@ namespace gui {
$main_ui.init(); $main_ui.init();
$loot_ui.init(); $loot_ui.init();
for(auto& [name, scene] : $scenes) { for(auto& name : $screens.screens.keys()) {
scene->init(); $screens.screens[name]->init();
} }
// BUG: maybe this is a function on main_ui? // BUG: maybe this is a function on main_ui?
@ -326,8 +326,8 @@ namespace gui {
void FSM::mouse_action(guecs::Modifiers mods) { void FSM::mouse_action(guecs::Modifiers mods) {
sf::Vector2f pos = mouse_position(); sf::Vector2f pos = mouse_position();
if($cur_scene != nullptr) { if($screens.is_visible()) {
$cur_scene->mouse(pos.x, pos.y, mods); $screens.mouse(pos.x, pos.y, mods);
return; return;
} }
@ -415,8 +415,8 @@ namespace gui {
} }
void FSM::draw_gui() { void FSM::draw_gui() {
if($cur_scene != nullptr) { if($screens.is_visible()) {
$cur_scene->render($window); $screens.render($window);
} else if($story != nullptr) { } else if($story != nullptr) {
$story->render($window); $story->render($window);
} else { } else {
@ -432,8 +432,8 @@ namespace gui {
} }
void FSM::update() { void FSM::update() {
if($cur_scene != nullptr) { if($screens.is_visible()) {
$cur_scene->update(); $screens.update();
} else if($story != nullptr) { } else if($story != nullptr) {
$story->update(); $story->update();
} }
@ -564,12 +564,12 @@ namespace gui {
} }
void FSM::show_scene(const std::string& name) { void FSM::show_scene(const std::string& name) {
dbc::check($scenes.contains(name), $F("$scenes does not contain {}", name)); $screens.set_active(name);
$cur_scene = $scenes[name]; $screens.set_visible(true);
} }
void FSM::close_scene() { void FSM::close_scene() {
$cur_scene = nullptr; $screens.set_visible(false);
} }
void FSM::player_died() { void FSM::player_died() {
@ -584,7 +584,7 @@ namespace gui {
if(level.index < levels_to_win) { if(level.index < levels_to_win) {
show_scene("NEXT_LEVEL"); show_scene("NEXT_LEVEL");
$cur_scene->set_text(fmt::format("ENTERING\nLEVEL\n{}", level.index+2)); $screens.current_ui()->set_text(fmt::format("ENTERING\nLEVEL\n{}", level.index+2));
state(State::NEXT_LEVEL_SCENE); state(State::NEXT_LEVEL_SCENE);
} else { } else {
show_scene("WIN"); show_scene("WIN");

View file

@ -13,6 +13,7 @@
#include "events.hpp" #include "events.hpp"
#include "gui/scene_ui.hpp" #include "gui/scene_ui.hpp"
#include "gui/storyboard.hpp" #include "gui/storyboard.hpp"
#include "gui/uistack.hpp"
namespace gui { namespace gui {
enum class State { enum class State {
@ -43,14 +44,14 @@ namespace gui {
gui::routing::Router $router; gui::routing::Router $router;
DNDLoot $dnd_loot; DNDLoot $dnd_loot;
System::Registry $systems; System::Registry $systems;
std::unordered_map<std::string, std::shared_ptr<gui::SceneUI>> $scenes{
gui::UIStack<gui::SceneUI> $screens{.screens={
{"STARTING", std::make_shared<gui::SceneUI>("STARTING")}, {"STARTING", std::make_shared<gui::SceneUI>("STARTING")},
{"DEATH", std::make_shared<gui::SceneUI>("DEATH")}, {"DEATH", std::make_shared<gui::SceneUI>("DEATH")},
{"WIN", std::make_shared<gui::SceneUI>("WIN")}, {"WIN", std::make_shared<gui::SceneUI>("WIN")},
{"NEXT_LEVEL", std::make_shared<gui::SceneUI>("NEXT_LEVEL")}, {"NEXT_LEVEL", std::make_shared<gui::SceneUI>("NEXT_LEVEL")},
}; }};
std::shared_ptr<gui::SceneUI> $cur_scene = nullptr;
std::shared_ptr<storyboard::UI> $story = nullptr; std::shared_ptr<storyboard::UI> $story = nullptr;
bool $display_help = false; bool $display_help = false;

6
src/gui/uistack.cpp Normal file
View file

@ -0,0 +1,6 @@
#include "multiscreen.hpp"
namespace gui {
using namespace std::chrono_literals;
}

90
src/gui/uistack.hpp Normal file
View file

@ -0,0 +1,90 @@
#include <guecs/ui.hpp>
#include "dbc.hpp"
#include "constants.hpp"
#include <flat_map>
namespace gui {
template<typename SCREEN_TYPE>
struct UIStack {
using UIStackMap = std::flat_map<std::string, std::shared_ptr<SCREEN_TYPE>>;
UIStackMap screens{};
bool visible = false;
UIStackMap::iterator $current{screens.begin()};
SCREEN_TYPE* $active = nullptr;
void add(const std::string& name, std::shared_ptr<SCREEN_TYPE> screen) {
screens.insert_or_assign(name, screen);
update_active(screens.begin());
}
void update_active(const UIStackMap::iterator& itr) {
$current = itr;
$active = (*$current).second.get();
}
void set_active(const std::string& name) {
dbc::check(screens.contains(name), $F("screen {} not in stack", name));
update_active(screens.find(name));
}
void set_visible(bool new_value) {
visible = new_value;
}
bool is_visible() {
return visible;
}
void render(sf::RenderTarget& target) {
dbc::check($active != nullptr, "you didn't set active");
$active->render(target);
}
void update() {
dbc::check($active != nullptr, "you didn't set active");
$active->update();
}
bool mouse(float x, float y, guecs::Modifiers mods = guecs::NO_MODS) {
dbc::check($active != nullptr, "you didn't set active");
return $active->mouse(x, y, mods);
}
bool move(const UIStackMap::iterator& itr, const UIStackMap::iterator& avoid, const UIStackMap::iterator& result) {
if(itr != avoid) {
update_active(result);
return true;
} else {
return false;
}
}
bool next() {
return move($current + 1, screens.end(), $current + 1);
}
bool prev() {
return move($current, screens.begin(), $current - 1);
}
void first() {
update_active(screens.begin());
}
void last() {
update_active(screens.end() - 1);
}
const std::string& current_name() {
dbc::check($active != nullptr, "you didn't set active");
return (*$current).first;
}
std::shared_ptr<SCREEN_TYPE> current_ui() {
dbc::check($active != nullptr, "you didn't set active");
return (*$current).second;
}
};
}