Refactor menu input a bit

This commit is contained in:
2026-09-11 11:38:01 +02:00
parent 3dbda96d31
commit cc850debf2
11 changed files with 282 additions and 189 deletions
+53 -51
View File
@@ -1,12 +1,11 @@
use bevy::{
asset::uuid::Uuid,
math::VectorSpace,
picking::pointer::{Location, PointerId, PointerInput, PointerLocation},
picking::{pointer::{Location, PointerAction, PointerId, PointerInput, PointerLocation}, Pickable},
prelude::*,
window::{NormalizedWindowRef, WindowRef},
window::WindowRef,
};
use crate::{game_settings::GameSettings, input::LocalInputAssignments, menus::input::MenuInput};
use crate::{input::LocalInputAssignments, menus::input::{MenuInput, MenuInputState}};
#[derive(Default)]
pub enum MenuCursorInputSource {
@@ -19,28 +18,20 @@ pub enum MenuCursorInputSource {
pub struct FGMenuCursor {
pub input_source: MenuCursorInputSource,
pub velocity: Vec2,
pub accepting: bool,
}
impl FGMenuCursor {
pub fn create_cursor(
player_slot: usize,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
mapping: Res<LocalInputAssignments>,
meshes: &mut Assets<Mesh>,
materials: &mut Assets<ColorMaterial>,
) -> impl Bundle {
let (_, mapping) = mapping
.iter()
.find(|(slot, _)| *slot == player_slot)
.unwrap();
let material = materials.add(ColorMaterial::from_color(
bevy::color::palettes::tailwind::ROSE_600,
));
let circle_mesh = meshes.add(Circle::new(25.0));
let pointer_id = match mapping {
crate::input::LocalInputSource::Keyboard => PointerId::Mouse,
crate::input::LocalInputSource::Gamepad(_) => PointerId::Custom(Uuid::new_v4()),
};
let pointer_id = PointerId::Custom(Uuid::new_v4());
(
FGMenuCursor {
input_source: super::cursor::MenuCursorInputSource::Player(player_slot),
@@ -51,42 +42,37 @@ impl FGMenuCursor {
Mesh2d(circle_mesh),
Transform::IDENTITY,
GlobalZIndex(1000),
Pickable::IGNORE,
)
}
}
pub fn cursor_input(
window: Single<Entity, With<bevy::window::PrimaryWindow>>,
window: Single<(Entity, &Window), With<bevy::window::PrimaryWindow>>,
query: Query<(
&mut FGMenuCursor,
&PointerLocation,
&PointerId,
)>,
key: Res<ButtonInput<KeyCode>>,
assignments: Res<LocalInputAssignments>,
game_settings: Res<GameSettings>,
menu_inputs: Res<MenuInputState>,
time: Res<Time>,
pads: Query<(Entity, &Gamepad)>,
mut pointer_writer: MessageWriter<PointerInput>,
) {
let (window_entity, window) = window.into_inner();
for (mut cursor, location, pointer_id) in query {
let input = match cursor.input_source {
MenuCursorInputSource::Any => {
let mut input = MenuInput::default();
for (_, source) in assignments.iter() {
input.accumulate(&MenuInput::from_source(
source,
&key,
&pads,
&assignments,
&game_settings,
));
input.accumulate(&menu_inputs.get(source));
}
input
}
MenuCursorInputSource::Player(slot) => {
if let Some((_, source)) = assignments.iter().find(|(idx, _)| *idx == slot) {
MenuInput::from_source(source, &key, &pads, &assignments, &game_settings)
menu_inputs.get(source)
} else {
MenuInput::default()
}
@@ -96,35 +82,45 @@ pub fn cursor_input(
let movement_screen_space = input.movement * Vec2::new(1.0, -1.0);
cursor.velocity = movement_screen_space * 500.0;
if cursor.velocity == Vec2::ZERO {
continue;
}
let initial_cursor_pos = Vec2::new(window.width(), window.height()) / 2.0;
let old_cursor_pos = location
.location
.clone()
.map(|loc| loc.position)
.unwrap_or(Vec2::ZERO);
let cursor_pos = old_cursor_pos + cursor.velocity * time.delta_secs();
.unwrap_or(initial_cursor_pos);
let cursor_pos = (old_cursor_pos + cursor.velocity * time.delta_secs())
.clamp(Vec2::ZERO, Vec2::new(window.width(), window.height()));
let pointer_location = Location {
target: bevy::camera::NormalizedRenderTarget::Window(
WindowRef::Primary
.normalize(Some(window_entity))
.expect("Primary window should be valid"),
),
position: cursor_pos,
};
dbg!(cursor_pos);
if location.location.is_none() || cursor_pos != old_cursor_pos {
pointer_writer.write(PointerInput {
pointer_id: *pointer_id,
location: pointer_location.clone(),
action: PointerAction::Move {
delta: cursor_pos - old_cursor_pos,
},
});
}
pointer_writer.write(PointerInput {
pointer_id: *pointer_id,
location: Location {
target: bevy::camera::NormalizedRenderTarget::Window(
WindowRef::Primary
.normalize(Some(window.entity()))
.expect("Primary window should be valid"),
),
position: cursor_pos,
},
action: bevy::picking::pointer::PointerAction::Move {
delta: cursor_pos - old_cursor_pos,
},
});
//cursor.position
if input.accept != cursor.accepting {
cursor.accepting = input.accept;
pointer_writer.write(PointerInput {
pointer_id: *pointer_id,
location: pointer_location,
action: if input.accept {
PointerAction::Press(PointerButton::Primary)
} else {
PointerAction::Release(PointerButton::Primary)
},
});
}
}
}
@@ -150,3 +146,9 @@ pub fn update_cursor_transform(
trf.translation = Vec3::new(cursor_pos_viewport.x, cursor_pos_viewport.y, 0.0);
}
}
pub fn despawn_cursors(query: Query<Entity, With<FGMenuCursor>>, mut commands: Commands) {
for entity in query {
commands.entity(entity).despawn();
}
}