feat: anchor point for working set
This commit is contained in:
@@ -5,10 +5,11 @@ use std::{
|
|||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
#[cfg(feature = "openxr")]
|
#[cfg(feature = "openxr")]
|
||||||
use openxr as xr;
|
use openxr as xr;
|
||||||
|
|
||||||
use glam::{Affine3A, Vec2, Vec3A, Vec3Swizzles};
|
use glam::{Affine3A, Vec2, Vec3, Vec3A, Vec3Swizzles};
|
||||||
use idmap::IdMap;
|
use idmap::IdMap;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@@ -16,6 +17,7 @@ use thiserror::Error;
|
|||||||
use crate::{
|
use crate::{
|
||||||
config::{AStrMapExt, AStrSetExt},
|
config::{AStrMapExt, AStrSetExt},
|
||||||
overlays::{
|
overlays::{
|
||||||
|
anchor::create_anchor,
|
||||||
keyboard::{create_keyboard, KEYBOARD_NAME},
|
keyboard::{create_keyboard, KEYBOARD_NAME},
|
||||||
screen::WlxClientAlias,
|
screen::WlxClientAlias,
|
||||||
watch::{create_watch, WATCH_NAME},
|
watch::{create_watch, WATCH_NAME},
|
||||||
@@ -102,6 +104,9 @@ where
|
|||||||
app.screens.push(meta);
|
app.screens.push(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let anchor = create_anchor(app)?;
|
||||||
|
overlays.insert(anchor.state.id, anchor);
|
||||||
|
|
||||||
let mut watch = create_watch::<T>(app)?;
|
let mut watch = create_watch::<T>(app)?;
|
||||||
watch.state.want_visible = true;
|
watch.state.want_visible = true;
|
||||||
overlays.insert(watch.state.id, watch);
|
overlays.insert(watch.state.id, watch);
|
||||||
@@ -314,6 +319,13 @@ where
|
|||||||
.values()
|
.values()
|
||||||
.any(|o| o.state.show_hide && o.state.want_visible);
|
.any(|o| o.state.show_hide && o.state.want_visible);
|
||||||
|
|
||||||
|
if !any_shown {
|
||||||
|
static ANCHOR_LOCAL: Lazy<Affine3A> =
|
||||||
|
Lazy::new(|| Affine3A::from_translation(Vec3::NEG_Z));
|
||||||
|
let hmd = snap_upright(app.input_state.hmd, Vec3A::Y);
|
||||||
|
app.anchor = hmd * *ANCHOR_LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
self.overlays.values_mut().for_each(|o| {
|
self.overlays.values_mut().for_each(|o| {
|
||||||
if o.state.show_hide {
|
if o.state.show_hide {
|
||||||
o.state.want_visible = !any_shown;
|
o.state.want_visible = !any_shown;
|
||||||
@@ -332,7 +344,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize, Debug)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum OverlaySelector {
|
pub enum OverlaySelector {
|
||||||
Id(usize),
|
Id(usize),
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
use std::{collections::VecDeque, time::Instant};
|
use std::{collections::VecDeque, time::Instant};
|
||||||
|
|
||||||
use glam::{Affine3A, Vec2, Vec3A};
|
use glam::{Affine3A, Vec2, Vec3, Vec3A};
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
use crate::backend::common::snap_upright;
|
use crate::backend::common::{snap_upright, OverlaySelector, TaskType};
|
||||||
use crate::config::{save_state, AStrMapExt, GeneralConfig};
|
use crate::config::{save_state, AStrMapExt, GeneralConfig};
|
||||||
|
use crate::overlays::anchor::ANCHOR_NAME;
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
|
|
||||||
|
use super::common::TaskContainer;
|
||||||
use super::{
|
use super::{
|
||||||
common::{raycast_cylinder, raycast_plane, OverlayContainer},
|
common::{raycast_cylinder, raycast_plane, OverlayContainer},
|
||||||
overlay::OverlayData,
|
overlay::OverlayData,
|
||||||
@@ -244,6 +246,7 @@ pub struct GrabData {
|
|||||||
pub offset: Vec3A,
|
pub offset: Vec3A,
|
||||||
pub grabbed_id: usize,
|
pub grabbed_id: usize,
|
||||||
pub old_curvature: Option<f32>,
|
pub old_curvature: Option<f32>,
|
||||||
|
pub grab_all: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
@@ -286,7 +289,13 @@ where
|
|||||||
let mut pointer = &mut app.input_state.pointers[idx];
|
let mut pointer = &mut app.input_state.pointers[idx];
|
||||||
if let Some(grab_data) = pointer.interaction.grabbed {
|
if let Some(grab_data) = pointer.interaction.grabbed {
|
||||||
if let Some(grabbed) = overlays.mut_by_id(grab_data.grabbed_id) {
|
if let Some(grabbed) = overlays.mut_by_id(grab_data.grabbed_id) {
|
||||||
pointer.handle_grabbed(grabbed, &hmd, &mut app.session.config);
|
pointer.handle_grabbed(
|
||||||
|
grabbed,
|
||||||
|
&hmd,
|
||||||
|
&app.anchor,
|
||||||
|
&mut app.tasks,
|
||||||
|
&mut app.session.config,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
log::warn!("Grabbed overlay {} does not exist", grab_data.grabbed_id);
|
log::warn!("Grabbed overlay {} does not exist", grab_data.grabbed_id);
|
||||||
pointer.interaction.grabbed = None;
|
pointer.interaction.grabbed = None;
|
||||||
@@ -348,7 +357,7 @@ where
|
|||||||
log::trace!("Hit: {} {:?}", hovered.state.name, hit);
|
log::trace!("Hit: {} {:?}", hovered.state.name, hit);
|
||||||
|
|
||||||
if pointer.now.grab && !pointer.before.grab && hovered.state.grabbable {
|
if pointer.now.grab && !pointer.before.grab && hovered.state.grabbable {
|
||||||
pointer.start_grab(hovered);
|
pointer.start_grab(hovered, &mut app.tasks);
|
||||||
return (
|
return (
|
||||||
hit.dist,
|
hit.dist,
|
||||||
Some(Haptics {
|
Some(Haptics {
|
||||||
@@ -455,7 +464,7 @@ impl Pointer {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_grab<O>(&mut self, overlay: &mut OverlayData<O>)
|
fn start_grab<O>(&mut self, overlay: &mut OverlayData<O>, tasks: &mut TaskContainer)
|
||||||
where
|
where
|
||||||
O: Default,
|
O: Default,
|
||||||
{
|
{
|
||||||
@@ -468,7 +477,21 @@ impl Pointer {
|
|||||||
offset,
|
offset,
|
||||||
grabbed_id: overlay.state.id,
|
grabbed_id: overlay.state.id,
|
||||||
old_curvature: overlay.state.curvature,
|
old_curvature: overlay.state.curvature,
|
||||||
|
grab_all: matches!(self.interaction.mode, PointerMode::Right),
|
||||||
});
|
});
|
||||||
|
tasks.enqueue(TaskType::Overlay(
|
||||||
|
OverlaySelector::Name(ANCHOR_NAME.clone()),
|
||||||
|
Box::new(|app, o| {
|
||||||
|
o.transform = app.anchor
|
||||||
|
* Affine3A::from_scale_rotation_translation(
|
||||||
|
Vec3::ONE * o.spawn_scale,
|
||||||
|
o.spawn_rotation,
|
||||||
|
o.spawn_point.into(),
|
||||||
|
);
|
||||||
|
o.dirty = true;
|
||||||
|
o.want_visible = true;
|
||||||
|
}),
|
||||||
|
));
|
||||||
log::info!("Hand {}: grabbed {}", self.idx, overlay.state.name);
|
log::info!("Hand {}: grabbed {}", self.idx, overlay.state.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,6 +499,8 @@ impl Pointer {
|
|||||||
&mut self,
|
&mut self,
|
||||||
overlay: &mut OverlayData<O>,
|
overlay: &mut OverlayData<O>,
|
||||||
hmd: &Affine3A,
|
hmd: &Affine3A,
|
||||||
|
anchor: &Affine3A,
|
||||||
|
tasks: &mut TaskContainer,
|
||||||
config: &mut GeneralConfig,
|
config: &mut GeneralConfig,
|
||||||
) where
|
) where
|
||||||
O: Default,
|
O: Default,
|
||||||
@@ -509,7 +534,7 @@ impl Pointer {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
overlay.state.saved_transform =
|
overlay.state.saved_transform =
|
||||||
Some(snap_upright(*hmd, Vec3A::Y).inverse() * overlay.state.transform);
|
Some(snap_upright(*anchor, Vec3A::Y).inverse() * overlay.state.transform);
|
||||||
|
|
||||||
if let Some(grab_data) = self.interaction.grabbed.as_ref() {
|
if let Some(grab_data) = self.interaction.grabbed.as_ref() {
|
||||||
let mut state_dirty = false;
|
let mut state_dirty = false;
|
||||||
@@ -531,6 +556,12 @@ impl Pointer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.interaction.grabbed = None;
|
self.interaction.grabbed = None;
|
||||||
|
tasks.enqueue(TaskType::Overlay(
|
||||||
|
OverlaySelector::Name(ANCHOR_NAME.clone()),
|
||||||
|
Box::new(|_app, o| {
|
||||||
|
o.want_visible = false;
|
||||||
|
}),
|
||||||
|
));
|
||||||
log::info!("Hand {}: dropped {}", self.idx, overlay.state.name);
|
log::info!("Hand {}: dropped {}", self.idx, overlay.state.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,6 +213,8 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
|||||||
TaskType::Overlay(sel, f) => {
|
TaskType::Overlay(sel, f) => {
|
||||||
if let Some(o) = overlays.mut_by_selector(&sel) {
|
if let Some(o) = overlays.mut_by_selector(&sel) {
|
||||||
f(&mut state, &mut o.state);
|
f(&mut state, &mut o.state);
|
||||||
|
} else {
|
||||||
|
log::warn!("Overlay not found for task: {:?}", sel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TaskType::CreateOverlay(sel, f) => {
|
TaskType::CreateOverlay(sel, f) => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use vulkano::{Handle, VulkanObject};
|
|||||||
use crate::{
|
use crate::{
|
||||||
backend::overlay::{OverlayData, RelativeTo},
|
backend::overlay::{OverlayData, RelativeTo},
|
||||||
graphics::WlxGraphics,
|
graphics::WlxGraphics,
|
||||||
overlays::watch::WATCH_NAME,
|
overlays::{anchor::ANCHOR_NAME, watch::WATCH_NAME},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,6 +50,10 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
self.data.sort_order = 68;
|
self.data.sort_order = 68;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *self.state.name == *ANCHOR_NAME.as_ref() {
|
||||||
|
self.data.sort_order = 67;
|
||||||
|
}
|
||||||
|
|
||||||
self.data.handle = Some(handle);
|
self.data.handle = Some(handle);
|
||||||
self.data.color = Vec4::ONE;
|
self.data.color = Vec4::ONE;
|
||||||
|
|
||||||
@@ -260,7 +264,7 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
m_pQueue: graphics.queue.handle().as_raw() as *mut _,
|
m_pQueue: graphics.queue.handle().as_raw() as *mut _,
|
||||||
m_nQueueFamilyIndex: graphics.queue.queue_family_index(),
|
m_nQueueFamilyIndex: graphics.queue.queue_family_index(),
|
||||||
};
|
};
|
||||||
log::debug!(
|
log::trace!(
|
||||||
"{}: UploadTex {:?}, {}x{}, {:?}",
|
"{}: UploadTex {:?}, {}x{}, {:?}",
|
||||||
self.state.name,
|
self.state.name,
|
||||||
format,
|
format,
|
||||||
|
|||||||
@@ -334,6 +334,8 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
|||||||
TaskType::Overlay(sel, f) => {
|
TaskType::Overlay(sel, f) => {
|
||||||
if let Some(o) = overlays.mut_by_selector(&sel) {
|
if let Some(o) = overlays.mut_by_selector(&sel) {
|
||||||
f(&mut app_state, &mut o.state);
|
f(&mut app_state, &mut o.state);
|
||||||
|
} else {
|
||||||
|
log::warn!("Overlay not found for task: {:?}", sel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TaskType::CreateOverlay(sel, f) => {
|
TaskType::CreateOverlay(sel, f) => {
|
||||||
|
|||||||
@@ -12,10 +12,7 @@ use vulkano::image::view::ImageView;
|
|||||||
|
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
|
|
||||||
use super::{
|
use super::input::{DummyInteractionHandler, Haptics, InteractionHandler, PointerHit};
|
||||||
common::snap_upright,
|
|
||||||
input::{DummyInteractionHandler, Haptics, InteractionHandler, PointerHit},
|
|
||||||
};
|
|
||||||
|
|
||||||
static AUTO_INCREMENT: AtomicUsize = AtomicUsize::new(0);
|
static AUTO_INCREMENT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
@@ -127,15 +124,10 @@ impl OverlayState {
|
|||||||
self.saved_transform = None;
|
self.saved_transform = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let hmd = snap_upright(app.input_state.hmd, Vec3A::Y);
|
self.transform = app.anchor * self.get_transform();
|
||||||
self.transform = hmd * self.get_transform();
|
|
||||||
|
|
||||||
if self.grabbable {
|
if self.grabbable && hard_reset {
|
||||||
if hard_reset {
|
self.realign(&app.input_state.hmd);
|
||||||
self.realign(&app.input_state.hmd);
|
|
||||||
} else {
|
|
||||||
//self.transform = snap_upright(self.transform, app.input_state.hmd.y_axis);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,13 +254,19 @@ impl GeneralConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const FALLBACKS: [&str; 3] = [
|
const FALLBACKS: [&str; 4] = [
|
||||||
include_str!("res/keyboard.yaml"),
|
include_str!("res/keyboard.yaml"),
|
||||||
include_str!("res/watch.yaml"),
|
include_str!("res/watch.yaml"),
|
||||||
include_str!("res/settings.yaml"),
|
include_str!("res/settings.yaml"),
|
||||||
|
include_str!("res/anchor.yaml"),
|
||||||
];
|
];
|
||||||
|
|
||||||
const FILES: [&str; 3] = ["keyboard.yaml", "watch.yaml", "settings.yaml"];
|
const FILES: [&str; 4] = [
|
||||||
|
"keyboard.yaml",
|
||||||
|
"watch.yaml",
|
||||||
|
"settings.yaml",
|
||||||
|
"anchor.yaml",
|
||||||
|
];
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
#[repr(usize)]
|
#[repr(usize)]
|
||||||
@@ -268,6 +274,7 @@ pub enum ConfigType {
|
|||||||
Keyboard,
|
Keyboard,
|
||||||
Watch,
|
Watch,
|
||||||
Settings,
|
Settings,
|
||||||
|
Anchor,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_known_yaml<T>(config_type: ConfigType) -> T
|
pub fn load_known_yaml<T>(config_type: ConfigType) -> T
|
||||||
|
|||||||
31
src/overlays/anchor.rs
Normal file
31
src/overlays/anchor.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
use glam::Vec3A;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::backend::overlay::{OverlayData, OverlayState};
|
||||||
|
use crate::config::{load_known_yaml, ConfigType};
|
||||||
|
use crate::gui::modular::{modular_canvas, ModularUiConfig};
|
||||||
|
use crate::state::AppState;
|
||||||
|
|
||||||
|
pub static ANCHOR_NAME: Lazy<Arc<str>> = Lazy::new(|| Arc::from("anchor"));
|
||||||
|
|
||||||
|
pub fn create_anchor<O>(state: &AppState) -> anyhow::Result<OverlayData<O>>
|
||||||
|
where
|
||||||
|
O: Default,
|
||||||
|
{
|
||||||
|
let config = load_known_yaml::<ModularUiConfig>(ConfigType::Anchor);
|
||||||
|
|
||||||
|
Ok(OverlayData {
|
||||||
|
state: OverlayState {
|
||||||
|
name: ANCHOR_NAME.clone(),
|
||||||
|
want_visible: false,
|
||||||
|
interactable: false,
|
||||||
|
grabbable: false,
|
||||||
|
spawn_scale: config.width,
|
||||||
|
spawn_point: Vec3A::NEG_Z * 0.5,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
backend: Box::new(modular_canvas(&config.size, &config.elements, state)?),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -85,12 +85,12 @@ where
|
|||||||
log::error!("Keyboard: EXEC args empty for {}", key);
|
log::error!("Keyboard: EXEC args empty for {}", key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
let mut iter = exec_args.iter().cloned();
|
||||||
maybe_state = Some(KeyButtonData::Exec {
|
maybe_state = Some(KeyButtonData::Exec {
|
||||||
program: exec_args
|
program: iter.next().unwrap(),
|
||||||
.first()
|
args: iter.by_ref().take_while(|arg| arg[..] != *"null").collect(),
|
||||||
.unwrap() // safe because we checked is_empty
|
release_program: iter.next(),
|
||||||
.clone(),
|
release_args: iter.collect(),
|
||||||
args: exec_args.iter().skip(1).cloned().collect(),
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
log::error!("Unknown key: {}", key);
|
log::error!("Unknown key: {}", key);
|
||||||
@@ -124,7 +124,7 @@ where
|
|||||||
recenter: true,
|
recenter: true,
|
||||||
interactable: true,
|
interactable: true,
|
||||||
spawn_scale: width,
|
spawn_scale: width,
|
||||||
spawn_point: vec3a(0., -0.5, -1.),
|
spawn_point: vec3a(0., -0.5, 0.),
|
||||||
interaction_transform,
|
interaction_transform,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -163,7 +163,7 @@ fn key_press(
|
|||||||
app.hid_provider.send_key(*vk as _, *press);
|
app.hid_provider.send_key(*vk as _, *press);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(KeyButtonData::Exec { program, args }) => {
|
Some(KeyButtonData::Exec { program, args, .. }) => {
|
||||||
// Reap previous processes
|
// Reap previous processes
|
||||||
data.processes
|
data.processes
|
||||||
.retain_mut(|child| !matches!(child.try_wait(), Ok(Some(_))));
|
.retain_mut(|child| !matches!(child.try_wait(), Ok(Some(_))));
|
||||||
@@ -200,6 +200,21 @@ fn key_release(
|
|||||||
app.hid_provider.set_modifiers(data.modifiers);
|
app.hid_provider.set_modifiers(data.modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(KeyButtonData::Exec {
|
||||||
|
release_program,
|
||||||
|
release_args,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
// Reap previous processes
|
||||||
|
data.processes
|
||||||
|
.retain_mut(|child| !matches!(child.try_wait(), Ok(Some(_))));
|
||||||
|
|
||||||
|
if let Some(program) = release_program {
|
||||||
|
if let Ok(child) = Command::new(program).args(release_args).spawn() {
|
||||||
|
data.processes.push(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,10 +255,23 @@ impl KeyboardData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum KeyButtonData {
|
enum KeyButtonData {
|
||||||
Key { vk: VirtualKey, pressed: bool },
|
Key {
|
||||||
Modifier { modifier: KeyModifier, sticky: bool },
|
vk: VirtualKey,
|
||||||
Macro { verbs: Vec<(VirtualKey, bool)> },
|
pressed: bool,
|
||||||
Exec { program: String, args: Vec<String> },
|
},
|
||||||
|
Modifier {
|
||||||
|
modifier: KeyModifier,
|
||||||
|
sticky: bool,
|
||||||
|
},
|
||||||
|
Macro {
|
||||||
|
verbs: Vec<(VirtualKey, bool)>,
|
||||||
|
},
|
||||||
|
Exec {
|
||||||
|
program: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
release_program: Option<String>,
|
||||||
|
release_args: Vec<String>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
static LAYOUT: Lazy<Layout> = Lazy::new(Layout::load_from_disk);
|
static LAYOUT: Lazy<Layout> = Lazy::new(Layout::load_from_disk);
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ pub fn new_mirror(
|
|||||||
show_hide,
|
show_hide,
|
||||||
want_visible: true,
|
want_visible: true,
|
||||||
spawn_scale: 0.5 * session.config.desktop_view_scale,
|
spawn_scale: 0.5 * session.config.desktop_view_scale,
|
||||||
spawn_point: vec3a(0., 0.5, -0.5),
|
spawn_point: vec3a(0., 0.5, 0.5),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let backend = Box::new(SplitOverlayBackend {
|
let backend = Box::new(SplitOverlayBackend {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
pub mod anchor;
|
||||||
pub mod custom;
|
pub mod custom;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
|
|||||||
@@ -622,7 +622,7 @@ fn create_screen_state(
|
|||||||
recenter: true,
|
recenter: true,
|
||||||
interactable: true,
|
interactable: true,
|
||||||
spawn_scale: 1.5 * session.config.desktop_view_scale,
|
spawn_scale: 1.5 * session.config.desktop_view_scale,
|
||||||
spawn_point: vec3a(0., 0.5, -1.),
|
spawn_point: vec3a(0., 0.5, 0.),
|
||||||
spawn_rotation: Quat::from_axis_angle(Vec3::Z, angle),
|
spawn_rotation: Quat::from_axis_angle(Vec3::Z, angle),
|
||||||
interaction_transform,
|
interaction_transform,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|||||||
26
src/res/anchor.yaml
Normal file
26
src/res/anchor.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# looking to make changes?
|
||||||
|
# drop me in ~/.config/wlxoverlay/anchor.yaml
|
||||||
|
#
|
||||||
|
|
||||||
|
width: 0.1
|
||||||
|
|
||||||
|
size: [200, 200]
|
||||||
|
|
||||||
|
# +X: right, +Y: up, +Z: back
|
||||||
|
spawn_pos: [0, 0, -1]
|
||||||
|
|
||||||
|
elements:
|
||||||
|
- type: Panel
|
||||||
|
rect: [98, 0, 4, 200]
|
||||||
|
bg_color: "#ffff00"
|
||||||
|
|
||||||
|
- type: Panel
|
||||||
|
rect: [0, 98, 200, 4]
|
||||||
|
bg_color: "#ffff00"
|
||||||
|
|
||||||
|
- type: Label
|
||||||
|
rect: [8, 90, 600, 70]
|
||||||
|
font_size: 18
|
||||||
|
fg_color: "#ffff00"
|
||||||
|
source: Static
|
||||||
|
text: Center
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::{io::Cursor, path::PathBuf, sync::Arc};
|
use std::{io::Cursor, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use glam::Vec3;
|
use glam::{Affine3A, Vec3};
|
||||||
use idmap::IdMap;
|
use idmap::IdMap;
|
||||||
use rodio::{Decoder, OutputStream, OutputStreamHandle, Source};
|
use rodio::{Decoder, OutputStream, OutputStreamHandle, Source};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -27,6 +27,7 @@ pub struct AppState {
|
|||||||
pub hid_provider: Box<dyn HidProvider>,
|
pub hid_provider: Box<dyn HidProvider>,
|
||||||
pub audio: AudioOutput,
|
pub audio: AudioOutput,
|
||||||
pub screens: SmallVec<[ScreenMeta; 8]>,
|
pub screens: SmallVec<[ScreenMeta; 8]>,
|
||||||
|
pub anchor: Affine3A,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
@@ -67,6 +68,7 @@ impl AppState {
|
|||||||
hid_provider: crate::hid::initialize(),
|
hid_provider: crate::hid::initialize(),
|
||||||
audio: AudioOutput::new(),
|
audio: AudioOutput::new(),
|
||||||
screens: smallvec![],
|
screens: smallvec![],
|
||||||
|
anchor: Affine3A::IDENTITY,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user