pub mod events;
pub mod fns;
pub mod relationship;
pub mod value;
use core::{any, fmt::Debug, time::Duration};
use bevy::prelude::*;
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
use crate::prelude::*;
use fns::ActionFns;
#[derive(Component, Deref, DerefMut)]
#[require(
Name::new(any::type_name::<A>()),
ActionFns::new::<A>(),
ActionValue::zero(A::Output::DIM),
ActionSettings,
ActionState,
ActionEvents,
ActionTime,
)]
pub struct Action<A: InputAction>(A::Output);
impl<A: InputAction> Clone for Action<A> {
fn clone(&self) -> Self {
*self
}
}
impl<A: InputAction> Copy for Action<A> {}
impl<A: InputAction> Default for Action<A> {
fn default() -> Self {
Self(Default::default())
}
}
impl<A: InputAction> PartialEq for Action<A> {
fn eq(&self, other: &Self) -> bool {
**self == **other
}
}
impl<A: InputAction> Action<A> {
pub fn new() -> Self {
Self::default()
}
}
pub trait InputAction: 'static {
type Output: ActionOutput;
}
pub trait ActionOutput:
From<ActionValue> + Default + Send + Sync + Debug + Clone + Copy + PartialEq
{
const DIM: ActionValueDim;
}
impl ActionOutput for bool {
const DIM: ActionValueDim = ActionValueDim::Bool;
}
impl ActionOutput for f32 {
const DIM: ActionValueDim = ActionValueDim::Axis1D;
}
impl ActionOutput for Vec2 {
const DIM: ActionValueDim = ActionValueDim::Axis2D;
}
impl ActionOutput for Vec3 {
const DIM: ActionValueDim = ActionValueDim::Axis3D;
}
#[derive(Component, Reflect, Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
pub struct ActionSettings {
pub accumulation: Accumulation,
pub require_reset: bool,
pub consume_input: bool,
}
impl Default for ActionSettings {
fn default() -> Self {
Self {
accumulation: Default::default(),
require_reset: false,
consume_input: true,
}
}
}
#[derive(Reflect, Debug, Default, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
pub enum Accumulation {
#[default]
Cumulative,
MaxAbs,
}
#[derive(Component, Reflect, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
pub enum ActionState {
#[default]
None,
Ongoing,
Fired,
}
#[derive(Component, Reflect, Debug, Default, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
pub struct ActionTime {
pub elapsed_secs: f32,
pub fired_secs: f32,
}
impl ActionTime {
pub fn update(&mut self, delta_secs: f32, state: ActionState) {
match state {
ActionState::None => {
self.elapsed_secs = 0.0;
self.fired_secs = 0.0;
}
ActionState::Ongoing => {
self.elapsed_secs += delta_secs;
self.fired_secs = 0.0;
}
ActionState::Fired => {
self.elapsed_secs += delta_secs;
self.fired_secs += delta_secs;
}
}
}
}
#[derive(Component, Reflect, Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
pub struct ActionMock {
pub state: ActionState,
pub value: ActionValue,
pub span: MockSpan,
pub enabled: bool,
}
impl ActionMock {
#[must_use]
pub fn once(state: ActionState, value: impl Into<ActionValue>) -> Self {
Self::new(state, value, MockSpan::Updates(1))
}
#[must_use]
pub fn new(
state: ActionState,
value: impl Into<ActionValue>,
span: impl Into<MockSpan>,
) -> Self {
Self {
state,
value: value.into(),
span: span.into(),
enabled: true,
}
}
}
#[derive(Reflect, Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
pub enum MockSpan {
Updates(u32),
Duration(Duration),
Manual,
}
impl From<Duration> for MockSpan {
fn from(value: Duration) -> Self {
Self::Duration(value)
}
}