#include "SelectionController.h" #include #include #include "DebrisSelectionChangedEvent.h" #include "EntitySelectionChangedEvent.h" #include "EventManager.h" #include "SelectionChangedEvent.h" namespace { template bool contains(const std::vector& items, const T& item) { return std::find(items.begin(), items.end(), item) != items.end(); } // Applies `hits` to `selection` per `mode`. Replace is handled by the caller so // that an empty hit list can mean "clear this category" there but "leave this // category alone" here. template void combine(std::vector& selection, const std::vector& hits, SelectionMode mode) { for (const T& hit : hits) { const typename std::vector::iterator it = std::find(selection.begin(), selection.end(), hit); if (it == selection.end()) { selection.push_back(hit); } else if (mode == SelectionMode::Toggle) { // Only a toggle removes; an additive box drag never deselects. selection.erase(it); } } } } // namespace const std::vector& SelectionController::getSelectedBuildings() const { return m_buildings; } const std::vector& SelectionController::getSelectedActors() const { return m_actors; } const std::vector& SelectionController::getSelectedDebris() const { return m_debris; } bool SelectionController::isActorSelected(entt::entity actor) const { return contains(m_actors, actor); } bool SelectionController::isDebrisSelected(entt::entity debris) const { return contains(m_debris, debris); } void SelectionController::selectBuildings(const std::vector& ids, SelectionMode mode) { // Buildings win over field objects (REQ-UI-SELECTION-CATEGORIES). if (clearActorsQuietly()) { publishActors(); } if (clearDebrisQuietly()) { publishDebris(); } if (mode == SelectionMode::Replace) { m_buildings = ids; } else { combine(m_buildings, ids, mode); } publishBuildings(); } void SelectionController::selectFieldObjects(const std::vector& actors, const std::vector& debris, SelectionMode mode) { if (clearBuildingsQuietly()) { publishBuildings(); } if (mode == SelectionMode::Replace) { m_actors = actors; m_debris = debris; } else { combine(m_actors, actors, mode); combine(m_debris, debris, mode); } publishActors(); publishDebris(); } void SelectionController::clearAll() { if (clearBuildingsQuietly()) { publishBuildings(); } if (clearActorsQuietly()) { publishActors(); } if (clearDebrisQuietly()) { publishDebris(); } } void SelectionController::setSelectedActors(std::vector actors) { if (actors == m_actors) { return; } m_actors = std::move(actors); publishActors(); } void SelectionController::setSelectedDebris(std::vector debris) { if (debris == m_debris) { return; } m_debris = std::move(debris); publishDebris(); } bool SelectionController::clearBuildingsQuietly() { if (m_buildings.empty()) { return false; } m_buildings.clear(); return true; } bool SelectionController::clearActorsQuietly() { if (m_actors.empty()) { return false; } m_actors.clear(); return true; } bool SelectionController::clearDebrisQuietly() { if (m_debris.empty()) { return false; } m_debris.clear(); return true; } void SelectionController::publishBuildings() const { EventManager::getInstance()->sendEventImmediately( std::make_shared(m_buildings)); } void SelectionController::publishActors() const { EventManager::getInstance()->sendEventImmediately( std::make_shared(m_actors)); } void SelectionController::publishDebris() const { EventManager::getInstance()->sendEventImmediately( std::make_shared(m_debris)); }