modular ui rework

This commit is contained in:
galister
2024-02-25 19:27:48 +01:00
parent b93ddfce5b
commit b045f46b12
20 changed files with 2161 additions and 1049 deletions

View File

@@ -9,14 +9,15 @@ use openxr as xr;
use glam::{Affine3A, Vec2, Vec3A};
use idmap::IdMap;
use serde::Deserialize;
use thiserror::Error;
use crate::{
overlays::{
keyboard::create_keyboard,
watch::{create_watch, WATCH_NAME, WATCH_SCALE},
watch::{create_watch, WATCH_NAME},
},
state::AppState,
state::{AppState, ScreenMeta},
};
use super::overlay::{OverlayBackend, OverlayData, OverlayState};
@@ -56,8 +57,15 @@ where
crate::overlays::screen::get_screens_x11(&app.session)?
};
let mut watch = create_watch::<T>(app, &screens)?;
log::info!("Watch Rotation: {:?}", watch.state.spawn_rotation);
app.screens.clear();
for screen in screens.iter() {
app.screens.push(ScreenMeta {
name: screen.state.name.clone(),
id: screen.state.id,
});
}
let mut watch = create_watch::<T>(app)?;
watch.state.want_visible = true;
overlays.insert(watch.state.id, watch);
@@ -147,13 +155,14 @@ where
}
// toggle watch back on if it was hidden
if !any_shown && *o.state.name == *WATCH_NAME {
o.state.spawn_scale = WATCH_SCALE * app.session.config.watch_scale;
o.state.reset(app, true);
}
})
}
}
#[derive(Clone)]
#[derive(Clone, Deserialize)]
#[serde(untagged)]
pub enum OverlaySelector {
Id(usize),
Name(Arc<str>),
@@ -181,17 +190,30 @@ impl Ord for AppTask {
}
}
pub enum SystemTask {
ColorGain(ColorChannel, f32),
ResetPlayspace,
FixFloor,
}
pub type OverlayTask = dyn FnOnce(&mut AppState, &mut OverlayState) + Send;
pub type CreateOverlayTask =
dyn FnOnce(&mut AppState) -> Option<(OverlayState, Box<dyn OverlayBackend>)> + Send;
pub enum TaskType {
Global(Box<dyn FnOnce(&mut AppState) + Send>),
Overlay(
OverlaySelector,
Box<dyn FnOnce(&mut AppState, &mut OverlayState) + Send>,
),
CreateOverlay(
OverlaySelector,
Box<dyn FnOnce(&mut AppState) -> Option<(OverlayState, Box<dyn OverlayBackend>)> + Send>,
),
Overlay(OverlaySelector, Box<OverlayTask>),
CreateOverlay(OverlaySelector, Box<CreateOverlayTask>),
DropOverlay(OverlaySelector),
System(SystemTask),
}
#[derive(Deserialize, Clone, Copy)]
pub enum ColorChannel {
R,
G,
B,
All,
}
pub struct TaskContainer {

View File

@@ -143,7 +143,6 @@ impl NotificationManager {
continue;
}
};
log::info!("Received notification message: {}", json_str);
let msg = match serde_json::from_str::<XsoMessage>(json_str) {
Ok(m) => m,
Err(e) => {

View File

@@ -1,8 +1,10 @@
use std::ffi::CStr;
use glam::Affine3A;
use ovr_overlay::{pose::Matrix3x4, sys::HmdMatrix34_t};
use ovr_overlay::{pose::Matrix3x4, settings::SettingsManager, sys::HmdMatrix34_t};
use thiserror::Error;
use crate::backend::common::BackendError;
use crate::backend::common::{BackendError, ColorChannel};
pub trait Affine3AConvert {
fn from_affine(affine: Affine3A) -> Self;
@@ -96,3 +98,92 @@ impl From<OVRError> for BackendError {
BackendError::Fatal(anyhow::Error::new(e))
}
}
use cstr::cstr;
const STEAMVR_SECTION: &CStr = cstr!("steamvr");
const COLOR_GAIN_CSTR: [&'static CStr; 3] = [
cstr!("hmdDisplayColorGainR"),
cstr!("hmdDisplayColorGainG"),
cstr!("hmdDisplayColorGainB"),
];
pub(super) fn adjust_gain(
settings: &mut SettingsManager,
ch: ColorChannel,
delta: f32,
) -> Option<()> {
let current = [
settings
.get_float(STEAMVR_SECTION, COLOR_GAIN_CSTR[0])
.ok()?,
settings
.get_float(STEAMVR_SECTION, COLOR_GAIN_CSTR[1])
.ok()?,
settings
.get_float(STEAMVR_SECTION, COLOR_GAIN_CSTR[2])
.ok()?,
];
// prevent user from turning everything black
let mut min = if current[0] + current[1] + current[2] < 0.11 {
0.1
} else {
0.0
};
match ch {
ColorChannel::R => {
settings
.set_float(
STEAMVR_SECTION,
COLOR_GAIN_CSTR[0],
(current[0] + delta).clamp(min, 1.0),
)
.ok()?;
}
ColorChannel::G => {
settings
.set_float(
STEAMVR_SECTION,
COLOR_GAIN_CSTR[1],
(current[1] + delta).clamp(min, 1.0),
)
.ok()?;
}
ColorChannel::B => {
settings
.set_float(
STEAMVR_SECTION,
COLOR_GAIN_CSTR[2],
(current[2] + delta).clamp(min, 1.0),
)
.ok()?;
}
ColorChannel::All => {
min *= 0.3333;
settings
.set_float(
STEAMVR_SECTION,
COLOR_GAIN_CSTR[0],
(current[0] + delta).clamp(min, 1.0),
)
.ok()?;
settings
.set_float(
STEAMVR_SECTION,
COLOR_GAIN_CSTR[1],
(current[1] + delta).clamp(min, 1.0),
)
.ok()?;
settings
.set_float(
STEAMVR_SECTION,
COLOR_GAIN_CSTR[2],
(current[2] + delta).clamp(min, 1.0),
)
.ok()?;
}
}
Some(())
}

View File

@@ -20,9 +20,11 @@ use vulkano::{
use crate::{
backend::{
common::SystemTask,
input::interact,
notifications::NotificationManager,
openvr::{
helpers::adjust_gain,
input::{set_action_manifest, OpenVrInputSource},
lines::LinePool,
manifest::{install_manifest, uninstall_manifest},
@@ -64,11 +66,11 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
log::info!("Using OpenVR runtime");
let mut overlay_mngr = context.overlay_mngr();
//let mut settings_mngr = context.settings_mngr();
let mut app_mgr = context.applications_mngr();
let mut input_mngr = context.input_mngr();
let mut system_mngr = context.system_mngr();
let mut overlay_mngr = context.overlay_mngr();
let mut settings_mngr = context.settings_mngr();
let mut chaperone_mgr = context.chaperone_setup_mngr();
let mut compositor_mngr = context.compositor_mngr();
@@ -185,6 +187,17 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
overlays.remove_by_selector(&sel);
}
}
TaskType::System(task) => match task {
SystemTask::ColorGain(channel, value) => {
let _ = adjust_gain(&mut settings_mngr, channel, value);
}
SystemTask::FixFloor => {
space_mover.fix_floor(&mut chaperone_mgr, &state.input_state);
}
SystemTask::ResetPlayspace => {
space_mover.reset_offset(&mut chaperone_mgr);
}
},
}
}

View File

@@ -1,7 +1,10 @@
use glam::Vec3A;
use ovr_overlay::{chaperone_setup::ChaperoneSetupManager, sys::EChaperoneConfigFile};
use crate::{backend::common::OverlayContainer, state::AppState};
use crate::{
backend::{common::OverlayContainer, input::InputState},
state::AppState,
};
use super::overlay::OpenVrOverlayData;
@@ -58,6 +61,18 @@ impl PlayspaceMover {
}
}
pub fn reset_offset(&mut self, chaperone_mgr: &mut ChaperoneSetupManager) {
self.offset = Vec3A::ZERO;
self.apply_offset(chaperone_mgr);
}
pub fn fix_floor(&mut self, chaperone_mgr: &mut ChaperoneSetupManager, input: &InputState) {
let y1 = input.pointers[0].pose.translation.y;
let y2 = input.pointers[1].pose.translation.y;
self.offset.y += y1.min(y2) - 0.03;
self.apply_offset(chaperone_mgr);
}
pub fn reset(&mut self) {
self.offset = Vec3A::ZERO;
self.start_position = Vec3A::ZERO;

View File

@@ -330,6 +330,9 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
// set for deletion after all images are done showing
delete_queue.push((o, cur_frame + 5));
}
TaskType::System(_task) => {
// Not implemented
}
}
}

View File

@@ -30,6 +30,7 @@ pub struct OverlayState {
pub alpha: f32,
pub transform: Affine3A,
pub saved_point: Option<Vec3A>,
pub saved_scale: Option<f32>,
pub spawn_scale: f32, // aka width
pub spawn_point: Vec3A,
pub spawn_rotation: Quat,
@@ -52,6 +53,7 @@ impl Default for OverlayState {
alpha: 1.0,
relative_to: RelativeTo::None,
saved_point: None,
saved_scale: None,
spawn_scale: 1.0,
spawn_point: Vec3A::NEG_Z,
spawn_rotation: Quat::IDENTITY,
@@ -97,10 +99,11 @@ impl OverlayState {
pub fn auto_movement(&mut self, app: &mut AppState) {
if let Some(parent) = self.parent_transform(app) {
let scale = self.saved_scale.unwrap_or(self.spawn_scale);
let point = self.saved_point.unwrap_or(self.spawn_point);
self.transform = parent
* Affine3A::from_scale_rotation_translation(
Vec3::ONE * self.spawn_scale,
Vec3::ONE * scale,
self.spawn_rotation,
point.into(),
);
@@ -110,13 +113,12 @@ impl OverlayState {
}
pub fn reset(&mut self, app: &mut AppState, hard_reset: bool) {
let scale = if hard_reset {
if hard_reset {
self.saved_point = None;
self.spawn_scale
} else {
self.transform.x_axis.length()
};
self.saved_scale = None;
}
let scale = self.saved_scale.unwrap_or(self.spawn_scale);
let point = self.saved_point.unwrap_or(self.spawn_point);
let translation = app.input_state.hmd.transform_point3a(point);
@@ -284,17 +286,9 @@ impl InteractionHandler for SplitOverlayBackend {
pub fn ui_transform(extent: &[u32; 2]) -> Affine2 {
let center = Vec2 { x: 0.5, y: 0.5 };
if extent[1] > extent[0] {
Affine2::from_cols(
Vec2::X * (extent[1] as f32 / extent[0] as f32),
Vec2::NEG_Y,
center,
)
} else {
Affine2::from_cols(
Vec2::X,
Vec2::NEG_Y * (extent[0] as f32 / extent[1] as f32),
center,
)
}
Affine2::from_cols(
Vec2::X,
Vec2::NEG_Y * (extent[0] as f32 / extent[1] as f32),
center,
)
}