break down select and pointer hover

This allows us to hook into the hovered piece for debugging
main
Elijah C. Voigt 2 years ago
parent 63ca981aa4
commit 4cebce8bf2

@ -13,6 +13,7 @@ impl Plugin for Display3dPlugin {
MaterialPlugin::<DissolveMaterial>::default(), MaterialPlugin::<DissolveMaterial>::default(),
)) ))
.init_state::<DissolvingAnimation>() .init_state::<DissolvingAnimation>()
.init_resource::<PiecePointer>()
.insert_resource(Msaa::Off) .insert_resource(Msaa::Off)
.insert_resource(AmbientLight { .insert_resource(AmbientLight {
color: Color::WHITE, color: Color::WHITE,
@ -69,6 +70,16 @@ impl Plugin for Display3dPlugin {
set_title_model.run_if(any_component_added::<TitleText>()), set_title_model.run_if(any_component_added::<TitleText>()),
set_valid_move_model.run_if(any_component_added::<game::ValidMove>()), set_valid_move_model.run_if(any_component_added::<game::ValidMove>()),
set_tile_hitbox.run_if(any_component_added::<game::Tile>()), set_tile_hitbox.run_if(any_component_added::<game::Tile>()),
entity_pointer
.run_if(in_state(GameState::Play))
.run_if(in_state(DisplayState::Display3d))
// Run if in debug state on mouse events
// Or just run when the left mouse button is clicked
.run_if(
in_state(debug::DebugState::Enabled)
.and_then(on_event::<MouseMotion>())
.or_else(just_pressed(MouseButton::Left))
),
select select
.run_if(in_state(GameState::Play)) .run_if(in_state(GameState::Play))
.run_if(in_state(DisplayState::Display3d)) .run_if(in_state(DisplayState::Display3d))
@ -653,27 +664,44 @@ fn update_pieces(
); );
} }
fn select(
// Query Selectable with BoardIndex
query: Query<(&BoardIndex, &Side), With<Selectable>>,
piece: Res<PiecePointer>,
mut selections: EventWriter<game::Selection>,
selected: Query<Entity, With<game::Selected>>,
state: Res<State<game::TurnState>>,
) {
// info!("Board index selected: {:?}", board_index);
match *piece {
PiecePointer(Some(e)) => {
query.get(e).iter().for_each(|(board_index, side)| {
let side_check = !selected.is_empty() || state.get().0 == **side;
if side_check {
selections.send(game::Selection(**board_index));
}
});
},
_ => ()
}
}
#[derive(Debug, Default, Resource)]
struct PiecePointer(Option<Entity>);
/// Select tiles and pieces in 3d /// Select tiles and pieces in 3d
/// There is a bug where we are selecting multiple entities... /// There is a bug where we are selecting multiple entities...
/// TODO: Selectable generalize picking pieces **and** hitboxes /// TODO: Selectable generalize picking pieces **and** hitboxes
fn select( fn entity_pointer(
mut events: EventReader<MouseButtonInput>,
query: Query<(Entity, &Handle<Mesh>, &GlobalTransform)>, query: Query<(Entity, &Handle<Mesh>, &GlobalTransform)>,
meshes: Res<Assets<Mesh>>, meshes: Res<Assets<Mesh>>,
cameras: Query<(&Camera, &GlobalTransform)>, cameras: Query<(&Camera, &GlobalTransform)>,
windows: Query<&Window, With<PrimaryWindow>>, windows: Query<&Window, With<PrimaryWindow>>,
selectable: Query<(Entity, &BoardIndex, &Side), (With<game::Selectable>, With<Display3d>)>, selectable: Query<Entity, (With<game::Selectable>, With<Display3d>)>,
selected: Query<Entity, With<game::Selected>>,
children: Query<&Children>, children: Query<&Children>,
mut selections: EventWriter<game::Selection>, mut pointer: ResMut<PiecePointer>,
state: Res<State<game::TurnState>>,
) { ) {
// For every mouse click event
events
.read()
// Only read button presses
.filter(|ev| ev.state == ButtonState::Pressed && ev.button == MouseButton::Left)
.for_each(|_| {
// For each window (there should be only one) // For each window (there should be only one)
windows.iter().for_each(|window| { windows.iter().for_each(|window| {
// Get the cursor position // Get the cursor position
@ -683,7 +711,7 @@ fn select(
// Get a ray from the camera through the cursor into the world // Get a ray from the camera through the cursor into the world
if let Some(ray) = camera.viewport_to_world(gt, pos) { if let Some(ray) = camera.viewport_to_world(gt, pos) {
// Iterate over every entity with a 3d scene // Iterate over every entity with a 3d scene
query let selected = query
.iter() .iter()
// Transform the scene handle into mesh data // Transform the scene handle into mesh data
.filter_map(|(entity, handle, gt)| { .filter_map(|(entity, handle, gt)| {
@ -698,12 +726,7 @@ fn select(
// Find this entity in the set of selectable entities // Find this entity in the set of selectable entities
selectable selectable
.iter() .iter()
.find_map(|(e, &board_index, &side)| { .find_map(|e| {
// Check the side of the selection if no piece is selected
// Otherwise this is fine, select away
let side_check =
!selected.is_empty() || state.get().0 == side;
let hit_check = { let hit_check = {
// This entity was hit (tile hitboxes) // This entity was hit (tile hitboxes)
let primary = entity == e; let primary = entity == e;
@ -717,29 +740,20 @@ fn select(
}; };
// Return the board index of this piece // Return the board index of this piece
(side_check && hit_check).then_some(board_index) hit_check.then_some((e, hit.clone()))
})
.map(|board_index| {
// Include the hit from the camera
(hit, board_index)
}) })
}) })
// Compare the distance of all hits, choosing the closest one // Compare the distance of all hits, choosing the closest one
.min_by(|(hit_a, _), (hit_b, _)| { .min_by(|(_, hit_a), (_, hit_b)| {
hit_a.distance.partial_cmp(&hit_b.distance).unwrap() hit_a.distance.partial_cmp(&hit_b.distance).unwrap()
}) })
// Iterate over the 0 or 1 outcomes of the above .map(|(e, _)| e);
.iter()
// Send an event that this board index was selected *pointer = PiecePointer(selected)
.for_each(|(_, board_index)| {
info!("Board index selected: {:?}", board_index);
selections.send(game::Selection(*board_index));
});
} }
}); });
} }
}); });
});
} }
fn selected_gizmo( fn selected_gizmo(

@ -1,10 +1,9 @@
use crate::prelude::*; use crate::prelude::*;
/// Hit data for 3d objects in Global (not Local) space and the distance from the Camera /// Hit data for 3d objects in Global (not Local) space and the distance from the Camera
#[derive(Debug)] #[derive(Debug, Clone)]
pub(crate) struct Hit3d { pub(crate) struct Hit3d {
pub distance: f32, pub distance: f32,
_point: Vec3,
} }
/// A 3D Triangle used for ray-intersection tests /// A 3D Triangle used for ray-intersection tests
@ -102,7 +101,6 @@ pub(crate) fn intersects3d(ray: &Ray3d, mesh: &Mesh, gt: &GlobalTransform) -> Op
}; };
hit.then_some(Hit3d { hit.then_some(Hit3d {
distance: d, distance: d,
_point: p,
}) })
} else { } else {
None None

Loading…
Cancel
Save