feat: Add placeholder interact menu (#25)
This commit is contained in:
@@ -19,6 +19,7 @@ impl Plugin for InputPlugin {
|
||||
app.add_systems(Update, move_click.run_if(in_state(AppState::GameScreen)));
|
||||
|
||||
app.add_message::<InteractStartMessage>();
|
||||
app.add_message::<TileClickMessage>();
|
||||
app.add_systems(
|
||||
Update,
|
||||
interact_click.run_if(in_state(AppState::GameScreen)),
|
||||
@@ -65,7 +66,7 @@ fn move_click(
|
||||
}
|
||||
|
||||
fn interact_click(
|
||||
mut interact_messages: MessageWriter<InteractStartMessage>,
|
||||
mut tile_click_messages: MessageWriter<TileClickMessage>,
|
||||
mouse_btn: Res<ButtonInput<MouseButton>>,
|
||||
keys: Res<ButtonInput<KeyCode>>,
|
||||
window: Single<&Window, With<PrimaryWindow>>,
|
||||
@@ -88,7 +89,7 @@ fn interact_click(
|
||||
};
|
||||
|
||||
println!("Interact Click: ({}, {})", x, y);
|
||||
interact_messages.write(InteractStartMessage { x, y });
|
||||
tile_click_messages.write(TileClickMessage { x, y });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,3 +16,9 @@ pub struct InteractStartMessage {
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
pub struct TileClickMessage {
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@ use utils::manhattan_distance;
|
||||
|
||||
pub mod components;
|
||||
pub mod messages;
|
||||
pub mod ui;
|
||||
pub mod utils;
|
||||
|
||||
pub struct PomPlugin;
|
||||
|
||||
impl Plugin for PomPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_plugins(ui::PomUiPlugin);
|
||||
app.add_systems(OnEnter(AppState::GameScreen), setup);
|
||||
app.add_systems(OnExit(AppState::GameScreen), cleanup);
|
||||
|
||||
|
||||
122
src/features/pom/ui/context_menu.rs
Normal file
122
src/features/pom/ui/context_menu.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
use crate::features::ui::utils::ui_blocks;
|
||||
use crate::prelude::*;
|
||||
use bevy::window::PrimaryWindow;
|
||||
|
||||
#[derive(Component)]
|
||||
pub enum RootMarker {
|
||||
ContextMenu,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub enum ButtonType {
|
||||
Interact { x: u32, y: u32 },
|
||||
Cancel,
|
||||
}
|
||||
|
||||
pub fn spawn_context_menu(
|
||||
mut commands: Commands,
|
||||
mut tile_click_messages: MessageReader<TileClickMessage>,
|
||||
root_query: Query<Entity, With<RootMarker>>,
|
||||
camera_query: Single<(&Camera, &GlobalTransform), With<Camera2d>>,
|
||||
config: Res<GameConfig>,
|
||||
) {
|
||||
for message in tile_click_messages.read() {
|
||||
// Despawn existing menu
|
||||
for entity in root_query.iter() {
|
||||
commands.entity(entity).try_despawn();
|
||||
}
|
||||
|
||||
let world_pos = grid_to_world_coords(
|
||||
message.x,
|
||||
message.y,
|
||||
Some(0.0),
|
||||
config.grid_width,
|
||||
config.grid_height,
|
||||
);
|
||||
|
||||
let (camera, camera_transform) = *camera_query;
|
||||
|
||||
if let Ok(screen_pos) = camera.world_to_viewport(camera_transform, world_pos) {
|
||||
commands
|
||||
.spawn((
|
||||
Node {
|
||||
position_type: PositionType::Absolute,
|
||||
left: px(screen_pos.x),
|
||||
top: px(screen_pos.y),
|
||||
padding: UiRect::all(px(5.0)),
|
||||
..Node::vstack(px(5.0))
|
||||
},
|
||||
ZIndex(100),
|
||||
BackgroundColor(Color::srgb(0.1, 0.1, 0.1)),
|
||||
BorderRadius::all(px(5)),
|
||||
RootMarker::ContextMenu,
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent.spawn(button(
|
||||
ButtonType::Interact {
|
||||
x: message.x,
|
||||
y: message.y,
|
||||
},
|
||||
ButtonVariant::Primary,
|
||||
Node {
|
||||
padding: UiRect::all(px(5)),
|
||||
..default()
|
||||
},
|
||||
|c| text("<Interact>", 20.0, c),
|
||||
));
|
||||
|
||||
parent.spawn(button(
|
||||
ButtonType::Cancel,
|
||||
ButtonVariant::Destructive,
|
||||
Node {
|
||||
padding: UiRect::all(px(5)),
|
||||
..default()
|
||||
},
|
||||
|c| text("Abbrechen", 20.0, c),
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn click_outside_context_menu(
|
||||
mut commands: Commands,
|
||||
mouse_btn: Res<ButtonInput<MouseButton>>,
|
||||
window: Single<&Window, With<PrimaryWindow>>,
|
||||
ui_query: Query<(&ComputedNode, &GlobalTransform), With<Node>>,
|
||||
root_query: Query<Entity, With<RootMarker>>,
|
||||
) {
|
||||
if mouse_btn.just_pressed(MouseButton::Left) {
|
||||
let Some(cursor_pos) = window.cursor_position() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !ui_blocks(window, cursor_pos, ui_query) {
|
||||
for entity in root_query.iter() {
|
||||
commands.entity(entity).try_despawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buttons(
|
||||
mut commands: Commands,
|
||||
mut button_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>,
|
||||
mut interact_messages: MessageWriter<InteractStartMessage>,
|
||||
root_query: Query<Entity, With<RootMarker>>,
|
||||
) {
|
||||
for (interaction, button_type) in button_query.iter_mut() {
|
||||
if *interaction == Interaction::Pressed {
|
||||
match button_type {
|
||||
ButtonType::Interact { x, y } => {
|
||||
interact_messages.write(InteractStartMessage { x: *x, y: *y });
|
||||
}
|
||||
ButtonType::Cancel => (),
|
||||
}
|
||||
|
||||
for entity in root_query.iter() {
|
||||
commands.entity(entity).despawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/features/pom/ui/mod.rs
Normal file
22
src/features/pom/ui/mod.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub mod context_menu;
|
||||
|
||||
pub struct PomUiPlugin;
|
||||
|
||||
impl Plugin for PomUiPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(
|
||||
Update,
|
||||
context_menu::spawn_context_menu.run_if(in_state(AppState::GameScreen)),
|
||||
);
|
||||
app.add_systems(
|
||||
Update,
|
||||
context_menu::click_outside_context_menu.run_if(in_state(AppState::GameScreen)),
|
||||
);
|
||||
app.add_systems(
|
||||
Update,
|
||||
context_menu::buttons.run_if(in_state(AppState::GameScreen)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ pub use crate::features::{
|
||||
phase::components::{CurrentPhase, Phase},
|
||||
pom::{
|
||||
components::{GridPosition, MovingState, Pom},
|
||||
messages::{InteractStartMessage, MoveMessage},
|
||||
messages::{InteractStartMessage, MoveMessage, TileClickMessage},
|
||||
},
|
||||
savegame::components::SavegamePath,
|
||||
ui::{components::ButtonVariant, consts::*, ui::*, utils::*},
|
||||
|
||||
Reference in New Issue
Block a user