|
|
|
|
@ -99,7 +99,6 @@ impl Plugin for Display3dPlugin {
|
|
|
|
|
.or_else(any_component_removed::<Promoted>()),
|
|
|
|
|
),
|
|
|
|
|
set_board_model.run_if(any_component_added::<game::BoardComponent>()),
|
|
|
|
|
set_title_model.run_if(any_component_added::<TitleText>()),
|
|
|
|
|
set_valid_move_model.run_if(any_component_added::<game::ValidMove>()),
|
|
|
|
|
set_tile_hitbox.run_if(any_component_added::<game::Tile>()),
|
|
|
|
|
dissolve_animation.run_if(any_with_component::<Dissolving>),
|
|
|
|
|
@ -164,17 +163,21 @@ impl Plugin for Display3dPlugin {
|
|
|
|
|
.add_systems(
|
|
|
|
|
OnEnter(GameState::Title),
|
|
|
|
|
(
|
|
|
|
|
intro_title_dissolve,
|
|
|
|
|
fade_title_in,
|
|
|
|
|
fixup_shadows
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
.add_systems(OnExit(GameState::Title), outro_title_dissolve)
|
|
|
|
|
.add_systems(OnExit(GameState::Title), fade_title_out)
|
|
|
|
|
.add_systems(
|
|
|
|
|
Update,
|
|
|
|
|
continue_title
|
|
|
|
|
.run_if(in_state(GameState::Title))
|
|
|
|
|
.run_if(not(any_with_component::<Dissolving>))
|
|
|
|
|
.run_if(just_pressed(KeyCode::Enter).or_else(just_pressed(MouseButton::Left))),
|
|
|
|
|
(
|
|
|
|
|
fade_title
|
|
|
|
|
.run_if(any_with_component::<Fading>),
|
|
|
|
|
continue_title
|
|
|
|
|
.run_if(in_state(GameState::Title))
|
|
|
|
|
.run_if(not(any_with_component::<Fading>))
|
|
|
|
|
.run_if(just_pressed(KeyCode::Enter).or_else(just_pressed(MouseButton::Left))),
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -197,6 +200,12 @@ pub(crate) enum Dissolving {
|
|
|
|
|
Out(f32),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
|
pub(crate) enum Fading {
|
|
|
|
|
In(f32),
|
|
|
|
|
Out(f32),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Resource)]
|
|
|
|
|
pub(crate) struct AnimationSpeed {
|
|
|
|
|
pub movement: f32,
|
|
|
|
|
@ -216,6 +225,7 @@ impl Default for AnimationSpeed {
|
|
|
|
|
struct AssetsMap {
|
|
|
|
|
hitbox_shape: Handle<Mesh>,
|
|
|
|
|
hitbox_material: Handle<StandardMaterial>,
|
|
|
|
|
title_image: Handle<Image>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Load 3d models
|
|
|
|
|
@ -225,6 +235,8 @@ fn load_assets(
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
|
|
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
|
|
|
tweaks_file: Res<tweak::GameTweaks>,
|
|
|
|
|
tweaks: Res<Assets<Tweaks>>,
|
|
|
|
|
) {
|
|
|
|
|
let hitbox_shape = meshes.add(Cuboid::new(1.0, 0.1, 1.0));
|
|
|
|
|
let hitbox_material = materials.add(StandardMaterial {
|
|
|
|
|
@ -234,15 +246,46 @@ fn load_assets(
|
|
|
|
|
alpha_mode: AlphaMode::Blend,
|
|
|
|
|
..default()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let tweak = tweaks
|
|
|
|
|
.get(tweaks_file.handle.clone())
|
|
|
|
|
.expect("Load tweakfile");
|
|
|
|
|
let title_image = tweak.get_handle::<Image>("title_image").unwrap();
|
|
|
|
|
|
|
|
|
|
commands.insert_resource(AssetsMap {
|
|
|
|
|
hitbox_shape,
|
|
|
|
|
hitbox_material,
|
|
|
|
|
title_image,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Initialize the board and pieces
|
|
|
|
|
fn initialize(mut commands: Commands, board: Res<game::Board>, assets: Res<AssetsMap>) {
|
|
|
|
|
debug!("Initializing root");
|
|
|
|
|
// Title
|
|
|
|
|
commands.spawn((
|
|
|
|
|
DisplayState::Display3d,
|
|
|
|
|
Display3d,
|
|
|
|
|
ImageBundle {
|
|
|
|
|
style: Style {
|
|
|
|
|
width: Val::Percent(75.0),
|
|
|
|
|
height: Val::Percent(75.0),
|
|
|
|
|
align_self: AlignSelf::Center,
|
|
|
|
|
justify_self: JustifySelf::Center,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
background_color: Color::WHITE.with_a(0.0).into(),
|
|
|
|
|
image: UiImage {
|
|
|
|
|
texture: assets.title_image.clone(),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
visibility: Visibility::Hidden,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
TitleText,
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
// 3D objects root
|
|
|
|
|
commands
|
|
|
|
|
.spawn((
|
|
|
|
|
SpatialBundle {
|
|
|
|
|
@ -254,22 +297,6 @@ fn initialize(mut commands: Commands, board: Res<game::Board>, assets: Res<Asset
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
debug!("Intializing 3D Board!");
|
|
|
|
|
|
|
|
|
|
// Title
|
|
|
|
|
parent.spawn((
|
|
|
|
|
DisplayState::Display3d,
|
|
|
|
|
Display3d,
|
|
|
|
|
// GameState::Title,
|
|
|
|
|
SceneBundle {
|
|
|
|
|
visibility: Visibility::Hidden,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
TitleText,
|
|
|
|
|
Dissolvable {
|
|
|
|
|
start: 0.0,
|
|
|
|
|
duration: 12.0,
|
|
|
|
|
}, // Marks title text as dissolving
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
// Board
|
|
|
|
|
parent
|
|
|
|
|
.spawn((
|
|
|
|
|
@ -530,45 +557,6 @@ fn set_board_model(
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_title_model(
|
|
|
|
|
mut titles: Query<
|
|
|
|
|
(&mut Handle<Scene>, &mut Transform, &mut Visibility),
|
|
|
|
|
(Added<TitleText>, With<Display3d>),
|
|
|
|
|
>,
|
|
|
|
|
gltfs: Res<Assets<Gltf>>,
|
|
|
|
|
tweaks: Res<Assets<Tweaks>>,
|
|
|
|
|
tweaks_file: Res<tweak::GameTweaks>,
|
|
|
|
|
) {
|
|
|
|
|
let tweak = tweaks
|
|
|
|
|
.get(tweaks_file.handle.clone())
|
|
|
|
|
.expect("Load tweakfile");
|
|
|
|
|
titles
|
|
|
|
|
.iter_mut()
|
|
|
|
|
.for_each(|(mut handle, mut transform, mut visibility)| {
|
|
|
|
|
debug!("Setting title model");
|
|
|
|
|
let assets_handle = tweak
|
|
|
|
|
.get_handle::<Gltf>("display3d_models_assets_file")
|
|
|
|
|
.unwrap();
|
|
|
|
|
let gltf = gltfs.get(assets_handle).expect("Load GLTF content");
|
|
|
|
|
*handle = gltf
|
|
|
|
|
.named_scenes
|
|
|
|
|
.get(
|
|
|
|
|
tweak
|
|
|
|
|
.get::<String>("display3d_models_scenes_title")
|
|
|
|
|
.unwrap()
|
|
|
|
|
.as_str(),
|
|
|
|
|
)
|
|
|
|
|
.expect("Game title model")
|
|
|
|
|
.clone();
|
|
|
|
|
|
|
|
|
|
transform.translation -= Vec3::Y * 0.5;
|
|
|
|
|
transform.rotate_local_z(std::f32::consts::PI);
|
|
|
|
|
transform.rotate_local_y(std::f32::consts::PI / 2.0);
|
|
|
|
|
|
|
|
|
|
*visibility = Visibility::Hidden;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Given a board index returns the Vec3 location in space
|
|
|
|
|
fn board_translation(&BoardIndex { x, y }: &BoardIndex) -> Vec3 {
|
|
|
|
|
// Scale x down by 4 to account for -4..4 scaling
|
|
|
|
|
@ -1269,28 +1257,6 @@ fn monitor_animations(
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn intro_title_dissolve(
|
|
|
|
|
mut query: Query<(Entity, &Dissolvable), With<TitleText>>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
query.iter_mut().for_each(|(entity, dissolving)| {
|
|
|
|
|
commands
|
|
|
|
|
.entity(entity)
|
|
|
|
|
.insert(Dissolving::In(dissolving.duration));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn outro_title_dissolve(
|
|
|
|
|
mut query: Query<(Entity, &Dissolvable), With<TitleText>>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
query.iter_mut().for_each(|(entity, dissolving)| {
|
|
|
|
|
commands
|
|
|
|
|
.entity(entity)
|
|
|
|
|
.insert(Dissolving::Out(dissolving.duration));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn continue_title(mut next_state: ResMut<NextState<GameState>>) {
|
|
|
|
|
next_state.set(GameState::Play)
|
|
|
|
|
}
|
|
|
|
|
@ -1438,3 +1404,71 @@ fn bloom_tweak(
|
|
|
|
|
bloom.intensity = tweak.get::<f32>("color_bloom_intensity").unwrap();
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fade_title_in(
|
|
|
|
|
query: Query<Entity, With<TitleText>>,
|
|
|
|
|
tweaks: Res<Assets<Tweaks>>,
|
|
|
|
|
tweaks_file: Res<tweak::GameTweaks>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
let tweak = tweaks
|
|
|
|
|
.get(tweaks_file.handle.clone())
|
|
|
|
|
.expect("Load tweakfile");
|
|
|
|
|
let seconds = tweak.get::<f32>("title_fade_in_seconds").unwrap();
|
|
|
|
|
|
|
|
|
|
query.iter().for_each(|e| {
|
|
|
|
|
commands.entity(e).insert(Fading::In(seconds));
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fade_title_out(
|
|
|
|
|
query: Query<Entity, With<TitleText>>,
|
|
|
|
|
tweaks: Res<Assets<Tweaks>>,
|
|
|
|
|
tweaks_file: Res<tweak::GameTweaks>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
let tweak = tweaks
|
|
|
|
|
.get(tweaks_file.handle.clone())
|
|
|
|
|
.expect("Load tweakfile");
|
|
|
|
|
let seconds = tweak.get::<f32>("title_fade_in_seconds").unwrap();
|
|
|
|
|
|
|
|
|
|
query.iter().for_each(|e| {
|
|
|
|
|
commands.entity(e).insert(Fading::Out(seconds));
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fade_title(
|
|
|
|
|
mut query: Query<(Entity, &mut BackgroundColor, &mut Visibility, &Fading), With<TitleText>>,
|
|
|
|
|
time: Res<Time>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
query.iter_mut().for_each(|(e, mut bgc, mut v, d)| {
|
|
|
|
|
if *v != Visibility::Inherited {
|
|
|
|
|
*v = Visibility::Inherited;
|
|
|
|
|
}
|
|
|
|
|
// Determine how much to change alpha
|
|
|
|
|
let step = match d {
|
|
|
|
|
Fading::In(duration) => {
|
|
|
|
|
// If we are fully saturated, remove dissolving
|
|
|
|
|
if bgc.0.a() >= 1.0 {
|
|
|
|
|
commands.entity(e).remove::<Fading>().insert(Visibility::Inherited);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delta is simple
|
|
|
|
|
time.delta_seconds() / duration
|
|
|
|
|
},
|
|
|
|
|
Fading::Out(duration) => {
|
|
|
|
|
// If we are fully saturated, remove dissolving
|
|
|
|
|
if bgc.0.a() <= 0.0 {
|
|
|
|
|
commands.entity(e).remove::<Fading>().insert(Visibility::Hidden);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Negative delta because we are fading out
|
|
|
|
|
-(time.delta_seconds() / duration)
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
// Increment/decrement the alpha value
|
|
|
|
|
let new_a = (bgc.0.a() + step).min(1.0).max(0.0);
|
|
|
|
|
bgc.0.set_a(new_a);
|
|
|
|
|
})
|
|
|
|
|
}
|