Refactor tonemapping example's image viewer update into two systems (#11519)

# Objective

Alternative to #11515.

Fixes change detection being triggered on the "image viewer image
material" every frame.

## Solution

- Split the megasystem into two separate systems: one to handle drop
events, and one to handle asset change events.
- Move the event reader iteration "outside." so that we're only doing
stuff when there are events.
- Flatten some of the more extreme nesting
- Other bits of cleanup, removing an unnecessary clone and unused
variable.

I think these systems can even run in parallel now, not that it
particularly matters.
This commit is contained in:
Rob Parrett 2024-01-27 09:06:34 -07:00 committed by GitHub
parent 45e920c2e1
commit 7da144bc3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -40,7 +40,8 @@ fn main() {
.add_systems( .add_systems(
Update, Update,
( (
update_image_viewer, drag_drop_image,
resize_image,
toggle_scene, toggle_scene,
toggle_tonemapping_method, toggle_tonemapping_method,
update_color_grading_settings, update_color_grading_settings,
@ -292,58 +293,68 @@ fn setup_image_viewer_scene(
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[allow(clippy::too_many_arguments)] fn drag_drop_image(
fn update_image_viewer( image_mat: Query<&Handle<StandardMaterial>, With<HDRViewer>>,
image_mesh: Query<(&Handle<StandardMaterial>, &Handle<Mesh>), With<HDRViewer>>,
text: Query<Entity, (With<Text>, With<SceneNumber>)>, text: Query<Entity, (With<Text>, With<SceneNumber>)>,
mut materials: ResMut<Assets<StandardMaterial>>, mut materials: ResMut<Assets<StandardMaterial>>,
mut meshes: ResMut<Assets<Mesh>>,
images: Res<Assets<Image>>,
mut drop_events: EventReader<FileDragAndDrop>, mut drop_events: EventReader<FileDragAndDrop>,
mut drop_hovered: Local<bool>,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
mut image_events: EventReader<AssetEvent<Image>>,
mut commands: Commands, mut commands: Commands,
) { ) {
let mut new_image: Option<Handle<Image>> = None; let Some(new_image) = drop_events.read().find_map(|e| match e {
FileDragAndDrop::DroppedFile { path_buf, .. } => {
Some(asset_server.load(path_buf.to_string_lossy().to_string()))
}
_ => None,
}) else {
return;
};
for event in drop_events.read() { for mat_h in &image_mat {
match event { if let Some(mat) = materials.get_mut(mat_h) {
FileDragAndDrop::DroppedFile { path_buf, .. } => { mat.base_color_texture = Some(new_image.clone());
new_image = Some(asset_server.load(&path_buf.to_string_lossy().to_string()));
*drop_hovered = false; // Despawn the image viewer instructions
if let Ok(text_entity) = text.get_single() {
commands.entity(text_entity).despawn();
} }
FileDragAndDrop::HoveredFile { .. } => *drop_hovered = true,
FileDragAndDrop::HoveredFileCanceled { .. } => *drop_hovered = false,
} }
} }
}
for (mat_h, mesh_h) in &image_mesh { fn resize_image(
if let Some(mat) = materials.get_mut(mat_h) { image_mesh: Query<(&Handle<StandardMaterial>, &Handle<Mesh>), With<HDRViewer>>,
if let Some(ref new_image) = new_image { materials: Res<Assets<StandardMaterial>>,
mat.base_color_texture = Some(new_image.clone()); mut meshes: ResMut<Assets<Mesh>>,
images: Res<Assets<Image>>,
mut image_events: EventReader<AssetEvent<Image>>,
) {
for event in image_events.read() {
let (AssetEvent::Added { id } | AssetEvent::Modified { id }) = event else {
continue;
};
if let Ok(text_entity) = text.get_single() { for (mat_h, mesh_h) in &image_mesh {
commands.entity(text_entity).despawn(); let Some(mat) = materials.get(mat_h) else {
} continue;
} };
for event in image_events.read() { let Some(ref base_color_texture) = mat.base_color_texture else {
let image_changed_id = *match event { continue;
AssetEvent::Added { id } | AssetEvent::Modified { id } => id, };
_ => continue,
}; if *id != base_color_texture.id() {
if let Some(base_color_texture) = mat.base_color_texture.clone() { continue;
if image_changed_id == base_color_texture.id() { };
if let Some(image_changed) = images.get(image_changed_id) {
let size = image_changed.size_f32().normalize_or_zero() * 1.4; let Some(image_changed) = images.get(*id) else {
// Resize Mesh continue;
let quad = Mesh::from(shape::Quad::new(size)); };
meshes.insert(mesh_h, quad);
} let size = image_changed.size_f32().normalize_or_zero() * 1.4;
} // Resize Mesh
} let quad = Mesh::from(shape::Quad::new(size));
} meshes.insert(mesh_h, quad);
} }
} }
} }