Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# Bevy Tweening
[](https://opensource.org/licenses/MIT) [](https://docs.rs/bevy_tweening) [](https://crates.io/crates/bevy_tweening)
Tweening animation plugin for Bevy.
## Usage
### System setup
Add the tweening plugin to your app:
```rust
App::default()
.add_default_plugins()
.add_plugin(TweeningPlugin)
.run();
```
### Animate a component
Animate the transform position of an entity:
```rust
commands
// Spawn a Sprite entity to animate the position of
.spawn_bundle(SpriteBundle {
sprite: Sprite {
color: Color::RED,
custom_size: Some(Vec2::new(size, size)),
..Default::default()
},
..Default::default()
})
// Add an Animator component to perform the animation
.insert(Animator::new(
// Use a quadratic easing on both endpoints
EaseFunction::QuadraticInOut,
// Loop animation back and forth over 1 second, with a 0.5 second
// pause after each cycle (start -> end -> start).
TweeningType::PingPong {
duration: Duration::from_secs(1),
pause: Some(Duration::from_millis(500)),
},
// The lens gives access to the Transform component of the Sprite,
// for the Animator to animate it. It also contains the start and
// end values associated with the animation ratios 0. and 1.
TransformPositionLens {
start: Vec3::new(0., 0., 0.),
end: Vec3::new(1., 2., -4.),
},
));
```
## Predefined Lenses
The naming scheme for predefined lenses is `"<TargetName><FieldName>Lens"`, where `<TargetName>` is the name of the target component or asset which is queried, and `<FieldName>` is the field which is mutated in place.
### Bevy Components
| Target Component | Animated Field | Lens |
|---|---|---|
| [`Sprite`](https://docs.rs/bevy/0.6.0/bevy/sprite/struct.Sprite.html) | [`color`](https://docs.rs/bevy/0.6.0/bevy/sprite/struct.Sprite.html#structfield.color) | [`SpriteColorLens`](https://docs.rs/bevy_tweening/latest/bevy_tweening/struct.SpriteColorLens.html) |
| [`Transform`](https://docs.rs/bevy/0.6.0/bevy/transform/components/struct.Transform.html) | [`translation`](https://docs.rs/bevy/0.6.0/bevy/transform/components/struct.Transform.html#structfield.translation) | [`TransformPositionLens`](https://docs.rs/bevy_tweening/latest/bevy_tweening/struct.TransformPositionLens.html) |
| | [`rotation`](https://docs.rs/bevy/0.6.0/bevy/transform/components/struct.Transform.html#structfield.rotation) | [`TransformRotationLens`](https://docs.rs/bevy_tweening/latest/bevy_tweening/struct.TransformRotationLens.html) |
| | [`scale`](https://docs.rs/bevy/0.6.0/bevy/transform/components/struct.Transform.html#structfield.scale) | [`TransformScaleLens`](https://docs.rs/bevy_tweening/latest/bevy_tweening/struct.TransformScaleLens.html) |
| [`Style`](https://docs.rs/bevy/0.6.0/bevy/ui/struct.Style.html) | [`position`](https://docs.rs/bevy/0.6.0/bevy/ui/struct.Style.html#structfield.position) | [`UiPositionLens`](https://docs.rs/bevy_tweening/latest/bevy_tweening/struct.UiPositionLens.html) |
| [`Text`](https://docs.rs/bevy/0.6.0/bevy/text/struct.Text.html) | [`TextStyle::color`](https://docs.rs/bevy/0.6.0/bevy/text/struct.TextStyle.html#structfield.color) | [`TextColorLens`](https://docs.rs/bevy_tweening/latest/bevy_tweening/struct.TextColorLens.html) |
### Bevy Assets
| Target Asset | Animated Field | Lens |
|---|---|---|
| [`ColorMaterial`](https://docs.rs/bevy/0.6.0/bevy/sprite/struct.ColorMaterial.html) | [`color`](https://docs.rs/bevy/0.6.0/bevy/sprite/struct.ColorMaterial.html#structfield.color) | [`ColorMaterialColorLens`](https://docs.rs/bevy_tweening/latest/bevy_tweening/struct.ColorMaterialColorLens.html) |
### Custom component support
To be able to animate some fields of a custom component, a custom lens need to be implemented for that component, which **linearly** interpolates the field(s) of that component.
```rust
#[derive(Component)]
struct CustomComponent(f32);
struct CustomLens {
start: f32,
end: f32,
}
impl Lens<CustomComponent> for CustomLens {
fn lerp(&self, target: &mut CustomComponent, ratio: f32) -> f32 {
target.0 = self.start + (self.end - self.start) * ratio;
}
}
```
This process can also be used to interpolate fields of existing Bevy built-in components for which a predfined lens is not provided.
The basic formula for lerp (linear interpolation) is either of:
- `start + (end - start) * scalar`
- `start * (1.0 - scalar) + end * scalar`
The two formulations are mathematically equivalent, but one may be more suited than the other depending on the type interpolated and the operations available, and the potential floating-point precision errors.
Then, the system `component_animator_system::<CustomComponent>` needs to be added to the application.
## Custom asset support
The process is similar to custom components, creating a custom lens for the custom asset. The system to add is `asset_animator_system::<CustomAsset>`.
## Examples
See the [`examples/`](https://github.com/djeedai/bevy_tweening/tree/main/examples) folder.
### [`sprite_color`](examples/sprite_color.rs)
```rust
cargo run --example sprite_color --features="bevy/bevy_winit"
```

### [`transform_rotation`](examples/transform_rotation.rs)
```rust
cargo run --example transform_rotation --features="bevy/bevy_winit"
```

### [`transform_translation`](examples/transform_translation.rs)
```rust
cargo run --example transform_translation --features="bevy/bevy_winit"
```

### [`colormaterial_color`](examples/colormaterial_color.rs)
```rust
cargo run --example colormaterial_color --features="bevy/bevy_winit"
```

### [`ui_position`](examples/ui_position.rs)
```rust
cargo run --example ui_position --features="bevy/bevy_winit"
```

## Ease Functions
Many [ease functions](https://docs.rs/interpolation/0.2.0/interpolation/enum.EaseFunction.html) are available:
- QuadraticIn
- QuadraticOut
- QuadraticInOut
- CubicIn
- CubicOut
- CubicInOut
- QuarticIn
- QuarticOut
- QuarticInOut
- QuinticIn
- QuinticOut
- QuinticInOut
- SineIn
- SineOut
- SineInOut
- CircularIn
- CircularOut
- CircularInOut
- ExponentialIn
- ExponentialOut
- ExponentialInOut
- ElasticIn
- ElasticOut
- ElasticInOut
- BackIn
- BackOut
- BackInOut
- BounceIn
- BounceOut
- BounceInOut
## Compatible Bevy versions
The `main` branch is compatible with the latest Bevy release.
Compatibility of `bevy_tweening` versions:
| `bevy_tweening` | `bevy` |
| :-- | :-- |
| `0.2` | `0.6` |
| `0.1` | `0.5` |
## Comparison with `bevy_easings`
The `bevy_tweening` library started as a fork of [the `bevy_easings` library by François Mocker](https://github.com/vleue/bevy_easings), with the goals to:
- explore an alternative design based on lenses instead of generic types for each easer/animator. This reduces both the number of generic types needed, and hopefully the code size, as well as the number of systems needed to perform the interpolation.
- improve the interpolation of assets to avoid creating many copies like `bevy_easings` does, and instead mutate the assets (and, by similarity, the components too) in-place without making a copy. The in-place mutation also allows a more optimal interpolation limited to modifying the fields of interest only, instead of creating a new copy of the entire component each tick.