Code Monkey home page Code Monkey logo

bevy_tweening's People

Contributors

arendjr avatar dgsantana avatar djee-ms avatar djeedai avatar enaut avatar guyguy2001 avatar gyrobifastigium avatar iancormac84 avatar peepo-juice avatar shuoli84 avatar sjael avatar supercilex avatar wainwrightmark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

bevy_tweening's Issues

Repeat broken after first iteration

Run any example (except menu currently broken due to #41) : the color animation goes from red to blue smoothly during the first loop, then from the second loop ping-pongs between full red and full blue without any interpolation.

@SUPERCILEX this is probably due to a bug in #19.

This is blocking #34

Working with `bevy_vector_shapes`

Is there nice a way to use this plugin in arbitrary systems? I wanted to use this plugin with bevy_vector_shapes:

fn draw(mut painter: ShapePainter) {
    // Draw a circle
    painter.circle(100.0);
}

But since bevy_tweening works by targeting specific components using lenses, I can't figure out an ergonomic way of making it work together.

Any ideas?

how to remove animator from entity

As far as i can see the Animator<> is generic over the Tweenable and that becomes very hairy and bespoke for each tween generated to be able to remove the whole Animator again from an entity.

What is the best practice here?

ColorMaterialColorLens bug

bevy::prelude::ColorMaterial does not implement bevy::prelude::Component, which breaks ColorMaterialColorLens.

Full error message:

error[E0277]: the trait bound bevy::prelude::ColorMaterial: bevy::prelude::Component is not satisfied
--> src\main.rs:265:44
|
265 | commands.entity(e2).insert(Animator::new(Tween::new(
| ^^^^^^^^ the trait bevy::prelude::Component is not implemented for bevy::prelude::ColorMaterial
|
= help: the following other types implement trait bevy::prelude::Component:
AdditionalMassProperties
AlphaMode
AnimationPlayer
Animator
AssetAnimator
BackgroundColor
Ball
BloomSettings
and 120 others
note: required by a bound in Animator
--> {DIRECTORY}\bevy_tweening-0.6.0\src\lib.rs:408:24
|
408 | pub struct Animator<T: Component> {
| ^^^^^^^^^ required by this bound in Animator

Completion events on all Tweenables

set_completed_event/with_completed_event are currently only available on the Tween type. It'd be nice to have them on any Tweenable, but especially on the compound ones: Sequence and Tracks.

My current workaround for this is to attach the completion to the last tweenable in sequence. This is pretty awkward, because you have to do it before you type-erase it, e.g.:

// `transitions` is Vec<(Duration, /* target alpha */ f32)>
let mut sequence: Vec<BoxedTweenable<Sprite>> = Vec::with_capacity(transitions.len());

let mut current_alpha = initial;
for (i, &(duration, end_alpha)) in transitions.iter().enumerate() {
    if (end_alpha - current_alpha).abs() < 0.01 {
        sequence.push(Box::new(Delay::new(duration)));
    } else {
        let lens = SpriteColorLens {
            start: fade_sprite_color(current_alpha),
            end: fade_sprite_color(end_alpha),
        };

        let mut tween = Tween::new(EaseMethod::Linear, TweeningType::Once, duration, lens);
        if i == transitions.len() - 1 {
            tween.set_completed_event(TWEEN_COMPLETION_COOKIE);
        }

        sequence.push(Box::new(tween));
    }
    current_alpha = end_alpha;
}

Sequence::new(sequence)

This also doesn't work if the last tweenable is Delay. For that case, you need to turn your Sequence into Tracks, with a parallel Tween that does nothing but provide the completion event. This might require a custom NoopLens<T: Component> type.

All in all, pretty messy. Having set_completed_event on more tweenable types would eliminate the need for tricks like this.

Investigate providing `&mut world` in tweenable callback vs. using events

Currently a tweenable callback has little information. It contains a reference to the Tween<T>, and (change not merged yet) the Entity of the Animator<T> or AssetAnimator<T>.

Kero on Discord suggested providing a &mut world to allow the callback to do something useful, similar to what bevy-tick-timers does. But this forces the system ticking the animators to take a global lock and become exclusive, serializing execution and being a potential choke point for other Bevy systems, which can cause performance issues. This is particularly bad for bevy_tweening which has a series of such systems, once per component type:

pub fn component_animator_system<T: Component>(
time: Res<Time>,
mut query: Query<(&mut T, &mut Animator<T>)>,
) {
for (ref mut target, ref mut animator) in query.iter_mut() {
if animator.state != AnimatorState::Paused {
if let Some(tweenable) = animator.tweenable_mut() {
tweenable.tick(time.delta(), target);
}
}
}
}

A possible alternative which sounds more Bevy-esque would be to replace the callback with a Bevy event. This way the user app can design any system they want to read that event, with any resource / query they need. This however implies being able to write an event without knowing its type at build time, to avoid depending on the event type as an extra generic parameter for the system:

let mut tween = Tween::new(...);
tween.set_completed::<MyEvent>();

then

pub fn component_animator_system<T: Component>( 
    time: Res<Time>, 
    mut query: Query<(&mut T, &mut Animator<T>)>,
    mut writer: EventWriter<????>, //< Here we don't know the type
) { 
    for (ref mut target, ref mut animator) in query.iter_mut() { 
        if animator.state != AnimatorState::Paused { 
            if let Some(tweenable) = animator.tweenable_mut() { 
                tweenable.tick(time.delta(), target, writer); 
            } 
        } 
    } 
} 

Bevy Event/Callback Example

The docs show 4 features front and center for this crate.


The first three are all well covered by the examples you have, but

Raise a Bevy event or invoke a callback when an tween completed

is not. At least one example per major feature would be nice :)

Add example for tick()

Could you add an example for calling tick()?

I have no idea what Targetable needs:
tween.tick(Duration::ZERO, ???, e, &mut writer);

Translation values still being changed after Animation played "Once" finished

Whenever I use the TransformPositionLens with TweeningType::Once, even after the animation is completed, the entitities transform seems to be "changed" still. I know this because I have another system listening on transform Change and it is triggering every frame.

#[derive(Component)]
pub struct ImTweeningHere;

pub fn move_player_on_click(
    mut commands: Commands,
    mouse_input: Res<Input<MouseButton>>,
    grid_dimensions: Res<GridDimensions>,
    mouse_map_pos: Option<Res<MouseMapPos>>,
    player: Query<(Entity, &Transform), (With<Player>, Without<ImTweeningHere>)>,
) {
    if let (true, Some(mouse_map_pos)) = (
        mouse_input.just_pressed(MouseButton::Left),
        mouse_map_pos.as_deref(),
    ) {
        if let Ok((entity, player_transform)) = player.get_single() {
            let end_position = grid_dimensions.grid_loc_to_vec2(
                (mouse_map_pos.0.x / grid_dimensions.tile_area).floor(),
                (mouse_map_pos.0.y / grid_dimensions.tile_area).floor(),
            );

            let tween = Tween::new(
                EaseFunction::CircularInOut,
                TweeningType::Once,
                std::time::Duration::from_millis(500),
                TransformPositionLens {
                    start: player_transform.translation,
                    end: Transform::from_translation(end_position.extend(player_transform.translation.z))
                        .translation,
                },
            )
            .with_completed_event(true, 0);

            let animator = Animator::new(tween);
            commands
                .entity(entity)
                .insert(animator)
                .insert(ImTweeningHere);
        }
    }
}

the above system triggers the animation on map click, when the animation completes, the entities Transform still fires off

fn player_transforming(
    player: Query<&Transform, (With<Player>, Changed<Transform>)>,
) {
    if let Ok(transforming) = player.get_single() {
        info!("player is transforming!: {transforming:?}");
    }
}

as a work around, I manually remove the AnimatorTransform on tween complete

fn movement_completed(mut commands: Commands, mut on_tween_complete: EventReader<TweenCompleted>) {
    for evt in on_tween_complete.iter() {
        if evt.user_data == 0 {
            commands
                .entity(evt.entity)
                .remove::<ImTweeningHere>()
                .remove::<Animator<Transform>>();
        }
    }
}

However, I am not sure if this is the intended behavior. do we need to remove the Animator on animation complete. I expect that the intended behavior when using a TweeningType of Once is the component will be removed on animation complete for the entity and we use the TweenCompleted event for other stuff, like my use case here to remove my own component.

The 'custom component' description is misleading

As noted on discord, the the custom component part of the readme is a bit misleading and a common source of confusion. The readme should probably be more explicit about the fact that not all built-in components are supported (and probably just link to the plugin source as both an example of adding the system and to show which types are added by default).

How to tween both translation and scale of Transform simultaneously?

This was pretty easy to do with the old bevy_easings crate, that this crate was based on, because it dealt with the entire Transform all at once.

Here, you are providing separate "lenses" for translation, rotation, and scale, and all of them set the generic parameter on Lens<T> to T: Transform, meaning that I cannot add multiple to the same entity simultaneously. There is no lens for working with the whole transform. :(

So have you made it impossible to tween between two Transforms? Only leaving the possibility to operate on one field at a time?

`Sequence::tick` accumulates timing error whenever a tween completes

let tween_state = tween.tick(delta, target, entity, event_writer);

Sequence::tick spends its entire delta time on its current tween with no carry-over. If for example delta is 16ms and there are only 2ms left to complete the current tween, then the current tween will get ticked for the entire 16ms and the next tween will start from zero instead of starting 14ms in. Every time the Sequence crosses a tween boundary, the error accumulates and the sequence drifts further and further from where it should be.

Sequence with repeat_count

Hey,

I was trying to have an object zoom into existence then wiggle infinitely... I tried doing that with:

Tween::new(
            EaseFunction::QuadraticInOut,
            Duration::from_millis(1000),
            TransformScaleLens {
                start: Vec3::ZERO,
                end: Vec3::ONE,
            },
        )
        .then(
            Tween::new(
                EaseFunction::QuadraticInOut,
                Duration::from_millis(200),
                TransformRotateZLens {
                    start: 0.05,
                    end: -0.05,
                },
            )
            .with_repeat_strategy(bevy_tweening::RepeatStrategy::MirroredRepeat)
            .with_repeat_count(RepeatCount::Infinite),
        )

But when Running the first animation works well, however the second one panics with:

thread 'Compute Task Pool (13)' panicked at 'overflow when subtracting durations', library/core/src/time.rs:930:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

The same happens if repeat_count is set to a finite number even when set to 1.

It might be that this is "known" or "intended" but if so it should probably be in the documentation for the then method or the Sequence type.

The Behaviour I expected would have been an infinite sequence first the zoom then forever wiggling...

Design what happens to completion events when playback jumps backward

The set_progress() (and discussed set_elapsed()) method allow you to move the animation to an earlier point than the one it's in currently. Traditionally for tick-based animation the tween will emit a completion event each time it's completed. However, when playback jumps backward, it's unclear what should be done for completion events, especially when the tween is repeating, and jumping backward can decrease the completed count (times_completed) by more than one.

Conceptually it feels like jumping backward this way is not a natural way of animating, and is more geared toward editors or manual seeking, so it feels like ignoring completion events (and callbacks) in that case is the best approach.

Note however that there is also the playback direction which allows smooth playback but in reverse order. Although this is a distinct and probably orthogonal feature (it only swaps the endpoints of the lens), conceptually it can be confusing to make a distinction between "moving by 1 second in backward direction" and "seeking 1 second before the current point", which both result in the same state for the underlying animated component, but not for the tween which has a different direction.

Improve capabilities of modifying Tweenables after creation

I have implemented a drag and drop system for Sprite and would like to build on this by having sprite ease back towards its original position after being dropped.

Here I came across some limitations of bevy_tweening.

For this I query Animator<Transform> in a system that checks for the Sprite position and whether it has been dropped. Today, there seems to be no way to update the TransformationPositionLens of the Tween of that Animator with a new start value, or change other fields of the Tween (as they are private).

The only way to get this working that I found is to use the set_tweenable method on the Animator to set a new Tween. I am not sure about performance impact, but it seems not an ideal way to do things. This also means that the Tween originally defined for this Animator is just unused boilerplate.

I would like to define an initial Tween and then change some of its parameters in a system call, without having to instantiate a new Tween.

I donโ€™t know if this is in the scope of this crate or if there are technical reasons this is not possible, but this seems like an area where improved ergonomics would make bevy_tweening even more useful.

Circle rotation results in invisible entity

Here is the code:

use bevy::prelude::*;
use bevy_tweening::{lens::*, *};

fn main() {
    App::default()
        .add_plugins(DefaultPlugins)
        .add_plugin(TweeningPlugin)
        .add_startup_system(setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn_bundle(OrthographicCameraBundle::new_2d());

    let size = 80.;
    let tween = Tween::new(
        EaseMethod::Linear,
        TweeningType::PingPong,
        std::time::Duration::from_secs(1),
        TransformRotationLens {
            start: Quat::IDENTITY,
            end: Quat::from_axis_angle(Vec3::Z, std::f32::consts::PI),
        },
    );

    commands
        .spawn_bundle((
            Transform::default(),
            GlobalTransform::default(),
        ))
        .with_children(|parent| {
            parent
                .spawn_bundle(SpriteBundle {
                    sprite: Sprite {
                        color: Color::RED,
                        custom_size: Some(Vec2::new(size, size * 0.5)),
                        ..Default::default()
                    },
                    ..Default::default()
                })
                .insert(Animator::new(tween));
        });
}

It works correctly, sprite rotates. But if you replace std::f32::consts::PI with std::f32::consts::TAU the sprite becomes invisible.

Avoid unnecessary change detection resulting from component lens

Right now the Lens trait's lerp method takes &mut T for T: Component, but it should only need Mut<T>.

The system invokes DerefMut so we have no chance to avoid change detection in a custom lens:

&mut target,

Specifically, I have a custom lens that acts like a discrete switch that changes from one value to another at a specific ratio. This would only require a single DerefMut, but in fact it happens every frame that the Animator is running.

Make `Sequence` loopable

This is a sub-issue of #8. Opening this separately because for Sequence the problem is I believe well-defined, and work can move forward. This is not the case for Tracks though, so splitting the issue in two for clarity.

Allow Sequence to be loopable both with TweeningType::Loop (play all child tweenables once, then restart at first one) and with TweeningType::PingPong (play all child tweenables once, then restart from last back to first, then restart from first to last, etc.).

Tween `ResMut` resources

Is there a way to use resources (ResMut) as a target for the tween? Would open up a lot of nice possibilities.

Adding new tweens to existing ones

Let's say I have an entity that is set up with a tween targeting the entity's transform.rotation. The tween loops infinitely throughout the game.

But I also want to have a system that can insert a new tween that targets said entity's transform.scale, depending on the state of the game. The tween loops only once. I also want to be able to replay that tween, depending on the game state.

The problem is that this requires you to put more than one Animator<Transform> component on the entity, which is currently not possible in Bevy. Is there a good solution for this use-case?

Animating sprite sheets

First of all. Thanks for this repo. I just discovered it and it's really well made and saving me a lot of time.

It feels natural to use this to tick the index of a TextureAtlas so I gave it a thought. I'm coming up on some loose ends. Here's what I can gauge:

  • Using Tween to tick the TextureAtlas doesn't feel right since each frame of the index could take varying amounts of time. Tween only takes one duration.
  • String together Tween into Sequence is verbose, and loses some of the functionality of Tween, such as the ability to repeat the sequence as a whole or sending events on completion.
  • It feels natural to use EaseMethod::Discrete for this purpose but the value returned by progress is exclusive, hence you're limited to doing something like EaseMethod::Discrete(0.999), which isn't that bad but feels hacky. This is what I'm coming up against if I were to choose to implement a custom Lens.

Any thoughts on how to use it to tick sprite sheet indices? Is this something you could support?

Allow tweenables to play backward

Allow all Tweenable to play backward once or looped, or to start from end in ping-pong mode.

Also allow this direction to be changed at runtime at any point, to allow some animation to "go back to start" without having to create a new Tweenable which encodes the reverse animation explicitly.

Note: this is a prerequisite for #16

Support for MorphWeights

Are MorphWeights supported? I am trying to implement lerping between morph weights (or blendshapes as I call them since I came from working in unity) but from I can tell the lens never gets called.

I am also still really new to bevy and rust in general.

Here is what I currently have.

        commands.spawn((
            SceneBundle {
                scene: asset_server.load("Nukude.glb#Scene0"),
                ..default()
            },
            Animator::new(Dummy::<MorphWeights>::new()),
            AnimatorState::Sad,
            MetaData {
                mesh: asset_server.load("Nukude.glb#Mesh0/Primitive0"),
                material: asset_server.load("Nukude.glb#Material0"),
                blendshapes: Vec::new()
            },
            Face,
        ));
    fn check_blink_status(mut query: Query<(&mut Animator<MorphWeights>, &MetaData), With<Face>>,
                          time: Res<Time>,
                          mut timer: ResMut<BlinkTimer>) {
        if timer.tick(time.delta()).finished() {
            let mut rng = rand::thread_rng();
            for (mut animator, meta_data) in &mut query {
                let index = utils::get_index(&meta_data.blendshapes, "Blink");
                let tween_close = Tween::new(
                    EaseFunction::SineInOut,
                    Duration::from_secs_f64(0.25),
                    BlendshapeLens {
                        index,
                        start: 0.0,
                        end: 1.0
                    }
                );
                let tween_open = Tween::new(
                    EaseFunction::SineInOut,
                    Duration::from_secs_f64(0.25),
                    BlendshapeLens {
                        index,
                        start: 1.0,
                        end: 0.0
                    }
                );
                animator.set_tweenable(tween_close.then(tween_open));
                timer.0 = Timer::from_seconds(rng.gen_range(3..30) as f32, TimerMode::Once)
            }
        }
    }

My custom lens for MorphWeights

use bevy::prelude::MorphWeights;
use bevy_tweening::Lens;

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct BlendshapeLens {
    pub index: usize,
    pub start: f32,
    pub end: f32
}

impl Lens<MorphWeights> for BlendshapeLens {
    fn lerp(&mut self, target: &mut MorphWeights, ratio: f32) {
        target.weights_mut()[self.index] = self.start * (1.0 - ratio) + self.end * ratio;
        println!("{}", target.weights_mut()[self.index]);
    }
}

I added the println as a way to test if it is getting called but as far as I can tell it isn't.

Here is example of elsewhere where I manually manipulate them in code. I have MorphWeights as it's own query because it was causing the other query to not pull any data.

    fn play_expression(mut query: Query<(&mut Animator<MorphWeights>, &AnimatorState, &MetaData), Changed<AnimatorState>>,
                       mut morph_weights: Query<&mut MorphWeights>,
                       mut materials: ResMut<Assets<StandardMaterial>>,
    ) {
        if query.is_empty() { return; }
        let (mut animator, state, meta_data) = query.single_mut();

        // Clear the blendshapes before ww set the new expression
        let mut morphs = morph_weights.single_mut();
        let blendshapes = morphs.weights_mut();
        blendshapes[utils::get_index(&meta_data.blendshapes, "MoveEye")] = 1.0;
        blendshapes[utils::get_index(&meta_data.blendshapes, "HideBlush")] = 1.0;
        blendshapes[utils::get_index(&meta_data.blendshapes, "Frown")] = 0.0;
        blendshapes[utils::get_index(&meta_data.blendshapes, "Doubt")] = 0.0;
        blendshapes[utils::get_index(&meta_data.blendshapes, "Surprised")] = 0.0;
        blendshapes[utils::get_index(&meta_data.blendshapes, "Sadness")] = 0.0;
        blendshapes[utils::get_index(&meta_data.blendshapes, "Anger")] = 0.0;

I am working on some cosplay software that takes a face model and renders it to some LED matrices. Looking at other animation options because the default AnimationClips override what I set for the blendshapes and I plan to implement visemes as well.

Add speed test ticking a tween

Add an animator speed test which actually ticks a tween. Currently because the ticking is deferred to the tween itself, and applied "manually" by the built-in animator systems, it's easy to break the feature without noticing as the systems are also not tested.

Custom lens not working

Hi, i was trying to implement simple custom lens for animating my ui image alpha, but it doesn't work, am i doing something wrong ?

struct ImageOpacityLens {
    start: f32,
    end: f32,
}

impl Lens<BackgroundColor> for ImageOpacityLens {
    fn lerp(&mut self, target: &mut BackgroundColor, ratio: f32) {
        let interpolated_value = self.start + (self.end - self.start) * ratio;
        target.0.set_a(interpolated_value);
    }
}
let tween = Tween::new(
        EaseFunction::QuadraticInOut,
        Duration::from_secs(2),
        ImageOpacityLens {
            start: 0.0,
            end: 1.0,
        },
    )
    .with_repeat_count(RepeatCount::Finite(2))
    .with_repeat_strategy(RepeatStrategy::MirroredRepeat);

commands.spawn((
        ImageBundle {
            style: Style {
                margin: UiRect::all(Val::Auto),
                size: Size::new(Val::Px(300.0), Val::Auto),
                ..default()
            },
            image: UiImage(icon),
            ..default()
        },
        Animator::new(tween),
    ));

Use handle from component for asset animation (?)

MaterialMesh2dBundle<T> has a material: Handle<T> component, and this can be used to animate without needing to pass the handle to the animator. I implemented this in my own project and it seems to work although perhaps there are some implications I am not aware of?

Code:

#[derive(Component)]
pub struct AssetComponentAnimator<T: Asset> {
    pub state: AnimatorState,
    tweenable: BoxedTweenable<T>,
    speed: f32,
}

impl<T: Asset> AssetComponentAnimator<T> {
    pub fn new(tweenable: impl Tweenable<T> + 'static) -> Self {
        Self {
            state: AnimatorState::Playing,
            tweenable: Box::new(tweenable),
            speed: 1.0,
        }
    }

    pub fn speed(&self) -> f32 {
        self.speed
    }

    pub fn tweenable_mut(&mut self) -> &mut dyn Tweenable<T> {
        self.tweenable.as_mut()
    }
}

pub struct AssetComponentTarget<'a, T: Asset> {
    assets: ResMut<'a, Assets<T>>,
    pub handle: Handle<T>,
}

impl<'a, T: Asset> AssetComponentTarget<'a, T> {
    pub fn new(assets: ResMut<'a, Assets<T>>) -> Self {
        Self {
            assets,
            handle: Handle::weak(HandleId::default::<T>()),
        }
    }

    pub fn is_valid(&self) -> bool {
        self.assets.contains(&self.handle)
    }
}

impl<'a, T: Asset> Targetable<T> for AssetComponentTarget<'a, T> {
    fn target_mut(&mut self) -> &mut T {
        self.assets.get_mut(&self.handle).unwrap()
    }
}

pub fn asset_component_animator_system<T: Asset>(
    time: Res<Time>,
    assets: ResMut<Assets<T>>,
    mut query: Query<(Entity, &Handle<T>, &mut AssetComponentAnimator<T>)>,
    events: ResMut<Events<TweenCompleted>>,
) {
    let mut events: Mut<Events<TweenCompleted>> = events.into();
    let mut target = AssetComponentTarget::new(assets);
    for (entity, handle, mut animator) in query.iter_mut() {
        if animator.state != AnimatorState::Paused {
            target.handle = handle.clone();
            let speed = animator.speed();
            animator.tweenable_mut().tick(
                time.delta().mul_f32(speed),
                &mut target,
                entity,
                &mut events,
            );
        }
    }
}

Support Time<Real> (in bevy 0.12)

This's is just a prep issue for the upcoming bevy 0.12 release.
Time scaling was added in bevyengine/bevy#8964 with Time<()> being the default. In normal systems that's Time<Virtual> (scaled) which makes sense, but it would be nice to be able to animate in unscaled time (Time<Real>) (e.g. for a pause UI).

Adding a field to Animator like use_real_time: bool and adding the appropriate builder functions might do the trick for the API.

Extend Tracks and Sequence functionality

To combine multiply tweens and loop them I have to create custom lens which is not very ergonomic. We currently have Tracks and Sequence, but they aren't loopable.
I would like to request to extend their functionality. It would be great if we could combine multiply tweens with different tweening type. For example, to animate healing pickup like in Owerwatch I need rotation tween with Loop and translation tween with PingPong. Video of how such pickups look.

Support Bevy 0.9

Admitted โ€“ this issue is not very original, but it does not hurt to have it filed: Bevy 0.9 has just been released, and there is a migration guide at https://bevyengine.org/learn/book/migration-guides/0.8-0.9/

I am still inexperienced with rust and cargo and run into the most basic of problems: bevy_tweening 0.5.0 still depends on bevy 0.8.1, and I am getting compilation errors related to mismatching dependency versions.

Bevy 0.11 support

This crate is fantastic. It would be nice to support most recent version of Bevy

[Support?] How to animate complex shapes involving modifying a path, position, and rotation with multiple steps?

Hey,

I want to create a turtlegraphics clone in bevy. So far I achieved the basic functionality:

2022-08-26.10-02-58.mp4

I did so by one line/circle etc each being one bundle with an animator...

Now I would like to make this form filled: like here https://github.com/sunjay/turtle/blob/master/docs/assets/images/examples/ferris.gif

But to fill that all the lines need to be in one bundle I think. Of course I could create a rather complicated lens that draws that bundle but the lerping would break because all the steps in the middle would be faster than at the beginning or the end...

I'm not sure if I found all the relevant documentation so I might miss something obvious. However I'd very much appreciate some hints on how such a thing could be achieved.

Thank you!

Tracks should allow tweens with different lens type

Basically what I want to do is to animate a simple text to move up and at the same time have a color fade. I believe this code should work:

let tracks = Tracks::new([
    Tween::new(
        EaseFunction::QuadraticIn,
        Duration::from_secs(1),
        TransformPositionLens {
            start: Vec3::new(40.0, 0.0, 1.0),
            end: Vec3::new(40.0, 15.0, 1.0),
        },
    )
    .with_completed_event(1),
    Tween::new(
        EaseFunction::QuadraticIn,
        Duration::from_secs(1),
        TextColorLens {
            section: 0,
            start: Color::BLACK,
            end: Color::Rgba {
                red: 0.0,
                green: 0.0,
                blue: 0.0,
                alpha: 0.0,
            },
        },
    ),
]);

But this gives me this error: expected struct Tween<Transform> found struct Tween<bevy::prelude::Text>

Multiply tweens to a single entity

Is it possible to apply multiply tweens to a single entity? Like TransformPositionLens + TransformRotateYLens. Or should I create a custom lens in this case?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.