|
|
|
|
@ -558,21 +558,34 @@ fn select(
|
|
|
|
|
mut selections: EventWriter<game::Selection>,
|
|
|
|
|
state: Res<State<game::TurnState>>,
|
|
|
|
|
) {
|
|
|
|
|
// For every mouse click event
|
|
|
|
|
events
|
|
|
|
|
.read()
|
|
|
|
|
// Only read button presses
|
|
|
|
|
.filter(|ev| ev.state == ButtonState::Pressed)
|
|
|
|
|
.for_each(|_| {
|
|
|
|
|
// For each window (there should be only one)
|
|
|
|
|
windows.iter().for_each(|window| {
|
|
|
|
|
// Get the cursor position
|
|
|
|
|
if let Some(pos) = window.cursor_position() {
|
|
|
|
|
// iterate over every camera
|
|
|
|
|
cameras.iter().for_each(|(camera, gt)| {
|
|
|
|
|
// Get a ray from the camera through the cursor into the world
|
|
|
|
|
if let Some(ray) = camera.viewport_to_world(gt, pos) {
|
|
|
|
|
// Iterate over every entity with a 3d scene
|
|
|
|
|
query
|
|
|
|
|
.iter()
|
|
|
|
|
// Transform the scene handle into mesh data
|
|
|
|
|
.filter_map(|(entity, handle, gt)| {
|
|
|
|
|
meshes.get(handle).map(|mesh| (entity, mesh, gt))
|
|
|
|
|
})
|
|
|
|
|
.for_each(|(entity, mesh, gt)| {
|
|
|
|
|
if let Some(_hit) = hit::intersects3d(&ray, mesh, gt) {
|
|
|
|
|
// Iterate over every mesh + global transform
|
|
|
|
|
.filter_map(|(entity, mesh, gt)| {
|
|
|
|
|
// If the camera -> cursor -> * ray intersects with the mesh
|
|
|
|
|
hit3d::intersects3d(&ray, mesh, gt).map(|hit| (entity, hit))
|
|
|
|
|
})
|
|
|
|
|
.filter_map(|(entity, hit)| {
|
|
|
|
|
// Find this entity in the set of selectable entities
|
|
|
|
|
selectable
|
|
|
|
|
.iter()
|
|
|
|
|
.find_map(|(e, &board_index, &side)| {
|
|
|
|
|
@ -593,14 +606,24 @@ fn select(
|
|
|
|
|
primary || secondary
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Return the board index of this piece
|
|
|
|
|
(side_check && hit_check).then_some(board_index)
|
|
|
|
|
})
|
|
|
|
|
.map(|board_index| {
|
|
|
|
|
// Include the hit from the camera
|
|
|
|
|
(hit, board_index)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
// Compare the distance of all hits, choosing the closest one
|
|
|
|
|
.min_by(|(hit_a, _), (hit_b, _)| {
|
|
|
|
|
hit_a.distance.partial_cmp(&hit_b.distance).unwrap()
|
|
|
|
|
})
|
|
|
|
|
// Iterate over the 0 or 1 outcomes of the above
|
|
|
|
|
.iter()
|
|
|
|
|
.for_each(|&board_index| {
|
|
|
|
|
// Send an event that this board index was selected
|
|
|
|
|
.for_each(|(_, board_index)| {
|
|
|
|
|
info!("Board index selected: {:?}", board_index);
|
|
|
|
|
selections.send(game::Selection(board_index));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
selections.send(game::Selection(*board_index));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|