de_controller 0.0.1

Handling of user input in Digital Extinction.
Documentation
use bevy::prelude::*;
use de_core::{
    gconfig::GameConfig,
    objects::{BuildingType, ObjectType},
    stages::GameStage,
};
use de_spawner::{Draft, DraftBundle, SpawnBundle};

use super::Labels;
use crate::pointer::Pointer;

pub(crate) struct DraftPlugin;

impl Plugin for DraftPlugin {
    fn build(&self, app: &mut App) {
        app.add_event::<SpawnDraftsEvent>()
            .add_event::<NewDraftEvent>()
            .add_event::<DiscardDraftsEvent>()
            .add_system_set_to_stage(
                GameStage::Input,
                SystemSet::new()
                    .with_system(spawn.after(Labels::InputUpdate))
                    .with_system(new_drafts.after(Labels::InputUpdate))
                    .with_system(discard_drafts.after(Labels::InputUpdate))
                    .with_system(
                        move_drafts
                            .label(Labels::InputUpdate)
                            .after(Labels::PreInputUpdate),
                    ),
            );
    }
}

pub(crate) struct SpawnDraftsEvent;

pub(crate) struct NewDraftEvent {
    point: Vec3,
    building_type: BuildingType,
}

pub(crate) struct DiscardDraftsEvent;

impl NewDraftEvent {
    pub(crate) fn new(point: Vec3, building_type: BuildingType) -> Self {
        Self {
            point,
            building_type,
        }
    }

    fn point(&self) -> Vec3 {
        self.point
    }

    fn building_type(&self) -> BuildingType {
        self.building_type
    }
}

fn spawn(
    mut commands: Commands,
    game_config: Res<GameConfig>,
    mut events: EventReader<SpawnDraftsEvent>,
    drafts: Query<(Entity, &Transform, &ObjectType, &Draft)>,
) {
    if events.iter().count() == 0 {
        return;
    }

    for (entity, &transform, &object_type, draft) in drafts.iter() {
        if draft.allowed() {
            commands.entity(entity).despawn_recursive();
            commands
                .spawn_bundle(SpawnBundle::new(object_type, transform))
                .insert(game_config.player());
        }
    }
}

fn new_drafts(
    mut commands: Commands,
    mut events: EventReader<NewDraftEvent>,
    drafts: Query<Entity, With<Draft>>,
) {
    let event = match events.iter().last() {
        Some(event) => event,
        None => return,
    };

    for entity in drafts.iter() {
        commands.entity(entity).despawn_recursive();
    }

    commands.spawn_bundle(DraftBundle::new(
        event.building_type(),
        Transform {
            translation: event.point(),
            ..Default::default()
        },
    ));
}

fn discard_drafts(
    mut commands: Commands,
    mut events: EventReader<DiscardDraftsEvent>,
    drafts: Query<Entity, With<Draft>>,
) {
    if events.iter().count() == 0 {
        return;
    }
    for entity in drafts.iter() {
        commands.entity(entity).despawn_recursive();
    }
}

fn move_drafts(pointer: Res<Pointer>, mut drafts: Query<&mut Transform, With<Draft>>) {
    let point = match pointer.terrain_point() {
        Some(point) => point,
        None => return,
    };
    for mut transform in drafts.iter_mut() {
        transform.translation = point;
    }
}