#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, 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; case MOUSE_CLICK: mouse_action(false); break; case MOUSE_DRAG: case MOUSE_MOVE: { if($grab_source) { auto& source = $loot_ui.$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; case TICK: // do nothing break; default: state(DNDState::LOOT_GRAB); } } 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; case MOUSE_CLICK: mouse_action(false); break; case MOUSE_DRAG: case MOUSE_MOVE: { if($grab_source) { auto& source = $status_ui.$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: state(DNDState::INV_GRAB); } } void DNDLoot::END(Event ev) { using enum Event; switch(ev) { case LOOT_ITEM: $loot_ui.active = true; $grab_source = std::nullopt; state(DNDState::LOOTING); break; case LOOT_OPEN: $loot_ui.active = true; $grab_source = std::nullopt; 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); } }