bevy_sprite3d icon indicating copy to clipboard operation
bevy_sprite3d copied to clipboard

Support update image and atlas through `Sprite`

Open dothanhtrung opened this issue 11 months ago • 1 comments

This PR aims to make this plugin more easier to use in Bevy way and help code is reusable between 2d and 3d.

Usage change

  • Spawning

    • old

      commands.spawn(Sprite3dBuilder {
              image: assets.image.clone(),
              pixels_per_metre: 32.,
              alpha_mode: AlphaMode::Blend,
              unlit: true,
              // pivot: Some(Vec2::new(0.5, 0.5)),
              ..default()
      }.bundle_with_atlas(&mut sprite_params, texture_atlas))
      .insert(AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)));
      
    • new

      commands.spawn((
          Sprite { image: assets.image.clone(), texture_atlas: Some(texture_atlas), ..default() },
          Sprite3d {
              pixels_per_metre: 32.,
              alpha_mode: AlphaMode::Blend,
              unlit: true,
              // pivot: Some(Vec2::new(0.5, 0.5)),
              ..default()
          },
          AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
      ));
      
  • Animate:

    • old

      // Need to call `Sprite3d`, cannot reuse in 2d code
      fn animate_sprite(
          time: Res<Time>,
          mut query: Query<(&mut AnimationTimer, &mut Sprite3d)>,
      ) {
          for (mut timer, mut sprite_3d) in query.iter_mut() {
              timer.tick(time.delta());
              if timer.just_finished() {
                  let length = sprite_3d.texture_atlas_keys.as_ref().unwrap().len();
                  let atlas = sprite_3d.texture_atlas.as_mut().unwrap();
                  atlas.index = (atlas.index + 1) % length;
              }
          }
      }
      
    • new

      // Same with 2d code for animate
      fn animate_sprite(
          time: Res<Time>,
          atlases: Res<Assets<TextureAtlasLayout>>,
          mut query: Query<(&mut AnimationTimer, &mut Sprite)>,
      ) {
          for (mut timer, mut sprite) in query.iter_mut() {
              timer.tick(time.delta());
              if timer.just_finished() {
                  let atlas = sprite.texture_atlas.as_mut().unwrap();
                  if let Some(layouts) = atlases.get(&atlas.layout) {
                      atlas.index = (atlas.index + 1) % layouts.textures.len();
                  }
              }
          }
      }
      
  • Easy to change spritesheet. Sprite can be flipped too:

    // Same code can be used for both 2d and 3d
    fn walk_left (
        spritesheets: Res<MySpriteSheets>
        mut query: Query<&mut Sprite>,
    ) {
        for mut sprite in query.iter_mut() {
            sprite.image = spritesheets.walk_right.clone();
            sprite.flip_x = true;
        }
    }
    

Code change

  • Replace bundle() and bundle_and_atlas() by system bundle_builder.
  • Attributes in Sprite3dBuilder are moved to Sprite3d.
  • Sprite3dBuilder now is used as a marker for entity that is not doing bundle_builder. After that, this component will be removed out of entity.
  • Add system handle_image to handle Sprite image change.
  • Sprite3dParams and Sprite3dBundle are unused and removed.
  • Atlas layout index is changed through Sprite.
  • Does not support changing atlas layout yet.

dothanhtrung avatar Dec 06 '24 11:12 dothanhtrung

This feels like a very good idea, code looks good too

tigerplush avatar Jan 02 '25 09:01 tigerplush

This would greatly improve usage.

It feels a bit mutually exclusive to the other PR by vertessian, which contains more ideas than simplifying the API, but is overall a very elegant solution focusing on the main issue of the crate I had when I needed a quick 3d sprite, and felt a bit overwhelmed.

g4borg avatar Jul 20 '25 21:07 g4borg

Hi @dothanhtrung, this looks good to me. Can you edit the usage in the readme to match? Will merge after.

FraserLee avatar Aug 02 '25 18:08 FraserLee

Thanks. I updated the usage in readme.

dothanhtrung avatar Aug 05 '25 03:08 dothanhtrung