oops, that wasn't supposed to be committed
parent
15c7f5c0fc
commit
1d17937b4a
@ -1,609 +0,0 @@
|
|||||||
// TODO: Camera Animations
|
|
||||||
// Intro animation
|
|
||||||
// Turn changing animations
|
|
||||||
// TODO: Pickup/put-down sound in 3d
|
|
||||||
// TODO: Background during menu
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
game::{Board, BoardIndex, Piece, Side},
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
use bevy::{
|
|
||||||
core_pipeline::{tonemapping::DebandDither, Skybox},
|
|
||||||
input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
|
|
||||||
render::{
|
|
||||||
render_resource::{TextureViewDescriptor, TextureViewDimension},
|
|
||||||
view::ColorGrading,
|
|
||||||
},
|
|
||||||
window::PrimaryWindow,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) struct Display3dPlugin;
|
|
||||||
|
|
||||||
impl Plugin for Display3dPlugin {
|
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.add_systems(OnEnter(GameState::Loading), load_assets)
|
|
||||||
.add_systems(
|
|
||||||
OnExit(GameState::Loading),
|
|
||||||
(initialize, fix_skybox.before(initialize)),
|
|
||||||
)
|
|
||||||
.add_systems(
|
|
||||||
Update,
|
|
||||||
(
|
|
||||||
hydrate_camera.run_if(any_component_added::<Camera3d>),
|
|
||||||
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
|
|
||||||
.run_if(in_state(GameState::Play))
|
|
||||||
.run_if(in_state(DisplayState::Display3d))
|
|
||||||
.run_if(on_event::<MouseButtonInput>()),
|
|
||||||
pick_up.run_if(any_component_added::<game::Selected>),
|
|
||||||
put_down.run_if(any_component_removed::<game::Selected>()),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.add_systems(
|
|
||||||
Update,
|
|
||||||
(
|
|
||||||
move_camera.run_if(on_event::<MouseMotion>()),
|
|
||||||
mouse_zoom.run_if(on_event::<MouseWheel>()),
|
|
||||||
gizmo_system,
|
|
||||||
selected_gizmo,
|
|
||||||
moves_gizmo,
|
|
||||||
)
|
|
||||||
.run_if(resource_exists::<debug::DebugEnabled>())
|
|
||||||
.run_if(in_state(GameState::Play))
|
|
||||||
.run_if(in_state(DisplayState::Display3d)),
|
|
||||||
)
|
|
||||||
.add_systems(
|
|
||||||
OnEnter(DisplayState::Display3d),
|
|
||||||
(activate::<Display3d>, set_piece_texture),
|
|
||||||
)
|
|
||||||
.add_systems(OnExit(DisplayState::Display3d), deactivate::<Display3d>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Component)]
|
|
||||||
pub(crate) struct Display3d;
|
|
||||||
|
|
||||||
#[derive(Debug, Resource)]
|
|
||||||
struct AssetsMap {
|
|
||||||
models: Handle<Gltf>,
|
|
||||||
skybox: Handle<Image>,
|
|
||||||
hitbox_shape: Handle<Mesh>,
|
|
||||||
hitbox_material: Handle<StandardMaterial>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Load 3d models
|
|
||||||
/// This is kind of pulling double duty.
|
|
||||||
/// Both loads the GLTF file _and_ populates the ModelMap once that is loaded.
|
|
||||||
fn load_assets(
|
|
||||||
server: Res<AssetServer>,
|
|
||||||
mut commands: Commands,
|
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
||||||
) {
|
|
||||||
let hitbox_shape = meshes.add(shape::Box::new(1.0, 0.1, 1.0).into());
|
|
||||||
let hitbox_material = materials.add(StandardMaterial {
|
|
||||||
base_color: Color::NONE,
|
|
||||||
perceptual_roughness: 0.0,
|
|
||||||
reflectance: 0.0,
|
|
||||||
alpha_mode: AlphaMode::Blend,
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
commands.insert_resource(AssetsMap {
|
|
||||||
models: server.load("models/Martian Chess.glb"),
|
|
||||||
skybox: server.load("images/skybox.png"),
|
|
||||||
hitbox_shape,
|
|
||||||
hitbox_material,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initialize the 3d board
|
|
||||||
fn initialize(mut commands: Commands, board: Res<game::Board>, assets: Res<AssetsMap>) {
|
|
||||||
info!("Initializing root");
|
|
||||||
commands
|
|
||||||
.spawn((
|
|
||||||
SpatialBundle {
|
|
||||||
visibility: Visibility::Hidden,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
Display3d,
|
|
||||||
))
|
|
||||||
.with_children(|parent| {
|
|
||||||
info!("Initializing 3D lights!");
|
|
||||||
parent.spawn((
|
|
||||||
Display3d,
|
|
||||||
PointLightBundle {
|
|
||||||
point_light: PointLight {
|
|
||||||
intensity: 3000.0,
|
|
||||||
shadows_enabled: true,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
transform: Transform::from_xyz(0.0, 10.0, 5.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
info!("Intializing 3D Board!");
|
|
||||||
parent
|
|
||||||
.spawn((Display3d, game::BoardComponent, SceneBundle { ..default() }))
|
|
||||||
.with_children(|parent| {
|
|
||||||
// Hitboxes
|
|
||||||
game::tiles().for_each(|(index, tile)| {
|
|
||||||
parent.spawn((
|
|
||||||
Display3d,
|
|
||||||
index,
|
|
||||||
tile,
|
|
||||||
PbrBundle {
|
|
||||||
mesh: assets.hitbox_shape.clone(),
|
|
||||||
material: assets.hitbox_material.clone(),
|
|
||||||
visibility: Visibility::Hidden,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
game::Selectable,
|
|
||||||
));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Pieces
|
|
||||||
board.pieces().iter().for_each(|(index, piece)| {
|
|
||||||
let side = Board::side(*index).expect("Spawn valid side");
|
|
||||||
|
|
||||||
parent.spawn((
|
|
||||||
side,
|
|
||||||
Display3d,
|
|
||||||
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, 12.5, 6.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::NONE, 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");
|
|
||||||
// NOTE: PNGs do not have any metadata that could indicate they contain a cubemap texture,
|
|
||||||
// so they appear as one texture. The following code reconfigures the texture as necessary.
|
|
||||||
if image.texture_descriptor.array_layer_count() == 1 {
|
|
||||||
image.reinterpret_stacked_2d_as_array(
|
|
||||||
image.texture_descriptor.size.height / image.texture_descriptor.size.width,
|
|
||||||
);
|
|
||||||
image.texture_view_descriptor = Some(TextureViewDescriptor {
|
|
||||||
dimension: Some(TextureViewDimension::Cube),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the model for each piece based on the game::Piece::* marker
|
|
||||||
fn set_piece_model(
|
|
||||||
mut events: Query<(&mut Handle<Scene>, &Piece), (Added<game::Piece>, With<Display3d>)>,
|
|
||||||
assets_map: Res<AssetsMap>,
|
|
||||||
gltfs: Res<Assets<Gltf>>,
|
|
||||||
) {
|
|
||||||
events.iter_mut().for_each(|(mut handle, piece)| {
|
|
||||||
let gltf = gltfs.get(&assets_map.models).expect("Load GLTF content");
|
|
||||||
*handle = match piece {
|
|
||||||
game::Piece::Pawn => gltf.named_scenes.get("Pawn"),
|
|
||||||
game::Piece::Drone => gltf.named_scenes.get("Drone"),
|
|
||||||
game::Piece::Queen => gltf.named_scenes.get("Queen"),
|
|
||||||
}
|
|
||||||
.expect("Game board model")
|
|
||||||
.clone();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_board_model(
|
|
||||||
mut events: Query<&mut Handle<Scene>, (With<game::BoardComponent>, With<Display3d>)>,
|
|
||||||
assets_map: Res<AssetsMap>,
|
|
||||||
gltfs: Res<Assets<Gltf>>,
|
|
||||||
) {
|
|
||||||
events.iter_mut().for_each(|mut handle| {
|
|
||||||
let gltf = gltfs.get(&assets_map.models).expect("Load GLTF content");
|
|
||||||
*handle = gltf
|
|
||||||
.named_scenes
|
|
||||||
.get("Gameboard")
|
|
||||||
.expect("Game board model")
|
|
||||||
.clone();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets a piece location given it's board index
|
|
||||||
fn set_piece_position(
|
|
||||||
mut events: Query<
|
|
||||||
(&mut Transform, &BoardIndex),
|
|
||||||
(With<game::Piece>, With<Display3d>, Changed<BoardIndex>),
|
|
||||||
>,
|
|
||||||
) {
|
|
||||||
events.iter_mut().for_each(|(mut t, i)| {
|
|
||||||
t.translation = board_translation(i);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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
|
|
||||||
let x = x as i8 - 4;
|
|
||||||
// Mirror y axis because our board index is inverted...
|
|
||||||
let y = -(y as i8) + 1;
|
|
||||||
|
|
||||||
let x = if x < 0 {
|
|
||||||
x as f32 * 1.3 + 0.325
|
|
||||||
} else {
|
|
||||||
x as f32 * 1.3 + 1.0
|
|
||||||
};
|
|
||||||
|
|
||||||
let y = y as f32 * 1.3 + 0.65;
|
|
||||||
|
|
||||||
Vec3::new(x, 0.0, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gizmo_system(mut gizmos: Gizmos) {
|
|
||||||
for y in 0..4 {
|
|
||||||
for x in 0..8 {
|
|
||||||
gizmos.cuboid(
|
|
||||||
Transform::from_translation(board_translation(&BoardIndex { x, y }))
|
|
||||||
.with_scale(Vec3::new(1.0, 0.1, 1.0)),
|
|
||||||
Color::PURPLE,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// TODO: This has bad feel, needs to be tuned
|
|
||||||
fn move_camera(
|
|
||||||
buttons: Res<Input<MouseButton>>,
|
|
||||||
mut events: EventReader<MouseMotion>,
|
|
||||||
mut camera: Query<&mut Transform, (With<Display3d>, With<Camera>)>,
|
|
||||||
) {
|
|
||||||
events.iter().for_each(|MouseMotion { delta }| {
|
|
||||||
if buttons.pressed(MouseButton::Left) {
|
|
||||||
camera.iter_mut().for_each(|mut t| {
|
|
||||||
t.rotate_around(Vec3::ZERO, Quat::from_rotation_y(delta.x / 256.0));
|
|
||||||
t.rotate_around(Vec3::ZERO, Quat::from_rotation_x(delta.y / 256.0));
|
|
||||||
t.look_at(Vec3::ZERO, Vec3::Y);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mouse_zoom(
|
|
||||||
mut events: EventReader<MouseWheel>,
|
|
||||||
mut camera: Query<&mut Transform, (With<Display3d>, With<Camera>)>,
|
|
||||||
) {
|
|
||||||
events.iter().for_each(|MouseWheel { unit, y, .. }| {
|
|
||||||
camera.iter_mut().for_each(|mut t| {
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the Texture for a piece given it's position (left or right) on the bord.
|
|
||||||
/// Executed when Side is changed or upon entry to Display3d state
|
|
||||||
/// Getting this to run _after_ GLTF is loaded is a pain.
|
|
||||||
/// PERF: We are saving what to work on in a Vector which is bad.
|
|
||||||
/// CAVEAT: We are only exeucting this when a piece changes or state is changed.
|
|
||||||
fn set_piece_texture(
|
|
||||||
events: Query<(Entity, &Piece, &Side), (With<game::Piece>, With<Display3d>, Changed<Side>)>,
|
|
||||||
all: Query<(Entity, &Piece, &Side), (With<game::Piece>, With<Display3d>)>,
|
|
||||||
gltfs: Res<Assets<Gltf>>,
|
|
||||||
assets_map: Res<AssetsMap>,
|
|
||||||
children: Query<&Children>,
|
|
||||||
mut models: Query<(&Name, &mut Handle<StandardMaterial>)>,
|
|
||||||
) {
|
|
||||||
let pieces = if events.is_empty() {
|
|
||||||
all.iter().collect::<Vec<(Entity, &Piece, &Side)>>()
|
|
||||||
} else {
|
|
||||||
events.iter().collect::<Vec<(Entity, &Piece, &Side)>>()
|
|
||||||
};
|
|
||||||
pieces.iter().for_each(|(entity, piece, side)| {
|
|
||||||
if let Some(gltf) = gltfs.get(&assets_map.models) {
|
|
||||||
children.iter_descendants(*entity).for_each(|child| {
|
|
||||||
if let Ok((n, mut m)) = models.get_mut(child) {
|
|
||||||
match (*piece, *side, n.as_str()) {
|
|
||||||
(Piece::Queen, Side::A, "Queen.0") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("Queen")
|
|
||||||
.expect("Load Red Queen texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Queen, Side::A, "Queen.1") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("Dots")
|
|
||||||
.expect("Load Red Dots texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Queen, Side::B, "Queen.0") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("QueenBlue")
|
|
||||||
.expect("Load Blue Queen texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Queen, Side::B, "Queen.1") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("DotsBlue")
|
|
||||||
.expect("Load Red Dots texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Drone, Side::A, "Drone.0") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("Drone")
|
|
||||||
.expect("Load Red Drone texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Drone, Side::A, "Drone.1") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("Dots")
|
|
||||||
.expect("Load Red Dots texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Drone, Side::B, "Drone.0") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("DroneBlue")
|
|
||||||
.expect("Load Blue Drone texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Drone, Side::B, "Drone.1") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("DotsBlue")
|
|
||||||
.expect("Load Blue Dots texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Pawn, Side::A, "Pawn.0") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("Pawn")
|
|
||||||
.expect("Load Red Pawn texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Pawn, Side::A, "Pawn.1") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("Dots")
|
|
||||||
.expect("Load Red Dots texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Pawn, Side::B, "Pawn.0") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("DroneBlue") // TODO: FIX
|
|
||||||
.expect("Load Blue Pawn texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
(Piece::Pawn, Side::B, "Pawn.1") => {
|
|
||||||
*m = gltf
|
|
||||||
.named_materials
|
|
||||||
.get("DotsBlue")
|
|
||||||
.expect("Load Blue Dots texture")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
_ => warn!("???"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Select tiles and pieces in 3d
|
|
||||||
/// There is a bug where we are selecting multiple entities...
|
|
||||||
/// 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>>,
|
|
||||||
selectable: Query<Entity, (With<game::Selectable>, With<Display3d>)>,
|
|
||||||
children: Query<&Children>,
|
|
||||||
mut commands: Commands,
|
|
||||||
selected: Query<
|
|
||||||
Entity,
|
|
||||||
(
|
|
||||||
With<game::Selected>,
|
|
||||||
With<game::Selectable>,
|
|
||||||
With<Display3d>,
|
|
||||||
),
|
|
||||||
>,
|
|
||||||
) {
|
|
||||||
events
|
|
||||||
.iter()
|
|
||||||
.filter(|ev| ev.state == ButtonState::Pressed)
|
|
||||||
.for_each(|_| {
|
|
||||||
windows.iter().for_each(|window| {
|
|
||||||
window.cursor_position().and_then(|pos| {
|
|
||||||
cameras.iter().for_each(|(camera, gt)| {
|
|
||||||
camera.viewport_to_world(gt, pos).and_then(|ray| {
|
|
||||||
query
|
|
||||||
.iter()
|
|
||||||
.filter_map(|(entity, handle, gt)| {
|
|
||||||
meshes.get(handle).map(|mesh| (entity, mesh, gt))
|
|
||||||
})
|
|
||||||
.for_each(|(entity, mesh, gt)| {
|
|
||||||
hit::intersects3d(&ray, mesh, >).and_then(|_hit| {
|
|
||||||
selectable
|
|
||||||
.iter()
|
|
||||||
.find(|&e| {
|
|
||||||
// A child was hit (pieces)
|
|
||||||
let primary = entity == e;
|
|
||||||
// This entity was hit (tile hitboxes)
|
|
||||||
let secondary = children
|
|
||||||
.iter_descendants(e)
|
|
||||||
.any(|child| child == entity);
|
|
||||||
|
|
||||||
primary || secondary
|
|
||||||
})
|
|
||||||
.iter()
|
|
||||||
.for_each(|&e| {
|
|
||||||
commands.entity(e).insert(game::Selected);
|
|
||||||
});
|
|
||||||
Some(())
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Some(())
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Some(())
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn selected_gizmo(
|
|
||||||
selected: Query<&Transform, (With<game::Selected>, With<Display3d>)>,
|
|
||||||
mut gizmos: Gizmos,
|
|
||||||
) {
|
|
||||||
selected.iter().for_each(|transform| {
|
|
||||||
gizmos.cuboid(transform.clone(), Color::GREEN);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn moves_gizmo(
|
|
||||||
selected: Query<&BoardIndex, (With<game::Piece>, With<game::Selected>, With<Display3d>)>,
|
|
||||||
board: Res<Board>,
|
|
||||||
mut gizmos: Gizmos,
|
|
||||||
) {
|
|
||||||
selected.iter().for_each(|idx| {
|
|
||||||
board
|
|
||||||
.possible_moves(*idx)
|
|
||||||
.iter()
|
|
||||||
.map(|i| Transform::from_translation(board_translation(i)))
|
|
||||||
.for_each(|t| gizmos.cuboid(t, Color::WHITE))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pick_up(
|
|
||||||
mut events: Query<
|
|
||||||
(Entity, &game::Piece),
|
|
||||||
(With<game::Piece>, With<Display3d>, Added<game::Selected>),
|
|
||||||
>,
|
|
||||||
assets_map: Res<AssetsMap>,
|
|
||||||
gltfs: Res<Assets<Gltf>>,
|
|
||||||
children: Query<&Children>,
|
|
||||||
mut players: Query<&mut AnimationPlayer>,
|
|
||||||
) {
|
|
||||||
events.iter_mut().for_each(|(entity, piece)| {
|
|
||||||
let gltf = gltfs.get(&assets_map.models).expect("Load GLTF content");
|
|
||||||
children.iter_descendants(entity).for_each(|child| {
|
|
||||||
if let Ok(mut player) = players.get_mut(child) {
|
|
||||||
let animation = match piece {
|
|
||||||
game::Piece::Queen => gltf.named_animations.get("QueenPickup"),
|
|
||||||
game::Piece::Drone => gltf.named_animations.get("DronePickup"),
|
|
||||||
game::Piece::Pawn => gltf.named_animations.get("PawnPickup"),
|
|
||||||
};
|
|
||||||
let idle = match piece {
|
|
||||||
game::Piece::Queen => gltf.named_animations.get("QueenIdle"),
|
|
||||||
game::Piece::Drone => gltf.named_animations.get("DroneIdle"),
|
|
||||||
game::Piece::Pawn => gltf.named_animations.get("PawnIdle"),
|
|
||||||
};
|
|
||||||
player
|
|
||||||
.start_with_transition(
|
|
||||||
animation.expect("Pickup Animation").clone(),
|
|
||||||
Duration::from_secs_f32(0.75),
|
|
||||||
)
|
|
||||||
.start_with_transition(
|
|
||||||
idle.expect("Idle animation").clone(),
|
|
||||||
Duration::from_secs_f32(1.5),
|
|
||||||
)
|
|
||||||
.repeat();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn put_down(
|
|
||||||
mut events: RemovedComponents<game::Selected>,
|
|
||||||
mut query: Query<&game::Piece, (With<game::Piece>, With<game::Selectable>, With<Display3d>)>,
|
|
||||||
assets_map: Res<AssetsMap>,
|
|
||||||
gltfs: Res<Assets<Gltf>>,
|
|
||||||
children: Query<&Children>,
|
|
||||||
mut players: Query<&mut AnimationPlayer>,
|
|
||||||
) {
|
|
||||||
events.iter().for_each(|entity| {
|
|
||||||
if let Ok(piece) = query.get_mut(entity) {
|
|
||||||
let gltf = gltfs.get(&assets_map.models).expect("Load GLTF content");
|
|
||||||
children.iter_descendants(entity).for_each(|child| {
|
|
||||||
if let Ok(mut player) = players.get_mut(child) {
|
|
||||||
let animation = match piece {
|
|
||||||
game::Piece::Queen => gltf.named_animations.get("QueenPutDown"),
|
|
||||||
game::Piece::Drone => gltf.named_animations.get("DronePutDown"),
|
|
||||||
game::Piece::Pawn => gltf.named_animations.get("PawnPutDown"),
|
|
||||||
};
|
|
||||||
player
|
|
||||||
.start_with_transition(
|
|
||||||
animation.expect("PutDown Animation").clone(),
|
|
||||||
Duration::from_secs_f32(0.75),
|
|
||||||
)
|
|
||||||
.stop_repeating();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_tile_hitbox(
|
|
||||||
mut events: Query<(&mut Transform, &BoardIndex), (With<Display3d>, Added<game::Tile>)>,
|
|
||||||
) {
|
|
||||||
events.iter_mut().for_each(|(mut transform, index)| {
|
|
||||||
*transform = Transform::from_translation(board_translation(index));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue