166 lines
4.1 KiB
C++
166 lines
4.1 KiB
C++
#include "SelectionController.h"
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
#include "DebrisSelectionChangedEvent.h"
|
|
#include "EntitySelectionChangedEvent.h"
|
|
#include "EventManager.h"
|
|
#include "SelectionChangedEvent.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
template <typename T>
|
|
bool contains(const std::vector<T>& 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 <typename T>
|
|
void combine(std::vector<T>& selection, const std::vector<T>& hits, SelectionMode mode)
|
|
{
|
|
for (const T& hit : hits)
|
|
{
|
|
const typename std::vector<T>::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<BuildingId>& SelectionController::getSelectedBuildings() const
|
|
{
|
|
return m_buildings;
|
|
}
|
|
|
|
const std::vector<entt::entity>& SelectionController::getSelectedActors() const
|
|
{
|
|
return m_actors;
|
|
}
|
|
|
|
const std::vector<entt::entity>& 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<BuildingId>& 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<entt::entity>& actors,
|
|
const std::vector<entt::entity>& 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<entt::entity> actors)
|
|
{
|
|
if (actors == m_actors) { return; }
|
|
m_actors = std::move(actors);
|
|
publishActors();
|
|
}
|
|
|
|
void SelectionController::setSelectedDebris(std::vector<entt::entity> 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<SelectionChangedEvent>(m_buildings));
|
|
}
|
|
|
|
void SelectionController::publishActors() const
|
|
{
|
|
EventManager::getInstance()->sendEventImmediately(
|
|
std::make_shared<EntitySelectionChangedEvent>(m_actors));
|
|
}
|
|
|
|
void SelectionController::publishDebris() const
|
|
{
|
|
EventManager::getInstance()->sendEventImmediately(
|
|
std::make_shared<DebrisSelectionChangedEvent>(m_debris));
|
|
}
|