|
|
|
@ -12,9 +12,9 @@ use bevy::{
|
|
|
|
Skybox,
|
|
|
|
Skybox,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
|
|
|
|
input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
|
|
|
|
pbr::{ScreenSpaceAmbientOcclusionBundle, ScreenSpaceAmbientOcclusionSettings},
|
|
|
|
pbr::{ScreenSpaceAmbientOcclusionBundle, ScreenSpaceAmbientOcclusionSettings, MaterialExtension, ExtendedMaterial, OpaqueRendererMethod},
|
|
|
|
render::{
|
|
|
|
render::{
|
|
|
|
render_resource::{TextureViewDescriptor, TextureViewDimension},
|
|
|
|
render_resource::{TextureViewDescriptor, TextureViewDimension, ShaderRef,AsBindGroup},
|
|
|
|
view::ColorGrading,
|
|
|
|
view::ColorGrading,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
window::PrimaryWindow,
|
|
|
|
window::PrimaryWindow,
|
|
|
|
@ -25,7 +25,10 @@ pub(crate) struct Display3dPlugin;
|
|
|
|
|
|
|
|
|
|
|
|
impl Plugin for Display3dPlugin {
|
|
|
|
impl Plugin for Display3dPlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
app.add_plugins(TemporalAntiAliasPlugin)
|
|
|
|
app.add_plugins((
|
|
|
|
|
|
|
|
TemporalAntiAliasPlugin,
|
|
|
|
|
|
|
|
MaterialPlugin::<DissolveMaterial>::default(),
|
|
|
|
|
|
|
|
))
|
|
|
|
.insert_resource(Msaa::Off)
|
|
|
|
.insert_resource(Msaa::Off)
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(
|
|
|
|
OnExit(GameState::Loading),
|
|
|
|
OnExit(GameState::Loading),
|
|
|
|
@ -1246,43 +1249,90 @@ pub(super) mod tweaks {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Type expressing the extended material of standardMaterial + dissolveMaterial
|
|
|
|
|
|
|
|
type DissolveMaterial = ExtendedMaterial<StandardMaterial, DissolveExtension>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Material extension for dissolving effect
|
|
|
|
|
|
|
|
#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
|
|
|
|
|
|
|
|
struct DissolveExtension {
|
|
|
|
|
|
|
|
#[uniform(100)]
|
|
|
|
|
|
|
|
percentage: f32,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl MaterialExtension for DissolveExtension {
|
|
|
|
|
|
|
|
fn fragment_shader() -> ShaderRef {
|
|
|
|
|
|
|
|
"shaders/dissolve.wgsl".into()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Component for 'backing up' components which are temporarily not used
|
|
|
|
|
|
|
|
#[derive(Debug, Component, Clone)]
|
|
|
|
|
|
|
|
struct Backup<T: Component>(T);
|
|
|
|
|
|
|
|
|
|
|
|
/// When a piece is captured...
|
|
|
|
/// When a piece is captured...
|
|
|
|
/// 1. Play a cool "captured" animation and a neat sound
|
|
|
|
/// 1. Play a cool "captured" animation and a neat sound
|
|
|
|
/// 2. Move the piece to the side of the board
|
|
|
|
/// 2. Move the piece to the side of the board
|
|
|
|
/// 3. Play the same "captured" animation in reverse
|
|
|
|
/// 3. Play the same "captured" animation in reverse
|
|
|
|
/// The animation is like a 'beam me up scotty' sorta thing.
|
|
|
|
/// The animation is like a 'beam me up scotty' sorta thing.
|
|
|
|
fn capture_piece(
|
|
|
|
fn capture_piece(
|
|
|
|
mut events: Query<Entity, (With<Display3d>, Added<game::Captured>)>,
|
|
|
|
events: Query<Entity, (With<Display3d>, Added<game::Captured>)>,
|
|
|
|
mut query: Query<(&mut Visibility, &mut Transform, &Side), (With<Display3d>, With<game::Captured>)>,
|
|
|
|
mut query: Query<(&mut Visibility, &mut Transform, &Side), (With<Display3d>, With<game::Captured>)>,
|
|
|
|
mut state: Local<Option<game::CaptureFlow>>,
|
|
|
|
mut state: Local<Option<game::CaptureFlow>>,
|
|
|
|
|
|
|
|
standard_materials: ResMut<Assets<StandardMaterial>>,
|
|
|
|
|
|
|
|
mut dissolve_materials: ResMut<Assets<DissolveMaterial>>,
|
|
|
|
|
|
|
|
object_standard_materials: Query<&Handle<StandardMaterial>>,
|
|
|
|
|
|
|
|
object_dissolve_materials: Query<&Handle<DissolveMaterial>>,
|
|
|
|
|
|
|
|
backup_material: Query<&Backup<Handle<StandardMaterial>>>,
|
|
|
|
|
|
|
|
children: Query<&Children>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
time: Res<Time>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
|
|
|
|
let duration: f32 = 2.0;
|
|
|
|
|
|
|
|
|
|
|
|
match *state {
|
|
|
|
match *state {
|
|
|
|
Some(s) => {
|
|
|
|
Some(s) => {
|
|
|
|
match s {
|
|
|
|
match s {
|
|
|
|
game::CaptureFlow::FadeOut(entity) => {
|
|
|
|
game::CaptureFlow::FadeOut(entity) => {
|
|
|
|
let (mut v, _, _) = query
|
|
|
|
// TODO: Do we need this?
|
|
|
|
|
|
|
|
let (_, _, _) = query
|
|
|
|
.get_mut(entity)
|
|
|
|
.get_mut(entity)
|
|
|
|
.expect("Visibility and Transform of captured piece");
|
|
|
|
.expect("Visibility and Transform of captured piece");
|
|
|
|
|
|
|
|
|
|
|
|
// Play fade-out animation
|
|
|
|
// Play fade-out animation
|
|
|
|
{
|
|
|
|
{
|
|
|
|
error!("Run fade-out animation");
|
|
|
|
object_dissolve_materials
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|handle| {
|
|
|
|
|
|
|
|
let extended_material = dissolve_materials
|
|
|
|
|
|
|
|
.get_mut(handle)
|
|
|
|
|
|
|
|
.expect("Get the dissolve material");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate how much of the animation has passed
|
|
|
|
|
|
|
|
let delta = time.delta_seconds() / duration;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Change the material's value to create animation
|
|
|
|
|
|
|
|
extended_material.extension.percentage -= delta; // TODO: Tweak this timing
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Play fade out animation {:?} {:?}", delta, extended_material.extension.percentage);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if extended_material.extension.percentage <= 0.0 {
|
|
|
|
|
|
|
|
// Set to exactly 0 for simplicity
|
|
|
|
|
|
|
|
extended_material.extension.percentage = 0.0;
|
|
|
|
|
|
|
|
|
|
|
|
// Move to next state now that animation is done
|
|
|
|
// Move to next state now that animation is done
|
|
|
|
*state = s.next();
|
|
|
|
*state = s.next();
|
|
|
|
|
|
|
|
}
|
|
|
|
// Hide piece now that animation is done
|
|
|
|
});
|
|
|
|
*v = Visibility::Hidden;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
game::CaptureFlow::Store(entity) => {
|
|
|
|
game::CaptureFlow::Store(entity) => {
|
|
|
|
let (_, mut t, side) = query
|
|
|
|
let (mut v, mut t, side) = query
|
|
|
|
.get_mut(entity)
|
|
|
|
.get_mut(entity)
|
|
|
|
.expect("Visibility and Transform of captured piece");
|
|
|
|
.expect("Visibility and Transform of captured piece");
|
|
|
|
|
|
|
|
|
|
|
|
// Move piece to next spot at side of table
|
|
|
|
// Hide piece now that animation is done
|
|
|
|
error!("Move piece to side of table");
|
|
|
|
*v = Visibility::Hidden;
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Dynamic number based on side's score
|
|
|
|
// TODO: Dynamic number based on side's score
|
|
|
|
t.translation = capture_translation(side, 1);
|
|
|
|
t.translation = capture_translation(side, 1);
|
|
|
|
|
|
|
|
|
|
|
|
@ -1298,18 +1348,67 @@ fn capture_piece(
|
|
|
|
|
|
|
|
|
|
|
|
// Play fade-in animation
|
|
|
|
// Play fade-in animation
|
|
|
|
{
|
|
|
|
{
|
|
|
|
error!("Run fade-in animation");
|
|
|
|
object_dissolve_materials
|
|
|
|
// When animation is done, move to next phase of flow
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|handle| {
|
|
|
|
|
|
|
|
let extended_material = dissolve_materials
|
|
|
|
|
|
|
|
.get_mut(handle)
|
|
|
|
|
|
|
|
.expect("Get the dissolve material");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate how much of the animation has passed
|
|
|
|
|
|
|
|
let delta = time.delta_seconds() / duration;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Change the material's value to create animation
|
|
|
|
|
|
|
|
extended_material.extension.percentage += delta; // TODO: Tweak this timing
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Play fade in animation {:?} {:?}", delta, extended_material.extension.percentage);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if extended_material.extension.percentage >= 1.0 {
|
|
|
|
|
|
|
|
// Move to next state now that animation is done
|
|
|
|
*state = s.next();
|
|
|
|
*state = s.next();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Remove the captured component for bookkeeping
|
|
|
|
// Remove the captured component for bookkeeping
|
|
|
|
commands.entity(entity).remove::<game::Captured>();
|
|
|
|
commands.entity(entity).remove::<game::Captured>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Remove the dissolve material
|
|
|
|
|
|
|
|
commands.entity(entity).remove::<Handle<DissolveMaterial>>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Re-add the original material
|
|
|
|
|
|
|
|
let orig = backup_material.get(entity).expect("Entity has original material");
|
|
|
|
|
|
|
|
commands.entity(entity).insert(orig.0.clone());
|
|
|
|
|
|
|
|
commands.entity(entity).remove::<Backup<Handle<StandardMaterial>>>();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
None => {
|
|
|
|
*state = events.iter().next().map(|entity| {
|
|
|
|
*state = events.iter().next().map(|entity| {
|
|
|
|
|
|
|
|
children
|
|
|
|
|
|
|
|
.iter_descendants(entity)
|
|
|
|
|
|
|
|
.filter_map(|e| {
|
|
|
|
|
|
|
|
object_standard_materials.get(e).ok().map(|h| (e, h))
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.for_each(|(child, handle)| {
|
|
|
|
|
|
|
|
// 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(handle).expect("Resolve material data").clone();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
base.opaque_render_method = OpaqueRendererMethod::Auto;
|
|
|
|
|
|
|
|
base.alpha_mode = AlphaMode::Mask(0.5);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commands.entity(child).insert(
|
|
|
|
|
|
|
|
dissolve_materials.add(ExtendedMaterial {
|
|
|
|
|
|
|
|
base,
|
|
|
|
|
|
|
|
extension,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
).insert(Backup(handle.clone()))
|
|
|
|
|
|
|
|
.remove::<Handle<StandardMaterial>>();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set the next state to start fading out
|
|
|
|
game::CaptureFlow::FadeOut(entity)
|
|
|
|
game::CaptureFlow::FadeOut(entity)
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|