Skip to content

Commit

Permalink
Sprite change image (#3207)
Browse files Browse the repository at this point in the history
# Objective

- Changing the underlying image would not update a sprite

## Solution

- 'Detect' if the underlying image changes to update the sprite

Currently, we don't support change detection on `RenderAssets`, so we have to manually check it. 
This method at least maintains the bind groups when the image isn't changing. They were cached, so I assume that's important.

This gives us correct behaviour here.

Co-authored-by: Carter Anderson <[email protected]>
  • Loading branch information
DJMcNab and cart committed Dec 1, 2021
1 parent 2def902 commit 5fe73be
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 4 deletions.
5 changes: 2 additions & 3 deletions pipelined/bevy_render2/src/render_asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,8 @@ fn extract_render_asset<A: RenderAsset>(
changed_assets.insert(handle);
}
AssetEvent::Removed { handle } => {
if !changed_assets.remove(handle) {
removed.push(handle.clone_weak());
}
changed_assets.remove(handle);
removed.push(handle.clone_weak());
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions pipelined/bevy_sprite2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ impl Plugin for SpritePlugin {
.init_resource::<SpecializedPipelines<SpritePipeline>>()
.init_resource::<SpriteMeta>()
.init_resource::<ExtractedSprites>()
.init_resource::<SpriteAssetEvents>()
.add_system_to_stage(RenderStage::Extract, render::extract_sprites)
.add_system_to_stage(RenderStage::Extract, render::extract_sprite_events)
.add_system_to_stage(RenderStage::Prepare, render::prepare_sprites)
.add_system_to_stage(RenderStage::Queue, queue_sprites);

Expand Down
43 changes: 42 additions & 1 deletion pipelined/bevy_sprite2/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
texture_atlas::{TextureAtlas, TextureAtlasSprite},
Rect, Sprite, SPRITE_SHADER_HANDLE,
};
use bevy_asset::{Assets, Handle};
use bevy_asset::{AssetEvent, Assets, Handle};
use bevy_core::FloatOrd;
use bevy_core_pipeline::Transparent2d;
use bevy_ecs::{
Expand Down Expand Up @@ -172,6 +172,37 @@ pub struct ExtractedSprites {
sprites: Vec<ExtractedSprite>,
}

#[derive(Default)]
pub struct SpriteAssetEvents {
images: Vec<AssetEvent<Image>>,
}

pub fn extract_sprite_events(
mut render_world: ResMut<RenderWorld>,
mut image_events: EventReader<AssetEvent<Image>>,
) {
let mut events = render_world
.get_resource_mut::<SpriteAssetEvents>()
.unwrap();
let SpriteAssetEvents { ref mut images } = *events;
images.clear();

for image in image_events.iter() {
// AssetEvent: !Clone
images.push(match image {
AssetEvent::Created { handle } => AssetEvent::Created {
handle: handle.clone_weak(),
},
AssetEvent::Modified { handle } => AssetEvent::Modified {
handle: handle.clone_weak(),
},
AssetEvent::Removed { handle } => AssetEvent::Removed {
handle: handle.clone_weak(),
},
});
}
}

pub fn extract_sprites(
mut render_world: ResMut<RenderWorld>,
images: Res<Assets<Image>>,
Expand Down Expand Up @@ -453,7 +484,17 @@ pub fn queue_sprites(
gpu_images: Res<RenderAssets<Image>>,
mut sprite_batches: Query<(Entity, &SpriteBatch)>,
mut views: Query<&mut RenderPhase<Transparent2d>>,
events: Res<SpriteAssetEvents>,
) {
// If an image has changed, the GpuImage has (probably) changed
for event in &events.images {
match event {
AssetEvent::Created { .. } => None,
AssetEvent::Modified { handle } => image_bind_groups.values.remove(handle),
AssetEvent::Removed { handle } => image_bind_groups.values.remove(handle),
};
}

if let Some(view_binding) = view_uniforms.uniforms.binding() {
sprite_meta.view_bind_group = Some(render_device.create_bind_group(&BindGroupDescriptor {
entries: &[BindGroupEntry {
Expand Down

0 comments on commit 5fe73be

Please sign in to comment.