Hey it worksgit add .; git commit Selection handling refactor FTW

bevy0.12
Elijah Voigt 2 years ago
parent 12bf2ea96d
commit 50d35533cc

@ -273,6 +273,7 @@ fn select(
&TextureAtlasSprite,
&Handle<TextureAtlas>,
&GlobalTransform,
&BoardIndex,
),
(
With<game::Selectable>,
@ -283,8 +284,8 @@ fn select(
windows: Query<&Window, With<PrimaryWindow>>,
cameras: Query<(&Camera, &GlobalTransform), With<Display2d>>,
atlases: Res<Assets<TextureAtlas>>,
mut commands: Commands,
selected: Query<Entity, (With<game::Selected>, With<game::Piece>, With<Display2d>)>,
mut selections: EventWriter<game::Selection>,
) {
// For each window (there is only one)
windows
@ -306,6 +307,7 @@ fn select(
TextureAtlasSprite { index, anchor, .. },
handle,
transform,
board_index,
)| {
let sprite_size = atlases
.get(handle)
@ -315,17 +317,16 @@ fn select(
.expect("Atlas Sprite Rectangle")
.size();
hit::intersects2d(sprite_size, anchor, transform, pos)
.then_some((entity, transform))
.then_some((transform, board_index))
},
)
.max_by(|(_, a), (_, b)| {
.max_by(|(a, _), (b, _)| {
a.translation().z.partial_cmp(&b.translation().z).unwrap()
})
.map(|(_, board_index)| board_index)
.iter()
.for_each(|(entity, _)| {
info!("Selected pieces: {:?}", selected.iter().len());
assert!(selected.iter().len() <= 2, "Selected too many pieces!");
commands.entity(*entity).insert(game::Selected);
.for_each(|&board_index| {
selections.send(game::Selection(board_index.clone()));
});
});
});

@ -465,10 +465,10 @@ fn select(
meshes: Res<Assets<Mesh>>,
cameras: Query<(&Camera, &GlobalTransform)>,
windows: Query<&Window, With<PrimaryWindow>>,
selectable: Query<Entity, (With<game::Selectable>, With<Display3d>)>,
selectable: Query<(Entity, &BoardIndex), (With<game::Selectable>, With<Display3d>)>,
children: Query<&Children>,
mut commands: Commands,
selected: Query<Entity, (With<game::Selected>, With<game::Piece>, With<Display3d>)>,
mut selections: EventWriter<game::Selection>,
) {
events
.iter()
@ -487,7 +487,7 @@ fn select(
hit::intersects3d(&ray, mesh, &gt).and_then(|_hit| {
selectable
.iter()
.find(|&e| {
.find_map(|(e, &board_index)| {
// A child was hit (pieces)
let primary = entity == e;
// This entity was hit (tile hitboxes)
@ -495,19 +495,12 @@ fn select(
.iter_descendants(e)
.any(|child| child == entity);
primary || secondary
(primary || secondary).then_some(board_index)
})
.iter()
.for_each(|&e| {
info!(
"Selected pieces: {:?}",
selected.iter().len()
);
assert!(
selected.iter().len() <= 2,
"Selected too many pieces selected!"
);
commands.entity(e).insert(game::Selected);
.for_each(|&board_index| {
selections
.send(game::Selection(board_index.clone()));
});
Some(())
});

@ -1,5 +1,6 @@
use bevy::utils::HashSet;
use crate::audio::AudioEvent;
use crate::prelude::*;
pub(crate) struct GamePlugin;
@ -7,23 +8,21 @@ pub(crate) struct GamePlugin;
impl Plugin for GamePlugin {
fn build(&self, app: &mut App) {
app.add_event::<Move>()
.add_event::<Selection>()
.add_systems(Startup, setup_board)
.add_systems(
Update,
(
menu::exit_to_menu.run_if(in_state(GameState::Play)),
update_board.run_if(on_event::<Move>()).after(select_sync),
update_board
.run_if(on_event::<Move>())
.after(handle_selection),
set_side.run_if(on_event::<Move>()).after(update_board),
cancel_place.run_if(|buttons: Res<Input<MouseButton>>| -> bool {
buttons.just_pressed(MouseButton::Right)
}),
select_sync
.run_if(any_component_added::<Selected>)
.after(deselect_sync),
deselect_sync.run_if(any_component_removed::<Selected>()),
move_piece.run_if(any_component_added::<Selected>),
handle_selection.run_if(on_event::<Selection>()),
capture_piece.run_if(any_component_added::<Captured>),
null_selections.run_if(any_component_added::<Selected>),
pick_up_audio::<display2d::Display2d>
.run_if(in_state(DisplayState::Display2d))
.run_if(any_component_added::<Selected>),
@ -292,6 +291,10 @@ pub(crate) struct Selected;
#[derive(Debug, Default, Component)]
pub(crate) struct Selectable;
/// Event for selecting board indexes for Moves
#[derive(Debug, Default, Event, Clone)]
pub(crate) struct Selection(pub BoardIndex);
fn setup_board(mut commands: Commands) {
use Piece::*;
commands.insert_resource(Board {
@ -347,6 +350,7 @@ fn debug_board(board: Res<Board>, mut debug_info: ResMut<debug::DebugInfo>) {
/// Update this method to use a diff between the board and the state of the 2d/3d worlds
pub(crate) fn update_board(
mut audio_events: EventWriter<AudioEvent>,
mut events: EventReader<Move>,
mut pieces: Query<(Entity, &mut BoardIndex), With<Piece>>,
selected: Query<Entity, With<Selected>>,
@ -359,6 +363,7 @@ pub(crate) fn update_board(
Some(to_idx) => {
info!("Moving piece {:?} to {:?}", entity, to_idx);
*index = to_idx.clone();
audio_events.send(audio::AudioEvent::PutDown);
}
None => {
info!("Capturing piece {:?}", entity);
@ -391,74 +396,59 @@ pub(crate) fn set_side(mut events: Query<(&mut Side, &BoardIndex), Changed<Board
});
}
fn select_sync(
events: Query<Entity, Added<Selected>>,
pieces: Query<(Entity, &BoardIndex), (With<Selectable>, With<Piece>)>,
mut commands: Commands,
) {
events.iter().for_each(|entity| {
if let Ok((this_e, this_idx)) = pieces.get(entity) {
if let Some((entangled, _)) = pieces
.iter()
.find(|(e, idx)| *idx == this_idx && *e != this_e)
{
commands.entity(entangled).insert(Selected);
}
}
})
}
fn deselect_sync(
mut events: RemovedComponents<Selected>,
pieces: Query<(Entity, &BoardIndex), (With<Selectable>, With<Piece>)>,
// TODO: Handle 3d Pickup (Not showing hover animation, but still selected?)
// TODO: Handle cancel move (currently 2d just drops it in place)
fn handle_selection(
mut selections: EventReader<Selection>,
mut move_events: EventWriter<Move>,
selected: Query<(Entity, &BoardIndex), (With<Selected>, With<Piece>)>,
pieces: Query<(Entity, &BoardIndex), (With<Selectable>, Without<Selected>, With<Piece>)>,
tiles: Query<(Entity, &BoardIndex), (With<Selectable>, With<Tile>)>,
mut board: ResMut<Board>,
mut commands: Commands,
) {
events.iter().for_each(|entity| {
if let Ok((this_e, this_idx)) = pieces.get(entity) {
if let Some((entangled, _)) = pieces
selections.iter().for_each(|Selection(index)| {
// There are no currently selected entities
// Mark the piece at this index as selected
if selected.is_empty() {
pieces
.iter()
.find(|(e, idx)| *idx == this_idx && *e != this_e)
{
info!("De-selecting entangled piece {:?}", entity);
commands.entity(entangled).remove::<Selected>();
}
}
})
}
/// Triggered when right-mouse-button clicked
fn cancel_place(current: Query<Entity, With<Selected>>, mut commands: Commands) {
current.iter().for_each(|entity| {
info!("De-selecting {:?}", entity);
commands.entity(entity).remove::<Selected>();
.filter(|(this, this_index)| *this_index == index)
.for_each(|(piece, piece_index)| {
info!("Selecting {:?} at {:?}", piece, piece_index);
commands.entity(piece).insert(Selected);
});
}
/// When a tile is selected, move all selected pieces to that index
fn move_piece(
events: Query<&BoardIndex, (With<BoardIndex>, Added<Selected>)>,
selected_pieces: Query<&BoardIndex, (With<Selected>, With<Piece>)>,
mut board: ResMut<Board>,
mut move_events: EventWriter<Move>,
mut writer: EventWriter<audio::AudioEvent>,
) {
events.iter().for_each(|to| {
selected_pieces.iter().for_each(|from| {
if from != to {
info!("Applying move {:?} -> {:?}", from, to);
// Move piece
match board.move_piece(*from, *to) {
}
// There is a currently selected entity, so submit moves
else {
assert!(
selected.iter().len() <= 2,
"There are too many pieces selected!"
);
selected.iter().for_each(|(current, current_index)| {
match board.move_piece(*current_index, *index) {
Ok(moves) => {
// De-select the piece
info!("Applying moves {:?}", moves);
moves.iter().for_each(|m| move_events.send(m.clone()));
writer.send(audio::AudioEvent::PutDown)
}
Err(GameError::NullMove) => warn!("Null move!"),
Err(GameError::InvalidIndex) => warn!("Invalid index!"),
}
});
}
});
}
/// Triggered when right-mouse-button clicked
fn cancel_place(current: Query<&BoardIndex, With<Selected>>, mut events: EventWriter<Move>) {
current.iter().for_each(|board_index| {
info!("De-selecting piece at {:?}", board_index);
events.send(Move {
from: board_index.clone(),
to: Some(board_index.clone()),
..default()
});
});
}
@ -471,26 +461,6 @@ fn pick_up_audio<D: Component>(
}
}
/// De-select anything that shouldn't be selected
/// Namely tiles when there are not selected pieces
fn null_selections(
events: Query<Entity, Added<Selected>>,
selected_pieces: Query<Entity, (With<Selected>, With<Piece>)>,
mut commands: Commands,
mut writer: EventWriter<audio::AudioEvent>,
) {
events.iter().for_each(|entity| {
if selected_pieces.is_empty() {
info!(
"De-selecting piece that should not be selected {:?}",
entity
);
commands.entity(entity).remove::<Selected>();
writer.send(audio::AudioEvent::PutDown);
}
});
}
/// When a piece's _BoardIndex_ is removed, we hide that entity from the viewer
fn capture_piece(mut events: Query<&mut Visibility, Added<Captured>>) {
events.iter_mut().for_each(|mut vis| {

Loading…
Cancel
Save