diff --git a/gui/event_router.cpp b/gui/event_router.cpp index 62e4b99..cb6321d 100644 --- a/gui/event_router.cpp +++ b/gui/event_router.cpp @@ -65,7 +65,7 @@ namespace gui { set_event(gui::Event::KEY_PRESS); break; default: - dbc::sentinel("invalid event"); + dbc::sentinel(fmt::format("invalid event: {}", int(ev))); } } diff --git a/gui/fsm.cpp b/gui/fsm.cpp index c1a5f1b..6f41720 100644 --- a/gui/fsm.cpp +++ b/gui/fsm.cpp @@ -27,6 +27,7 @@ namespace gui { $loot_ui($level), $font{FONT_FILE_NAME} { + $window.setPosition({0,0}); } void FSM::event(Event ev) { @@ -132,31 +133,42 @@ namespace gui { state(State::IDLE); break; case LOOT_SELECT: { - int slot_id = std::any_cast(data); + $grab_source = std::any_cast(data); - if(auto world_entity = $loot_ui.select_slot(slot_id)) { - $grab_source = $loot_ui.$gui.entity("item_", slot_id); + if(auto world_entity = $loot_ui.select_slot(*$grab_source)) { auto& source = $loot_ui.get_grabber(*$grab_source); - source.grab($window); source.move($router.position); - $status_ui.select_slot(slot_id, *world_entity); + $status_ui.select_slot(*world_entity); + } else { + // BUG: need a cancel operation here + $window.setMouseCursorVisible(true); + $grab_source = std::nullopt; } } break; case INV_SELECT: { - std::string slot_name = std::any_cast(data); - int slot_id = $status_ui.place_slot(slot_name); - dbc::check(slot_id != -1, "status_ui is trying to place -1 slot_id"); - if(slot_id != -1) { - $loot_ui.remove_slot(slot_id); + auto gui_id = std::any_cast(data); + dbc::log(fmt::format("INV_SELECT $grab_source null? {} gui_id {}", + $grab_source == std::nullopt, gui_id)); + + if($grab_source) { + auto& drop = $status_ui.$gui.get(gui_id); + + if(drop.action()) { + $loot_ui.remove_slot(*$grab_source); + $grab_source = std::nullopt; + } + + $window.setMouseCursorVisible(true); + dbc::log("INV_SELECT back to looting"); + state(State::LOOTING); } - $window.setMouseCursorVisible(true); - state(State::LOOTING); } break; case MOUSE_CLICK: mouse_action(false); break; + case MOUSE_DRAG: case MOUSE_MOVE: { if($grab_source) { auto& source = $loot_ui.get_grabber(*$grab_source); @@ -164,16 +176,9 @@ namespace gui { } mouse_action(true); } break; - case MOUSE_DRAG_START: { - mouse_action(false); - } break; - case MOUSE_DRAG: { - if($grab_source) { - auto& source = $loot_ui.get_grabber(*$grab_source); - source.move($router.position); - } - mouse_action(true); - } break; + case MOUSE_DRAG_START: + dbc::check(false, "DRAG START IN LOOT GRAB"); + break; case MOUSE_DROP: mouse_action(false); break; @@ -186,6 +191,10 @@ namespace gui { } void FSM::INV_GRAB(Event ev, std::any data) { + dbc::log("INV_SELECT NOT IMPlEMENTED"); + state(State::LOOTING); + return; + using enum Event; (void)data; @@ -297,9 +306,12 @@ namespace gui { auto& data = items["TORCH_BAD"]; for(int i = 0; $loot_ui.contents.size() < 10; i++) { - auto torch = $level.world->entity(); - components::configure_entity(*$level.world, torch, data["components"]); - $loot_ui.contents.push_back(torch); + auto gui_id = $loot_ui.$gui.entity("item_", i); + if(!$loot_ui.contents.contains(gui_id)) { + auto torch = $level.world->entity(); + components::configure_entity(*$level.world, torch, data["components"]); + $loot_ui.contents.try_emplace(gui_id, torch); + } } $loot_ui.update(); diff --git a/gui/guecstra.cpp b/gui/guecstra.cpp index cbb1bf3..553c83d 100644 --- a/gui/guecstra.cpp +++ b/gui/guecstra.cpp @@ -19,4 +19,18 @@ namespace guecs { target.send(event, ent, data); }}; } + + + void GrabSource::grab(sf::RenderWindow& window) { + window.setMouseCursorVisible(false); + sprite->setOrigin({128, 128}); + } + + void GrabSource::move(sf::Vector2i position) { + sprite->setPosition({ + float(position.x), + float(position.y) + }); + } + } diff --git a/gui/guecstra.hpp b/gui/guecstra.hpp index 4ad2d0c..88be0c4 100644 --- a/gui/guecstra.hpp +++ b/gui/guecstra.hpp @@ -9,20 +9,11 @@ namespace guecs { Clickable make_action(DinkyECS::World& target, Events::GUI event, std::any data); struct GrabSource : public Sprite { - void grab(sf::RenderWindow& window) { - window.setMouseCursorVisible(false); - sprite->setOrigin({128, 128}); - } - - void move(sf::Vector2i position) { - sprite->setPosition({ - float(position.x), - float(position.y) - }); - } + void grab(sf::RenderWindow& window); + void move(sf::Vector2i position); }; struct DropTarget { - + std::function action; }; } diff --git a/gui/loot_ui.cpp b/gui/loot_ui.cpp index 1a5d51d..fcb0a25 100644 --- a/gui/loot_ui.cpp +++ b/gui/loot_ui.cpp @@ -38,7 +38,7 @@ namespace gui { THEME.TRANSPARENT, THEME.LIGHT_MID }); $gui.set(id, {0.4f, "ui_shader"}); $gui.set(id, { - guecs::make_action(*$level.world, Events::GUI::LOOT_SELECT, {i}) + guecs::make_action(*$level.world, Events::GUI::LOOT_SELECT, {id}) }); } @@ -46,20 +46,16 @@ namespace gui { update(); } - std::optional LootUI::select_slot(int slot_id) { - if(slot_id >= 0 && size_t(slot_id) < contents.size()) { + std::optional LootUI::select_slot(DinkyECS::Entity slot_id) { + if(contents.contains(slot_id)) { return contents.at(slot_id); } else { return std::nullopt; } } - void LootUI::remove_slot(int slot_id) { - dbc::check(size_t(slot_id) < contents.size(), - fmt::format("invalid slot id {} give, contents.size={}", - slot_id, contents.size())); - - contents.erase(contents.begin() + slot_id); + void LootUI::remove_slot(DinkyECS::Entity slot_id) { + contents.erase(slot_id); update(); } @@ -73,8 +69,10 @@ namespace gui { $gui.remove(id); } - if(i < contents.size()) { - auto item = contents.at(i); + if(contents.contains(id)) { + auto item = contents.at(id); + dbc::check($level.world->has(item), + "item in inventory UI doesn't exist in world. New level?"); auto& sprite = $level.world->get(item); guecs::GrabSource grabber{sprite.name}; $gui.set_init(id, grabber); @@ -82,8 +80,14 @@ namespace gui { } } - guecs::GrabSource& LootUI::get_grabber(DinkyECS::Entity entity) { - return static_cast($gui.get(entity)); + bool LootUI::has_grabber(DinkyECS::Entity gui_id) { + return $gui.has(gui_id); + } + + guecs::GrabSource& LootUI::get_grabber(DinkyECS::Entity gui_id) { + dbc::check(has_grabber(gui_id), "invalid GrabSource requested, entity isn't in the GUI."); + + return static_cast($gui.get(gui_id)); } void LootUI::render(sf::RenderWindow& window) { @@ -92,6 +96,7 @@ namespace gui { void LootUI::update_level(GameLevel &level) { $level = level; + contents.clear(); init(); } diff --git a/gui/loot_ui.hpp b/gui/loot_ui.hpp index 9367f34..9b3cc95 100644 --- a/gui/loot_ui.hpp +++ b/gui/loot_ui.hpp @@ -12,7 +12,7 @@ namespace gui { bool active = false; guecs::UI $gui; GameLevel $level; - std::vector contents; + std::unordered_map contents; LootUI(GameLevel level); @@ -21,8 +21,9 @@ namespace gui { void render(sf::RenderWindow& window); void update_level(GameLevel &level); bool mouse(float x, float y, bool hover); - std::optional select_slot(int slot); - void remove_slot(int slot_id); + std::optional select_slot(DinkyECS::Entity slot); + void remove_slot(DinkyECS::Entity slot_id); guecs::GrabSource& get_grabber(DinkyECS::Entity entity); + bool has_grabber(DinkyECS::Entity gui_id); }; } diff --git a/gui/status_ui.cpp b/gui/status_ui.cpp index cd36a8d..f681a0a 100644 --- a/gui/status_ui.cpp +++ b/gui/status_ui.cpp @@ -43,7 +43,10 @@ namespace gui { } else { $gui.set(button, {guecs::to_wstring(name)}); $gui.set(button, { - guecs::make_action(*$level.world, Events::GUI::INV_SELECT, {name}) + guecs::make_action(*$level.world, Events::GUI::INV_SELECT, {button}) + }); + $gui.set(button, { + [&, button]() -> bool { return place_slot(button); } }); } } @@ -80,22 +83,20 @@ namespace gui { init(); } - void StatusUI::select_slot(int slot_id, DinkyECS::Entity entity) { - $selected_slot = slot_id; + void StatusUI::select_slot(DinkyECS::Entity entity) { $selected_entity = entity; } - int StatusUI::place_slot(const std::string &name) { - fmt::println("LOOT slot={}, entity={} PLACE into slot={}", - $selected_slot, $selected_entity, name); - + bool StatusUI::place_slot(DinkyECS::Entity gui_id) { if($level.world->has($selected_entity)) { auto& sprite = $level.world->get($selected_entity); - auto gui_id = $gui.entity(name); + $gui.set_init(gui_id, {sprite.name}); - $slots.insert_or_assign(name, $selected_entity); - } - return $selected_slot; + $slots.insert_or_assign(gui_id, $selected_entity); + return true; + } else { + return false; + } } } diff --git a/gui/status_ui.hpp b/gui/status_ui.hpp index 3be241f..cacc294 100644 --- a/gui/status_ui.hpp +++ b/gui/status_ui.hpp @@ -10,10 +10,9 @@ namespace gui { class StatusUI { public: guecs::UI $gui; - std::unordered_map $slots; + std::unordered_map $slots; GameLevel $level; ritual::UI $ritual_ui; - int $selected_slot = -1; DinkyECS::Entity $selected_entity; StatusUI(GameLevel level); @@ -23,7 +22,7 @@ namespace gui { void init(); void render(sf::RenderWindow &window); void update(); - void select_slot(int slot_id, DinkyECS::Entity entity); - int place_slot(const std::string &name); + void select_slot(DinkyECS::Entity entity); + bool place_slot(DinkyECS::Entity gui_id); }; }