Skip to content
Snippets Groups Projects
actions.rs 2 KiB
Newer Older
Kat Marchán's avatar
Kat Marchán committed
use specs::{Component, DenseVecStorage, Entities, Entity, LazyUpdate, ReadStorage, WriteStorage};
use typetag;

use crate::ActionEnt;

#[derive(Debug, Component)]
pub struct ActionManagerWrapper(pub(crate) Box<dyn ActionManager>);

#[derive(Debug, Component, Clone, Eq, PartialEq)]
pub enum ActionState {
    Init,
    Requested,
    Executing,
    Cancelled,
    Success,
    Failure,
}

impl ActionState {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn get<'a>(state_ent: &ActionEnt, states: &'a ReadStorage<ActionState>) -> &'a Self {
        states
            .get(state_ent.0.clone())
            .expect("ActionState doesn't exist?")
    }

    pub fn get_mut<'a>(
        state_ent: &ActionEnt,
        states: &'a mut WriteStorage<ActionState>,
    ) -> &'a mut Self {
        states
            .get_mut(state_ent.0.clone())
            .expect("ActionState doesn't exist?")
    }

    pub(crate) fn build(
        builder: Box<dyn Action>,
        actor: Entity,
        ents: &Entities,
        lazy: &LazyUpdate,
    ) -> ActionEnt {
        let action_ent = ActionEnt(ents.create());
        let ent_clone = action_ent.clone();
        lazy.insert(ent_clone.0, ActionState::default());
        lazy.insert(
            ent_clone.0,
            ActionManagerWrapper(builder.build(actor, action_ent.clone(), ents, lazy)),
        );
        action_ent
    }
}

impl Default for ActionState {
    fn default() -> Self {
        Self::Init
    }
}

/**
This trait defines new actions. In general, you should use the [derive macro](derive.Action.html) instead.
*/
#[typetag::deserialize]
pub trait Action: std::fmt::Debug + Send + Sync {
    fn build(
        self: Box<Self>,
        actor: Entity,
        action_ent: ActionEnt,
        ents: &Entities,
        lazy: &LazyUpdate,
    ) -> Box<dyn ActionManager>;
}

pub trait ActionManager: std::fmt::Debug + Send + Sync {
    fn activate(&self, actor: Entity, action: ActionEnt, lazy: &LazyUpdate);
    fn deactivate(&self, action: ActionEnt, lazy: &LazyUpdate);
}