#define FSM_DEBUG 1 #include "gui/guecstra.hpp" #include "gui/dnd_loot.hpp" #include "gui/uisystems.hpp" namespace gui { DNDLoot::DNDLoot(StatusUI& status_ui, LootUI& loot_ui, sf::RenderWindow &window, routing::Router& router) : $status_ui(status_ui), $loot_ui(loot_ui), $window(window), $router(router) { event(Event::STARTED); } bool DNDLoot::event(Event ev, std::any data) { switch($state) { FSM_STATE(DNDState, START, ev); FSM_STATE(DNDState, LOOTING, ev, data); FSM_STATE(DNDState, LOOT_GRAB, ev, data); FSM_STATE(DNDState, INV_GRAB, ev, data); FSM_STATE(DNDState, ITEM_PICKUP, ev, data); FSM_STATE(DNDState, END, ev); default: dbc::log(fmt::format("event received with data but state={} is not handled", int($state))); } return !in_state(DNDState::END); } void DNDLoot::START(Event ev) { dbc::check(ev == Event::STARTED, "START not given a STARTED event."); state(DNDState::END); } void DNDLoot::LOOTING(Event ev, std::any data) { using enum Event; switch(ev) { case LOOT_OPEN: $loot_ui.active = false; state(DNDState::END); break; case LOOT_SELECT: $grab_source = UISystem::loot_grab($loot_ui.$gui, data); if($grab_source) state(DNDState::LOOT_GRAB); break; case INV_SELECT: $grab_source = UISystem::loot_grab($status_ui.$gui, data); if($grab_source) state(DNDState::INV_GRAB); break; case MOUSE_DRAG_START: case MOUSE_CLICK: mouse_action(false); break; default: state(DNDState::LOOTING); } } void DNDLoot::LOOT_GRAB(Event ev, std::any data) { using enum Event; switch(ev) { case LOOT_OPEN: $loot_ui.active = false; state(DNDState::END); break; case LOOT_SELECT: $grab_source = UISystem::loot_grab($loot_ui.$gui, data); if($grab_source) state(DNDState::LOOTING); break; case INV_SELECT: if(UISystem::loot_drop($loot_ui.$gui, $status_ui.$gui, $grab_source, data)) { state(DNDState::LOOTING); } break; default: handle_mouse(ev, $loot_ui.$gui); } } void DNDLoot::INV_GRAB(Event ev, std::any data) { using enum Event; switch(ev) { case LOOT_OPEN: $loot_ui.active = false; state(DNDState::END); break; case LOOT_SELECT: if(UISystem::loot_drop($status_ui.$gui, $loot_ui.$gui, $grab_source, data)) { state(DNDState::LOOTING); } break; case INV_SELECT: $grab_source = UISystem::loot_grab($status_ui.$gui, data); state(DNDState::LOOTING); break; default: handle_mouse(ev, $status_ui.$gui); } } void DNDLoot::ITEM_PICKUP(Event ev, std::any data) { using enum Event; switch(ev) { case INV_SELECT: if(UISystem::loot_drop($loot_ui.$gui, $status_ui.$gui, $grab_source, data)) { $grab_source = std::nullopt; $grab_sprite = nullptr; state(DNDState::END); } break; case LOOT_ITEM: dbc::log("PUT IT BACK!"); break; default: handle_mouse(ev, $loot_ui.$gui); } } void DNDLoot::END(Event ev) { using enum Event; switch(ev) { case LOOT_ITEM: { // NOTE: if > 1 items, go to LOOT_OPEN instead auto gui_id = $loot_ui.$gui.entity("item_0"); $grab_source = UISystem::loot_grab($loot_ui.$gui, gui_id); if($grab_source) { auto& source = $loot_ui.$gui.get(*$grab_source); $grab_sprite = source.sprite; // call this once to properly position the sprite handle_mouse(Event::MOUSE_MOVE, $loot_ui.$gui); state(DNDState::ITEM_PICKUP); } } break; case LOOT_OPEN: $loot_ui.active = true; $grab_source = std::nullopt; $grab_sprite = nullptr; state(DNDState::LOOTING); break; default: dbc::sentinel(fmt::format("invalid event: {}", int(ev))); } } sf::Vector2f DNDLoot::mouse_position() { return $window.mapPixelToCoords($router.position); } void DNDLoot::mouse_action(bool hover) { sf::Vector2f pos = mouse_position(); $status_ui.mouse(pos.x, pos.y, hover); if($loot_ui.active) $loot_ui.mouse(pos.x, pos.y, hover); } void DNDLoot::handle_mouse(Event ev, guecs::UI& gui) { using enum Event; switch(ev) { case MOUSE_CLICK: mouse_action(false); break; case MOUSE_DRAG: case MOUSE_MOVE: { if($grab_source) { fmt::println("MOVING that thing"); auto& source = gui.get(*$grab_source); source.move($window.mapPixelToCoords($router.position)); } mouse_action(true); } break; case MOUSE_DRAG_START: mouse_action(false); break; case MOUSE_DROP: mouse_action(false); break; default: break; // ignored } } void DNDLoot::render() { if($grab_source && $grab_sprite) { $window.draw(*$grab_sprite); } } }