use bevy::{ asset::uuid::Uuid, picking::{ Pickable, pointer::{Location, PointerAction, PointerId, PointerInput, PointerLocation}, }, prelude::*, window::WindowRef, }; use crate::{ input::{LocalInputAssignments, LocalInputSource}, menus::{ input::{MenuInput, MenuInputState}, scaling, style::FGUiStyle, }, }; #[derive(Default)] pub enum MenuCursorInputSource { #[default] Any, Player(usize), } #[derive(Component, Default)] pub struct FGMenuCursor { pub input_source: MenuCursorInputSource, pub velocity: Vec2, pub accepting: bool, } impl FGMenuCursor { pub fn create_cursor( input_source: MenuCursorInputSource, style: &FGUiStyle, pointer_id: PointerId, ) -> impl Bundle { let circle_icon = style.cursor.handle().clone(); ( FGMenuCursor { input_source: input_source, ..default() }, Node { width: px(64), height: px(64), left: percent(50), top: percent(50), position_type: PositionType::Absolute, ..default() }, ImageNode { image: circle_icon, ..default() }, pointer_id, Transform::IDENTITY, GlobalZIndex(1000), Pickable::IGNORE, ) } pub fn create_shared_cursor(style: &FGUiStyle) -> impl Bundle { Self::create_cursor(MenuCursorInputSource::Any, style, PointerId::Mouse) } pub fn create_player_cursor( player_slot: usize, style: &FGUiStyle, input_source: &LocalInputSource, ) -> impl Bundle { let pointer_id = if matches!(input_source, LocalInputSource::Keyboard) { PointerId::Mouse } else { PointerId::Custom(Uuid::new_v4()) }; Self::create_cursor( MenuCursorInputSource::Player(player_slot), style, pointer_id, ) } } /// The player using the keyboard can input things with the mouse, so we should copy their movement input pub fn copy_mouse_input( mut query: Query<(&FGMenuCursor, &mut PointerLocation, &PointerId)>, assignments: Res, mut input_events: MessageReader>, ) { for event in input_events.read() { if let PointerId::Mouse = event.pointer_id { for (cursor, mut location, _) in query.iter_mut() { let is_mouse = match cursor.input_source { MenuCursorInputSource::Any => true, MenuCursorInputSource::Player(slot) => assignments .get(slot) .map(|(_, source)| matches!(source, LocalInputSource::Keyboard)) .unwrap_or_default(), }; if is_mouse { location.location = Some(event.pointer_location.clone()); } } } } } pub fn cursor_input( window: Single<(Entity, &Window), With>, query: Query<(&mut FGMenuCursor, &PointerLocation, &PointerId)>, assignments: Res, menu_inputs: Res, time: Res