#include "gui/status_ui.hpp" #include "components.hpp" #include #include "rand.hpp" #include #include "gui/guecstra.hpp" #include "systems.hpp" #include "inventory.hpp" namespace gui { using namespace guecs; using std::any, std::any_cast, std::string, std::make_any; StatusUI::StatusUI(GameLevel level) : $level(level), $ritual_ui(level) { $gui.position(STATUS_UI_X, STATUS_UI_Y, STATUS_UI_WIDTH, STATUS_UI_HEIGHT); $gui.layout( "[ritual_ui]" "[earring|armor_head|amulet]" "[back|*%(200,300)character_view|_|armor_bdy]" "[hand_r|_|_ |hand_l]" "[ring_r|_|_ |ring_l]" "[pocket_r|armor_leg|pocket_l]"); } void StatusUI::init() { $gui.set($gui.MAIN, {$gui.$parser}); 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, {}); $gui.set(gui_id, {"armored_knight"}); } else { $gui.set(gui_id, {}); $gui.set(gui_id, {make_any(name)}); if(name == "ritual_ui") { $gui.set(gui_id, { [this](auto, auto){ select_ritual(); } }); $gui.set(gui_id, {"pickup"}); } else { $gui.set(gui_id, {guecs::to_wstring(name)}); $gui.set(gui_id, { guecs::make_action($level, Events::GUI::INV_SELECT, {gui_id}) }); $gui.set(gui_id, { .commit=[&, gui_id](DinkyECS::Entity world_target) -> bool { return place_slot(gui_id, world_target); } }); } } } $ritual_ui.event(ritual::Event::STARTED); $gui.init(); update(); } bool StatusUI::mouse(float x, float y, bool hover) { if($ritual_ui.is_open()) { return $ritual_ui.mouse(x, y, hover); } else { return $gui.mouse(x, y, hover); } } void StatusUI::select_ritual() { $ritual_ui.event(ritual::Event::TOGGLE); } void StatusUI::update() { auto& inventory = $level.world->get_the(); for(auto& [slot, world_entity] : inventory.by_slot) { auto gui_id = $gui.entity(slot); auto& sprite = $level.world->get(world_entity); $gui.set_init(gui_id, {sprite.name}); guecs::GrabSource grabber{ world_entity, [&, gui_id]() { return remove_slot(gui_id); }}; grabber.setSprite($gui, gui_id); $gui.set(gui_id, grabber); } } void StatusUI::render(sf::RenderWindow &window) { $gui.render(window); // $gui.debug_layout(window); $ritual_ui.render(window); } void StatusUI::update_level(GameLevel &level) { $level = level; init(); } bool StatusUI::place_slot(guecs::Entity gui_id, DinkyECS::Entity world_entity) { auto& slot_name = $slot_to_name.at(gui_id); auto& inventory = $level.world->get_the(); for(auto [ent, slot] : inventory.by_entity) { fmt::println("BY_ENTITY: ent={}, slot={}", ent, slot); } for(auto [slot, ent] : inventory.by_slot) { fmt::println("BY_SLOT: ent={}, slot={}", ent, slot); } $level.world->make_constant(world_entity); inventory.add(slot_name, world_entity); update(); return true; } bool StatusUI::drop_item(DinkyECS::Entity item_id) { bool dropped = System::drop_item($level, item_id); $level.world->not_constant(item_id); if(dropped) update(); return dropped; } // NOTE: do I need this or how does it relate to drop_item? void StatusUI::remove_slot(guecs::Entity slot_id) { // NOTE: really the System should coordinate either dropping on the // 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. auto& slot_name = $slot_to_name.at(slot_id); auto& inventory = $level.world->get_the(); inventory.remove(slot_name); $gui.remove(slot_id); $gui.remove(slot_id); } }