|
|
|
@ -42,10 +42,11 @@ impl Plugin for BlocksPlugin {
|
|
|
|
Update,
|
|
|
|
Update,
|
|
|
|
(
|
|
|
|
(
|
|
|
|
updated_shape_asset.run_if(on_message::<AssetEvent<ShapeAsset>>),
|
|
|
|
updated_shape_asset.run_if(on_message::<AssetEvent<ShapeAsset>>),
|
|
|
|
update_grid_position.run_if(
|
|
|
|
update_grid_position_transform.run_if(
|
|
|
|
any_component_added::<GridPosition>
|
|
|
|
any_component_added::<GridPosition>
|
|
|
|
.or(any_component_changed::<GridPosition>),
|
|
|
|
.or(any_component_changed::<GridPosition>),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
|
|
|
|
propogate_orientation.run_if(any_component_changed::<Orientation>),
|
|
|
|
propogate_grid_position.run_if(any_component_changed::<GridPosition>),
|
|
|
|
propogate_grid_position.run_if(any_component_changed::<GridPosition>),
|
|
|
|
handle_kb_input.run_if(on_message::<KeyboardInput>),
|
|
|
|
handle_kb_input.run_if(on_message::<KeyboardInput>),
|
|
|
|
handle_movement.run_if(on_message::<Movement>),
|
|
|
|
handle_movement.run_if(on_message::<Movement>),
|
|
|
|
@ -84,6 +85,8 @@ impl ShapeAsset {
|
|
|
|
|
|
|
|
|
|
|
|
(
|
|
|
|
(
|
|
|
|
GridPosition { x: 5, y: 5 }, // TEMP
|
|
|
|
GridPosition { x: 5, y: 5 }, // TEMP
|
|
|
|
|
|
|
|
self.layout.clone(),
|
|
|
|
|
|
|
|
Orientation::Up,
|
|
|
|
related!(ShapeBlocks[
|
|
|
|
related!(ShapeBlocks[
|
|
|
|
(self.mesh.clone(), self.material.clone(), a),
|
|
|
|
(self.mesh.clone(), self.material.clone(), a),
|
|
|
|
(self.mesh.clone(), self.material.clone(), b),
|
|
|
|
(self.mesh.clone(), self.material.clone(), b),
|
|
|
|
@ -164,12 +167,13 @@ impl From<(isize, isize)> for RelativePosition {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Layout for a given shape
|
|
|
|
/// Layout for a given shape
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
#[derive(Debug, Component, Deserialize, PartialEq, Clone)]
|
|
|
|
pub(crate) struct ShapeLayout(pub Vec<Vec<u8>>);
|
|
|
|
pub(crate) struct ShapeLayout(pub Vec<Vec<u8>>);
|
|
|
|
|
|
|
|
|
|
|
|
impl ShapeLayout {
|
|
|
|
impl ShapeLayout {
|
|
|
|
pub(crate) fn positions(&self) -> [RelativePosition; 4] {
|
|
|
|
pub(crate) fn positions(&self) -> [RelativePosition; 4] {
|
|
|
|
let mut c: Vec<RelativePosition> = Vec::with_capacity(4);
|
|
|
|
let mut c: Vec<RelativePosition> = Vec::with_capacity(4);
|
|
|
|
|
|
|
|
|
|
|
|
let center: (isize, isize) = {
|
|
|
|
let center: (isize, isize) = {
|
|
|
|
// This could be less lines of code but it would be confusing af
|
|
|
|
// This could be less lines of code but it would be confusing af
|
|
|
|
let y = if self.0.len() % 2 == 1 {
|
|
|
|
let y = if self.0.len() % 2 == 1 {
|
|
|
|
@ -200,6 +204,44 @@ impl ShapeLayout {
|
|
|
|
|
|
|
|
|
|
|
|
[c[0], c[1], c[2], c[3]]
|
|
|
|
[c[0], c[1], c[2], c[3]]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn rotated(&self, o: Orientation) -> Self {
|
|
|
|
|
|
|
|
info!("Rotation: {:?} {:?}", o, self);
|
|
|
|
|
|
|
|
// Now we have the base layout, rotate it based on orientation
|
|
|
|
|
|
|
|
match o {
|
|
|
|
|
|
|
|
Orientation::Up => {
|
|
|
|
|
|
|
|
// The identity
|
|
|
|
|
|
|
|
self.clone()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Orientation::Right => {
|
|
|
|
|
|
|
|
// The main algorithm
|
|
|
|
|
|
|
|
let cols = self.0[0].len();
|
|
|
|
|
|
|
|
let rows = self.0.len();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut rotated = vec![vec![0;rows];cols];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// (i, j) -> (j,rows-1-i)
|
|
|
|
|
|
|
|
for i in 0..rows {
|
|
|
|
|
|
|
|
for j in 0..cols {
|
|
|
|
|
|
|
|
rotated[j][rows - 1 - i] = self.0[i][j];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ShapeLayout(rotated)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Orientation::Down => {
|
|
|
|
|
|
|
|
// Implemented as repeated turns right
|
|
|
|
|
|
|
|
self.rotated(Orientation::Right)
|
|
|
|
|
|
|
|
.rotated(Orientation::Right)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Orientation::Left => {
|
|
|
|
|
|
|
|
// Implemented as repeated turns right
|
|
|
|
|
|
|
|
self.rotated(Orientation::Right)
|
|
|
|
|
|
|
|
.rotated(Orientation::Right)
|
|
|
|
|
|
|
|
.rotated(Orientation::Right)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
#[derive(Default)]
|
|
|
|
@ -342,7 +384,7 @@ fn add_relative_position(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Populate Transform when GridPosition is added to an entity
|
|
|
|
/// Populate Transform when GridPosition is added to an entity
|
|
|
|
fn update_grid_position(
|
|
|
|
fn update_grid_position_transform(
|
|
|
|
mut query: Query<
|
|
|
|
mut query: Query<
|
|
|
|
(&GridPosition, &mut Transform),
|
|
|
|
(&GridPosition, &mut Transform),
|
|
|
|
Or<(Added<GridPosition>, Changed<GridPosition>)>,
|
|
|
|
Or<(Added<GridPosition>, Changed<GridPosition>)>,
|
|
|
|
@ -354,6 +396,7 @@ fn update_grid_position(
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// When grid position is updated on a shape, apply that to blocks
|
|
|
|
fn propogate_grid_position(
|
|
|
|
fn propogate_grid_position(
|
|
|
|
parent: Query<(&GridPosition, &ShapeBlocks), Changed<GridPosition>>,
|
|
|
|
parent: Query<(&GridPosition, &ShapeBlocks), Changed<GridPosition>>,
|
|
|
|
mut children: Query<(&mut GridPosition, &RelativePosition), Without<ShapeBlocks>>,
|
|
|
|
mut children: Query<(&mut GridPosition, &RelativePosition), Without<ShapeBlocks>>,
|
|
|
|
@ -366,6 +409,21 @@ fn propogate_grid_position(
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// When a shape's orientation changes, the blocks need to move
|
|
|
|
|
|
|
|
fn propogate_orientation(
|
|
|
|
|
|
|
|
parent: Query<(&GridPosition, &Orientation, &ShapeLayout, &ShapeBlocks), Changed<Orientation>>,
|
|
|
|
|
|
|
|
mut children: Query<&mut GridPosition, Without<ShapeBlocks>>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
parent.iter().for_each(|(parent_gp, parent_o, sl, sbs)| {
|
|
|
|
|
|
|
|
let new_layout = sl.rotated(*parent_o).positions();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sbs.iter().zip(new_layout).for_each(|(e, rp)| {
|
|
|
|
|
|
|
|
let mut gp = children.get_mut(e).unwrap();
|
|
|
|
|
|
|
|
*gp = parent_gp.clone() + rp;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Movement message used to propose/plan a move
|
|
|
|
/// Movement message used to propose/plan a move
|
|
|
|
#[derive(Debug, Message)]
|
|
|
|
#[derive(Debug, Message)]
|
|
|
|
enum Movement {
|
|
|
|
enum Movement {
|
|
|
|
@ -405,31 +463,55 @@ fn handle_kb_input(mut input: MessageReader<KeyboardInput>, mut moves: MessageWr
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Component, Default, Debug, Clone, Copy)]
|
|
|
|
|
|
|
|
pub(crate) enum Orientation {
|
|
|
|
|
|
|
|
#[default]
|
|
|
|
|
|
|
|
Up,
|
|
|
|
|
|
|
|
Right,
|
|
|
|
|
|
|
|
Down,
|
|
|
|
|
|
|
|
Left,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Orientation {
|
|
|
|
|
|
|
|
fn rotated(&self) -> Orientation {
|
|
|
|
|
|
|
|
match self {
|
|
|
|
|
|
|
|
Orientation::Up => Orientation::Right,
|
|
|
|
|
|
|
|
Orientation::Right => Orientation::Down,
|
|
|
|
|
|
|
|
Orientation::Down => Orientation::Left,
|
|
|
|
|
|
|
|
Orientation::Left => Orientation::Up,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn handle_movement(
|
|
|
|
fn handle_movement(
|
|
|
|
mut moves: MessageReader<Movement>,
|
|
|
|
mut moves: MessageReader<Movement>,
|
|
|
|
mut query: Query<&mut GridPosition, With<ShapeBlocks>>,
|
|
|
|
mut grid_positions: Query<&mut GridPosition, With<ShapeBlocks>>,
|
|
|
|
|
|
|
|
mut orientations: Query<&mut Orientation, With<ShapeBlocks>>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
moves.read().for_each(|m| match m {
|
|
|
|
moves.read().for_each(|m| match m {
|
|
|
|
Movement::Left => {
|
|
|
|
Movement::Left => {
|
|
|
|
query.iter_mut().for_each(|mut gp| {
|
|
|
|
grid_positions.iter_mut().for_each(|mut gp| {
|
|
|
|
info!("moving shape left");
|
|
|
|
info!("moving shape left");
|
|
|
|
*gp -= RelativePosition::new(1, 0);
|
|
|
|
*gp -= RelativePosition::new(1, 0);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Movement::Right => {
|
|
|
|
Movement::Right => {
|
|
|
|
query.iter_mut().for_each(|mut gp| {
|
|
|
|
grid_positions.iter_mut().for_each(|mut gp| {
|
|
|
|
info!("moving shape right");
|
|
|
|
info!("moving shape right");
|
|
|
|
*gp += RelativePosition::new(1, 0);
|
|
|
|
*gp += RelativePosition::new(1, 0);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Movement::Down => {
|
|
|
|
Movement::Down => {
|
|
|
|
query.iter_mut().for_each(|mut gp| {
|
|
|
|
grid_positions.iter_mut().for_each(|mut gp| {
|
|
|
|
info!("moving shape down");
|
|
|
|
info!("moving shape down");
|
|
|
|
*gp -= RelativePosition::new(0, 1);
|
|
|
|
*gp -= RelativePosition::new(0, 1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Movement::Rotate => {
|
|
|
|
Movement::Rotate => {
|
|
|
|
todo!()
|
|
|
|
orientations.iter_mut().for_each(|mut o| {
|
|
|
|
|
|
|
|
info!("rotating shape");
|
|
|
|
|
|
|
|
*o = o.rotated();
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|