playspace center?

This commit is contained in:
galister 2026-07-20 00:26:53 +09:00
parent 786660a4d5
commit e1879ca891
9 changed files with 97 additions and 17 deletions

View File

@ -22,7 +22,7 @@ use wgui::{
use wlx_common::{
async_executor::AsyncExecutor,
audio,
dash_interface::{BoxDashInterface, ConfigChangeKind, RecenterMode},
dash_interface::{BoxDashInterface, ConfigChangeKind, DashPlayspaceTask},
locale::WayVRLangProvider,
palette::load_palette,
timestep::{self, Timestep},
@ -31,8 +31,8 @@ use wlx_common::{
use crate::{
assets,
tab::{
Tab, TabType, apps::TabApps, donate::TabDonate, games::TabGames, home::TabHome, monado::TabMonado,
settings::TabSettings, welcome::TabWelcome,
apps::TabApps, donate::TabDonate, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings,
welcome::TabWelcome, Tab, TabType,
},
util::{
popup_manager::{MountPopupOnceParams, PopupManager, PopupManagerParams},
@ -553,7 +553,7 @@ impl<T: 'static> Frontend<T> {
}
fn action_recenter_playspace(&mut self, data: &mut T) -> anyhow::Result<()> {
self.interface.recenter_playspace(data, RecenterMode::Recenter)?;
self.interface.playspace(data, DashPlayspaceTask::Recenter)?;
Ok(())
}

View File

@ -23,7 +23,7 @@ use wgui::{
use wlx_common::{
config::GeneralConfig,
config_io::ConfigRoot,
dash_interface::{ConfigChangeKind, InterfaceFeats, RecenterMode},
dash_interface::{ConfigChangeKind, InterfaceFeats, DashPlayspaceTask},
};
use crate::{
@ -201,7 +201,7 @@ impl<T> Tab<T> for TabSettings<T> {
std::fs::create_dir(&path)?;
}
Task::ResetPlayspace => {
frontend.interface.recenter_playspace(data, RecenterMode::Reset)?;
frontend.interface.playspace(data, DashPlayspaceTask::Reset)?;
return Ok(());
}
Task::RestartSoftware => {

View File

@ -4,10 +4,12 @@ use ovr_overlay::{
compositor::CompositorManager,
sys::{EChaperoneConfigFile, ETrackingUniverseOrigin, HmdMatrix34_t},
};
use wgui::log::LogErr;
use wlx_common::config::GeneralConfig;
use crate::{
backend::{input::InputState, playspace_common, task::PlayspaceTask},
state::AppState,
state::{AppState, PlayspaceState, load_playspace_state, save_playspace_state},
windowing::manager::OverlayWindowManager,
};
@ -24,6 +26,7 @@ pub(super) struct PlayspaceMover {
drag: Option<MoverData<Vec3A>>,
rotate: Option<MoverData<Quat>>,
floor_y: Option<f32>,
playspace_state: PlayspaceState,
}
impl PlayspaceMover {
@ -33,6 +36,7 @@ impl PlayspaceMover {
drag: None,
rotate: None,
floor_y: None,
playspace_state: load_playspace_state().unwrap_or_default(),
}
}
@ -52,6 +56,9 @@ impl PlayspaceMover {
PlayspaceTask::Recenter => {
self.recenter(chaperone_mgr, &app.input_state);
}
PlayspaceTask::SaveCenter => {
self.save_center(chaperone_mgr);
}
}
}
@ -305,6 +312,26 @@ impl PlayspaceMover {
pub fn get_universe(&self) -> ETrackingUniverseOrigin {
self.universe.clone()
}
pub fn save_center(&mut self, chaperone_mgr: &mut ChaperoneSetupManager) {
if self.drag.is_some() {
log::info!("Space drag interrupted by save center");
self.drag = None;
}
if self.rotate.is_some() {
log::info!("Space rotate interrupted by save center");
self.rotate = None;
}
let Some(mat) = get_working_copy(&self.universe, chaperone_mgr) else {
log::warn!("Can't save center - failed to get zero pose");
return;
};
self.playspace_state.openvr_space_center = mat;
let _ =
save_playspace_state(&self.playspace_state).log_err("Could not save playspace state");
}
}
const fn universe_str(universe: &ETrackingUniverseOrigin) -> &'static str {

View File

@ -8,7 +8,7 @@ use crate::{
playspace_common::{self, SpaceGravity, SpaceGravityUpdateParams},
task::PlayspaceTask,
},
state::AppState,
state::{AppState, PlayspaceState, load_playspace_state},
windowing::manager::OverlayWindowManager,
};
@ -25,6 +25,7 @@ pub(super) struct PlayspaceMover {
rotate: Option<MoverData<Quat>>,
gravity: SpaceGravity,
floor_y: f32,
playspace_state: PlayspaceState,
}
impl PlayspaceMover {
@ -42,6 +43,7 @@ impl PlayspaceMover {
rotate: None,
gravity: SpaceGravity::new(),
floor_y: pose.position.y,
playspace_state: load_playspace_state().unwrap_or_default(),
})
}
@ -60,6 +62,7 @@ impl PlayspaceMover {
PlayspaceTask::Recenter => {
self.recenter(&app.input_state, &mut monado.ipc);
}
PlayspaceTask::SaveCenter => { /* OpenVR only */ }
}
}
@ -325,6 +328,28 @@ impl PlayspaceMover {
.set_reference_space_offset(ReferenceSpaceType::Stage, pose)
.inspect_err(|e| log::warn!("Could not fix floor due to libmonado error: {e:?}"));
}
pub fn save_center(&mut self, monado: &mut Monado) {
if self.drag.is_some() {
log::info!("Space drag interrupted by save center");
self.drag = None;
}
if self.rotate.is_some() {
log::info!("Space rotate interrupted by save center");
self.rotate = None;
}
let Ok(mut pose) = monado
.get_reference_space_offset(ReferenceSpaceType::Stage)
.inspect_err(|e| log::warn!("Could not fix floor due to libmonado error: {e:?}"))
else {
return;
};
self.playspace_state.openxr_space_center = mat;
let _ =
save_playspace_state(&self.playspace_state).log_err("Could not save playspace state");
}
}
fn apply_offset(transform: Affine3A, monado: &mut Monado) {

View File

@ -63,6 +63,8 @@ pub enum PlayspaceTask {
Recenter,
Reset,
FixFloor,
#[cfg(feature = "openvr")]
SaveCenter,
}
#[derive(Debug, Clone)]

View File

@ -20,7 +20,7 @@ use wgui::{
widget::EventResult,
};
use wlx_common::{
dash_interface::{self, ConfigChangeKind, DashInterface, RecenterMode},
dash_interface::{self, ConfigChangeKind, DashInterface, DashPlayspaceTask},
locale::WayVRLangProvider,
overlays::{BackendAttrib, BackendAttribValue},
};
@ -504,11 +504,17 @@ impl DashInterface<AppState> for DashInterfaceLive {
Ok(())
}
fn recenter_playspace(&mut self, app: &mut AppState, mode: RecenterMode) -> anyhow::Result<()> {
fn playspace_task(
&mut self,
app: &mut AppState,
mode: DashPlayspaceTask,
) -> anyhow::Result<()> {
let task = match mode {
RecenterMode::FixFloor => PlayspaceTask::FixFloor,
RecenterMode::Recenter => PlayspaceTask::Recenter,
RecenterMode::Reset => PlayspaceTask::Reset,
DashPlayspaceTask::FixFloor => PlayspaceTask::FixFloor,
DashPlayspaceTask::Recenter => PlayspaceTask::Recenter,
DashPlayspaceTask::Reset => PlayspaceTask::Reset,
#[cfg(feature = "openvr")]
DashPlayspaceTask::SaveCenter => PlayspaceTask::SaveCenter,
};
app.tasks.enqueue(TaskType::Playspace(task));
Ok(())

View File

@ -336,3 +336,22 @@ pub fn load_pw_token_config() -> anyhow::Result<PwTokenMap> {
let conf: TokenConf = serde_yaml::from_str(yaml.as_str())?;
Ok(conf.pw_tokens)
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct PlayspaceState {
pub openvr_space_center: Affine3A,
pub openxr_space_center: Affine3A,
}
pub fn load_playspace_state() -> anyhow::Result<PlayspaceState> {
let json = std::fs::read_to_string(config_io::get_config_file_path("playspace.json5"))?;
let state: PlayspaceState = serde_json5::from_str(json.as_str())?;
Ok(state)
}
pub fn save_playspace_state(state: &PlayspaceState) -> anyhow::Result<()> {
let json = serde_json5::to_string(state)?;
std::fs::write(config_io::get_config_file_path("playspace.json5"), json)?;
Ok(())
}

View File

@ -37,10 +37,11 @@ pub struct MonadoDumpSessionFrame {
}
#[derive(Clone, Copy)]
pub enum RecenterMode {
pub enum DashPlayspaceTask {
FixFloor,
Recenter,
Reset,
SaveCenter,
}
#[derive(Clone, Copy)]
@ -69,7 +70,7 @@ pub trait DashInterface<T> {
fn monado_brightness_set(&mut self, data: &mut T, brightness: f32) -> Option<()>;
fn monado_metrics_set_enabled(&mut self, data: &mut T, enabled: bool) -> bool;
fn monado_metrics_dump_session_frames(&mut self, data: &mut T) -> Vec<MonadoDumpSessionFrame>;
fn recenter_playspace(&mut self, data: &mut T, mode: RecenterMode) -> anyhow::Result<()>;
fn playspace_task(&mut self, data: &mut T, mode: DashPlayspaceTask) -> anyhow::Result<()>;
fn desktop_finder<'a>(&'a mut self, data: &'a mut T) -> &'a mut DesktopFinder;
fn general_config<'a>(&'a mut self, data: &'a mut T) -> &'a mut GeneralConfig;
fn config_changed(&mut self, data: &mut T, kind: ConfigChangeKind);

View File

@ -5,7 +5,7 @@ use wayvr_ipc::{
use crate::{
config::GeneralConfig,
dash_interface::{self, ConfigChangeKind, DashInterface, RecenterMode},
dash_interface::{self, ConfigChangeKind, DashInterface, DashPlayspaceTask},
desktop_finder::DesktopFinder,
gen_id,
};
@ -217,7 +217,7 @@ impl DashInterface<()> for DashInterfaceEmulated {
}
}
fn recenter_playspace(&mut self, _: &mut (), _: RecenterMode) -> anyhow::Result<()> {
fn playspace(&mut self, _: &mut (), _: DashPlayspaceTask) -> anyhow::Result<()> {
// stub!
Ok(())
}