Sprite change image (#3207)
# 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 <mcanders1@gmail.com>
This commit is contained in:
		
							parent
							
								
									2def9027d7
								
							
						
					
					
						commit
						5fe73be2b5
					
				| @ -102,12 +102,11 @@ fn extract_render_asset<A: RenderAsset>( | |||||||
|                 changed_assets.insert(handle); |                 changed_assets.insert(handle); | ||||||
|             } |             } | ||||||
|             AssetEvent::Removed { handle } => { |             AssetEvent::Removed { handle } => { | ||||||
|                 if !changed_assets.remove(handle) { |                 changed_assets.remove(handle); | ||||||
|                 removed.push(handle.clone_weak()); |                 removed.push(handle.clone_weak()); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     let mut extracted_assets = Vec::new(); |     let mut extracted_assets = Vec::new(); | ||||||
|     for handle in changed_assets.drain() { |     for handle in changed_assets.drain() { | ||||||
|  | |||||||
| @ -43,7 +43,9 @@ impl Plugin for SpritePlugin { | |||||||
|             .init_resource::<SpecializedPipelines<SpritePipeline>>() |             .init_resource::<SpecializedPipelines<SpritePipeline>>() | ||||||
|             .init_resource::<SpriteMeta>() |             .init_resource::<SpriteMeta>() | ||||||
|             .init_resource::<ExtractedSprites>() |             .init_resource::<ExtractedSprites>() | ||||||
|  |             .init_resource::<SpriteAssetEvents>() | ||||||
|             .add_system_to_stage(RenderStage::Extract, render::extract_sprites) |             .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::Prepare, render::prepare_sprites) | ||||||
|             .add_system_to_stage(RenderStage::Queue, queue_sprites); |             .add_system_to_stage(RenderStage::Queue, queue_sprites); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ use crate::{ | |||||||
|     texture_atlas::{TextureAtlas, TextureAtlasSprite}, |     texture_atlas::{TextureAtlas, TextureAtlasSprite}, | ||||||
|     Rect, Sprite, SPRITE_SHADER_HANDLE, |     Rect, Sprite, SPRITE_SHADER_HANDLE, | ||||||
| }; | }; | ||||||
| use bevy_asset::{Assets, Handle}; | use bevy_asset::{AssetEvent, Assets, Handle}; | ||||||
| use bevy_core::FloatOrd; | use bevy_core::FloatOrd; | ||||||
| use bevy_core_pipeline::Transparent2d; | use bevy_core_pipeline::Transparent2d; | ||||||
| use bevy_ecs::{ | use bevy_ecs::{ | ||||||
| @ -172,6 +172,37 @@ pub struct ExtractedSprites { | |||||||
|     sprites: Vec<ExtractedSprite>, |     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( | pub fn extract_sprites( | ||||||
|     mut render_world: ResMut<RenderWorld>, |     mut render_world: ResMut<RenderWorld>, | ||||||
|     images: Res<Assets<Image>>, |     images: Res<Assets<Image>>, | ||||||
| @ -453,7 +484,17 @@ pub fn queue_sprites( | |||||||
|     gpu_images: Res<RenderAssets<Image>>, |     gpu_images: Res<RenderAssets<Image>>, | ||||||
|     mut sprite_batches: Query<(Entity, &SpriteBatch)>, |     mut sprite_batches: Query<(Entity, &SpriteBatch)>, | ||||||
|     mut views: Query<&mut RenderPhase<Transparent2d>>, |     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() { |     if let Some(view_binding) = view_uniforms.uniforms.binding() { | ||||||
|         sprite_meta.view_bind_group = Some(render_device.create_bind_group(&BindGroupDescriptor { |         sprite_meta.view_bind_group = Some(render_device.create_bind_group(&BindGroupDescriptor { | ||||||
|             entries: &[BindGroupEntry { |             entries: &[BindGroupEntry { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Daniel McNab
						Daniel McNab