|
|
|
|
@ -1,15 +1,23 @@
|
|
|
|
|
// TODO: Camera Animations
|
|
|
|
|
// Intro animation
|
|
|
|
|
// Turn changing animations
|
|
|
|
|
// TODO: Pickup/put-down sound in 3d
|
|
|
|
|
// TODO: Unify the selection logic
|
|
|
|
|
// If you select in 2d, it should "be" selected in 3d.
|
|
|
|
|
// And if you select in 3d, 2d is selected.
|
|
|
|
|
// If you select in 2d, it should "be" selected in 3d.
|
|
|
|
|
// And if you select in 3d, 2d is selected.
|
|
|
|
|
// TODO: De-select pieces
|
|
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
|
game::{Board, BoardIndex, Piece, Side},
|
|
|
|
|
prelude::*,
|
|
|
|
|
};
|
|
|
|
|
use bevy::{
|
|
|
|
|
core_pipeline::Skybox,
|
|
|
|
|
ecs::removal_detection::RemovedComponentReader,
|
|
|
|
|
input::mouse::{MouseButtonInput, MouseMotion, MouseWheel},
|
|
|
|
|
render::render_resource::{TextureViewDescriptor, TextureViewDimension},
|
|
|
|
|
core_pipeline::{tonemapping::DebandDither, Skybox},
|
|
|
|
|
input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
|
|
|
|
|
render::{
|
|
|
|
|
render_resource::{TextureViewDescriptor, TextureViewDimension},
|
|
|
|
|
view::ColorGrading,
|
|
|
|
|
},
|
|
|
|
|
window::PrimaryWindow,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@ -25,13 +33,14 @@ impl Plugin for Display3dPlugin {
|
|
|
|
|
.add_systems(
|
|
|
|
|
Update,
|
|
|
|
|
(
|
|
|
|
|
hydrate_camera, // TODO: add run_if...
|
|
|
|
|
menu::exit_to_menu.run_if(in_state(GameState::Display3d)),
|
|
|
|
|
set_piece_model.run_if(any_component_added::<Piece>),
|
|
|
|
|
set_board_model.run_if(any_component_added::<game::BoardComponent>),
|
|
|
|
|
set_tile_hitbox.run_if(any_component_added::<game::Tile>),
|
|
|
|
|
set_piece_position.run_if(any_component_changed::<BoardIndex>),
|
|
|
|
|
set_piece_texture.run_if(any_component_changed::<Side>),
|
|
|
|
|
select_3d
|
|
|
|
|
select
|
|
|
|
|
.run_if(in_state(GameState::Display3d))
|
|
|
|
|
.run_if(on_event::<MouseButtonInput>()),
|
|
|
|
|
pick_up.run_if(any_component_added::<game::Selected>),
|
|
|
|
|
@ -42,15 +51,18 @@ impl Plugin for Display3dPlugin {
|
|
|
|
|
Update,
|
|
|
|
|
(
|
|
|
|
|
move_camera
|
|
|
|
|
.run_if(resource_exists::<debug::DebugEnabled>())
|
|
|
|
|
.run_if(in_state(GameState::Display3d))
|
|
|
|
|
.run_if(on_event::<MouseMotion>()),
|
|
|
|
|
gizmo_system.run_if(in_state(GameState::Display3d)),
|
|
|
|
|
gizmo_system
|
|
|
|
|
.run_if(resource_exists::<debug::DebugEnabled>())
|
|
|
|
|
.run_if(in_state(GameState::Display3d)),
|
|
|
|
|
mouse_zoom
|
|
|
|
|
.run_if(resource_exists::<debug::DebugEnabled>())
|
|
|
|
|
.run_if(in_state(GameState::Display3d))
|
|
|
|
|
.run_if(on_event::<MouseWheel>()),
|
|
|
|
|
selected_gizmo,
|
|
|
|
|
)
|
|
|
|
|
.run_if(resource_exists::<debug::DebugEnabled>()),
|
|
|
|
|
selected_gizmo.run_if(resource_exists::<debug::DebugEnabled>()),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
.add_systems(
|
|
|
|
|
OnEnter(GameState::Display3d),
|
|
|
|
|
@ -98,27 +110,6 @@ fn load_assets(
|
|
|
|
|
|
|
|
|
|
/// Initialize the 3d board
|
|
|
|
|
fn initialize(mut commands: Commands, board: Res<game::Board>, assets: Res<AssetsMap>) {
|
|
|
|
|
info!("Initialize 3d camera");
|
|
|
|
|
// let handle = server.load("images/mars.hdr");
|
|
|
|
|
commands.spawn((
|
|
|
|
|
Display3d,
|
|
|
|
|
Camera3dBundle {
|
|
|
|
|
camera: Camera {
|
|
|
|
|
is_active: false,
|
|
|
|
|
hdr: true,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
transform: Transform::from_xyz(0.0, 20.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
Skybox(assets.skybox.clone()),
|
|
|
|
|
EnvironmentMapLight {
|
|
|
|
|
diffuse_map: assets.skybox.clone(),
|
|
|
|
|
specular_map: assets.skybox.clone(),
|
|
|
|
|
},
|
|
|
|
|
UiCameraConfig { show_ui: true },
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
info!("Initializing root");
|
|
|
|
|
commands
|
|
|
|
|
.spawn((
|
|
|
|
|
@ -159,6 +150,7 @@ fn initialize(mut commands: Commands, board: Res<game::Board>, assets: Res<Asset
|
|
|
|
|
visibility: Visibility::Hidden,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
game::Selectable,
|
|
|
|
|
));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@ -172,12 +164,55 @@ fn initialize(mut commands: Commands, board: Res<game::Board>, assets: Res<Asset
|
|
|
|
|
piece.clone(),
|
|
|
|
|
index.clone(),
|
|
|
|
|
SceneBundle { ..default() },
|
|
|
|
|
game::Selectable,
|
|
|
|
|
));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn hydrate_camera(
|
|
|
|
|
events: Query<(&Name, Entity), Added<Camera>>,
|
|
|
|
|
assets: Res<AssetsMap>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
events
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|(name, _)| name.as_str() == "GameCam")
|
|
|
|
|
.for_each(|(_, entity)| {
|
|
|
|
|
info!("Initialize 3d camera");
|
|
|
|
|
commands.entity(entity).insert((
|
|
|
|
|
Display3d,
|
|
|
|
|
Camera3dBundle {
|
|
|
|
|
camera: Camera {
|
|
|
|
|
is_active: false,
|
|
|
|
|
hdr: true,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
transform: Transform::from_xyz(0.0, 20.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
|
|
|
|
|
dither: DebandDither::Enabled,
|
|
|
|
|
color_grading: ColorGrading { ..default() },
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
Skybox(assets.skybox.clone()),
|
|
|
|
|
EnvironmentMapLight {
|
|
|
|
|
diffuse_map: assets.skybox.clone(),
|
|
|
|
|
specular_map: assets.skybox.clone(),
|
|
|
|
|
},
|
|
|
|
|
UiCameraConfig { show_ui: true },
|
|
|
|
|
FogSettings {
|
|
|
|
|
color: Color::WHITE,
|
|
|
|
|
falloff: FogFalloff::from_visibility_colors(
|
|
|
|
|
100.0,
|
|
|
|
|
Color::ORANGE_RED,
|
|
|
|
|
Color::NONE,
|
|
|
|
|
),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fix_skybox(mut images: ResMut<Assets<Image>>, assets: Res<AssetsMap>) {
|
|
|
|
|
let image = images.get_mut(&assets.skybox).unwrap();
|
|
|
|
|
info!("Loaded skybox image");
|
|
|
|
|
@ -290,9 +325,16 @@ fn mouse_zoom(
|
|
|
|
|
mut events: EventReader<MouseWheel>,
|
|
|
|
|
mut camera: Query<&mut Transform, (With<Display3d>, With<Camera>)>,
|
|
|
|
|
) {
|
|
|
|
|
events.iter().for_each(|MouseWheel { y, .. }| {
|
|
|
|
|
events.iter().for_each(|MouseWheel { unit, y, .. }| {
|
|
|
|
|
camera.iter_mut().for_each(|mut t| {
|
|
|
|
|
t.translation *= 1.0 - (*y / 4.0);
|
|
|
|
|
match unit {
|
|
|
|
|
MouseScrollUnit::Line => {
|
|
|
|
|
t.translation *= 1.0 - (*y / 4.0);
|
|
|
|
|
}
|
|
|
|
|
MouseScrollUnit::Pixel => {
|
|
|
|
|
t.translation *= 1.0 - (*y / 64.0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
t.look_at(Vec3::ZERO, Vec3::Y);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
@ -413,18 +455,26 @@ fn set_piece_texture(
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Function for selecting entities based on ray intersection
|
|
|
|
|
/// Select tiles and pieces in 3d
|
|
|
|
|
/// There is a bug where we are selecting multiple entities...
|
|
|
|
|
fn select_3d(
|
|
|
|
|
/// TODO: Selectable generalize picking pieces **and** hitboxes
|
|
|
|
|
fn select(
|
|
|
|
|
mut events: EventReader<MouseButtonInput>,
|
|
|
|
|
query: Query<(Entity, &Handle<Mesh>, &GlobalTransform)>,
|
|
|
|
|
meshes: Res<Assets<Mesh>>,
|
|
|
|
|
cameras: Query<(&Camera, &GlobalTransform)>,
|
|
|
|
|
windows: Query<&Window, With<PrimaryWindow>>,
|
|
|
|
|
parents: Query<Entity, (With<game::Piece>, With<Display3d>)>,
|
|
|
|
|
selectable: Query<Entity, (With<game::Selectable>, With<Display3d>)>,
|
|
|
|
|
children: Query<&Children>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
selected: Query<Entity, (With<game::Selected>, With<game::Piece>, With<Display3d>)>,
|
|
|
|
|
selected: Query<
|
|
|
|
|
Entity,
|
|
|
|
|
(
|
|
|
|
|
With<game::Selected>,
|
|
|
|
|
With<game::Selectable>,
|
|
|
|
|
With<Display3d>,
|
|
|
|
|
),
|
|
|
|
|
>,
|
|
|
|
|
) {
|
|
|
|
|
events
|
|
|
|
|
.iter()
|
|
|
|
|
@ -440,8 +490,8 @@ fn select_3d(
|
|
|
|
|
meshes.get(handle).map(|mesh| (entity, mesh, gt))
|
|
|
|
|
})
|
|
|
|
|
.for_each(|(entity, mesh, gt)| {
|
|
|
|
|
hit3d::intersects(&ray, mesh, >).and_then(|_hit| {
|
|
|
|
|
parents
|
|
|
|
|
hit::intersects3d(&ray, mesh, >).and_then(|_hit| {
|
|
|
|
|
selectable
|
|
|
|
|
.iter()
|
|
|
|
|
.find(|&parent| {
|
|
|
|
|
children
|
|
|
|
|
@ -472,7 +522,14 @@ fn select_3d(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn selected_gizmo(
|
|
|
|
|
selected: Query<&Transform, (With<game::Selected>, With<game::Piece>, With<Display3d>)>,
|
|
|
|
|
selected: Query<
|
|
|
|
|
&Transform,
|
|
|
|
|
(
|
|
|
|
|
With<game::Selected>,
|
|
|
|
|
With<game::Selectable>,
|
|
|
|
|
With<Display3d>,
|
|
|
|
|
),
|
|
|
|
|
>,
|
|
|
|
|
mut gizmos: Gizmos,
|
|
|
|
|
) {
|
|
|
|
|
selected.iter().for_each(|transform| {
|
|
|
|
|
@ -504,15 +561,16 @@ fn pick_up(
|
|
|
|
|
game::Piece::Drone => gltf.named_animations.get("DroneIdle"),
|
|
|
|
|
game::Piece::Pawn => gltf.named_animations.get("PawnIdle"),
|
|
|
|
|
};
|
|
|
|
|
player.play_with_transition(
|
|
|
|
|
animation.expect("Pickup Animation").clone(),
|
|
|
|
|
Duration::from_secs_f32(0.75),
|
|
|
|
|
);
|
|
|
|
|
player.play_with_transition(
|
|
|
|
|
idle.expect("Idle animation").clone(),
|
|
|
|
|
Duration::from_secs_f32(1.5),
|
|
|
|
|
);
|
|
|
|
|
player.repeat();
|
|
|
|
|
player
|
|
|
|
|
.start_with_transition(
|
|
|
|
|
animation.expect("Pickup Animation").clone(),
|
|
|
|
|
Duration::from_secs_f32(0.75),
|
|
|
|
|
)
|
|
|
|
|
.play_with_transition(
|
|
|
|
|
idle.expect("Idle animation").clone(),
|
|
|
|
|
Duration::from_secs_f32(1.5),
|
|
|
|
|
)
|
|
|
|
|
.repeat();
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
});
|
|
|
|
|
@ -520,7 +578,7 @@ fn pick_up(
|
|
|
|
|
|
|
|
|
|
fn put_down(
|
|
|
|
|
mut events: RemovedComponents<game::Selected>,
|
|
|
|
|
mut query: Query<&game::Piece, (With<game::Piece>, With<Display3d>)>,
|
|
|
|
|
mut query: Query<&game::Piece, (With<game::Piece>, With<game::Selectable>, With<Display3d>)>,
|
|
|
|
|
assets_map: Res<AssetsMap>,
|
|
|
|
|
gltfs: Res<Assets<Gltf>>,
|
|
|
|
|
children: Query<&Children>,
|
|
|
|
|
@ -536,11 +594,12 @@ fn put_down(
|
|
|
|
|
game::Piece::Drone => gltf.named_animations.get("DronePutDown"),
|
|
|
|
|
game::Piece::Pawn => gltf.named_animations.get("PawnPutDown"),
|
|
|
|
|
};
|
|
|
|
|
player.stop_repeating();
|
|
|
|
|
player.play_with_transition(
|
|
|
|
|
animation.expect("PutDown Animation").clone(),
|
|
|
|
|
Duration::from_secs_f32(0.75),
|
|
|
|
|
);
|
|
|
|
|
player
|
|
|
|
|
.play_with_transition(
|
|
|
|
|
animation.expect("PutDown Animation").clone(),
|
|
|
|
|
Duration::from_secs_f32(0.75),
|
|
|
|
|
)
|
|
|
|
|
.stop_repeating();
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|