refactor overlay windowing
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use libmonado::{ClientState, Monado};
|
||||
use log::{info, warn};
|
||||
|
||||
use crate::{backend::overlay::OverlayID, state::AppState};
|
||||
use crate::{state::AppState, windowing::OverlayID};
|
||||
|
||||
pub(super) struct InputBlocker {
|
||||
hovered_last_frame: bool,
|
||||
|
||||
@@ -17,11 +17,10 @@ use vulkano::{Handle, VulkanObject};
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
common::{BackendError, OverlayContainer},
|
||||
input::interact,
|
||||
openxr::{lines::LinePool, overlay::OpenXrOverlayData},
|
||||
overlay::{OverlayData, ShouldRender},
|
||||
task::{SystemTask, TaskType},
|
||||
BackendError,
|
||||
},
|
||||
graphics::{init_openxr_graphics, CommandBuffers},
|
||||
overlays::{
|
||||
@@ -30,6 +29,7 @@ use crate::{
|
||||
},
|
||||
state::AppState,
|
||||
subsystem::notifications::NotificationManager,
|
||||
windowing::{backend::ShouldRender, manager::OverlayWindowManager, window::OverlayWindowData},
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
@@ -94,7 +94,7 @@ pub fn openxr_run(
|
||||
);
|
||||
}
|
||||
|
||||
let mut overlays = OverlayContainer::<OpenXrOverlayData>::new(&mut app, headless)?;
|
||||
let mut overlays = OverlayWindowManager::<OpenXrOverlayData>::new(&mut app, headless)?;
|
||||
let mut lines = LinePool::new(&app)?;
|
||||
|
||||
let mut notifications = NotificationManager::new();
|
||||
@@ -336,7 +336,7 @@ pub fn openxr_run(
|
||||
|
||||
overlays
|
||||
.values_mut()
|
||||
.for_each(|o| o.state.auto_movement(&mut app));
|
||||
.for_each(|o| o.config.auto_movement(&mut app));
|
||||
|
||||
let lengths_haptics = interact(&mut overlays, &mut app);
|
||||
for (idx, (len, haptics)) in lengths_haptics.iter().enumerate() {
|
||||
@@ -355,10 +355,11 @@ pub fn openxr_run(
|
||||
app.hid_provider.inner.commit();
|
||||
|
||||
let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic
|
||||
let watch_transform = watch.state.transform;
|
||||
if !watch.state.want_visible {
|
||||
watch.state.want_visible = true;
|
||||
watch.state.transform = Affine3A::from_scale(Vec3 {
|
||||
let watch_state = watch.config.active_state.as_mut().unwrap();
|
||||
let watch_transform = watch_state.transform;
|
||||
if watch_state.alpha < 0.05 {
|
||||
//FIXME: Temporary workaround for Monado bug
|
||||
watch_state.transform = Affine3A::from_scale(Vec3 {
|
||||
x: 0.001,
|
||||
y: 0.001,
|
||||
z: 0.001,
|
||||
@@ -381,9 +382,9 @@ pub fn openxr_run(
|
||||
|
||||
for o in overlays.values_mut() {
|
||||
o.data.cur_visible = false;
|
||||
if !o.state.want_visible {
|
||||
let Some(alpha) = o.config.active_state.as_ref().map(|x| x.alpha) else {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if !o.data.init {
|
||||
o.init(&mut app)?;
|
||||
@@ -392,7 +393,7 @@ pub fn openxr_run(
|
||||
|
||||
let should_render = match o.should_render(&mut app)? {
|
||||
ShouldRender::Should => true,
|
||||
ShouldRender::Can => (o.data.last_alpha - o.state.alpha).abs() > f32::EPSILON,
|
||||
ShouldRender::Can => (o.data.last_alpha - alpha).abs() > f32::EPSILON,
|
||||
ShouldRender::Unable => false, //try show old image if exists
|
||||
};
|
||||
|
||||
@@ -401,11 +402,11 @@ pub fn openxr_run(
|
||||
continue;
|
||||
}
|
||||
let tgt = o.data.swapchain.as_mut().unwrap().acquire_wait_image()?; // want
|
||||
if !o.render(&mut app, tgt, &mut buffers, o.state.alpha)? {
|
||||
if !o.render(&mut app, tgt, &mut buffers, alpha)? {
|
||||
o.data.swapchain.as_mut().unwrap().ensure_image_released()?; // want
|
||||
continue;
|
||||
}
|
||||
o.data.last_alpha = o.state.alpha;
|
||||
o.data.last_alpha = alpha;
|
||||
} else if o.data.swapchain.is_none() {
|
||||
continue;
|
||||
}
|
||||
@@ -435,9 +436,11 @@ pub fn openxr_run(
|
||||
if !o.data.cur_visible {
|
||||
continue;
|
||||
}
|
||||
let dist_sq = (app.input_state.hmd.translation - o.state.transform.translation)
|
||||
// unwrap: above if only passes if active_state is some
|
||||
let active_state = o.config.active_state.as_ref().unwrap();
|
||||
let dist_sq = (app.input_state.hmd.translation - active_state.transform.translation)
|
||||
.length_squared()
|
||||
+ (100f32 - o.state.z_order as f32);
|
||||
+ (100f32 - o.config.z_order as f32);
|
||||
if !dist_sq.is_normal() {
|
||||
o.data.swapchain.as_mut().unwrap().ensure_image_released()?;
|
||||
continue;
|
||||
@@ -489,7 +492,7 @@ pub fn openxr_run(
|
||||
match task {
|
||||
TaskType::Overlay(sel, f) => {
|
||||
if let Some(o) = overlays.mut_by_selector(&sel) {
|
||||
f(&mut app, &mut o.state);
|
||||
f(&mut app, &mut o.config);
|
||||
} else {
|
||||
log::warn!("Overlay not found for task: {sel:?}");
|
||||
}
|
||||
@@ -498,22 +501,22 @@ pub fn openxr_run(
|
||||
let None = overlays.mut_by_selector(&sel) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some((mut overlay_state, overlay_backend)) = f(&mut app) else {
|
||||
let Some(overlay_config) = f(&mut app) else {
|
||||
continue;
|
||||
};
|
||||
overlay_state.birthframe = cur_frame;
|
||||
|
||||
overlays.add(OverlayData {
|
||||
state: overlay_state,
|
||||
..OverlayData::from_backend(overlay_backend)
|
||||
});
|
||||
overlays.add(
|
||||
OverlayWindowData {
|
||||
birthframe: cur_frame,
|
||||
..OverlayWindowData::from_config(overlay_config)
|
||||
},
|
||||
&mut app,
|
||||
);
|
||||
}
|
||||
TaskType::DropOverlay(sel) => {
|
||||
if let Some(o) = overlays.mut_by_selector(&sel)
|
||||
&& o.state.birthframe < cur_frame
|
||||
&& o.birthframe < cur_frame
|
||||
{
|
||||
log::debug!("{}: destroy", o.state.name);
|
||||
log::debug!("{}: destroy", o.config.name);
|
||||
if let Some(o) = overlays.remove_by_selector(&sel) {
|
||||
// set for deletion after all images are done showing
|
||||
delete_queue.push((o, cur_frame + 5));
|
||||
@@ -539,6 +542,9 @@ pub fn openxr_run(
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
TaskType::ToggleSet(set) => {
|
||||
overlays.switch_or_toggle_set(&mut app, set);
|
||||
}
|
||||
#[cfg(feature = "wayvr")]
|
||||
TaskType::WayVR(action) => {
|
||||
wayvr_action(&mut app, &mut overlays, &action);
|
||||
@@ -548,8 +554,9 @@ pub fn openxr_run(
|
||||
|
||||
delete_queue.retain(|(_, frame)| *frame > cur_frame);
|
||||
|
||||
//FIXME: Temporary workaround for Monado bug
|
||||
let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic
|
||||
watch.state.transform = watch_transform;
|
||||
watch.config.active_state.as_mut().unwrap().transform = watch_transform;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -5,11 +5,9 @@ use xr::EyeVisibility;
|
||||
|
||||
use super::{CompositionLayer, XrState, helpers, swapchain::WlxSwapchain};
|
||||
use crate::{
|
||||
backend::{
|
||||
openxr::swapchain::{SwapchainOpts, create_swapchain},
|
||||
overlay::OverlayData,
|
||||
},
|
||||
backend::openxr::swapchain::{SwapchainOpts, create_swapchain},
|
||||
state::AppState,
|
||||
windowing::window::OverlayWindowData,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -21,7 +19,7 @@ pub struct OpenXrOverlayData {
|
||||
pub(super) last_alpha: f32,
|
||||
}
|
||||
|
||||
impl OverlayData<OpenXrOverlayData> {
|
||||
impl OverlayWindowData<OpenXrOverlayData> {
|
||||
pub(super) fn ensure_swapchain<'a>(
|
||||
&'a mut self,
|
||||
app: &AppState,
|
||||
@@ -30,7 +28,7 @@ impl OverlayData<OpenXrOverlayData> {
|
||||
let Some(meta) = self.frame_meta() else {
|
||||
log::warn!(
|
||||
"{}: swapchain cannot be created due to missing metadata",
|
||||
self.state.name
|
||||
self.config.name
|
||||
);
|
||||
return Ok(false);
|
||||
};
|
||||
@@ -46,7 +44,7 @@ impl OverlayData<OpenXrOverlayData> {
|
||||
|
||||
log::debug!(
|
||||
"{}: recreating swapchain at {}x{}",
|
||||
self.state.name,
|
||||
self.config.name,
|
||||
meta.extent[0],
|
||||
meta.extent[1],
|
||||
);
|
||||
@@ -64,17 +62,20 @@ impl OverlayData<OpenXrOverlayData> {
|
||||
xr: &'a XrState,
|
||||
) -> anyhow::Result<CompositionLayer<'a>> {
|
||||
let Some(swapchain) = self.data.swapchain.as_mut() else {
|
||||
log::warn!("{}: swapchain not ready", self.state.name);
|
||||
log::warn!("{}: swapchain not ready", self.config.name);
|
||||
return Ok(CompositionLayer::None);
|
||||
};
|
||||
if !swapchain.ever_acquired {
|
||||
log::warn!("{}: swapchain not rendered", self.state.name);
|
||||
log::warn!("{}: swapchain not rendered", self.config.name);
|
||||
return Ok(CompositionLayer::None);
|
||||
}
|
||||
swapchain.ensure_image_released()?;
|
||||
|
||||
// overlays without active_state don't get queued for present
|
||||
let state = self.config.active_state.as_ref().unwrap();
|
||||
|
||||
let sub_image = swapchain.get_subimage();
|
||||
let transform = self.state.transform * self.backend.frame_meta().unwrap().transform; // contract
|
||||
let transform = state.transform * self.config.backend.frame_meta().unwrap().transform; // contract
|
||||
|
||||
let aspect_ratio = swapchain.extent[1] as f32 / swapchain.extent[0] as f32;
|
||||
let (scale_x, scale_y) = if aspect_ratio < 1.0 {
|
||||
@@ -85,7 +86,7 @@ impl OverlayData<OpenXrOverlayData> {
|
||||
(major / aspect_ratio, major)
|
||||
};
|
||||
|
||||
if let Some(curvature) = self.state.curvature {
|
||||
if let Some(curvature) = state.curvature {
|
||||
let radius = scale_x / (2.0 * PI * curvature);
|
||||
let quat = helpers::transform_to_norm_quat(&transform);
|
||||
let center_point = transform.translation + quat.mul_vec3a(Vec3A::Z * radius);
|
||||
@@ -120,14 +121,21 @@ impl OverlayData<OpenXrOverlayData> {
|
||||
}
|
||||
|
||||
pub(super) fn after_input(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
if self.data.last_visible != self.state.want_visible {
|
||||
if self.state.want_visible {
|
||||
self.backend.resume(app)?;
|
||||
let want_visible = self
|
||||
.config
|
||||
.active_state
|
||||
.as_ref()
|
||||
.map(|x| x.alpha > 0.05)
|
||||
.unwrap_or(false);
|
||||
|
||||
if self.data.last_visible != want_visible {
|
||||
if want_visible {
|
||||
self.config.backend.resume(app)?;
|
||||
} else {
|
||||
self.backend.pause(app)?;
|
||||
self.config.backend.pause(app)?;
|
||||
}
|
||||
}
|
||||
self.data.last_visible = self.state.want_visible;
|
||||
self.data.last_visible = want_visible;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@ use glam::{Affine3A, Quat, Vec3A};
|
||||
use libmonado::{Monado, Pose, ReferenceSpaceType};
|
||||
|
||||
use crate::{
|
||||
backend::{common::OverlayContainer, input::InputState},
|
||||
state::AppState,
|
||||
backend::input::InputState, state::AppState, windowing::manager::OverlayWindowManager,
|
||||
};
|
||||
|
||||
use super::overlay::OpenXrOverlayData;
|
||||
@@ -44,7 +43,7 @@ impl PlayspaceMover {
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
overlays: &mut OverlayContainer<OpenXrOverlayData>,
|
||||
overlays: &mut OverlayWindowManager<OpenXrOverlayData>,
|
||||
state: &AppState,
|
||||
monado: &mut Monado,
|
||||
) {
|
||||
@@ -129,10 +128,13 @@ impl PlayspaceMover {
|
||||
let overlay_offset = data.pose.inverse().transform_vector3a(relative_pos) * -1.0;
|
||||
|
||||
overlays.values_mut().for_each(|overlay| {
|
||||
if overlay.state.grabbable {
|
||||
overlay.state.dirty = true;
|
||||
overlay.state.transform.translation += overlay_offset;
|
||||
let Some(state) = overlay.config.active_state.as_mut() else {
|
||||
return;
|
||||
};
|
||||
if state.positioning.moves_with_space() {
|
||||
state.transform.translation += overlay_offset;
|
||||
}
|
||||
overlay.config.dirty = true;
|
||||
});
|
||||
|
||||
data.pose.translation += relative_pos;
|
||||
|
||||
Reference in New Issue
Block a user