#include "selection_system.h" #include "../../app/utils/selection_utils.h" #include "../../render/gl/camera.h" #include "../core/component.h" #include "../core/event_manager.h" #include "../core/world.h" #include "command_service.h" #include "picking_service.h" #include "units/spawn_type.h" #include #include #include #include #include #include #include namespace Game::Systems { void SelectionSystem::update(Engine::Core::World *world, float delta_time) {} void SelectionSystem::select_unit(Engine::Core::EntityID unit_id) { auto it = std::find(m_selected_units.begin(), m_selected_units.end(), unit_id); if (it == m_selected_units.end()) { m_selected_units.push_back(unit_id); Engine::Core::EventManager::instance().publish( Engine::Core::UnitSelectedEvent(unit_id)); } } void SelectionSystem::deselect_unit(Engine::Core::EntityID unit_id) { auto it = std::find(m_selected_units.begin(), m_selected_units.end(), unit_id); if (it != m_selected_units.end()) { m_selected_units.erase(it); } } void SelectionSystem::clear_selection() { m_selected_units.clear(); } void SelectionSystem::select_units_in_area(float x1, float y1, float x2, float y2) {} auto SelectionSystem::is_unit_in_area(Engine::Core::Entity *entity, float x1, float y1, float x2, float y2) -> bool { auto *transform = entity->get_component(); if (transform == nullptr) { return false; } float const x = transform->position.x; float const z = transform->position.z; return x >= std::min(x1, x2) && x <= std::max(x1, x2) && z >= std::min(y1, y2) && z <= std::max(y1, y2); } SelectionController::SelectionController(Engine::Core::World *world, SelectionSystem *selection_system, PickingService *picking_service, QObject *parent) : QObject(parent), m_world(world), m_selection_system(selection_system), m_picking_service(picking_service) {} void SelectionController::on_click_select(qreal sx, qreal sy, bool additive, int viewport_width, int viewport_height, void *camera, int local_owner_id) { if ((m_selection_system == nullptr) || (m_picking_service == nullptr) || (camera == nullptr) || (m_world == nullptr)) { return; } auto *cam = static_cast(camera); Engine::Core::EntityID const picked = Game::Systems::PickingService::pick_single( float(sx), float(sy), *m_world, *cam, viewport_width, viewport_height, local_owner_id, true); if (picked != 0U) { if (!additive) { m_selection_system->clear_selection(); } m_selection_system->select_unit(picked); sync_selection_flags(); emit selection_changed(); return; } if (!additive && !m_selection_system->get_selected_units().empty()) { m_selection_system->clear_selection(); sync_selection_flags(); emit selection_changed(); } } void SelectionController::on_area_selected(qreal x1, qreal y1, qreal x2, qreal y2, bool additive, int viewport_width, int viewport_height, void *camera, int local_owner_id) { if ((m_selection_system == nullptr) || (m_picking_service == nullptr) || (camera == nullptr) || (m_world == nullptr)) { return; } if (!additive) { m_selection_system->clear_selection(); } auto *cam = static_cast(camera); auto picked = Game::Systems::PickingService::pick_in_rect( float(x1), float(y1), float(x2), float(y2), *m_world, *cam, viewport_width, viewport_height, local_owner_id); for (auto id : picked) { m_selection_system->select_unit(id); } sync_selection_flags(); emit selection_changed(); } void SelectionController::on_right_click_clear_selection() { if (m_selection_system == nullptr) { return; } m_selection_system->clear_selection(); sync_selection_flags(); emit selection_changed(); } void SelectionController::select_all_player_troops(int local_owner_id) { if ((m_selection_system == nullptr) || (m_world == nullptr)) { return; } m_selection_system->clear_selection(); auto entities = m_world->get_entities_with(); for (auto *e : entities) { auto *unit = e->get_component(); if ((unit == nullptr) || unit->owner_id != local_owner_id) { continue; } if (e->has_component()) { continue; } if (unit->health <= 0) { continue; } m_selection_system->select_unit(e->get_id()); } sync_selection_flags(); emit selection_changed(); } void SelectionController::select_single_unit(Engine::Core::EntityID id, int local_owner_id) { if ((m_selection_system == nullptr) || (m_world == nullptr)) { return; } auto *entity = m_world->get_entity(id); if (entity == nullptr) { return; } auto *unit = entity->get_component(); if ((unit == nullptr) || (unit->health <= 0) || (unit->owner_id != local_owner_id)) { return; } m_selection_system->clear_selection(); m_selection_system->select_unit(id); sync_selection_flags(); emit selection_changed(); } auto SelectionController::has_units_selected() const -> bool { if (m_selection_system == nullptr) { return false; } const auto &sel = m_selection_system->get_selected_units(); return !sel.empty(); } void SelectionController::get_selected_unit_ids( std::vector &out) const { out.clear(); if (m_selection_system == nullptr) { return; } const auto &ids = m_selection_system->get_selected_units(); out.assign(ids.begin(), ids.end()); } auto SelectionController::has_selected_type(const QString &type) const -> bool { if ((m_world == nullptr) || (m_selection_system == nullptr)) { return false; } const auto &sel = m_selection_system->get_selected_units(); for (auto id : sel) { if (auto *e = m_world->get_entity(id)) { if (auto *u = e->get_component()) { if (QString::fromStdString( Game::Units::spawn_typeToString(u->spawn_type)) == type) { return true; } } } } return false; } void SelectionController::sync_selection_flags() { if ((m_world == nullptr) || (m_selection_system == nullptr)) { return; } App::Utils::sanitize_selection(m_world, m_selection_system); } } // namespace Game::Systems