diff --git a/src/display3d.rs b/src/display3d.rs index 801d55a..2b0e340 100644 --- a/src/display3d.rs +++ b/src/display3d.rs @@ -4,23 +4,18 @@ use crate::{ tweak::Tweaks, }; use bevy::{ - animation::RepeatAnimation, - core_pipeline::{ + animation::RepeatAnimation, core_pipeline::{ experimental::taa::{TemporalAntiAliasPlugin, TemporalAntiAliasSettings}, prepass::MotionVectorPrepass, tonemapping::{DebandDither, Tonemapping}, Skybox, - }, - input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel}, - pbr::{ + }, input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel}, pbr::{ ExtendedMaterial, MaterialExtension, OpaqueRendererMethod, ScreenSpaceAmbientOcclusionBundle, ScreenSpaceAmbientOcclusionSettings, - }, - render::{ + }, render::{ render_resource::{AsBindGroup, ShaderRef, TextureViewDescriptor, TextureViewDimension}, view::ColorGrading, - }, - window::PrimaryWindow, + }, utils::HashMap, window::PrimaryWindow }; use tweaks::*; @@ -75,6 +70,7 @@ impl Plugin for Display3dPlugin { .or_else(any_component_added::) .or_else(on_event::>()), ), + setup_capture_piece.run_if(any_component_added::), capture_piece.run_if(any_with_component::()), ), ) @@ -1283,6 +1279,58 @@ impl MaterialExtension for DissolveExtension { #[derive(Debug, Component, Clone)] struct Backup(T); +/// Sets up all pieces to have an associated "dissolve" material ready for capture +fn setup_capture_piece( + // Only process newly created pieces (we do not delete pieces at runtime) + events: Query>, + // Children of pieces are the actual meshes that need materials + children: Query<&Children>, + // All entities with materials are candidates for this procedure + query: Query<(Entity, &Handle)>, + // Used to create DissovleMaterial + standard_materials: Res>, + // Used to create Handle + mut dissolve_materials: ResMut>, + // Used to insert Backup(Handle); + mut commands: Commands, + // Cache dissolve textures that have already been created + mut cache: Local, Handle>>, +) { + events.iter().for_each(|entity| { + query + .iter_many(children.iter_descendants(entity)) + .for_each(|(child, std_handle)| { + let dis_handle = match cache.get(std_handle) { + // We have not seen this material, so create a new dissolve material + None => { + // Extension we will add to existing gltf-sourced materials + let extension = DissolveExtension { percentage: 1.0 }; + // Base material we will extend for the duration of the dissolve effect + let mut base = standard_materials + .get(std_handle) + .expect("Resolve material data") + .clone(); + + base.opaque_render_method = OpaqueRendererMethod::Auto; + base.alpha_mode = AlphaMode::Mask(0.5); + + dissolve_materials.add(ExtendedMaterial { base, extension }) + }, + Some(dis_handle) => dis_handle.clone(), + }; + + cache.insert(std_handle.clone(), dis_handle.clone()); + + commands + .entity(child) + .insert(dis_handle.clone()) + .insert(Backup(std_handle.clone())) + .remove::>(); + }) + } + ); +} + /// When a piece is captured... /// 1. Play a cool "captured" animation and a neat sound /// 2. Move the piece to the side of the board @@ -1295,11 +1343,11 @@ fn capture_piece( (With, With), >, mut state: Local>, - standard_materials: ResMut>, + mut kids: Local>, + mut prog: Local, mut dissolve_materials: ResMut>, - object_standard_materials: Query<&Handle>, - object_dissolve_materials: Query<&Handle>, - backup_material: Query<&Backup>>, + object_standard_materials: Query<(Entity, &Handle, &Backup>)>, + object_dissolve_materials: Query<(Entity, &Handle, &Backup>)>, children: Query<&Children>, mut commands: Commands, time: Res