|
|
|
|
@ -1,7 +1,25 @@
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
|
// - When shape asset is updated, shape should update in real time
|
|
|
|
|
// - When shape asset is updated, shape layout update in real time
|
|
|
|
|
// - Rotating shape when arrow up pressed
|
|
|
|
|
// - Shape moves left/right/down when respective keys pressed
|
|
|
|
|
// - Add Orientation component
|
|
|
|
|
// - Add functionality to ShapeLayout
|
|
|
|
|
// - Write tests before functionality
|
|
|
|
|
// - Debug: gizmo outline entities
|
|
|
|
|
// - conditional enable/disable
|
|
|
|
|
// - entities without mesh should draw empty cross
|
|
|
|
|
// - Debug: gizmo draw relationship lines
|
|
|
|
|
// - conditional enable/disable
|
|
|
|
|
// - Debug: show FPS
|
|
|
|
|
// - conditional enable/disable
|
|
|
|
|
// - Line entities
|
|
|
|
|
// - Debug: Nametags
|
|
|
|
|
// - If it has a Name component, display that at the same Translation
|
|
|
|
|
// - Disable shape when placed
|
|
|
|
|
// - Assign shapes blocks to lines
|
|
|
|
|
// - When line full, clear it
|
|
|
|
|
|
|
|
|
|
/// Create tetris game with camera that renders to subset of viewport
|
|
|
|
|
///
|
|
|
|
|
@ -21,10 +39,16 @@ impl Plugin for BlocksPlugin {
|
|
|
|
|
Update,
|
|
|
|
|
updated_shape_asset.run_if(on_message::<AssetEvent<ShapeAsset>>),
|
|
|
|
|
)
|
|
|
|
|
.add_observer(add_shape);
|
|
|
|
|
.add_observer(add_shape)
|
|
|
|
|
.add_observer(add_relative_position)
|
|
|
|
|
.add_observer(add_grid_position);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SCALE: f32 = 20.0;
|
|
|
|
|
const X_MAX: usize = 10;
|
|
|
|
|
const Y_MAX: usize = 20;
|
|
|
|
|
|
|
|
|
|
/// Shape asset
|
|
|
|
|
/// Stores shape data in an asset file, likely toml
|
|
|
|
|
#[derive(Asset, TypePath, Debug, Deserialize)]
|
|
|
|
|
@ -44,14 +68,43 @@ fn default_tint() -> String {
|
|
|
|
|
|
|
|
|
|
impl ShapeAsset {
|
|
|
|
|
fn as_bundle(&self) -> impl Bundle {
|
|
|
|
|
// Get shape block's relative positions
|
|
|
|
|
let [a, b, c, d] = self.layout.positions();
|
|
|
|
|
|
|
|
|
|
related!(ShapeBlocks[
|
|
|
|
|
(self.mesh.clone(), self.material.clone(), a),
|
|
|
|
|
(self.mesh.clone(), self.material.clone(), b),
|
|
|
|
|
(self.mesh.clone(), self.material.clone(), c),
|
|
|
|
|
(self.mesh.clone(), self.material.clone(), d),
|
|
|
|
|
])
|
|
|
|
|
(
|
|
|
|
|
GridPosition { x: 5, y: 5 }, // TEMP
|
|
|
|
|
related!(ShapeBlocks[
|
|
|
|
|
(self.mesh.clone(), self.material.clone(), a),
|
|
|
|
|
(self.mesh.clone(), self.material.clone(), b),
|
|
|
|
|
(self.mesh.clone(), self.material.clone(), c),
|
|
|
|
|
(self.mesh.clone(), self.material.clone(), d),
|
|
|
|
|
])
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The main play area grid coordinates
|
|
|
|
|
#[derive(Component)]
|
|
|
|
|
#[require(Transform)]
|
|
|
|
|
struct GridPosition {
|
|
|
|
|
pub x: usize,
|
|
|
|
|
pub y: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl GridPosition {
|
|
|
|
|
fn with_relative_offset(&self, other: &RelativePosition) -> GridPosition {
|
|
|
|
|
GridPosition {
|
|
|
|
|
x: self.x.checked_add_signed(other.x).unwrap(),
|
|
|
|
|
y: self.y.checked_add_signed(other.y).unwrap(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Into<Vec3> for &GridPosition {
|
|
|
|
|
fn into(self) -> Vec3 {
|
|
|
|
|
let x = (self.x as f32 * SCALE) - ((X_MAX / 2) as f32 * SCALE);
|
|
|
|
|
let y = (self.y as f32 * SCALE) - ((Y_MAX / 2) as f32 * SCALE);
|
|
|
|
|
Vec3::new(x, y, 0.0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -135,7 +188,7 @@ impl AssetLoader for ShapeAssetLoader {
|
|
|
|
|
let parsed = toml::from_slice::<ShapeAsset>(bytes.as_slice())?;
|
|
|
|
|
let mesh = {
|
|
|
|
|
// https://docs.rs/bevy/latest/bevy/asset/struct.LoadContext.html#method.add_labeled_asset
|
|
|
|
|
let m: Mesh = Rectangle::new(100.0, 100.0).into();
|
|
|
|
|
let m: Mesh = Rectangle::new(SCALE, SCALE).into();
|
|
|
|
|
let h: Handle<Mesh> =
|
|
|
|
|
load_context.add_labeled_asset(format!("{}#mesh", load_context.asset_path()), m);
|
|
|
|
|
Mesh2d(h)
|
|
|
|
|
@ -211,6 +264,7 @@ fn add_shape(
|
|
|
|
|
commands.entity(event.entity).insert(shape.as_bundle());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// When a shape asset is updated, propogate other required changes
|
|
|
|
|
fn updated_shape_asset(
|
|
|
|
|
mut messages: MessageReader<AssetEvent<ShapeAsset>>,
|
|
|
|
|
query: Query<&AssetComponent<ShapeAsset>>,
|
|
|
|
|
@ -228,3 +282,25 @@ fn updated_shape_asset(
|
|
|
|
|
AssetEvent::LoadedWithDependencies { id } => debug!("Asset lodaed: {id:?}"),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// What to do when a relative position is added to a block
|
|
|
|
|
fn add_relative_position(
|
|
|
|
|
event: On<Add, RelativePosition>,
|
|
|
|
|
relative_positions: Query<&RelativePosition>,
|
|
|
|
|
blocks: Query<&ShapeBlock>,
|
|
|
|
|
grid_positions: Query<&GridPosition>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
let parent_shape = blocks.get(event.entity).unwrap();
|
|
|
|
|
let rp = relative_positions.get(event.entity).unwrap();
|
|
|
|
|
let gp = grid_positions.get(parent_shape.0).unwrap();
|
|
|
|
|
commands.entity(event.entity).insert(gp.with_relative_offset(rp));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn add_grid_position(
|
|
|
|
|
event: On<Add, GridPosition>,
|
|
|
|
|
mut query: Query<(&GridPosition, &mut Transform)>,
|
|
|
|
|
) {
|
|
|
|
|
let (gp, mut t) = query.get_mut(event.entity).unwrap();
|
|
|
|
|
t.translation = gp.into();
|
|
|
|
|
}
|
|
|
|
|
|