From 110612c33a24f6b5c8db5228616bfbd75e7f9080 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 9 May 2026 23:52:40 -0400 Subject: [PATCH] First batch of changes merged back from Under. Fixes the router, adds magic_enum to FSM, and makes it easy to reset the world. --- meson.build | 7 ++++++- src/algos/simplefsm.hpp | 6 +++--- src/boss/fight.cpp | 2 +- src/game/components.hpp | 1 + src/game/level.cpp | 9 ++++++++- src/game/level.hpp | 2 ++ src/gui/event_router.cpp | 14 +++++++++++--- src/gui/event_router.hpp | 14 ++++++++------ src/gui/fsm.cpp | 2 +- tools/animator.cpp | 2 +- tools/storyboard.cpp | 4 ++-- 11 files changed, 44 insertions(+), 19 deletions(-) diff --git a/meson.build b/meson.build index 45120d8..8ba66af 100644 --- a/meson.build +++ b/meson.build @@ -76,13 +76,18 @@ sfml_system = subproject('sfml').get_variable('sfml_system_dep') sfml_window = subproject('sfml').get_variable('sfml_window_dep') lel_guecs = subproject('lel-guecs').get_variable('lel_guecs_dep') +# have to disable tests because this dude's using catch2 from the 1890s +magic_enum_proj = subproject('magic_enum', default_options: { + 'test': false}) +magic_enum = magic_enum_proj.get_variable('magic_enum_dep') + inc_dirs = include_directories('src') subdir('src') subdir('tests') dependencies += [ - fmt, json, freetype2, + fmt, json, freetype2, magic_enum, flac, ogg, vorbis, vorbisfile, vorbisenc, sfml_audio, sfml_graphics, sfml_network, sfml_system, diff --git a/src/algos/simplefsm.hpp b/src/algos/simplefsm.hpp index 4eb5718..157de57 100644 --- a/src/algos/simplefsm.hpp +++ b/src/algos/simplefsm.hpp @@ -1,12 +1,12 @@ #pragma once - #include #ifndef FSM_DEBUG #define FSM_STATE(C, S, E, ...) case C::S: S(E, ##__VA_ARGS__); break #else +#include static int last_event=-1; -#define FSM_STATE(C, S, E, ...) case C::S: if(last_event != int(E)) { last_event = int(E); fmt::println(">> " #C " " #S " event={}, state={}", int(E), int($state));}; S(E, ##__VA_ARGS__); break +#define FSM_STATE(C, S, E, ...) case C::S: if(last_event != int(E)) { last_event = int(E); fmt::println(">> [{}:EVENT] " #S " event={}", FSM_DEBUG, magic_enum::enum_name(E));}; S(E, ##__VA_ARGS__); break #endif template @@ -21,7 +21,7 @@ public: void state(S next_state) { #ifdef FSM_DEBUG - fmt::println("<< STATE: {} -> {}", int($state), int(next_state)); + fmt::println(">> [{}:TRANS]: {} -> {}", FSM_DEBUG, magic_enum::enum_name($state), magic_enum::enum_name(next_state)); #endif $state = next_state; } diff --git a/src/boss/fight.cpp b/src/boss/fight.cpp index fce2f78..ba15be9 100644 --- a/src/boss/fight.cpp +++ b/src/boss/fight.cpp @@ -235,7 +235,7 @@ namespace boss { dbc::check($window != nullptr, "you didn't set_window"); while(const auto ev = $window->pollEvent()) { - auto gui_ev = $router.process_event(ev); + auto [gui_ev, mods] = $router.process_event(ev); if(gui_ev == game::Event::KEY_PRESS) { using KEY = sf::Keyboard::Scan; diff --git a/src/game/components.hpp b/src/game/components.hpp index ca64914..3d62c8b 100644 --- a/src/game/components.hpp +++ b/src/game/components.hpp @@ -73,6 +73,7 @@ namespace components { settings::Config bosses; settings::Config rituals; settings::Config stories; + settings::Config scenes; }; struct Personality { diff --git a/src/game/level.cpp b/src/game/level.cpp index 67c3a4f..8c0a9b5 100644 --- a/src/game/level.cpp +++ b/src/game/level.cpp @@ -94,6 +94,12 @@ namespace GameDB { } } + void reset() { + LDB = make_shared(); + initialized = true; + new_level(NULL); + } + shared_ptr current_world() { dbc::check(initialized, "Forgot to call GameDB::init()"); return current_level().world; @@ -132,7 +138,8 @@ namespace GameDB { settings::get("devices"), settings::get("bosses"), settings::get("rituals"), - settings::get("stories") + settings::get("stories"), + settings::get("scenes") }); } } diff --git a/src/game/level.hpp b/src/game/level.hpp index f41ec98..bbdc694 100644 --- a/src/game/level.hpp +++ b/src/game/level.hpp @@ -24,7 +24,9 @@ namespace GameDB { Level& create_level(); void init(); + void reset(); Level ¤t_level(); + void new_level(std::shared_ptr prev_world); std::shared_ptr current_world(); components::Position& player_position(); DinkyECS::Entity the_player(); diff --git a/src/gui/event_router.cpp b/src/gui/event_router.cpp index 9ea1b9f..469731d 100644 --- a/src/gui/event_router.cpp +++ b/src/gui/event_router.cpp @@ -1,3 +1,4 @@ +#define FSM_DEBUG "router" #include "event_router.hpp" #include "dbc.hpp" #include "events.hpp" @@ -7,17 +8,22 @@ namespace gui { using enum Event; using enum State; - game::Event Router::process_event(std::optional ev) { + std::pair Router::process_event(std::optional ev) { $next_event = game::Event::TICK; if(ev->is()) { - return game::Event::QUIT; + return {game::Event::QUIT, guecs::NO_MODS}; } if(const auto* mouse = ev->getIf()) { if(mouse->button == sf::Mouse::Button::Left || mouse->button == sf::Mouse::Button::Right) { left_button = mouse->button == sf::Mouse::Button::Left; position = mouse->position; + if(left_button) { + mouse_mods = {1 << guecs::ModBit::left}; + } else { + mouse_mods = {1 << guecs::ModBit::right}; + } event(MOUSE_DOWN); } } else if(const auto* mouse = ev->getIf()) { @@ -25,10 +31,12 @@ namespace gui { if(mouse->button == sf::Mouse::Button::Left || mouse->button == sf::Mouse::Button::Right) { left_button = mouse->button == sf::Mouse::Button::Left; position = mouse->position; + mouse_mods = guecs::NO_MODS; event(MOUSE_UP); } } else if(const auto* mouse = ev->getIf()) { position = mouse->position; + mouse_mods = {1 << guecs::ModBit::hover}; event(MOUSE_MOVE); } @@ -37,7 +45,7 @@ namespace gui { event(KEY_PRESS); } - return $next_event; + return {$next_event, mouse_mods}; } void Router::event(Event ev) { diff --git a/src/gui/event_router.hpp b/src/gui/event_router.hpp index 2985889..5445ac4 100644 --- a/src/gui/event_router.hpp +++ b/src/gui/event_router.hpp @@ -3,15 +3,16 @@ #include "events.hpp" #include "algos/simplefsm.hpp" #include +#include namespace gui { namespace routing { enum class State { - START, - IDLE, - MOUSE_ACTIVE, - MOUSE_MOVING, - MOUSE_DRAGGING + START=__LINE__, + IDLE=__LINE__, + MOUSE_ACTIVE=__LINE__, + MOUSE_MOVING=__LINE__, + MOUSE_DRAGGING=__LINE__ }; enum class Event { @@ -25,6 +26,7 @@ namespace gui { class Router : public DeadSimpleFSM { public: sf::Vector2i position; + guecs::Modifiers mouse_mods = guecs::NO_MODS; sf::Keyboard::Scancode scancode; game::Event $next_event = game::Event::TICK; int move_count = 0; @@ -39,7 +41,7 @@ namespace gui { void MOUSE_MOVING(Event ev); void MOUSE_DRAGGING(Event ev); - game::Event process_event(std::optional ev); + std::pair process_event(std::optional ev); void set_event(game::Event ev) { $next_event = ev; diff --git a/src/gui/fsm.cpp b/src/gui/fsm.cpp index 1d07f1e..9f44431 100644 --- a/src/gui/fsm.cpp +++ b/src/gui/fsm.cpp @@ -305,7 +305,7 @@ namespace gui { void FSM::handle_keyboard_mouse() { while(const auto ev = $window.pollEvent()) { - auto gui_ev = $router.process_event(ev); + auto [gui_ev, mods] = $router.process_event(ev); if(gui_ev == Event::KEY_PRESS) { using KEY = sf::Keyboard::Scan; diff --git a/tools/animator.cpp b/tools/animator.cpp index 4f47b73..e69ec74 100644 --- a/tools/animator.cpp +++ b/tools/animator.cpp @@ -174,7 +174,7 @@ namespace animator { while(const auto ev = $window.pollEvent()) { using enum game::Event; using KEY = sf::Keyboard::Scan; - auto gui_ev = $router.process_event(ev); + auto [gui_ev, mods] = $router.process_event(ev); auto mouse_pos = $window.mapPixelToCoords($router.position); switch(gui_ev) { diff --git a/tools/storyboard.cpp b/tools/storyboard.cpp index 8964ab6..b28b537 100644 --- a/tools/storyboard.cpp +++ b/tools/storyboard.cpp @@ -31,13 +31,13 @@ int main(int, char*[]) { main.render(window); while(const auto ev = window.pollEvent()) { - auto gui_ev = router.process_event(ev); + auto [gui_ev, mods] = router.process_event(ev); auto mouse_pos = window.mapPixelToCoords(router.position); if(gui_ev == game::Event::QUIT) { return 0; } else if(gui_ev == game::Event::MOUSE_CLICK) { - main.mouse(mouse_pos.x, mouse_pos.y, guecs::NO_MODS); + main.mouse(mouse_pos.x, mouse_pos.y, mods); } }