You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
5.8 KiB
Rust

use bevy::{
animation::{animated_field, AnimationTarget, AnimationTargetId},
input::{keyboard::KeyboardInput, ButtonState},
prelude::*,
utils::HashMap,
};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, init)
.add_systems(Update, switch)
.run();
}
#[derive(Resource)]
struct AnimationStore(HashMap<String, (AnimationGraphHandle, AnimationNodeIndex)>);
fn init(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
mut animations: ResMut<Assets<AnimationClip>>,
mut graphs: ResMut<Assets<AnimationGraph>>,
) {
commands.spawn(Camera2d);
commands.spawn((
Text2d("Press 1/2/3 to trigger animation".into()),
Node {
top: Val::Px(-50.0),
height: Val::Percent(100.0),
..default()
},
));
let mut hash_map = HashMap::new();
{
let mut a = AnimationClip::default();
let animatable_curve = AnimatableCurve::new(
animated_field!(Transform::translation),
UnevenSampleAutoCurve::new([0.0, 1.0, 2.0, 3.0, 4.0].into_iter().zip([
Vec3::new(200.0, 200.0, 0.0),
Vec3::new(-200.0, 200.0, 0.0),
Vec3::new(-200.0, -200.0, 0.0),
Vec3::new(200.0, -200.0, 0.0),
// in case seamless looping is wanted, the last keyframe should
// be the same as the first one
Vec3::new(200.0, 200.0, 0.0),
]))
.expect("should be able to build translation curve because we pass in valid samples"),
);
a.add_curve_to_target(
AnimationTargetId::from_name(&Name::new("Circle")),
animatable_curve,
);
let (graph, animation_index) = AnimationGraph::from_clip(animations.add(a));
let graph_handle = AnimationGraphHandle(graphs.add(graph));
hash_map.insert("Box".into(), (graph_handle, animation_index));
};
{
let mut a = AnimationClip::default();
let animatable_curve = AnimatableCurve::new(
animated_field!(Transform::translation),
UnevenSampleAutoCurve::new([0.0, 1.0, 2.0].into_iter().zip([
Vec3::new(200.0, 200.0, 0.0),
Vec3::new(-200.0, -200.0, 0.0),
Vec3::new(200.0, 200.0, 0.0),
]))
.expect("should be able to build translation curve because we pass in valid samples"),
);
a.add_curve_to_target(
AnimationTargetId::from_name(&Name::new("Circle")),
animatable_curve,
);
let (graph, animation_index) = AnimationGraph::from_clip(animations.add(a));
let graph_handle = AnimationGraphHandle(graphs.add(graph));
hash_map.insert("Diag1".into(), (graph_handle, animation_index));
};
{
let mut a = AnimationClip::default();
let animatable_curve = AnimatableCurve::new(
animated_field!(Transform::translation),
UnevenSampleAutoCurve::new([0.0, 1.0, 2.0].into_iter().zip([
Vec3::new(-200.0, 200.0, 0.0),
Vec3::new(200.0, -200.0, 0.0),
// in case seamless looping is wanted, the last keyframe should
// be the same as the first one
Vec3::new(-200.0, 200.0, 0.0),
]))
.expect("should be able to build translation curve because we pass in valid samples"),
);
a.add_curve_to_target(
AnimationTargetId::from_name(&Name::new("Circle")),
animatable_curve,
);
let (graph, animation_index) = AnimationGraph::from_clip(animations.add(a));
let graph_handle = AnimationGraphHandle(graphs.add(graph));
hash_map.insert("Diag2".into(), (graph_handle, animation_index));
};
let store = AnimationStore(hash_map);
commands.insert_resource(store);
let shape = meshes.add(Circle::new(50.0));
let material = materials.add(Color::WHITE);
commands.spawn((
Mesh2d(shape),
MeshMaterial2d(material),
Name::new("Circle"),
AnimationPlayer::default(),
));
}
fn switch(
mut commands: Commands,
mut evr_kbd: EventReader<KeyboardInput>,
mut query: Query<(Entity, &Name, &mut AnimationPlayer)>,
store: Res<AnimationStore>,
) {
evr_kbd
.read()
.filter(|ev| ev.state == ButtonState::Pressed)
.for_each(|ev| match ev.key_code {
KeyCode::Digit1 => {
let (g, ai) = store.0.get("Box".into()).unwrap();
let (e, n, mut ap) = query.single_mut();
ap.stop_all().play(ai.clone());
commands.entity(e).insert((
g.clone(),
AnimationTarget {
id: AnimationTargetId::from_name(n),
player: e,
},
));
}
KeyCode::Digit2 => {
let (g, ai) = store.0.get("Diag1".into()).unwrap();
let (e, n, mut ap) = query.single_mut();
ap.stop_all().play(ai.clone());
commands.entity(e).insert((
g.clone(),
AnimationTarget {
id: AnimationTargetId::from_name(n),
player: e,
},
));
}
KeyCode::Digit3 => {
let (g, ai) = store.0.get("Diag2".into()).unwrap();
let (e, n, mut ap) = query.single_mut();
ap.stop_all().play(ai.clone());
commands.entity(e).insert((
g.clone(),
AnimationTarget {
id: AnimationTargetId::from_name(n),
player: e,
},
));
}
_ => (),
});
}