use shrev::{EventChannel, ReaderId}; use space_crush_common::{ components::{Orbit, Position}, continue_if_none, misc::WorldHelper, systems::FleetControlEvent, }; use specs::{prelude::*, Entities, Entity, ReadStorage, System, World}; use crate::{ misc::MouseEvent, resources::{Camera, Config, GameState, InputState, Selection}, Error, }; pub struct FleetMove { mouse_event_id: ReaderId, target_orbit: Option, } #[derive(SystemData)] pub struct FleetMoveData<'a> { game_state: WriteExpect<'a, GameState>, fleet_control: WriteExpect<'a, EventChannel>, mouse_events: ReadExpect<'a, EventChannel>, input_state: ReadExpect<'a, InputState>, camera: ReadExpect<'a, Camera>, config: ReadExpect<'a, Config>, entities: Entities<'a>, positions: ReadStorage<'a, Position>, orbits: ReadStorage<'a, Orbit>, } impl FleetMove { pub fn new(world: &mut World) -> Result { let mouse_event_id = world.register_event_reader::()?; let target_orbit = None; Ok(Self { mouse_event_id, target_orbit, }) } } impl<'a> System<'a> for FleetMove { type SystemData = FleetMoveData<'a>; fn run(&mut self, data: Self::SystemData) { let FleetMoveData { mut game_state, mut fleet_control, mouse_events, input_state, camera, config, entities, positions, orbits, } = data; let events = mouse_events.read(&mut self.mouse_event_id); for event in events { match event { MouseEvent::ButtonDown(button) if button == &config.input.fleet_move_button => { let pos = camera.view_to_world(input_state.mouse_pos); for (id, position, orbit) in (&entities, &positions, &orbits).join() { let r = orbit.max() * orbit.max(); if (position.pos() - pos).length_sqr() <= r { self.target_orbit = Some(id); break; } } } MouseEvent::ButtonUp(button) if button == &config.input.fleet_move_button => { let selection = game_state.selection_mut().take(); let selection = continue_if_none!(selection); let Selection { fleet, count } = selection; let target = continue_if_none!(self.target_orbit); let player = game_state.player_id(); let event = FleetControlEvent::move_(player, target, fleet, count); fleet_control.single_write(event); } MouseEvent::Move(_, _) => { self.target_orbit = None; } _ => (), } } } }