Compare commits
No commits in common. 'f15421a4612cb5878485303007f7a41dc4ea91ff' and '1cbf30704da17955b38f802344010664c08c44f5' have entirely different histories.
f15421a461
...
1cbf30704d
30 changed files with 147 additions and 453 deletions
@ -1,11 +1,4 @@ |
|||||||
[ |
[ |
||||||
"vampire_black", |
"default", |
||||||
"demon_girl_red", |
"platform", |
||||||
"star_blonde", |
|
||||||
"slime_green", |
|
||||||
"idol_teal", |
|
||||||
"kitten_blue", |
|
||||||
"dragon_scale_purple", |
|
||||||
"mermaid_pink", |
|
||||||
"default_cube_gray", |
|
||||||
] |
] |
||||||
|
|||||||
@ -0,0 +1,3 @@ |
|||||||
|
( |
||||||
|
color: (124, 144, 255), |
||||||
|
) |
||||||
@ -1,3 +0,0 @@ |
|||||||
( |
|
||||||
color: (200, 200, 200), |
|
||||||
) |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
( |
|
||||||
color: (198, 80, 88), |
|
||||||
) |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
( |
|
||||||
color: (128, 67, 145), |
|
||||||
) |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
( |
|
||||||
color: (0, 150, 135), |
|
||||||
) |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
( |
|
||||||
color: (76, 136, 255), |
|
||||||
) |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
( |
|
||||||
color: (255, 187, 217), |
|
||||||
) |
|
||||||
@ -0,0 +1,3 @@ |
|||||||
|
( |
||||||
|
color: (64, 64, 64), |
||||||
|
) |
||||||
@ -1,3 +0,0 @@ |
|||||||
( |
|
||||||
color: (161, 197, 109), |
|
||||||
) |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
( |
|
||||||
color: (255, 230, 177), |
|
||||||
) |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
( |
|
||||||
color: (26, 28, 30), |
|
||||||
) |
|
||||||
@ -1,27 +1,15 @@ |
|||||||
use bevy::prelude::*; |
use bevy::prelude::*; |
||||||
|
|
||||||
pub mod client_inputs; |
mod client_inputs; |
||||||
pub mod cursor_grab; |
mod cursor_grab; |
||||||
pub mod head_orientation; |
mod head_orientation; |
||||||
|
|
||||||
pub use cursor_grab::is_cursor_grabbed; |
pub use cursor_grab::is_cursor_grabbed; |
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) { |
pub fn plugin(app: &mut App) { |
||||||
app.add_plugins(( |
app.add_plugins(( |
||||||
client_inputs::plugin, |
client_inputs::plugin, |
||||||
cursor_grab::plugin, |
cursor_grab::plugin, |
||||||
head_orientation::plugin, |
head_orientation::plugin, |
||||||
)); |
)); |
||||||
|
|
||||||
// Make entities require the `Pickable` component if
|
|
||||||
// they should be considered for the picking system.
|
|
||||||
app.insert_resource(MeshPickingSettings { |
|
||||||
require_markers: true, |
|
||||||
..default() |
|
||||||
}); |
|
||||||
|
|
||||||
// Insert `MeshPickingCamera` component on any 3D camera.
|
|
||||||
app.add_observer(|event: On<Add, Camera3d>, mut commands: Commands| { |
|
||||||
commands.entity(event.entity).insert(MeshPickingCamera); |
|
||||||
}); |
|
||||||
} |
} |
||||||
|
|||||||
@ -1,150 +0,0 @@ |
|||||||
use bevy::color::palettes::css::*; |
|
||||||
use bevy::prelude::*; |
|
||||||
use common::prelude::*; |
|
||||||
|
|
||||||
use bevy::window::{CursorGrabMode, CursorOptions}; |
|
||||||
|
|
||||||
use crate::assets::block_visuals::BlockVisuals; |
|
||||||
|
|
||||||
const SCALE: i32 = 4; |
|
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) { |
|
||||||
let blocks_changed = Manifest::<BlockVisuals>::changed; |
|
||||||
app.add_systems(PostUpdate, setup_selection_ui.run_if(blocks_changed)); |
|
||||||
app.add_systems(Update, update_selection_visibility); |
|
||||||
let selection_changed = resource_exists_and_changed::<SelectedBlock>; |
|
||||||
app.add_systems(Update, update_selected_cell.run_if(selection_changed)); |
|
||||||
} |
|
||||||
|
|
||||||
#[derive(Resource, Deref, DerefMut)] |
|
||||||
pub struct SelectedBlock(Identifier<Block>); |
|
||||||
|
|
||||||
#[derive(Component)] |
|
||||||
struct BlockSelectionLayout; |
|
||||||
|
|
||||||
#[derive(Component)] |
|
||||||
#[require(Button, Pickable)] |
|
||||||
struct BlockSelectionCell { |
|
||||||
id: Identifier<Block>, |
|
||||||
} |
|
||||||
|
|
||||||
fn setup_selection_ui( |
|
||||||
existing: Option<Single<Entity, With<BlockSelectionLayout>>>, |
|
||||||
blocks: Manifest<BlockVisuals>, |
|
||||||
mut commands: Commands, |
|
||||||
) { |
|
||||||
// Despawn previous block selection UI, if present.
|
|
||||||
if let Some(existing) = existing { |
|
||||||
commands.entity(*existing).despawn(); |
|
||||||
} |
|
||||||
|
|
||||||
commands |
|
||||||
.spawn(( |
|
||||||
BlockSelectionLayout, |
|
||||||
Node { |
|
||||||
width: percent(100), |
|
||||||
height: percent(100), |
|
||||||
align_items: AlignItems::Center, |
|
||||||
justify_content: JustifyContent::Center, |
|
||||||
..default() |
|
||||||
}, |
|
||||||
)) |
|
||||||
.with_children(|builder| { |
|
||||||
builder |
|
||||||
.spawn(( |
|
||||||
Pickable::default(), |
|
||||||
Node { |
|
||||||
display: Display::Grid, |
|
||||||
padding: UiRect::all(px(4 * SCALE)), |
|
||||||
grid_template_columns: RepeatedGridTrack::auto(9), |
|
||||||
overflow: Overflow::scroll_y(), |
|
||||||
..default() |
|
||||||
}, |
|
||||||
BackgroundColor(BLACK.with_alpha(0.4).into()), |
|
||||||
)) |
|
||||||
.observe(|mut event: On<Pointer<Click>>| { |
|
||||||
// Ensure the event doesn't propagate up to the
|
|
||||||
// `Window`, which would grab the mouse cursor.
|
|
||||||
event.propagate(false); |
|
||||||
}) |
|
||||||
.with_children(|builder| { |
|
||||||
for block in blocks.iter() { |
|
||||||
spawn_block_cell(builder, block); |
|
||||||
} |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
fn spawn_block_cell(builder: &mut ChildSpawnerCommands, block: &BlockVisuals) { |
|
||||||
let id = block.id().clone(); |
|
||||||
builder |
|
||||||
.spawn(( |
|
||||||
BlockSelectionCell { id }, |
|
||||||
Node { |
|
||||||
width: px(16 * SCALE), |
|
||||||
height: px(16 * SCALE), |
|
||||||
margin: UiRect::all(px(2 * SCALE)), |
|
||||||
padding: UiRect::all(px(2 * SCALE)), |
|
||||||
border: UiRect::all(px(2 * SCALE)), |
|
||||||
..default() |
|
||||||
}, |
|
||||||
BackgroundColor(block.color()), |
|
||||||
BorderColor::all(BLACK), |
|
||||||
)) |
|
||||||
.observe(on_cell_click) |
|
||||||
.observe(on_cell_over) |
|
||||||
.observe(on_cell_out); |
|
||||||
} |
|
||||||
|
|
||||||
// TODO: Ideally visibility should be toggled when pressing `E`, but this works for now.
|
|
||||||
fn update_selection_visibility( |
|
||||||
cursor: Single<&CursorOptions, Changed<CursorOptions>>, |
|
||||||
crosshair: Single<&mut Visibility, With<BlockSelectionLayout>>, |
|
||||||
) { |
|
||||||
let is_grabbed = cursor.grab_mode != CursorGrabMode::None; |
|
||||||
let mut selection_visibility = crosshair.into_inner(); |
|
||||||
*selection_visibility = is_grabbed.then_some(Visibility::Hidden).unwrap_or_default(); |
|
||||||
} |
|
||||||
|
|
||||||
fn update_selected_cell( |
|
||||||
cells: Query<(&BlockSelectionCell, &mut BorderColor)>, |
|
||||||
selected_block: Res<SelectedBlock>, |
|
||||||
) { |
|
||||||
for (cell, mut color) in cells { |
|
||||||
let is_selected = cell.id == **selected_block; |
|
||||||
*color = if is_selected { WHITE } else { BLACK }.into(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
fn on_cell_click( |
|
||||||
event: On<Pointer<Click>>, |
|
||||||
mut cells: Query<&BlockSelectionCell>, |
|
||||||
mut commands: Commands, |
|
||||||
) { |
|
||||||
// SAFETY: Entity is known to have this component.
|
|
||||||
let cell = cells.get_mut(event.entity).unwrap(); |
|
||||||
// Resource mightn't've been added yet, so let's just insert / replace it.
|
|
||||||
commands.insert_resource(SelectedBlock(cell.id.clone())); |
|
||||||
} |
|
||||||
|
|
||||||
fn on_cell_over( |
|
||||||
event: On<Pointer<Over>>, |
|
||||||
mut cells: Query<(&BlockSelectionCell, &mut BorderColor)>, |
|
||||||
selected_block: Option<Res<SelectedBlock>>, |
|
||||||
) { |
|
||||||
// SAFETY: Entity is known to have these components.
|
|
||||||
let (cell, mut color) = cells.get_mut(event.entity).unwrap(); |
|
||||||
let is_selected = selected_block.is_some_and(|s| cell.id == **s); |
|
||||||
*color = if is_selected { WHITE } else { GRAY }.into(); |
|
||||||
} |
|
||||||
|
|
||||||
fn on_cell_out( |
|
||||||
event: On<Pointer<Out>>, |
|
||||||
mut cells: Query<(&BlockSelectionCell, &mut BorderColor)>, |
|
||||||
selected_block: Option<Res<SelectedBlock>>, |
|
||||||
) { |
|
||||||
// SAFETY: Entity is known to have these components.
|
|
||||||
let (cell, mut color) = cells.get_mut(event.entity).unwrap(); |
|
||||||
let is_selected = selected_block.is_some_and(|s| cell.id == **s); |
|
||||||
*color = if is_selected { WHITE } else { BLACK }.into(); |
|
||||||
} |
|
||||||
@ -1,33 +1,8 @@ |
|||||||
use bevy::prelude::*; |
use bevy::prelude::*; |
||||||
|
|
||||||
pub mod block_selection; |
mod crosshair; |
||||||
pub mod crosshair; |
mod loading_screen; |
||||||
pub mod loading_screen; |
|
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) { |
pub fn plugin(app: &mut App) { |
||||||
app.add_plugins(( |
app.add_plugins((crosshair::plugin, loading_screen::plugin)); |
||||||
block_selection::plugin, |
|
||||||
crosshair::plugin, |
|
||||||
loading_screen::plugin, |
|
||||||
)); |
|
||||||
|
|
||||||
// Make entities require the `Pickable` component if
|
|
||||||
// they should be considered for the picking system.
|
|
||||||
app.insert_resource(UiPickingSettings { |
|
||||||
require_markers: true, |
|
||||||
}); |
|
||||||
|
|
||||||
app.add_systems(Startup, setup_ui_camera); |
|
||||||
} |
|
||||||
|
|
||||||
fn setup_ui_camera(mut commands: Commands) { |
|
||||||
commands.spawn(( |
|
||||||
Camera2d, |
|
||||||
Camera { |
|
||||||
order: 1, // above 3D camera
|
|
||||||
..default() |
|
||||||
}, |
|
||||||
IsDefaultUiCamera, |
|
||||||
UiPickingCamera, |
|
||||||
)); |
|
||||||
} |
} |
||||||
|
|||||||
Loading…
Reference in new issue