The event router is working well and I can do drag-n-drop but I'll have to rethink where to use it.

master
Zed A. Shaw 2 days ago
parent 5aa54d875f
commit c509162be1
  1. 4
      Makefile
  2. 8
      events.hpp
  3. 56
      gui/event_router.cpp
  4. 4
      gui/event_router.hpp
  5. 97
      gui/fsm.cpp
  6. 3
      gui/fsm.hpp
  7. 11
      gui/status_ui.cpp
  8. 2
      gui/status_ui.hpp

@ -26,7 +26,7 @@ tracy_build:
meson compile -j 10 -C builddir meson compile -j 10 -C builddir
test: build test: build
./builddir/runtests "[event_router]" ./builddir/runtests
run: build test run: build test
ifeq '$(OS)' 'Windows_NT' ifeq '$(OS)' 'Windows_NT'
@ -49,7 +49,7 @@ clean:
meson compile --clean -C builddir meson compile --clean -C builddir
debug_test: build debug_test: build
gdb --nx -x .gdbinit --ex run --args builddir/runtests -e "[event_router]" gdb --nx -x .gdbinit --ex run --args builddir/runtests -e
win_installer: win_installer:
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp' powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'

@ -34,6 +34,12 @@ namespace gui {
LOOT_OPEN=14, LOOT_OPEN=14,
LOOT_SELECT=15, LOOT_SELECT=15,
LOOT_PLACE=16, LOOT_PLACE=16,
QUIT = 17 QUIT = 17,
MOUSE_CLICK=18,
MOUSE_MOVE=19,
MOUSE_DRAG=20,
MOUSE_DRAG_START=21,
MOUSE_DROP=22,
KEY_PRESS=23
}; };
} }

@ -1,4 +1,3 @@
#define FSM_DEBUG 1
#include "event_router.hpp" #include "event_router.hpp"
#include "dbc.hpp" #include "dbc.hpp"
#include "events.hpp" #include "events.hpp"
@ -44,6 +43,7 @@ namespace gui {
FSM_STATE(State, IDLE, ev); FSM_STATE(State, IDLE, ev);
FSM_STATE(State, MOUSE_ACTIVE, ev); FSM_STATE(State, MOUSE_ACTIVE, ev);
FSM_STATE(State, MOUSE_MOVING, ev); FSM_STATE(State, MOUSE_MOVING, ev);
FSM_STATE(State, MOUSE_DRAGGING, ev);
} }
} }
@ -54,17 +54,15 @@ namespace gui {
void Router::IDLE(Event ev) { void Router::IDLE(Event ev) {
switch(ev) { switch(ev) {
case MOUSE_DOWN: case MOUSE_DOWN:
move_count=0;
set_event(gui::Event::TICK); set_event(gui::Event::TICK);
state(State::MOUSE_ACTIVE); state(State::MOUSE_ACTIVE);
break; break;
case MOUSE_UP:
dbc::log("mouse up in IDLE");
break;
case MOUSE_MOVE: case MOUSE_MOVE:
dbc::log("mouse move, send moved event"); set_event(gui::Event::MOUSE_MOVE);
break; break;
case KEY_PRESS: case KEY_PRESS:
dbc::log("key pressed"); set_event(gui::Event::KEY_PRESS);
break; break;
default: default:
dbc::sentinel("invalid event"); dbc::sentinel("invalid event");
@ -73,18 +71,17 @@ namespace gui {
void Router::MOUSE_ACTIVE(Event ev) { void Router::MOUSE_ACTIVE(Event ev) {
switch(ev) { switch(ev) {
case MOUSE_DOWN:
dbc::log("mouse down in MOUSE_ACTIVE");
break;
case MOUSE_UP: case MOUSE_UP:
dbc::log("mouse up, send click event"); set_event(gui::Event::MOUSE_CLICK);
state(State::IDLE); state(State::IDLE);
break; break;
case MOUSE_MOVE: case MOUSE_MOVE:
move_count++;
set_event(gui::Event::MOUSE_DRAG);
state(State::MOUSE_MOVING); state(State::MOUSE_MOVING);
break; break;
case KEY_PRESS: case KEY_PRESS:
dbc::log("send the key but cancel"); set_event(gui::Event::KEY_PRESS);
state(State::IDLE); state(State::IDLE);
break; break;
default: default:
@ -94,22 +91,45 @@ namespace gui {
void Router::MOUSE_MOVING(Event ev) { void Router::MOUSE_MOVING(Event ev) {
switch(ev) { switch(ev) {
case MOUSE_DOWN: case MOUSE_UP: {
dbc::log("mouse down in MOUSE_MOVING state"); dbc::check(move_count < $drag_tolerance, "mouse up but not in dragging state");
set_event(gui::Event::MOUSE_CLICK);
state(State::IDLE);
} break;
case MOUSE_MOVE:
move_count++;
if(move_count < $drag_tolerance) {
set_event(gui::Event::MOUSE_DRAG);
} else {
set_event(gui::Event::MOUSE_DRAG_START);
state(State::MOUSE_DRAGGING);
}
break;
case KEY_PRESS:
set_event(gui::Event::KEY_PRESS);
break; break;
default:
dbc::sentinel("invalid event");
}
}
void Router::MOUSE_DRAGGING(Event ev) {
switch(ev) {
case MOUSE_UP: case MOUSE_UP:
dbc::log("mouse up, send drop event"); set_event(gui::Event::MOUSE_DROP);
state(State::IDLE); state(State::IDLE);
break; break;
case MOUSE_MOVE: case MOUSE_MOVE:
dbc::log("mouse move, send drag event"); move_count++;
set_event(gui::Event::MOUSE_DRAG);
break; break;
case KEY_PRESS: case KEY_PRESS:
dbc::log("send the key but cancel"); set_event(gui::Event::KEY_PRESS);
state(State::IDLE);
break; break;
default: default:
dbc::sentinel("invalid event"); dbc::sentinel("invalid events");
} }
} }
} }

@ -10,6 +10,7 @@ namespace gui {
IDLE, IDLE,
MOUSE_ACTIVE, MOUSE_ACTIVE,
MOUSE_MOVING, MOUSE_MOVING,
MOUSE_DRAGGING
}; };
enum class Event { enum class Event {
@ -25,6 +26,8 @@ namespace gui {
sf::Vector2i position; sf::Vector2i position;
sf::Keyboard::Scancode scancode; sf::Keyboard::Scancode scancode;
gui::Event $next_event = gui::Event::TICK; gui::Event $next_event = gui::Event::TICK;
int move_count = 0;
int $drag_tolerance = 4;
void event(Event ev); void event(Event ev);
@ -32,6 +35,7 @@ namespace gui {
void IDLE(Event ev); void IDLE(Event ev);
void MOUSE_ACTIVE(Event ev); void MOUSE_ACTIVE(Event ev);
void MOUSE_MOVING(Event ev); void MOUSE_MOVING(Event ev);
void MOUSE_DRAGGING(Event ev);
gui::Event process_event(std::optional<sf::Event> ev); gui::Event process_event(std::optional<sf::Event> ev);

@ -127,6 +127,7 @@ namespace gui {
state(State::IDLE); state(State::IDLE);
break; break;
case LOOT_SELECT: { case LOOT_SELECT: {
fmt::println("loot is selected");
int slot_id = std::any_cast<int>(data); int slot_id = std::any_cast<int>(data);
if(auto entity = $loot_ui.select_slot(slot_id)) { if(auto entity = $loot_ui.select_slot(slot_id)) {
@ -137,8 +138,26 @@ namespace gui {
case LOOT_PLACE: { case LOOT_PLACE: {
std::string slot_name = std::any_cast<std::string>(data); std::string slot_name = std::any_cast<std::string>(data);
int slot_id = $status_ui.place_slot(slot_name); int slot_id = $status_ui.place_slot(slot_name);
$loot_ui.remove_slot(slot_id); // BUG: fix this bullshit
if(slot_id != -1) {
$loot_ui.remove_slot(slot_id);
}
} break; } break;
case MOUSE_CLICK:
mouse_action(false);
break;
case MOUSE_MOVE:
mouse_action(true);
break;
case MOUSE_DRAG_START:
mouse_action(false);
break;
case MOUSE_DRAG:
mouse_action(true);
break;
case MOUSE_DROP:
mouse_action(false);
break;
case TICK: case TICK:
// do nothing // do nothing
break; break;
@ -214,6 +233,17 @@ namespace gui {
case LOOT_PLACE: case LOOT_PLACE:
// ignored // ignored
break; break;
case MOUSE_CLICK:
mouse_action(false);
break;
case MOUSE_MOVE:
mouse_action(true);
break;
case MOUSE_DRAG: // ignored
case MOUSE_DRAG_START: // ignored
case MOUSE_DROP: // ignored
break;
default: default:
dbc::sentinel("unhandled event in IDLE"); dbc::sentinel("unhandled event in IDLE");
} }
@ -227,6 +257,15 @@ namespace gui {
sound::play("ambient"); sound::play("ambient");
next_level(); next_level();
state(State::IDLE); state(State::IDLE);
break;
case MOUSE_CLICK: {
sf::Vector2f pos = mouse_position();
$boss_fight_ui->mouse(pos.x, pos.y, false);
if($boss_fight_ui->boss_dead()) {
event(Event::STAIRS_DOWN);
}
} break;
default: default:
break; // do nothing for now break; // do nothing for now
} }
@ -236,6 +275,12 @@ namespace gui {
using enum Event; using enum Event;
switch(ev) { switch(ev) {
case MOUSE_CLICK:
mouse_action(false);
break;
case MOUSE_MOVE:
mouse_action(true);
break;
case ATTACK: case ATTACK:
$main_ui.dirty(); $main_ui.dirty();
sound::play("Sword_Hit_1"); sound::play("Sword_Hit_1");
@ -280,45 +325,27 @@ namespace gui {
dbc::log(fmt::format("END: received event after done: {}", int(ev))); dbc::log(fmt::format("END: received event after done: {}", int(ev)));
} }
sf::Vector2f FSM::mouse_position() {
return $window.mapPixelToCoords($router.position);
}
void FSM::mouse_action(bool hover) {
sf::Vector2f pos = mouse_position();
if($debug_ui.active) $debug_ui.mouse(pos.x, pos.y, hover);
$combat_ui.mouse(pos.x, pos.y, hover);
$status_ui.mouse(pos.x, pos.y, hover);
$main_ui.mouse(pos.x, pos.y, hover);
if($loot_ui.active) $loot_ui.mouse(pos.x, pos.y, hover);
}
void FSM::handle_keyboard_mouse() { void FSM::handle_keyboard_mouse() {
while(const auto ev = $window.pollEvent()) { while(const auto ev = $window.pollEvent()) {
auto gui_ev = $router.process_event(ev); auto gui_ev = $router.process_event(ev);
if(gui_ev != gui::Event::TICK) { if(gui_ev == Event::KEY_PRESS) {
event(gui_ev);
continue;
}
if(const auto* mouse = ev->getIf<sf::Event::MouseButtonPressed>()) {
if(mouse->button == sf::Mouse::Button::Left) {
sf::Vector2f pos = $window.mapPixelToCoords(mouse->position);
if(in_state(State::NEXT_LEVEL)) {
$boss_fight_ui->mouse(pos.x, pos.y, false);
if($boss_fight_ui->boss_dead()) {
event(Event::STAIRS_DOWN);
}
} else {
if($debug_ui.active) $debug_ui.mouse(pos.x, pos.y, false);
$combat_ui.mouse(pos.x, pos.y, false);
$status_ui.mouse(pos.x, pos.y, false);
$main_ui.mouse(pos.x, pos.y, false);
if($loot_ui.active) $loot_ui.mouse(pos.x, pos.y, false);
}
}
} else if(const auto* mouse = ev->getIf<sf::Event::MouseMoved>()) {
sf::Vector2f pos = $window.mapPixelToCoords(mouse->position);
if($debug_ui.active) $debug_ui.mouse(pos.x, pos.y, true);
$combat_ui.mouse(pos.x, pos.y, true);
$status_ui.mouse(pos.x, pos.y, true);
$main_ui.mouse(pos.x, pos.y, true);
}
if(const auto* key = ev->getIf<sf::Event::KeyPressed>()) {
using KEY = sf::Keyboard::Scan; using KEY = sf::Keyboard::Scan;
switch(key->scancode) { switch($router.scancode) {
case KEY::W: case KEY::W:
event(Event::MOVE_FORWARD); event(Event::MOVE_FORWARD);
break; break;
@ -368,6 +395,8 @@ namespace gui {
default: default:
break; // ignored break; // ignored
} }
} else {
event(gui_ev);
} }
} }
} }

@ -46,6 +46,7 @@ namespace gui {
LootUI $loot_ui; LootUI $loot_ui;
sf::Font $font; sf::Font $font;
gui::routing::Router $router; gui::routing::Router $router;
shared_ptr<sf::Sprite> $dumb_sprite = nullptr;
FSM(); FSM();
@ -67,6 +68,8 @@ namespace gui {
void END(Event ev); void END(Event ev);
void try_move(int dir, bool strafe); void try_move(int dir, bool strafe);
sf::Vector2f mouse_position();
void mouse_action(bool hover);
void handle_keyboard_mouse(); void handle_keyboard_mouse();
void draw_gui(); void draw_gui();
void render(); void render();

@ -89,11 +89,12 @@ namespace gui {
fmt::println("LOOT slot={}, entity={} PLACE into slot={}", fmt::println("LOOT slot={}, entity={} PLACE into slot={}",
$selected_slot, $selected_entity, name); $selected_slot, $selected_entity, name);
auto& sprite = $level.world->get<components::Sprite>($selected_entity); if($level.world->has<components::Sprite>($selected_entity)) {
auto gui_id = $gui.entity(name); auto& sprite = $level.world->get<components::Sprite>($selected_entity);
$gui.set_init<guecs::Sprite>(gui_id, {sprite.name}); auto gui_id = $gui.entity(name);
$gui.set_init<guecs::Sprite>(gui_id, {sprite.name});
$slots.insert_or_assign(name, $selected_entity); $slots.insert_or_assign(name, $selected_entity);
}
return $selected_slot; return $selected_slot;
} }

@ -13,7 +13,7 @@ namespace gui {
std::unordered_map<std::string, DinkyECS::Entity> $slots; std::unordered_map<std::string, DinkyECS::Entity> $slots;
GameLevel $level; GameLevel $level;
ritual::UI $ritual_ui; ritual::UI $ritual_ui;
int $selected_slot; int $selected_slot = -1;
DinkyECS::Entity $selected_entity; DinkyECS::Entity $selected_entity;
StatusUI(GameLevel level); StatusUI(GameLevel level);

Loading…
Cancel
Save