#[cfg(feature = "bevy_reflect")]
use bevy_ecs::reflect::ReflectResource;
use bevy_ecs::{
component::Component,
resource::Resource,
system::SystemParamItem,
world::{FromWorld, World},
};
use crate::{
next_state::{NextState, NextStateMut},
pattern::StatePattern,
state::State,
};
#[derive(Resource, Component, Debug)]
#[cfg_attr(
feature = "bevy_reflect",
derive(bevy_reflect::Reflect),
reflect(Resource)
)]
pub struct NextStateBuffer<S: State>(
pub Option<S>,
);
impl<S: State> NextState for NextStateBuffer<S> {
type State = S;
type Param = ();
fn empty() -> Self {
Self::disabled()
}
fn next_state<'s>(
&'s self,
_param: &'s SystemParamItem<Self::Param>,
) -> Option<&'s Self::State> {
self.get()
}
}
impl<S: State> NextStateMut for NextStateBuffer<S> {
type ParamMut = ();
fn next_state_from_mut<'s>(
&'s self,
_param: &'s SystemParamItem<Self::ParamMut>,
) -> Option<&'s Self::State> {
self.get()
}
fn next_state_mut<'s>(
&'s mut self,
_param: &'s mut SystemParamItem<Self::ParamMut>,
) -> Option<&'s mut Self::State> {
self.get_mut()
}
fn set_next_state(
&mut self,
_param: &mut SystemParamItem<Self::ParamMut>,
state: Option<Self::State>,
) {
self.set(state);
}
}
impl<S: State + FromWorld> FromWorld for NextStateBuffer<S> {
fn from_world(world: &mut World) -> Self {
Self::enabled(S::from_world(world))
}
}
impl<S: State> NextStateBuffer<S> {
pub fn disabled() -> Self {
Self(None)
}
pub fn enabled(state: S) -> Self {
Self(Some(state))
}
pub fn get(&self) -> Option<&S> {
self.0.as_ref()
}
pub fn get_mut(&mut self) -> Option<&mut S> {
self.0.as_mut()
}
pub fn set(&mut self, state: Option<S>) {
self.0 = state;
}
pub fn unwrap(&self) -> &S {
self.get().unwrap()
}
pub fn unwrap_mut(&mut self) -> &mut S {
self.get_mut().unwrap()
}
pub fn is_disabled(&self) -> bool {
self.0.is_none()
}
pub fn is_enabled(&self) -> bool {
self.0.is_some()
}
pub fn is_in<P: StatePattern<S>>(&self, pattern: &P) -> bool {
matches!(self.get(), Some(x) if pattern.matches(x))
}
pub fn disable(&mut self) {
self.0 = None;
}
pub fn enable(&mut self, state: S) -> &mut S {
self.0.get_or_insert(state)
}
pub fn toggle(&mut self, state: S) {
if self.is_enabled() {
self.disable();
} else {
self.enter(state);
}
}
pub fn enter(&mut self, value: S) -> &mut S {
self.0.insert(value)
}
}