diff --git a/gui/dnd_loot.cpp b/gui/dnd_loot.cpp index e3ca5a2..4cbb2dc 100644 --- a/gui/dnd_loot.cpp +++ b/gui/dnd_loot.cpp @@ -61,11 +61,13 @@ namespace gui { case LOOT_OPEN: END(CLOSE); break; - case LOOT_SELECT: - if(commit_move($loot_ui.$gui, $grab_source, data)) { - state(DNDState::LOOTING); - } - break; + case LOOT_SELECT: { + auto drop_id = std::any_cast(data); + + if(move_or_swap($loot_ui, drop_id)) { + state(DNDState::LOOTING); + } + } break; case INV_SELECT: if(commit_drop($loot_ui.$gui, $status_ui.$gui, $grab_source, data)) @@ -92,11 +94,12 @@ namespace gui { state(DNDState::LOOTING); } break; - case INV_SELECT: - if(commit_move($status_ui.$gui, $grab_source, data)) { - state(DNDState::LOOTING); - } - break; + case INV_SELECT: { + auto drop_id = std::any_cast(data); + if(move_or_swap($status_ui, drop_id)) { + state(DNDState::LOOTING); + } + } break; default: handle_mouse(ev, $status_ui.$gui); } @@ -114,15 +117,10 @@ namespace gui { } break; case INV_SELECT: { auto drop_id = std::any_cast(data); - - if($status_ui.occupied(drop_id)) { - $status_ui.swap(*$grab_source, drop_id); - END(CLOSE); - } else if(commit_move($status_ui.$gui, $grab_source, data)) { + if(move_or_swap($status_ui, drop_id)) { END(CLOSE); } - } break; - break; + } break; default: handle_mouse(ev, $status_ui.$gui); } @@ -252,13 +250,12 @@ namespace gui { } } - bool DNDLoot::commit_move(guecs::UI& gui, std::optional source_id, std::any data) { + bool DNDLoot::commit_move(guecs::UI& gui, std::optional source_id, guecs::Entity drop_id) { dbc::check(source_id != std::nullopt, "source_id must exist"); auto& grab = gui.get(*source_id); grab.commit(); - auto drop_id = std::any_cast(data); auto& drop = gui.get(drop_id); if(drop.commit(grab.world_entity)) { @@ -307,4 +304,30 @@ namespace gui { clear_grab(); return result; } + + /* + * If I refactored everything to use a levelmanager module then + * this and many other things could go away. Access to $level is + * making this too complicated. Do this for now, but fix bug #59. + */ + bool DNDLoot::move_or_swap(StatusUI& ui, guecs::Entity drop_id) { + if(ui.occupied(drop_id)) { + ui.swap(*$grab_source, drop_id); + clear_grab(); + return true; + } else { + return commit_move(ui.$gui, $grab_source, drop_id); + } + } + + bool DNDLoot::move_or_swap(LootUI& ui, guecs::Entity drop_id) { + if(ui.occupied(drop_id)) { + ui.swap(*$grab_source, drop_id); + clear_grab(); + return true; + } else { + return commit_move(ui.$gui, $grab_source, drop_id); + } + } + } diff --git a/gui/dnd_loot.hpp b/gui/dnd_loot.hpp index f18b114..9978e1d 100644 --- a/gui/dnd_loot.hpp +++ b/gui/dnd_loot.hpp @@ -50,13 +50,16 @@ namespace gui { std::optional source_id, std::any data); bool commit_move(guecs::UI& gui, - std::optional source_id, std::any data); + std::optional source_id, guecs::Entity drop_id); bool hold_item(guecs::UI& gui, guecs::Entity gui_id); bool throw_on_floor(guecs::UI& gui, bool from_status); void clear_grab(); + bool move_or_swap(StatusUI& status_ui, guecs::Entity drop_id); + bool move_or_swap(LootUI& ui, guecs::Entity drop_id); + sf::Vector2f mouse_position(); }; } diff --git a/gui/loot_ui.cpp b/gui/loot_ui.cpp index 664ea6e..9a751d1 100644 --- a/gui/loot_ui.cpp +++ b/gui/loot_ui.cpp @@ -47,7 +47,6 @@ namespace gui { for(int i = 0; i < INV_SLOTS; i++) { auto name = fmt::format("item_{}", i); auto id = $gui.entity(name); - $slot_to_name.insert_or_assign(id, name); $gui.set(id, {THEME.PADDING, THEME.TRANSPARENT, THEME.LIGHT_MID }); @@ -69,7 +68,7 @@ namespace gui { for(size_t i = 0; i < INV_SLOTS; i++) { auto id = $gui.entity("item_", int(i)); - auto& slot_name = $slot_to_name.at(id); + auto& slot_name = $gui.name_for(id); if(contents.has(slot_name)) { auto item = contents.get(slot_name); @@ -97,7 +96,7 @@ namespace gui { } void LootUI::remove_slot(guecs::Entity slot_id) { - auto& name = $slot_to_name.at(slot_id); + auto& name = $gui.name_for(slot_id); fmt::println("LootUI remove slot inv::Model id={} slot={}", $target, name); System::remove_from_container(*$level.world, $target, name); update(); @@ -106,7 +105,8 @@ namespace gui { bool LootUI::place_slot(guecs::Entity id, DinkyECS::Entity world_entity) { fmt::println("LootUI target={} placing world entity {} in slot id {}", $target, id, world_entity); - auto& name = $slot_to_name.at(id); + auto& name = $gui.name_for(id); + bool worked = System::place_in_container(*$level.world, $target, name, world_entity); if(worked) update(); return worked; @@ -136,4 +136,18 @@ namespace gui { bool LootUI::mouse(float x, float y, bool hover) { return $gui.mouse(x, y, hover); } + + bool LootUI::occupied(guecs::Entity slot) { + return System::inventory_occupied($level, $target, $gui.name_for(slot)); + } + + void LootUI::swap(guecs::Entity gui_a, guecs::Entity gui_b) { + if(gui_a != gui_b) { + auto& a_name = $gui.name_for(gui_a); + auto& b_name = $gui.name_for(gui_b); + System::inventory_swap($level, $target, a_name, b_name); + } + + update(); + } } diff --git a/gui/loot_ui.hpp b/gui/loot_ui.hpp index 4727ff3..d1d87ba 100644 --- a/gui/loot_ui.hpp +++ b/gui/loot_ui.hpp @@ -13,7 +13,6 @@ namespace gui { bool active = false; guecs::UI $gui; GameLevel $level; - std::unordered_map $slot_to_name; DinkyECS::Entity $temp_loot; DinkyECS::Entity $target; @@ -34,5 +33,7 @@ namespace gui { bool place_slot(guecs::Entity gui_id, DinkyECS::Entity world_entity); void add_loose_item(DinkyECS::Entity entity); bool drop_item(DinkyECS::Entity item_id); + bool occupied(guecs::Entity gui_id); + void swap(guecs::Entity gui_a, guecs::Entity gui_b); }; } diff --git a/gui/status_ui.cpp b/gui/status_ui.cpp index 31b9939..f10b210 100644 --- a/gui/status_ui.cpp +++ b/gui/status_ui.cpp @@ -29,7 +29,6 @@ namespace gui { for(auto& [name, cell] : $gui.cells()) { auto gui_id = $gui.entity(name); - $slot_to_name.insert_or_assign(gui_id, name); if(name == "character_view") { $gui.set(gui_id, {}); @@ -102,7 +101,7 @@ namespace gui { } bool StatusUI::place_slot(guecs::Entity gui_id, DinkyECS::Entity world_entity) { - auto& slot_name = $slot_to_name.at(gui_id); + auto& slot_name = $gui.name_for(gui_id); auto player = $level.world->get_the(); auto& inventory = $level.world->get(player.entity); @@ -128,8 +127,7 @@ namespace gui { // ground or moving from one container or another, so when loot_ui // moves to use an ECS id to a container I can have the System // do it. - dbc::log(fmt::format("removing slot: {}", slot_id)); - auto& slot_name = $slot_to_name.at(slot_id); + auto& slot_name = $gui.name_for(slot_id); auto player = $level.world->get_the(); auto& inventory = $level.world->get(player.entity); @@ -143,25 +141,17 @@ namespace gui { void StatusUI::swap(guecs::Entity gui_a, guecs::Entity gui_b) { if(gui_a != gui_b) { + auto& a_name = $gui.name_for(gui_a); + auto& b_name = $gui.name_for(gui_b); auto player = $level.world->get_the(); - auto& inventory = $level.world->get(player.entity); - - auto& a_name = $slot_to_name.at(gui_a); - auto& b_name = $slot_to_name.at(gui_b); - auto a_ent = inventory.get(a_name); - auto b_ent = inventory.get(b_name); - inventory.swap(a_ent, b_ent); + System::inventory_swap($level, player.entity, a_name, b_name); } update(); } bool StatusUI::occupied(guecs::Entity slot) { - dbc::check($slot_to_name.contains(slot), "jank ass slot to name thing isn't loaded right you idiot."); - auto player = $level.world->get_the(); - auto& inventory = $level.world->get(player.entity); - auto& slot_name = $slot_to_name.at(slot); - return inventory.has(slot_name); + return System::inventory_occupied($level, player.entity, $gui.name_for(slot)); } } diff --git a/gui/status_ui.hpp b/gui/status_ui.hpp index 22e7df6..387be3b 100644 --- a/gui/status_ui.hpp +++ b/gui/status_ui.hpp @@ -12,7 +12,6 @@ namespace gui { public: guecs::UI $gui; GameLevel $level; - std::unordered_map $slot_to_name; ritual::UI $ritual_ui; explicit StatusUI(GameLevel level); diff --git a/systems.cpp b/systems.cpp index 48a0be6..c147ab9 100644 --- a/systems.cpp +++ b/systems.cpp @@ -562,3 +562,18 @@ Position& System::player_position(GameLevel& level) { auto& player = level.world->get_the(); return level.world->get(player.entity); } + +void System::inventory_swap(GameLevel &level, Entity container_id, const std::string& a_name, const std::string &b_name) { + dbc::check(a_name != b_name, "Attempt to inventory swap the same slot, you should check this and avoid calling me."); + + auto& inventory = level.world->get(container_id); + + auto a_ent = inventory.get(a_name); + auto b_ent = inventory.get(b_name); + inventory.swap(a_ent, b_ent); +} + +bool System::inventory_occupied(GameLevel& level, Entity container_id, const std::string& name) { + auto& inventory = level.world->get(container_id); + return inventory.has(name); +} diff --git a/systems.hpp b/systems.hpp index a70f78f..847cb35 100644 --- a/systems.hpp +++ b/systems.hpp @@ -37,4 +37,6 @@ namespace System { void remove_from_container(World& world, Entity cont_id, const std::string& name); void remove_from_world(GameLevel &level, Entity entity); Position& player_position(GameLevel& level); + void inventory_swap(GameLevel &level, Entity container_id, const std::string& a_name, const std::string &b_name); + bool inventory_occupied(GameLevel& level, Entity container_id, const std::string& name); } diff --git a/wraps/lel-guecs.wrap b/wraps/lel-guecs.wrap index e5b58d3..1a72774 100644 --- a/wraps/lel-guecs.wrap +++ b/wraps/lel-guecs.wrap @@ -1,5 +1,5 @@ [wrap-git] -directory=lel-guecs-0.2.0 +directory=lel-guecs-0.3.0 url=https://git.learnjsthehardway.com/learn-code-the-hard-way/lel-guecs.git revision=HEAD depth=1