wayvr: "Fix floor" countdown timer and sound

- 5-second timeout sound with countdown timer
- sort locale JSON
- modify toast lerp amount
This commit is contained in:
Aleksander 2026-03-15 18:59:27 +01:00 committed by galister
parent 769978560e
commit d9f89faf33
11 changed files with 116 additions and 75 deletions

View File

@ -109,9 +109,10 @@
"LAST_EXISTING_SET": "Dies ist das letzte vorhandene Set.",
"EMPTY_SET": "Leeres Set!",
"LETS_ADD_OVERLAYS": "Lass uns ein paar Overlays von der Uhr hinzufügen!",
"FIXING_FLOOR": "Boden wird in 5 Sekunden fixiert...",
"ONE_CONTROLLER_ON_FLOOR": "Lege einen Controller auf den Boden!",
"CANNOT_ADD_SET": "Satz kann nicht hinzugefügt werden!",
"MAXIMUM_SETS_REACHED": "Maximale Anzahl an Sets erreicht."
}
"MAXIMUM_SETS_REACHED": "Maximale Anzahl an Sets erreicht.",
"FIXING_FLOOR_IN_X_SECS": "Boden wird in {SECONDS} Sekunde(n) repariert..."
},
"DONE": "Erledigt"
}

View File

@ -4,41 +4,56 @@
},
"BAR": {
"ADD_MIRROR": "Add a new mirror overlay",
"EDIT_MODE_TOGGLE": "Toggle edit mode",
"ADD_NEW_SET": "Add new set",
"DELETE_CURRENT_SET": "Delete current set",
"TOGGLE_VISIBILITY": "Toggle visibility",
"RESET_POSITION": "Reset position",
"RELOAD_FROM_DISK": "Reload XML from disk",
"CLOSE_MIRROR": "Close mirror",
"CLOSE_APP": "Close app",
"CLOSE_MIRROR": "Close mirror",
"DELETE_CURRENT_SET": "Delete current set",
"EDIT_MODE_TOGGLE": "Toggle edit mode",
"FORCE_CLOSE_APP": "Force close app",
"HANDSFREE": {
"TITLE": "Handsfree mode",
"NONE": "Off",
"HMD": "HMD + pinch",
"EYE_ONLY": "Eye only",
"EYE_TRACKING": "Eye + pinch",
"HMD": "HMD + pinch",
"HMD_ONLY": "HMD only",
"EYE_ONLY": "Eye only"
}
"NONE": "Off",
"TITLE": "Handsfree mode"
},
"RELOAD_FROM_DISK": "Reload XML from disk",
"RESET_POSITION": "Reset position",
"TOGGLE_VISIBILITY": "Toggle visibility"
},
"DEFAULT": "Default",
"DISABLED": "Disabled",
"DONE": "Done",
"EDIT_MODE": {
"ADJUST_CURVATURE": "Adjust curvature",
"ALIGN_TO_HMD": "Align to HMD",
"ALPHA_BLEND_MODE": "Alpha blend mode",
"BLENDING_ADDITIVE": "Additive blending",
"ANGLE_FADE": "Angle fade",
"ANGLE_FADE_HELP": "Fade when not facing HMD",
"BLENDING_ADDITIVE": "Additive blending",
"BLOCK_INPUT": "Block game input",
"CURVATURE": "Curvature",
"DELETE": "Long press to remove from current set",
"DISABLE_GRAB": "Disable grab",
"GLOBAL": "Always visible",
"HINT_POINT_WINDOW": "Point at a window to change its parameters.\nOnce done, leave edit mode using the button on the right.",
"INTERPOLATION": "Interpolation",
"ALIGN_TO_HMD": "Align to HMD",
"KEYBOARD": "Keyboard",
"LEAVE": "Leave edit mode",
"LOCK_INTERACTION": "Lock interaction",
"MOUSE": {
"FLIP180": "Flipped 180°",
"FLIP270": "Flipped 270°",
"FLIP90": "Flipped 90°",
"FLIPPED": "Flipped",
"NORMAL": "Normal",
"ROTATE180": "Rotated 180°",
"ROTATE270": "Rotated 270°",
"ROTATE90": "Rotated 90°",
"TITLE": "Mouse fixes",
"WRONG_SCREEN_SELECTION_HELP": "If the cursor moves on a completely different screen,\nthe screens were likely selected wrong. See readme."
},
"MOVE_PRESS_AND_DRAG": "Move (press & drag)",
"OPACITY": "Opacity",
"POS_ANCHORED": "Anchored: Moves with center marker. Default.",
@ -48,56 +63,42 @@
"POS_HMD": "Follow the HMD.",
"POS_STATIC": "Static: Not part of any set, no recenter.",
"POSITIONING": "Positioning",
"GLOBAL": "Always visible",
"BLOCK_INPUT": "Block game input",
"RESIZE_PRESS_AND_DRAG": "Resize (press & drag)",
"STEREO_3D_MODE": {
"ADJUST_MOUSE": "Adjust mouse",
"FULL_FRAME": "Full 3D",
"FULL_FRAME_BAT": "Full-BAT",
"FULL_FRAME_SBS": "Full-SBS",
"FULL_FRAME_TAB": "Full-TAB",
"SPLIT_BOTTOM_TOP": "BOTTOM→TOP",
"SPLIT_LEFT_RIGHT": "LEFT→RIGHT",
"SPLIT_RIGHT_LEFT": "RIGHT→LEFT",
"SPLIT_TOP_BOTTOM": "TOP→BOTTOM",
"TITLE": "3D Stereo Mode",
"FULL_FRAME": "Full 3D",
"FULL_FRAME_SBS": "Full-SBS",
"FULL_FRAME_TAB": "Full-TAB",
"FULL_FRAME_BAT": "Full-BAT"
},
"MOUSE": {
"TITLE": "Mouse fixes",
"WRONG_SCREEN_SELECTION_HELP": "If the cursor moves on a completely different screen,\nthe screens were likely selected wrong. See readme.",
"NORMAL": "Normal",
"ROTATE90": "Rotated 90°",
"ROTATE180": "Rotated 180°",
"ROTATE270": "Rotated 270°",
"FLIPPED": "Flipped",
"FLIP90": "Flipped 90°",
"FLIP180": "Flipped 180°",
"FLIP270": "Flipped 270°"
"TITLE": "3D Stereo Mode"
}
},
"GRAB": {
"ADJUST_DISTANCE": "Adjust distance",
"ADJUST_SIZE": "Adjust size",
"UNRESTRICTED_MOVEMENT": "Unrestricted movement",
"GRABBING_WATCH": "To swap hands, move the watch in front and grab it with the other hand.",
"GRABBING_STATIC": "This overlay is Static and will stay in place, ignoring recenter.",
"GRABBING_ANCHORED": "Anchored overlays all move together. Separate a single window by grabbing it with the other hand while still grabbing the anchor.",
"GRABBING_ANCHORED_EDIT": "This overlay will stay anchored to the center marker.",
"GRABBING_FLOATING": "This overlay is Floating and will stay in place, unless recentered.",
"GRABBING_FOLLOW": "This overlay will follow the device it is attached to."
"GRABBING_FOLLOW": "This overlay will follow the device it is attached to.",
"GRABBING_STATIC": "This overlay is Static and will stay in place, ignoring recenter.",
"GRABBING_WATCH": "To swap hands, move the watch in front and grab it with the other hand.",
"UNRESTRICTED_MOVEMENT": "Unrestricted movement"
},
"TOAST": {
"DEFAULT_TITLE": "Notification",
"ERROR": "Error",
"CANNOT_ADD_SET": "Cannot add set!",
"MAXIMUM_SETS_REACHED": "Maximum number of sets reached.",
"CANNOT_REMOVE_SET": "Cannot remove set!",
"NO_SET_SELECTED": "No set is selected.",
"LAST_EXISTING_SET": "This is the last existing set.",
"DEFAULT_TITLE": "Notification",
"EMPTY_SET": "Empty set!",
"ERROR": "Error",
"FIXING_FLOOR_IN_X_SECS": "Fixing floor in {SECONDS} second(s)...",
"LAST_EXISTING_SET": "This is the last existing set.",
"LETS_ADD_OVERLAYS": "Let's add some overlays from the watch!",
"FIXING_FLOOR": "Fixing floor in 5 seconds...",
"MAXIMUM_SETS_REACHED": "Maximum number of sets reached.",
"NO_SET_SELECTED": "No set is selected.",
"ONE_CONTROLLER_ON_FLOOR": "Place one controller on the floor!"
},
"WATCH": {

View File

@ -109,9 +109,10 @@
"LAST_EXISTING_SET": "Este es el último conjunto existente.",
"EMPTY_SET": "¡Conjunto vacío!",
"LETS_ADD_OVERLAYS": "¡Añadamos algunos overlays desde el reloj!",
"FIXING_FLOOR": "Fijando el suelo en 5 segundos...",
"ONE_CONTROLLER_ON_FLOOR": "¡Coloca un mando en el suelo!",
"CANNOT_ADD_SET": "¡No se puede agregar el conjunto!",
"MAXIMUM_SETS_REACHED": "Se ha alcanzado el número máximo de sets."
}
"MAXIMUM_SETS_REACHED": "Se ha alcanzado el número máximo de sets.",
"FIXING_FLOOR_IN_X_SECS": "Corrigiendo el suelo en {SECONDS} segundo(s)..."
},
"DONE": "Hecho"
}

View File

@ -97,8 +97,8 @@
"LAST_EXISTING_SET": "Questo è l'ultimo set esistente.",
"EMPTY_SET": "Set vuoto!",
"LETS_ADD_OVERLAYS": "Aggiungiamo degli overlay dal Watch!",
"FIXING_FLOOR": "Rifissaggio del pavimento tra 5 secondi...",
"ONE_CONTROLLER_ON_FLOOR": "Posiziona un controller a terra!"
"ONE_CONTROLLER_ON_FLOOR": "Posiziona un controller a terra!",
"FIXING_FLOOR_IN_X_SECS": "Correzione del pavimento in {SECONDS} secondo/i..."
},
"WATCH": {
"ADD_NEW_SET": "Aggiungi un nuovo set",
@ -111,5 +111,6 @@
"RECENTER": "Recentra l'area di gioco",
"SWITCH_TO_SET": "Passa a set",
"TOGGLE_FOR_CURRENT_SET": "Attiva/disattiva per il set corrente"
}
},
"DONE": "Fatto"
}

View File

@ -107,9 +107,10 @@
"LAST_EXISTING_SET": "これが最後の設定です。",
"EMPTY_SET": "空のセットです!",
"LETS_ADD_OVERLAYS": "ウォッチからオーバーレイを追加しましょう!",
"FIXING_FLOOR": "5秒後にフロアを固定します...",
"ONE_CONTROLLER_ON_FLOOR": "コントローラーを床に置いてください!",
"CANNOT_ADD_SET": "セットを追加できません!",
"MAXIMUM_SETS_REACHED": "最大セット数に達しました。"
}
"MAXIMUM_SETS_REACHED": "最大セット数に達しました。",
"FIXING_FLOOR_IN_X_SECS": "{SECONDS}秒で床を固定中..."
},
"DONE": "完了"
}

View File

@ -107,9 +107,10 @@
"LAST_EXISTING_SET": "To jest ostatni istniejący zestaw.",
"EMPTY_SET": "Pusty zestaw!",
"LETS_ADD_OVERLAYS": "Dodajmy kilka nakładek z zegarka!",
"FIXING_FLOOR": "Naprawianie podłogi za 5 sekund...",
"ONE_CONTROLLER_ON_FLOOR": "Umieść jeden kontroler na podłodze!",
"CANNOT_ADD_SET": "Nie można dodać zestawu!",
"MAXIMUM_SETS_REACHED": "Osiągnięto maksymalną liczbę zestawów."
}
"MAXIMUM_SETS_REACHED": "Osiągnięto maksymalną liczbę zestawów.",
"FIXING_FLOOR_IN_X_SECS": "Naprawianie podłogi za {SECONDS} sekund(y)..."
},
"DONE": "Gotowe"
}

View File

@ -97,8 +97,8 @@
"LAST_EXISTING_SET": "这是最后一个现有的集合。",
"EMPTY_SET": "空集合!",
"LETS_ADD_OVERLAYS": "让我们从手表添加一些覆盖层吧!",
"FIXING_FLOOR": "将在 5 秒内修复地面...",
"ONE_CONTROLLER_ON_FLOOR": "请将一个控制器放在地面上!"
"ONE_CONTROLLER_ON_FLOOR": "请将一个控制器放在地面上!",
"FIXING_FLOOR_IN_X_SECS": "{SECONDS}秒内固定地面..."
},
"WATCH": {
"ADD_NEW_SET": "添加新集合",
@ -111,5 +111,6 @@
"RECENTER": "重置游玩区中心 (Recenter)",
"SWITCH_TO_SET": "切换到集合",
"TOGGLE_FOR_CURRENT_SET": "切换当前集合"
}
},
"DONE": "完成"
}

View File

@ -577,19 +577,37 @@ pub(super) fn setup_custom_button<S: 'static>(
return Ok(EventResult::Pass);
}
Toast::new(
ToastTopic::System,
"TOAST.FIXING_FLOOR".into(),
"TOAST.ONE_CONTROLLER_ON_FLOOR".into(),
)
.with_timeout(5.)
.with_sound(true)
.submit(app);
let globals = app.wgui_globals.clone();
app.tasks.enqueue_at(
TaskType::Playspace(PlayspaceTask::FixFloor),
Instant::now() + Duration::from_secs(5),
);
let duration_secs = 5;
let now = Instant::now();
for i in 0..duration_secs {
Toast::new(
ToastTopic::System,
globals.i18n().translate_and_replace(
"TOAST.FIXING_FLOOR_IN_X_SECS",
("{SECONDS}", &format!("{}", duration_secs - i)),
),
"TOAST.ONE_CONTROLLER_ON_FLOOR".into(),
)
.with_timeout(1.0)
.with_lerp_amount(1.0)
.with_sound(i == 0)
.submit_at(app, now + Duration::from_secs(i as _));
}
app.audio_sample_player
.play_sample(&mut app.audio_system, "fix_floor");
let deadline = now + Duration::from_secs(duration_secs);
app.tasks
.enqueue_at(TaskType::Playspace(PlayspaceTask::FixFloor), deadline);
Toast::new(ToastTopic::System, "DONE".into(), String::new())
.with_timeout(2.0)
.submit_at(app, deadline);
Ok(EventResult::Consumed)
}),
"::Shutdown" => Box::new(move |_common, data, app, _| {

View File

@ -30,6 +30,7 @@ pub struct Toast {
pub body: String,
pub opacity: f32,
pub timeout: f32,
pub lerp_amount: f32,
pub sound: bool,
pub topic: ToastTopic,
}
@ -41,6 +42,7 @@ impl Toast {
title,
body,
opacity: 1.0,
lerp_amount: 0.1,
timeout: 3.0,
sound: false,
topic,
@ -50,6 +52,10 @@ impl Toast {
self.timeout = timeout;
self
}
pub const fn with_lerp_amount(mut self, lerp: f32) -> Self {
self.lerp_amount = lerp;
self
}
pub const fn with_opacity(mut self, opacity: f32) -> Self {
self.opacity = opacity;
self
@ -118,7 +124,9 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<OverlayWindowConfig> {
ToastDisplayMethod::Center => (
vec3(0., -0.2, -0.5),
Quat::IDENTITY,
Positioning::FollowHead { lerp: 0.1 },
Positioning::FollowHead {
lerp: toast.lerp_amount,
},
),
ToastDisplayMethod::Watch => {
let relative_to = Positioning::FollowHand {

BIN
wayvr/src/res/fix_floor.mp3 Normal file

Binary file not shown.

View File

@ -98,7 +98,7 @@ impl AppState {
let mut audio_sample_player = audio::SamplePlayer::new();
audio_sample_player.register_sample(
"key_click",
audio::AudioSample::from_mp3(&*audio::AudioSample::bytes_from_config_or_default(
audio::AudioSample::from_mp3(&audio::AudioSample::bytes_from_config_or_default(
"sound/key_click.mp3",
include_bytes!("res/key_click.mp3"),
))?,
@ -106,12 +106,20 @@ impl AppState {
audio_sample_player.register_sample(
"toast",
audio::AudioSample::from_mp3(&*audio::AudioSample::bytes_from_config_or_default(
audio::AudioSample::from_mp3(&audio::AudioSample::bytes_from_config_or_default(
"sound/toast.mp3",
include_bytes!("res/toast.mp3"),
))?,
)?;
audio_sample_player.register_sample(
"fix_floor",
audio::AudioSample::from_mp3(&audio::AudioSample::bytes_from_config_or_default(
"sound/fix_floor.mp3",
include_bytes!("res/fix_floor.mp3"),
))?,
)?;
let mut assets = Box::new(gui::asset::GuiAsset {});
audio_sample_player.register_wgui_samples(assets.as_mut())?;