animgraph 0.1.0

Animation data flow library using hierarchical state machines
Documentation
use serde_derive::{Deserialize, Serialize};

use crate::{
    io::{Event, EventEmit},
    GraphBoolean, GraphNodeConstructor,
};

use super::{GraphNode, GraphVisitor};

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct StateEventNode {
    pub event: Event,
    pub condition: GraphBoolean,
    pub emit: EventEmit,
}

impl GraphNodeConstructor for StateEventNode {
    fn identity() -> &'static str {
        "state_event"
    }

    fn construct_entry(
        self,
        metrics: &crate::GraphMetrics,
    ) -> anyhow::Result<crate::GraphNodeEntry> {
        metrics.validate_event(&self.event, Self::identity())?;
        metrics.validate_bool(self.condition, Self::identity())?;
        Ok(crate::GraphNodeEntry::Process(Box::new(self)))
    }
}

impl GraphNode for StateEventNode {
    fn visit(&self, visitor: &mut GraphVisitor) {
        let state = visitor.graph.get_state(visitor.context.state);
        if visitor.graph.get_bool(self.condition) {
            self.event.emit(visitor, state, self.emit);
        } else {
            self.event.emit(visitor, state, EventEmit::Never);
        }
    }
}

#[cfg(feature = "compiler")]
pub mod compile {
    use serde_derive::{Deserialize, Serialize};
    use serde_json::Value;

    use crate::{
        compiler::prelude::{
            Extras, IOSlot, IOType, Node, NodeCompilationError, NodeCompiler,
            NodeSerializationContext, NodeSettings,
        },
        io::{Event, EventEmit},
    };

    pub use super::StateEventNode;

    #[derive(Default, Debug, Clone, Serialize, Deserialize)]
    pub struct StateEventSettings {
        emit: EventEmit,
    }

    impl NodeSettings for StateEventSettings {
        fn name() -> &'static str {
            "state_event"
        }

        fn input() -> &'static [(&'static str, IOType)] {
            use IOType::*;
            &[("event", Event), ("condition", Bool)]
        }

        fn output() -> &'static [(&'static str, IOType)] {
            &[]
        }

        fn build(self) -> anyhow::Result<Extras> {
            Ok(serde_json::to_value(self)?)
        }
    }

    impl NodeCompiler for StateEventNode {
        type Settings = StateEventSettings;
        fn build<'a>(
            context: &NodeSerializationContext<'a>,
        ) -> Result<Value, NodeCompilationError> {
            let event = context.input_event(0)?;
            let condition = context.input_bool(1)?;
            let settings = context.settings::<StateEventSettings>()?;

            context.serialize_node(StateEventNode {
                event,
                condition,
                emit: settings.emit,
            })
        }
    }

    pub fn state_event(
        event: impl IOSlot<Event>,
        condition: impl IOSlot<bool>,
        emit: EventEmit,
    ) -> Node {
        let settings = StateEventSettings { emit };
        let input = vec![event.into_slot("event"), condition.into_slot("condition")];
        Node::new(input, vec![], settings).expect("Valid")
    }
}