use bevy::prelude::*;
use crate::combinator::TargetState;
use crate::interpolate::{CurrentValue, Interpolator, PreviousValue};
use bevy_time_runner::{TimeContext, TimeSpanProgress};
mod systems;
#[cfg(feature = "bevy_asset")]
pub use systems::{
apply_asset_tween_system, asset_dyn_tween_system, asset_tween_system,
};
pub use systems::{
apply_component_tween_system, component_dyn_tween_system,
component_dyn_tween_system_with_time_context, component_tween_system,
component_tween_system_with_time_context,
};
pub use systems::{
apply_resource_tween_system, resource_dyn_tween_system,
resource_tween_system, resource_tween_system_with_time_context,
};
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Component, Reflect)]
#[reflect(Component)]
pub struct SkipTween;
#[derive(Debug, Component, Clone, Copy, PartialEq, Reflect)]
#[reflect(Component)] pub struct TweenInterpolationValue(pub f32);
#[derive(
Debug, Default, Component, Clone, Copy, PartialEq, Eq, Hash, Reflect,
)]
#[require(TweenPreviousValue)]
#[reflect(Component)]
pub struct Tween<T, I> {
#[allow(missing_docs)]
pub target: T,
#[allow(missing_docs)]
pub interpolator: I,
}
#[derive(Debug, Default, Component, Clone, Copy, Reflect)]
#[reflect(Component)]
pub struct TweenPreviousValue(pub f32);
impl<T, I> Tween<T, I>
where
I: Interpolator,
{
pub fn new_target<G>(target: G, interpolator: I) -> Self
where
G: Into<T>,
{
Tween {
interpolator,
target: target.into(),
}
}
}
impl<T, I> Tween<T, I>
where
T: Default,
I: Interpolator,
{
pub fn new(interpolator: I) -> Self {
Tween::new_target(T::default(), interpolator)
}
}
impl<T, Item> Tween<T, Box<dyn Interpolator<Item = Item>>>
where
Item: 'static,
{
pub fn new_target_boxed<G, I>(target: G, interpolator: I) -> Self
where
G: Into<T>,
I: Interpolator<Item = Item>,
{
Self::new_target(target, Box::new(interpolator))
}
}
impl<T, Item> Tween<T, Box<dyn Interpolator<Item = Item>>>
where
T: Default,
Item: 'static,
{
pub fn new_boxed<I>(interpolator: I) -> Self
where
I: Interpolator<Item = Item>,
{
Self::new(Box::new(interpolator))
}
}
pub type ComponentTween<I> = Tween<TargetComponent, I>;
pub type ComponentDynTween<C> =
Tween<TargetComponent, Box<dyn Interpolator<Item = C>>>;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Reflect)]
pub enum TargetComponent {
#[non_exhaustive]
Marker,
Entity(Entity),
Entities(Vec<Entity>),
}
impl TargetComponent {
pub fn marker() -> TargetComponent {
TargetComponent::Marker
}
pub fn entity(entity: Entity) -> TargetComponent {
TargetComponent::Entity(entity)
}
pub fn entities<I>(entities: I) -> TargetComponent
where
I: IntoIterator<Item = Entity>,
{
TargetComponent::from_iter(entities)
}
pub fn state<V>(&self, value: V) -> TargetState<Self, V> {
TargetState::new(self.clone(), value)
}
pub fn with<I>(&self, interpolator: I) -> Tween<Self, I> {
Tween {
target: self.clone(),
interpolator,
}
}
pub fn with_closure<F, C>(
&self,
closure: F,
) -> Tween<Self, Box<dyn Interpolator<Item = C>>>
where
F: Fn(&mut C, CurrentValue, PreviousValue) + Send + Sync + 'static,
C: Component,
{
let closure = crate::interpolate::closure(closure);
let interpolator: Box<dyn Interpolator<Item = C>> = Box::new(closure);
Tween {
target: self.clone(),
interpolator,
}
}
}
impl Default for TargetComponent {
fn default() -> Self {
TargetComponent::marker()
}
}
impl From<Entity> for TargetComponent {
fn from(value: Entity) -> Self {
TargetComponent::entity(value)
}
}
impl FromIterator<Entity> for TargetComponent {
fn from_iter<T: IntoIterator<Item = Entity>>(iter: T) -> Self {
TargetComponent::Entities(iter.into_iter().collect())
}
}
impl<const N: usize> From<[Entity; N]> for TargetComponent {
fn from(value: [Entity; N]) -> Self {
TargetComponent::entities(value)
}
}
impl From<Vec<Entity>> for TargetComponent {
fn from(value: Vec<Entity>) -> Self {
TargetComponent::entities(value)
}
}
impl From<&Vec<Entity>> for TargetComponent {
fn from(value: &Vec<Entity>) -> Self {
TargetComponent::entities(value.iter().copied())
}
}
impl From<&[Entity]> for TargetComponent {
fn from(value: &[Entity]) -> Self {
TargetComponent::entities(value.iter().copied())
}
}
impl<const N: usize> From<&[Entity; N]> for TargetComponent {
fn from(value: &[Entity; N]) -> Self {
TargetComponent::entities(value.iter().copied())
}
}
#[derive(Default, Debug, Component, Reflect)]
#[reflect(Component)]
pub struct AnimationTarget;
impl<I> ComponentTween<I>
where
I: Interpolator,
I::Item: Component,
{
}
impl<C> ComponentDynTween<C> where C: Component {}
pub type ResourceTween<I> = Tween<TargetResource, I>;
pub type ResourceDynTween<R> =
Tween<TargetResource, Box<dyn Interpolator<Item = R>>>;
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Reflect)]
pub struct TargetResource;
impl TargetResource {
pub fn new() -> TargetResource {
TargetResource
}
pub fn state<V>(&self, value: V) -> TargetState<Self, V> {
TargetState::new(self.clone(), value)
}
pub fn with<I>(&self, interpolator: I) -> Tween<Self, I> {
Tween {
target: self.clone(),
interpolator,
}
}
pub fn with_closure<F, C>(
&self,
closure: F,
) -> Tween<Self, Box<dyn Interpolator<Item = C>>>
where
F: Fn(&mut C, CurrentValue, PreviousValue) + Send + Sync + 'static,
C: Component,
{
let closure = crate::interpolate::closure(closure);
let interpolator: Box<dyn Interpolator<Item = C>> = Box::new(closure);
Tween {
target: self.clone(),
interpolator,
}
}
}
#[cfg(feature = "bevy_asset")]
pub type AssetTween<I> = Tween<TargetAsset<<I as Interpolator>::Item>, I>;
#[cfg(feature = "bevy_asset")]
pub type AssetDynTween<A> =
Tween<TargetAsset<A>, Box<dyn Interpolator<Item = A>>>;
#[cfg(feature = "bevy_asset")]
#[derive(Debug, PartialEq, Eq, Hash, Reflect)]
pub enum TargetAsset<A: Asset>
where
A: Asset,
{
Asset(Handle<A>),
Assets(Vec<Handle<A>>),
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> TargetAsset<A> {
pub fn asset(asset: Handle<A>) -> Self {
TargetAsset::Asset(asset)
}
pub fn assets<I>(assets: I) -> Self
where
I: IntoIterator<Item = Handle<A>>,
{
TargetAsset::from_iter(assets)
}
pub fn state<V>(&self, value: V) -> TargetState<Self, V> {
TargetState::new(self.clone(), value)
}
pub fn with<I>(&self, interpolator: I) -> Tween<Self, I> {
Tween {
target: self.clone(),
interpolator,
}
}
pub fn with_closure<F, C>(
&self,
closure: F,
) -> Tween<Self, Box<dyn Interpolator<Item = C>>>
where
F: Fn(&mut C, CurrentValue, PreviousValue) + Send + Sync + 'static,
C: Component,
{
let closure = crate::interpolate::closure(closure);
let interpolator: Box<dyn Interpolator<Item = C>> = Box::new(closure);
Tween {
target: self.clone(),
interpolator,
}
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> Clone for TargetAsset<A> {
fn clone(&self) -> Self {
match self {
TargetAsset::Asset(handle) => TargetAsset::Asset(handle.clone()),
TargetAsset::Assets(v) => TargetAsset::Assets(v.clone()),
}
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> Default for TargetAsset<A> {
fn default() -> Self {
TargetAsset::Asset(Default::default())
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> From<Handle<A>> for TargetAsset<A> {
fn from(value: Handle<A>) -> Self {
TargetAsset::Asset(value)
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> FromIterator<Handle<A>> for TargetAsset<A> {
fn from_iter<T: IntoIterator<Item = Handle<A>>>(iter: T) -> Self {
TargetAsset::Assets(iter.into_iter().collect())
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset, const N: usize> From<[Handle<A>; N]> for TargetAsset<A> {
fn from(value: [Handle<A>; N]) -> Self {
TargetAsset::assets(value)
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> From<Vec<Handle<A>>> for TargetAsset<A> {
fn from(value: Vec<Handle<A>>) -> Self {
TargetAsset::assets(value)
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> From<&Vec<Handle<A>>> for TargetAsset<A> {
fn from(value: &Vec<Handle<A>>) -> Self {
TargetAsset::assets(value.iter().cloned())
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> From<&[Handle<A>]> for TargetAsset<A> {
fn from(value: &[Handle<A>]) -> Self {
TargetAsset::assets(value.iter().cloned())
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset, const N: usize> From<&[Handle<A>; N]> for TargetAsset<A> {
fn from(value: &[Handle<A>; N]) -> Self {
TargetAsset::assets(value.iter().cloned())
}
}
pub trait IntoTarget {
type Target;
fn into_target(self) -> Self::Target;
}
impl IntoTarget for Entity {
type Target = TargetComponent;
fn into_target(self) -> Self::Target {
TargetComponent::entity(self)
}
}
impl<const N: usize> IntoTarget for [Entity; N] {
type Target = TargetComponent;
fn into_target(self) -> Self::Target {
TargetComponent::entities(self)
}
}
impl IntoTarget for Vec<Entity> {
type Target = TargetComponent;
fn into_target(self) -> Self::Target {
TargetComponent::entities(self)
}
}
impl IntoTarget for &[Entity] {
type Target = TargetComponent;
fn into_target(self) -> Self::Target {
TargetComponent::entities(self.iter().copied())
}
}
impl<const N: usize> IntoTarget for &[Entity; N] {
type Target = TargetComponent;
fn into_target(self) -> Self::Target {
TargetComponent::entities(self.iter().copied())
}
}
impl IntoTarget for &Vec<Entity> {
type Target = TargetComponent;
fn into_target(self) -> Self::Target {
TargetComponent::entities(self.iter().copied())
}
}
impl IntoTarget for AnimationTarget {
type Target = TargetComponent;
fn into_target(self) -> Self::Target {
TargetComponent::marker()
}
}
#[cfg(feature = "bevy_asset")]
impl<A> IntoTarget for Handle<A>
where
A: Asset,
{
type Target = TargetAsset<A>;
fn into_target(self) -> Self::Target {
TargetAsset::asset(self)
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset, const N: usize> IntoTarget for [Handle<A>; N] {
type Target = TargetAsset<A>;
fn into_target(self) -> Self::Target {
TargetAsset::assets(self)
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> IntoTarget for Vec<Handle<A>> {
type Target = TargetAsset<A>;
fn into_target(self) -> Self::Target {
TargetAsset::assets(self)
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> IntoTarget for &[Handle<A>] {
type Target = TargetAsset<A>;
fn into_target(self) -> Self::Target {
TargetAsset::assets(self.iter().cloned())
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset, const N: usize> IntoTarget for &[Handle<A>; N] {
type Target = TargetAsset<A>;
fn into_target(self) -> Self::Target {
TargetAsset::assets(self.iter().cloned())
}
}
#[cfg(feature = "bevy_asset")]
impl<A: Asset> IntoTarget for &Vec<Handle<A>> {
type Target = TargetAsset<A>;
fn into_target(self) -> Self::Target {
TargetAsset::assets(self.iter().cloned())
}
}
#[deprecated(
since = "0.6.0",
note = "use `bevy_tween::tween_event::TweenEvent` instead"
)]
#[allow(missing_docs)]
#[doc(hidden)]
pub type TweenEvent<Data> = crate::tween_event::TweenEvent<Data>;
#[deprecated(
since = "0.6.0",
note = "use `bevy_tween::tween_event::TweenEventData` instead"
)]
#[allow(missing_docs)]
#[doc(hidden)]
pub type TweenEventData<Data> = crate::tween_event::TweenEventData<Data>;
#[deprecated(
since = "0.6.0",
note = "use `bevy_tween::tween_event::DefaultTweenEventPlugins` instead"
)]
#[allow(missing_docs)]
#[doc(hidden)]
pub type DefaultTweenEventsPlugin =
crate::tween_event::DefaultTweenEventPlugins;
#[deprecated(
since = "0.6.0",
note = "use `bevy_tween::tween_event::tween_event_system` instead or `TweenEventPlugin` if you're registering custom tween event"
)]
#[allow(missing_docs)]
#[doc(hidden)]
#[allow(deprecated)]
#[allow(clippy::type_complexity)]
pub fn tween_event_system<Data, TimeCtx>(
commands: Commands,
q_tween_event_data: Query<
(
Entity,
&TweenEventData<Data>,
&TimeSpanProgress,
Option<&TweenInterpolationValue>,
),
(Without<SkipTween>, With<TimeContext<TimeCtx>>),
>,
event_writer: MessageWriter<TweenEvent<Data>>,
) where
Data: Clone + Send + Sync + 'static,
TimeCtx: Default + Send + Sync + 'static,
{
crate::tween_event::tween_event_system(
commands,
q_tween_event_data,
event_writer,
)
}