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,50 +293,64 @@ 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 {
for event in drop_events.read() {
match event {
FileDragAndDrop::DroppedFile { path_buf, .. } => { FileDragAndDrop::DroppedFile { path_buf, .. } => {
new_image = Some(asset_server.load(&path_buf.to_string_lossy().to_string())); Some(asset_server.load(path_buf.to_string_lossy().to_string()))
*drop_hovered = false;
}
FileDragAndDrop::HoveredFile { .. } => *drop_hovered = true,
FileDragAndDrop::HoveredFileCanceled { .. } => *drop_hovered = false,
}
} }
_ => None,
}) else {
return;
};
for (mat_h, mesh_h) in &image_mesh { for mat_h in &image_mat {
if let Some(mat) = materials.get_mut(mat_h) { if let Some(mat) = materials.get_mut(mat_h) {
if let Some(ref new_image) = new_image {
mat.base_color_texture = Some(new_image.clone()); mat.base_color_texture = Some(new_image.clone());
// Despawn the image viewer instructions
if let Ok(text_entity) = text.get_single() { if let Ok(text_entity) = text.get_single() {
commands.entity(text_entity).despawn(); commands.entity(text_entity).despawn();
} }
} }
}
}
fn resize_image(
image_mesh: Query<(&Handle<StandardMaterial>, &Handle<Mesh>), With<HDRViewer>>,
materials: Res<Assets<StandardMaterial>>,
mut meshes: ResMut<Assets<Mesh>>,
images: Res<Assets<Image>>,
mut image_events: EventReader<AssetEvent<Image>>,
) {
for event in image_events.read() { for event in image_events.read() {
let image_changed_id = *match event { let (AssetEvent::Added { id } | AssetEvent::Modified { id }) = event else {
AssetEvent::Added { id } | AssetEvent::Modified { id } => id, continue;
_ => continue,
}; };
if let Some(base_color_texture) = mat.base_color_texture.clone() {
if image_changed_id == base_color_texture.id() { for (mat_h, mesh_h) in &image_mesh {
if let Some(image_changed) = images.get(image_changed_id) { let Some(mat) = materials.get(mat_h) else {
continue;
};
let Some(ref base_color_texture) = mat.base_color_texture else {
continue;
};
if *id != base_color_texture.id() {
continue;
};
let Some(image_changed) = images.get(*id) else {
continue;
};
let size = image_changed.size_f32().normalize_or_zero() * 1.4; let size = image_changed.size_f32().normalize_or_zero() * 1.4;
// Resize Mesh // Resize Mesh
let quad = Mesh::from(shape::Quad::new(size)); let quad = Mesh::from(shape::Quad::new(size));
@ -343,10 +358,6 @@ fn update_image_viewer(
} }
} }
} }
}
}
}
}
fn toggle_scene( fn toggle_scene(
keys: Res<ButtonInput<KeyCode>>, keys: Res<ButtonInput<KeyCode>>,