# Bevy Aseprite Ultra
[![License: MIT or Apache 2.0](https://img.shields.io/badge/License-MIT%20or%20Apache2-blue.svg)](./LICENSE)
[![Crate](https://img.shields.io/crates/v/bevy_aseprite_ultra.svg)](https://crates.io/crates/bevy_aseprite_ultra)
The ultimate bevy aseprite plugin. This plugin allows you to import aseprite files into bevy, with 100% unbreakable
hot reloading. You can also import static sprites from an aseprite atlas type file using slices with functional pivot offsets!
| Bevy Version | Plugin Version |
| -----------: | -------------: |
| 0.14 | 0.2.4 |
| 0.13 | 0.1.0 |
I use it in my game, check it out on my [blog](https://lommix.com)
## Supported aseprite features
- Animations
- Tags
- Frame duration, repeat, and animation direction
- Layer visibility
- Blend modes
- Static slices and pivot offsets
## Features in bevy
- Hot reload anything, anytime, anywhere!
- Full control over animations using Components.
- One shot animations and events when they finish.
- Static sprites with slices. Use aseprite for all your icon and ui needs!
(for hotreload to work, you must have the `file_watcher` cargo dependency for bevy installed)
## Example
```bash
cargo run --example slices
cargo run --example animations
```
![Example](docs/example.gif)
character animation by [Benjamin](https://github.com/headcr4sh)
---
There are two main Bundles added by this plugin, `AsepriteAnimationBundle` and `AsepriteSliceBundle`.
```rust
use bevy::prelude::*;
use bevy_aseprite_ultra::prelude::*;
...
// Load the an animation from an aseprite file
fn spawn_demo_animation(mut cmd : Commands, server : Res){
cmd.spawn(AsepriteAnimationBundle {
aseprite: server.load("player.aseprite"),
transform: Transform::from_translation(Vec3::new(15., -20., 0.)),
animation: Animation::default()
.with_tag("walk-right")
.with_speed(2.)
// Aseprite provides a repeat config per tag, which is beeing ignored on purpose.
.with_repeat(AnimationRepeat::Count(42))
// The direction is provided by the asperite config for the tag, but can be overwritten
// after the animation is loaded.
.with_direction(AnimationDirection::PingPong)
// you can also chain finite animations, loop animations with never finish
.with_then("walk-left", AnimationRepeat::Count(4))
.with_then("walk-up", AnimationRepeat::Loop)
// you can override the default sprite settings here
sprite: Sprite {
flip_x: true,
..default()
},
..default()
});
}
// Load a static slice from an aseprite file
fn spawn_demo_static_slice(mut cmd : Commands, server : Res){
cmd.spawn(AsepriteSliceBundle {
slice: "ghost_blue".into(),
// you can override the default sprite settings here
// the `rect` will be overriden by the slice
// if there is a pivot provided in the aseprite slice, the `anchor` will be overwritten
// and changes the origin of rotation.
sprite: Sprite {
flip_x: true,
..default()
},
aseprite: server.load("ghost_slices.aseprite"),
transform: Transform::from_translation(Vec3::new(32., 0., 0.)),
..default()
});
}
// animation events - tell me when the animation is done
// this is useful for one shot animations like explosions
fn despawn_on_finish(mut events: EventReader, mut cmd : Commands){
for event in events.read() {
match event {
AnimationEvents::Finished(entity) => cmd.entity(*entity).despawn_recursive(),
// you can also listen for loop cycle repeats
AnimationEvents::LoopCycleFinished(_entity) => (),
};
}
}
```
## Bevy Ui
There is also an Ui Bundle for Bevy Ui Nodes!
```rust
// animations in bevy ui
cmd.spawn((
ButtonBundle{
// node config
..default()
},
AsepriteAnimationUiBundle{
aseprite: server.load("yourfile.aseprite"),
animation: Animation{
tag : Some("idle".to_string()),
..default()
},
..default()
},
));
// slices in bevy ui
cmd.spawn((
ImageBundle{
// node config
..default()
},
AsepriteSliceUiBundle{
aseprite: server.load("yourfile.aseprite"),
slice: AsepriteSlice::from("your_slice"),
..default()
},
));
```