diff --git a/assets/sprites/pointer_dot.png b/assets/sprites/pointer_dot.png new file mode 100644 index 0000000..70a1fcf Binary files /dev/null and b/assets/sprites/pointer_dot.png differ diff --git a/assets/sprites/reticule4.png b/assets/sprites/pointer_tri.png similarity index 100% rename from assets/sprites/reticule4.png rename to assets/sprites/pointer_tri.png diff --git a/src/hud.rs b/src/hud.rs index 0791c34..4167b5c 100644 --- a/src/hud.rs +++ b/src/hud.rs @@ -17,6 +17,7 @@ use bevy::prelude::*; use bevy::scene::SceneInstance; use bevy::transform::TransformSystem; use bevy_xpbd_3d::prelude::*; +use serde::{Deserialize, Serialize}; use std::collections::VecDeque; use std::time::SystemTime; @@ -57,6 +58,12 @@ pub const PLAYER_AR_AVATARS: &[(Avatar, &str, f32, &str)] = &[ (Avatar::Asteroid, "metis", 1.3, "Asteroid"), ]; +pub const POINTERS: &[(Pointer, Option<&str>, &str)] = &[ + (Pointer::None, None, "Off"), + (Pointer::Tri, Some("sprites/pointer_tri.png"), "Default"), + (Pointer::Dot, Some("sprites/pointer_dot.png"), "Dot"), +]; + pub struct HudPlugin; impl Plugin for HudPlugin { fn build(&self, app: &mut App) { @@ -77,6 +84,7 @@ impl Plugin for HudPlugin { ( update_overlay_visibility, update_avatar.run_if(on_event::()), + update_pointer.run_if(on_event::()), update_ar_overlays .run_if(game_running) .after(camera::position_to_transform) @@ -105,6 +113,7 @@ impl Plugin for HudPlugin { ))); app.add_event::(); app.add_event::(); + app.add_event::(); app.add_event::(); } } @@ -115,6 +124,8 @@ pub struct TargetEvent(pub Option); pub struct UpdateOverlayVisibility; #[derive(Event)] pub struct UpdateAvatarEvent; +#[derive(Event)] +pub struct UpdatePointerEvent; #[derive(Component)] struct NodeHud; #[derive(Component)] @@ -126,7 +137,7 @@ struct NodeSpeedometerText; #[derive(Component)] struct NodeCurrentChatLine; #[derive(Component)] -struct Reticule; +struct PointerComponent(pub Pointer); #[derive(Component)] struct Speedometer; #[derive(Component)] @@ -180,6 +191,14 @@ pub struct AugmentedRealityOverlay { #[derive(Resource)] struct FPSUpdateTimer(Timer); +#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)] +pub enum Pointer { + None, + #[default] + Tri, + Dot, +} + pub enum Avatar { None, ChefHat, @@ -296,6 +315,7 @@ impl Log { pub fn setup( mut commands: Commands, settings: Res, + prefs: Res, asset_server: Res, mut ew_updateoverlays: EventWriter, ) { @@ -387,31 +407,38 @@ pub fn setup( parent.spawn((bundle_chatbox, NodeConsole)); }); - // Add Reticule - let reticule_handle: Handle = asset_server.load("sprites/reticule4.png"); - commands - .spawn(( - NodeBundle { - style: style_centered(), - visibility, - ..default() - }, - ToggleableHudElement, - )) - .with_children(|builder| { - builder.spawn(( - ImageBundle { - image: UiImage::new(reticule_handle), - style: Style { - width: Val::VMin(5.0), - height: Val::VMin(5.0), + // Add Pointer + for (pointer_enum, sprite, _) in POINTERS { + if sprite.is_none() { + continue; + } + let sprite = sprite.unwrap(); + let pointer_handle: Handle = asset_server.load(sprite.to_string()); + commands + .spawn(( + NodeBundle { + style: style_centered(), + visibility, + ..default() + }, + ToggleableHudElement, + )) + .with_children(|builder| { + builder.spawn(( + ImageBundle { + image: UiImage::new(pointer_handle), + style: Style { + width: Val::VMin(5.0), + height: Val::VMin(5.0), + ..Default::default() + }, + visibility: bool2vis(prefs.pointer == *pointer_enum), ..Default::default() }, - ..Default::default() - }, - Reticule, - )); - }); + PointerComponent(pointer_enum.clone()), + )); + }); + } // HP/O2/Suit Integrity/Power Gauges let gauges_handle: Handle = asset_server.load("sprites/gauge_horizontal.png"); @@ -1300,6 +1327,19 @@ fn update_overlay_visibility( }; } +fn update_pointer( + prefs: ResMut, + mut q_pointer: Query<(&PointerComponent, &mut Visibility)>, +) { + for (pointer, mut vis) in &mut q_pointer { + *vis = if pointer.0 == prefs.pointer { + Visibility::Inherited + } else { + Visibility::Hidden + } + } +} + fn update_avatar( mut commands: Commands, mut settings: ResMut, diff --git a/src/menu.rs b/src/menu.rs index 82f6a32..7cfd3c0 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -65,6 +65,7 @@ pub enum DeathScreenEvent { pub const MENUDEF: &[(&str, MenuAction)] = &[ ("", MenuAction::ToggleAR), ("", MenuAction::ChangeARAvatar), + ("", MenuAction::ChangePointer), ("", MenuAction::ToggleMap), ("", MenuAction::ModLightAmp), ("", MenuAction::ModFlashlightPower), @@ -84,6 +85,7 @@ pub enum MenuAction { ToggleMap, ToggleAR, ChangeARAvatar, + ChangePointer, ModLightAmp, ModFlashlightPower, ModThrusterBoost, @@ -544,6 +546,14 @@ pub fn update_menu( text.sections[i].value = format!("Avatar: {avatar_title}\n"); } } + MenuAction::ChangePointer => { + for pointer in hud::POINTERS { + if pointer.0 == prefs.pointer { + text.sections[i].value = format!("Pointer: {}\n", pointer.2); + break; + } + } + } MenuAction::ToggleMap => { let onoff = bool2string(settings.map_active); text.sections[i].value = format!("Map: {onoff} [M]\n"); @@ -577,6 +587,7 @@ pub fn handle_input( mut ew_sfx: EventWriter, mut ew_updatemenu: EventWriter, mut ew_updateavatar: EventWriter, + mut ew_updatepointer: EventWriter, mut ew_updateoverlays: EventWriter, ) { let last_menu_entry = MENUDEF.len() - 1; @@ -631,6 +642,24 @@ pub fn handle_input( settings.ar_avatar += 1; ew_updateavatar.send(hud::UpdateAvatarEvent); } + MenuAction::ChangePointer => { + let mut index = 0; + for (i, pointer) in hud::POINTERS.iter().enumerate() { + if pointer.0 == prefs.pointer { + index = i; + break; + } + } + index = (index + 1) % hud::POINTERS.len(); + for (i, pointer) in hud::POINTERS.iter().enumerate() { + if i == index { + prefs.pointer = pointer.0; + break; + } + } + ew_updatepointer.send(hud::UpdatePointerEvent); + ew_updatemenu.send(UpdateMenuEvent); + } MenuAction::ModLightAmp => { prefs.light_amp += 1; if prefs.light_amp > 3 { diff --git a/src/var.rs b/src/var.rs index 300e23a..5125afa 100644 --- a/src/var.rs +++ b/src/var.rs @@ -473,6 +473,7 @@ pub struct Preferences { pub third_person: bool, pub shadows_sun: bool, pub avatar: usize, + pub pointer: hud::Pointer, #[serde(default = "Preferences::default_light_amp")] pub light_amp: usize, // 0-3 #[serde(default = "Preferences::default_flashlight_power")]