modular ui rework
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user