screens & basic interactions
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -4024,7 +4024,6 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "wlx-capture"
|
name = "wlx-capture"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/galister/wlx-capture.git#56eba19fac9834e2dfb77dd3a0a93b088a93dee9"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ashpd",
|
"ashpd",
|
||||||
"drm-fourcc",
|
"drm-fourcc",
|
||||||
|
|||||||
11
Cargo.toml
11
Cargo.toml
@@ -1,3 +1,12 @@
|
|||||||
|
[profile.release-with-debug]
|
||||||
|
inherits = "release"
|
||||||
|
debuginfo-level = 1
|
||||||
|
jemalloc = false
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[rust]
|
||||||
|
debuginfo-level = 1
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "wlx-overlay-s"
|
name = "wlx-overlay-s"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -36,5 +45,5 @@ vulkano-shaders = "0.33.0"
|
|||||||
vulkano-util = "0.33.0"
|
vulkano-util = "0.33.0"
|
||||||
vulkano-win = "0.33.0"
|
vulkano-win = "0.33.0"
|
||||||
winit = "0.28.6"
|
winit = "0.28.6"
|
||||||
wlx-capture = { git = "https://github.com/galister/wlx-capture.git" }
|
wlx-capture = { path = "../wlx-capture" }
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::{collections::VecDeque, time::Instant};
|
use std::{collections::VecDeque, time::Instant};
|
||||||
|
|
||||||
use glam::{Affine3A, Vec2, Vec3A};
|
use glam::{Affine3A, Vec2, Vec3A};
|
||||||
use log::warn;
|
|
||||||
use ovr_overlay::TrackedDeviceIndex;
|
use ovr_overlay::TrackedDeviceIndex;
|
||||||
use tinyvec::array_vec;
|
use tinyvec::array_vec;
|
||||||
|
|
||||||
@@ -42,6 +41,39 @@ impl<TState, THand> InputState<TState, THand> {
|
|||||||
|
|
||||||
pub fn post_update(&mut self) {
|
pub fn post_update(&mut self) {
|
||||||
for hand in &mut self.pointers {
|
for hand in &mut self.pointers {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
if hand.now.click != hand.before.click {
|
||||||
|
log::debug!("Hand {}: click {}", hand.idx, hand.now.click);
|
||||||
|
}
|
||||||
|
if hand.now.grab != hand.before.grab {
|
||||||
|
log::debug!("Hand {}: grab {}", hand.idx, hand.now.grab);
|
||||||
|
}
|
||||||
|
if hand.now.alt_click != hand.before.alt_click {
|
||||||
|
log::debug!("Hand {}: alt_click {}", hand.idx, hand.now.alt_click);
|
||||||
|
}
|
||||||
|
if hand.now.show_hide != hand.before.show_hide {
|
||||||
|
log::debug!("Hand {}: show_hide {}", hand.idx, hand.now.show_hide);
|
||||||
|
}
|
||||||
|
if hand.now.space_drag != hand.before.space_drag {
|
||||||
|
log::debug!("Hand {}: space_drag {}", hand.idx, hand.now.space_drag);
|
||||||
|
}
|
||||||
|
if hand.now.click_modifier_right != hand.before.click_modifier_right {
|
||||||
|
log::debug!(
|
||||||
|
"Hand {}: click_modifier_right {}",
|
||||||
|
hand.idx,
|
||||||
|
hand.now.click_modifier_right
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if hand.now.click_modifier_middle != hand.before.click_modifier_middle {
|
||||||
|
log::debug!(
|
||||||
|
"Hand {}: click_modifier_middle {}",
|
||||||
|
hand.idx,
|
||||||
|
hand.now.click_modifier_middle
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if hand.now.click_modifier_right {
|
if hand.now.click_modifier_right {
|
||||||
hand.interaction.mode = PointerMode::Right;
|
hand.interaction.mode = PointerMode::Right;
|
||||||
continue;
|
continue;
|
||||||
@@ -176,7 +208,7 @@ pub enum PointerMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<THand> Pointer<THand> {
|
impl<THand> Pointer<THand> {
|
||||||
pub fn interact<O>(&mut self, overlays: &mut OverlayContainer<O>, app: &mut AppState)
|
pub fn interact<O>(&mut self, overlays: &mut OverlayContainer<O>, app: &mut AppState) -> f32
|
||||||
where
|
where
|
||||||
O: Default,
|
O: Default,
|
||||||
{
|
{
|
||||||
@@ -184,10 +216,10 @@ impl<THand> Pointer<THand> {
|
|||||||
if let Some(grabbed) = overlays.mut_by_id(grab_data.grabbed_id) {
|
if let Some(grabbed) = overlays.mut_by_id(grab_data.grabbed_id) {
|
||||||
self.handle_grabbed(grabbed, grab_data.offset);
|
self.handle_grabbed(grabbed, grab_data.offset);
|
||||||
} else {
|
} else {
|
||||||
warn!("Grabbed overlay {} does not exist", grab_data.grabbed_id);
|
log::warn!("Grabbed overlay {} does not exist", grab_data.grabbed_id);
|
||||||
self.interaction.grabbed = None;
|
self.interaction.grabbed = None;
|
||||||
}
|
}
|
||||||
return;
|
return grab_data.offset.length(); // grab interaction
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(mut hit) = self.get_nearest_hit(overlays) else {
|
let Some(mut hit) = self.get_nearest_hit(overlays) else {
|
||||||
@@ -208,7 +240,7 @@ impl<THand> Pointer<THand> {
|
|||||||
clicked.backend.on_pointer(app, &hit, false);
|
clicked.backend.on_pointer(app, &hit, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return 0.0; // no hit
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(hovered_id) = self.interaction.hovered_id {
|
if let Some(hovered_id) = self.interaction.hovered_id {
|
||||||
@@ -222,14 +254,14 @@ impl<THand> Pointer<THand> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let Some(hovered) = overlays.mut_by_id(hit.overlay) else {
|
let Some(hovered) = overlays.mut_by_id(hit.overlay) else {
|
||||||
warn!("Hit overlay {} does not exist", hit.overlay);
|
log::warn!("Hit overlay {} does not exist", hit.overlay);
|
||||||
return;
|
return 0.0; // no hit
|
||||||
};
|
};
|
||||||
|
|
||||||
self.interaction.hovered_id = Some(hit.overlay);
|
self.interaction.hovered_id = Some(hit.overlay);
|
||||||
|
|
||||||
if let Some(primary_pointer) = hovered.primary_pointer {
|
if let Some(primary_pointer) = hovered.primary_pointer {
|
||||||
if hit.pointer < primary_pointer {
|
if hit.pointer <= primary_pointer {
|
||||||
hovered.primary_pointer = Some(hit.pointer);
|
hovered.primary_pointer = Some(hit.pointer);
|
||||||
hit.primary = true;
|
hit.primary = true;
|
||||||
}
|
}
|
||||||
@@ -237,6 +269,14 @@ impl<THand> Pointer<THand> {
|
|||||||
hovered.primary_pointer = Some(hit.pointer);
|
hovered.primary_pointer = Some(hit.pointer);
|
||||||
hit.primary = true;
|
hit.primary = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::debug!("Hit: {} {:?}", hovered.state.name, hit);
|
||||||
|
|
||||||
|
if self.now.grab && !self.before.grab {
|
||||||
|
self.start_grab(hovered);
|
||||||
|
return hit.dist;
|
||||||
|
}
|
||||||
|
|
||||||
hovered.backend.on_hover(app, &hit);
|
hovered.backend.on_hover(app, &hit);
|
||||||
|
|
||||||
if self.now.scroll.abs() > 0.1 {
|
if self.now.scroll.abs() > 0.1 {
|
||||||
@@ -255,6 +295,7 @@ impl<THand> Pointer<THand> {
|
|||||||
hovered.backend.on_pointer(app, &hit, false);
|
hovered.backend.on_pointer(app, &hit, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hit.dist
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_nearest_hit<O>(&mut self, overlays: &mut OverlayContainer<O>) -> Option<PointerHit>
|
fn get_nearest_hit<O>(&mut self, overlays: &mut OverlayContainer<O>) -> Option<PointerHit>
|
||||||
@@ -276,15 +317,17 @@ impl<THand> Pointer<THand> {
|
|||||||
hits.sort_by(|a, b| a.dist.partial_cmp(&b.dist).unwrap());
|
hits.sort_by(|a, b| a.dist.partial_cmp(&b.dist).unwrap());
|
||||||
|
|
||||||
for hit in hits.iter() {
|
for hit in hits.iter() {
|
||||||
let uv = overlays
|
let overlay = overlays.get_by_id(hit.overlay).unwrap(); // this is safe
|
||||||
.get_by_id(hit.overlay)
|
|
||||||
.unwrap() // this is safe
|
let uv = overlay
|
||||||
.state
|
.state
|
||||||
.transform
|
.transform
|
||||||
.inverse()
|
.inverse()
|
||||||
.transform_point3a(hit.hit_pos)
|
.transform_point3a(hit.hit_pos)
|
||||||
.truncate();
|
.truncate();
|
||||||
|
|
||||||
|
let uv = overlay.state.interaction_transform.transform_point2(uv);
|
||||||
|
|
||||||
if uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0 {
|
if uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -315,7 +358,9 @@ impl<THand> Pointer<THand> {
|
|||||||
offset,
|
offset,
|
||||||
grabbed_id: overlay.state.id,
|
grabbed_id: overlay.state.id,
|
||||||
});
|
});
|
||||||
|
log::info!("Hand {}: grabbed {}", self.idx, overlay.state.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_grabbed<O>(&mut self, overlay: &mut OverlayData<O>, offset: Vec3A)
|
fn handle_grabbed<O>(&mut self, overlay: &mut OverlayData<O>, offset: Vec3A)
|
||||||
where
|
where
|
||||||
O: Default,
|
O: Default,
|
||||||
@@ -324,7 +369,7 @@ impl<THand> Pointer<THand> {
|
|||||||
overlay.state.transform.translation = self.pose.transform_point3a(offset);
|
overlay.state.transform.translation = self.pose.transform_point3a(offset);
|
||||||
|
|
||||||
if self.now.click && !self.before.click {
|
if self.now.click && !self.before.click {
|
||||||
warn!("todo: click-while-grabbed");
|
log::warn!("todo: click-while-grabbed");
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.interaction.mode {
|
match self.interaction.mode {
|
||||||
@@ -339,11 +384,14 @@ impl<THand> Pointer<THand> {
|
|||||||
.mul_scalar(1.0 + 0.01 * self.now.scroll);
|
.mul_scalar(1.0 + 0.01 * self.now.scroll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
overlay.state.dirty = true;
|
||||||
} else {
|
} else {
|
||||||
overlay.state.spawn_point = overlay.state.transform.translation;
|
overlay.state.spawn_point = overlay.state.transform.translation;
|
||||||
self.interaction.grabbed = None;
|
self.interaction.grabbed = None;
|
||||||
|
log::info!("Hand {}: dropped {}", self.idx, overlay.state.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ray_test(&self, overlay: usize, plane: &Affine3A) -> Option<RayHit> {
|
fn ray_test(&self, overlay: usize, plane: &Affine3A) -> Option<RayHit> {
|
||||||
let plane_normal = plane.transform_vector3a(Vec3A::NEG_Z);
|
let plane_normal = plane.transform_vector3a(Vec3A::NEG_Z);
|
||||||
let ray_dir = self.pose.transform_vector3a(Vec3A::NEG_Z);
|
let ray_dir = self.pose.transform_vector3a(Vec3A::NEG_Z);
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ pub(super) struct OpenVrInputState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct OpenVrHandState {
|
pub(super) struct OpenVrHandState {
|
||||||
|
pub(super) line_id: usize,
|
||||||
has_pose: bool,
|
has_pose: bool,
|
||||||
input_hnd: InputValueHandle,
|
input_hnd: InputValueHandle,
|
||||||
pose_hnd: ActionHandle,
|
pose_hnd: ActionHandle,
|
||||||
@@ -103,6 +104,7 @@ impl InputState<OpenVrInputState, OpenVrHandState> {
|
|||||||
pose: Affine3A::IDENTITY,
|
pose: Affine3A::IDENTITY,
|
||||||
interaction: InteractionState::default(),
|
interaction: InteractionState::default(),
|
||||||
data: OpenVrHandState {
|
data: OpenVrHandState {
|
||||||
|
line_id: 0,
|
||||||
has_pose: false,
|
has_pose: false,
|
||||||
input_hnd: input_hnd[i],
|
input_hnd: input_hnd[i],
|
||||||
pose_hnd: pose_hnd[i],
|
pose_hnd: pose_hnd[i],
|
||||||
|
|||||||
130
src/backend/openvr/lines.rs
Normal file
130
src/backend/openvr/lines.rs
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
use std::f32::consts::PI;
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use glam::{Affine3A, Vec3, Vec3A, Vec4};
|
||||||
|
use idmap::IdMap;
|
||||||
|
use ovr_overlay::overlay::OverlayManager;
|
||||||
|
use vulkano::command_buffer::CommandBufferUsage;
|
||||||
|
use vulkano::format::Format;
|
||||||
|
use vulkano::image::view::ImageView;
|
||||||
|
use vulkano::image::{ImageAccess, ImageLayout, ImageViewAbstract, ImmutableImage};
|
||||||
|
|
||||||
|
use crate::backend::overlay::{OverlayData, OverlayRenderer, OverlayState, SplitOverlayBackend};
|
||||||
|
use crate::graphics::WlxGraphics;
|
||||||
|
use crate::state::AppState;
|
||||||
|
|
||||||
|
use super::overlay::OpenVrOverlayData;
|
||||||
|
|
||||||
|
static AUTO_INCREMENT: AtomicUsize = AtomicUsize::new(1);
|
||||||
|
|
||||||
|
pub(super) struct LinePool {
|
||||||
|
lines: IdMap<usize, OverlayData<OpenVrOverlayData>>,
|
||||||
|
view: Arc<ImageView<ImmutableImage>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LinePool {
|
||||||
|
pub fn new(graphics: Arc<WlxGraphics>) -> Self {
|
||||||
|
let mut command_buffer = graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit);
|
||||||
|
|
||||||
|
let buf = vec![255; 16];
|
||||||
|
|
||||||
|
let texture = command_buffer.texture2d(2, 2, Format::R8G8B8A8_UNORM, buf);
|
||||||
|
command_buffer.build_and_execute_now();
|
||||||
|
|
||||||
|
graphics
|
||||||
|
.transition_layout(
|
||||||
|
texture.inner().image.clone(),
|
||||||
|
ImageLayout::ShaderReadOnlyOptimal,
|
||||||
|
ImageLayout::TransferSrcOptimal,
|
||||||
|
)
|
||||||
|
.wait(None)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let view = ImageView::new_default(texture).unwrap();
|
||||||
|
|
||||||
|
LinePool {
|
||||||
|
lines: IdMap::new(),
|
||||||
|
view,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate(&mut self, overlay: &mut OverlayManager, app: &mut AppState) -> usize {
|
||||||
|
let id = AUTO_INCREMENT.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let mut data = OverlayData::<OpenVrOverlayData> {
|
||||||
|
state: OverlayState {
|
||||||
|
name: Arc::from(format!("wlx-line{}", id)),
|
||||||
|
show_hide: true,
|
||||||
|
width: 0.002,
|
||||||
|
size: (0, 0),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
backend: Box::new(SplitOverlayBackend {
|
||||||
|
renderer: Box::new(StaticRenderer {
|
||||||
|
view: self.view.clone(),
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
data.data.sort_order = 69;
|
||||||
|
|
||||||
|
data.initialize(overlay, app);
|
||||||
|
data.upload_texture(overlay, &app.graphics);
|
||||||
|
|
||||||
|
self.lines.insert(id, data);
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_from(&mut self, id: usize, mut from: Affine3A, len: f32, color: Vec4) {
|
||||||
|
let rotation = Affine3A::from_axis_angle(Vec3::X, -PI * 0.5);
|
||||||
|
|
||||||
|
from.translation = from.translation + from.transform_vector3a(Vec3A::NEG_Z) * (len * 0.5);
|
||||||
|
let transform = from * rotation * Affine3A::from_scale(Vec3::new(1., len / 0.002, 1.));
|
||||||
|
|
||||||
|
self.draw_transform(id, transform, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_transform(&mut self, id: usize, transform: Affine3A, color: Vec4) {
|
||||||
|
if let Some(data) = self.lines.get_mut(id) {
|
||||||
|
data.state.want_visible = true;
|
||||||
|
data.state.transform = transform;
|
||||||
|
data.data.color = color;
|
||||||
|
} else {
|
||||||
|
log::warn!("Line {} does not exist", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hide(&mut self, id: usize) {
|
||||||
|
if let Some(data) = self.lines.get_mut(id) {
|
||||||
|
data.state.want_visible = false;
|
||||||
|
} else {
|
||||||
|
log::warn!("Line {} does not exist", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, overlay: &mut OverlayManager, app: &mut AppState) {
|
||||||
|
for data in self.lines.values_mut() {
|
||||||
|
data.after_input(overlay, app);
|
||||||
|
if data.state.want_visible {
|
||||||
|
data.upload_transform(overlay);
|
||||||
|
data.upload_color(overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StaticRenderer {
|
||||||
|
view: Arc<ImageView<ImmutableImage>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OverlayRenderer for StaticRenderer {
|
||||||
|
fn init(&mut self, _app: &mut AppState) {}
|
||||||
|
fn pause(&mut self, _app: &mut AppState) {}
|
||||||
|
fn resume(&mut self, _app: &mut AppState) {}
|
||||||
|
fn render(&mut self, _app: &mut AppState) {}
|
||||||
|
fn view(&mut self) -> Option<Arc<dyn ImageViewAbstract>> {
|
||||||
|
Some(self.view.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
|
use glam::Vec4;
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
path::Path,
|
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use log::{error, info};
|
|
||||||
use ovr_overlay::{
|
use ovr_overlay::{
|
||||||
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
|
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
|
||||||
TrackedDeviceIndex,
|
TrackedDeviceIndex,
|
||||||
@@ -15,7 +14,7 @@ use vulkano::{
|
|||||||
Handle, VulkanObject,
|
Handle, VulkanObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::state::AppState;
|
use crate::{backend::openvr::lines::LinePool, state::AppState};
|
||||||
|
|
||||||
use self::{input::action_manifest_path, overlay::OpenVrOverlayData};
|
use self::{input::action_manifest_path, overlay::OpenVrOverlayData};
|
||||||
|
|
||||||
@@ -25,12 +24,13 @@ use super::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub mod input;
|
pub mod input;
|
||||||
|
pub mod lines;
|
||||||
pub mod overlay;
|
pub mod overlay;
|
||||||
|
|
||||||
pub fn openvr_run() {
|
pub fn openvr_run() {
|
||||||
let app_type = EVRApplicationType::VRApplication_Overlay;
|
let app_type = EVRApplicationType::VRApplication_Overlay;
|
||||||
let Ok(context) = ovr_overlay::Context::init(app_type) else {
|
let Ok(context) = ovr_overlay::Context::init(app_type) else {
|
||||||
error!("Failed to initialize OpenVR");
|
log::error!("Failed to initialize OpenVR");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,12 +56,12 @@ pub fn openvr_run() {
|
|||||||
let mut overlays = OverlayContainer::<OpenVrOverlayData>::new(&mut state);
|
let mut overlays = OverlayContainer::<OpenVrOverlayData>::new(&mut state);
|
||||||
|
|
||||||
if let Err(e) = input_mngr.set_action_manifest(action_manifest_path()) {
|
if let Err(e) = input_mngr.set_action_manifest(action_manifest_path()) {
|
||||||
error!("Failed to set action manifest: {}", e.description());
|
log::error!("Failed to set action manifest: {}", e.description());
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(mut input) = InputState::new(&mut input_mngr) else {
|
let Ok(mut input) = InputState::new(&mut input_mngr) else {
|
||||||
error!("Failed to initialize input");
|
log::error!("Failed to initialize input");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -69,21 +69,25 @@ pub fn openvr_run() {
|
|||||||
TrackedDeviceIndex::HMD,
|
TrackedDeviceIndex::HMD,
|
||||||
ETrackedDeviceProperty::Prop_DisplayFrequency_Float,
|
ETrackedDeviceProperty::Prop_DisplayFrequency_Float,
|
||||||
) else {
|
) else {
|
||||||
error!("Failed to get display refresh rate");
|
log::error!("Failed to get display refresh rate");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("HMD running @ {} Hz", refresh_rate);
|
log::info!("HMD running @ {} Hz", refresh_rate);
|
||||||
|
|
||||||
let frame_time = (1000.0 / refresh_rate).floor() * 0.001;
|
let frame_time = (1000.0 / refresh_rate).floor() * 0.001;
|
||||||
let mut next_device_update = Instant::now();
|
let mut next_device_update = Instant::now();
|
||||||
let mut due_tasks = VecDeque::with_capacity(4);
|
let mut due_tasks = VecDeque::with_capacity(4);
|
||||||
|
|
||||||
|
let mut lines = LinePool::new(state.graphics.clone());
|
||||||
|
input.pointers[0].data.line_id = lines.allocate(&mut overlay_mngr, &mut state);
|
||||||
|
input.pointers[1].data.line_id = lines.allocate(&mut overlay_mngr, &mut state);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
while let Some(event) = system_mngr.poll_next_event() {
|
while let Some(event) = system_mngr.poll_next_event() {
|
||||||
match event.event_type {
|
match event.event_type {
|
||||||
EVREventType::VREvent_Quit => {
|
EVREventType::VREvent_Quit => {
|
||||||
info!("Received quit event, shutting down.");
|
log::info!("Received quit event, shutting down.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EVREventType::VREvent_TrackedDeviceActivated
|
EVREventType::VREvent_TrackedDeviceActivated
|
||||||
@@ -93,6 +97,7 @@ pub fn openvr_run() {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if next_device_update <= Instant::now() {
|
if next_device_update <= Instant::now() {
|
||||||
input.update_devices(&mut system_mngr);
|
input.update_devices(&mut system_mngr);
|
||||||
@@ -115,10 +120,17 @@ pub fn openvr_run() {
|
|||||||
input.update(&mut input_mngr, &mut system_mngr);
|
input.update(&mut input_mngr, &mut system_mngr);
|
||||||
input.post_update();
|
input.post_update();
|
||||||
|
|
||||||
input
|
input.pointers.iter_mut().for_each(|p| {
|
||||||
.pointers
|
let dist = p.interact(&mut overlays, &mut state);
|
||||||
.iter_mut()
|
if dist > 0.001 {
|
||||||
.for_each(|p| p.interact(&mut overlays, &mut state));
|
lines.draw_from(p.data.line_id, p.pose, dist, Vec4::ONE);
|
||||||
|
} else {
|
||||||
|
lines.draw_from(p.data.line_id, p.pose, 20.0, Vec4::ONE);
|
||||||
|
// lines.hide(p.data.line_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
lines.update(&mut overlay_mngr, &mut state);
|
||||||
|
|
||||||
overlays
|
overlays
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@@ -143,14 +155,15 @@ pub fn openvr_run() {
|
|||||||
|
|
||||||
// playspace moved end frame
|
// playspace moved end frame
|
||||||
|
|
||||||
|
state.input.on_new_frame();
|
||||||
|
|
||||||
let mut seconds_since_vsync = 0f32;
|
let mut seconds_since_vsync = 0f32;
|
||||||
std::thread::sleep(Duration::from_secs_f32(
|
std::thread::sleep(Duration::from_secs_f32(
|
||||||
if system_mngr.get_time_since_last_vsync(&mut seconds_since_vsync, &mut 0u64) {
|
if system_mngr.get_time_since_last_vsync(&mut seconds_since_vsync, &mut 0u64) {
|
||||||
(frame_time - seconds_since_vsync).max(0.0)
|
frame_time - (seconds_since_vsync % frame_time)
|
||||||
} else {
|
} else {
|
||||||
0.011
|
frame_time
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ use ovr_overlay::{
|
|||||||
};
|
};
|
||||||
use vulkano::{image::ImageAccess, Handle, VulkanObject};
|
use vulkano::{image::ImageAccess, Handle, VulkanObject};
|
||||||
|
|
||||||
use crate::{backend::overlay::OverlayData, graphics::WlxGraphics, state::AppState};
|
use crate::{
|
||||||
|
backend::overlay::{OverlayData, RelativeTo},
|
||||||
|
graphics::WlxGraphics,
|
||||||
|
state::AppState,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct OpenVrOverlayData {
|
pub(super) struct OpenVrOverlayData {
|
||||||
@@ -16,10 +20,11 @@ pub(super) struct OpenVrOverlayData {
|
|||||||
pub(super) color: Vec4,
|
pub(super) color: Vec4,
|
||||||
pub(super) curvature: f32,
|
pub(super) curvature: f32,
|
||||||
pub(super) sort_order: u32,
|
pub(super) sort_order: u32,
|
||||||
|
pub(super) relative_to: RelativeTo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OverlayData<OpenVrOverlayData> {
|
impl OverlayData<OpenVrOverlayData> {
|
||||||
pub fn initialize(
|
pub(super) fn initialize(
|
||||||
&mut self,
|
&mut self,
|
||||||
overlay: &mut OverlayManager,
|
overlay: &mut OverlayManager,
|
||||||
app: &mut AppState,
|
app: &mut AppState,
|
||||||
@@ -33,6 +38,11 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
};
|
};
|
||||||
log::debug!("{}: initialize", self.state.name);
|
log::debug!("{}: initialize", self.state.name);
|
||||||
|
|
||||||
|
//watch
|
||||||
|
if self.state.id == 0 {
|
||||||
|
self.data.sort_order = 68;
|
||||||
|
}
|
||||||
|
|
||||||
self.data.handle = Some(handle);
|
self.data.handle = Some(handle);
|
||||||
self.data.color = Vec4::ONE;
|
self.data.color = Vec4::ONE;
|
||||||
|
|
||||||
@@ -41,11 +51,12 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
self.upload_width(overlay);
|
self.upload_width(overlay);
|
||||||
self.upload_color(overlay);
|
self.upload_color(overlay);
|
||||||
self.upload_curvature(overlay);
|
self.upload_curvature(overlay);
|
||||||
|
self.upload_sort_order(overlay);
|
||||||
|
|
||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn after_input(&mut self, overlay: &mut OverlayManager, app: &mut AppState) {
|
pub(super) fn after_input(&mut self, overlay: &mut OverlayManager, app: &mut AppState) {
|
||||||
if self.state.want_visible && !self.data.visible {
|
if self.state.want_visible && !self.data.visible {
|
||||||
self.show(overlay, app);
|
self.show(overlay, app);
|
||||||
} else if !self.state.want_visible && self.data.visible {
|
} else if !self.state.want_visible && self.data.visible {
|
||||||
@@ -53,9 +64,12 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn after_render(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) {
|
pub(super) fn after_render(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) {
|
||||||
if self.data.visible {
|
if self.data.visible {
|
||||||
|
if self.state.dirty {
|
||||||
self.upload_transform(overlay);
|
self.upload_transform(overlay);
|
||||||
|
self.state.dirty = false;
|
||||||
|
}
|
||||||
self.upload_texture(overlay, graphics);
|
self.upload_texture(overlay, graphics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +97,7 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
self.data.visible = false;
|
self.data.visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upload_color(&self, overlay: &mut OverlayManager) {
|
pub(super) fn upload_color(&self, overlay: &mut OverlayManager) {
|
||||||
let Some(handle) = self.data.handle else {
|
let Some(handle) = self.data.handle else {
|
||||||
log::debug!("{}: No overlay handle", self.state.name);
|
log::debug!("{}: No overlay handle", self.state.name);
|
||||||
return;
|
return;
|
||||||
@@ -104,7 +118,7 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upload_width(&self, overlay: &mut OverlayManager) {
|
pub(super) fn upload_width(&self, overlay: &mut OverlayManager) {
|
||||||
let Some(handle) = self.data.handle else {
|
let Some(handle) = self.data.handle else {
|
||||||
log::debug!("{}: No overlay handle", self.state.name);
|
log::debug!("{}: No overlay handle", self.state.name);
|
||||||
return;
|
return;
|
||||||
@@ -134,7 +148,7 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upload_transform(&self, overlay: &mut OverlayManager) {
|
pub(super) fn upload_transform(&self, overlay: &mut OverlayManager) {
|
||||||
let Some(handle) = self.data.handle else {
|
let Some(handle) = self.data.handle else {
|
||||||
log::debug!("{}: No overlay handle", self.state.name);
|
log::debug!("{}: No overlay handle", self.state.name);
|
||||||
return;
|
return;
|
||||||
@@ -170,7 +184,7 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upload_texture(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) {
|
pub(super) fn upload_texture(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) {
|
||||||
let Some(handle) = self.data.handle else {
|
let Some(handle) = self.data.handle else {
|
||||||
log::debug!("{}: No overlay handle", self.state.name);
|
log::debug!("{}: No overlay handle", self.state.name);
|
||||||
return;
|
return;
|
||||||
@@ -210,8 +224,13 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
m_nQueueFamilyIndex: graphics.queue.queue_family_index(),
|
m_nQueueFamilyIndex: graphics.queue.queue_family_index(),
|
||||||
};
|
};
|
||||||
|
|
||||||
log::info!("Usages: {:?}", image.usage());
|
log::debug!(
|
||||||
log::info!("nImage: {}, nFormat: {:?}, nWidth: {}, nHeight: {}, nSampleCount: {}, nQueueFamilyIndex: {}", texture.m_nImage, format, texture.m_nWidth, texture.m_nHeight, texture.m_nSampleCount, texture.m_nQueueFamilyIndex);
|
"UploadTex: {:?}, {}x{}, {:?}",
|
||||||
|
format,
|
||||||
|
texture.m_nWidth,
|
||||||
|
texture.m_nHeight,
|
||||||
|
image.usage()
|
||||||
|
);
|
||||||
if let Err(e) = overlay.set_image_vulkan(handle, &mut texture) {
|
if let Err(e) = overlay.set_image_vulkan(handle, &mut texture) {
|
||||||
panic!("Failed to set overlay texture: {}", e);
|
panic!("Failed to set overlay texture: {}", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::sync::{
|
|||||||
Arc,
|
Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use glam::{Affine3A, Quat, Vec3A};
|
use glam::{Affine2, Affine3A, Quat, Vec3A};
|
||||||
use vulkano::image::ImageViewAbstract;
|
use vulkano::image::ImageViewAbstract;
|
||||||
|
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
@@ -22,12 +22,13 @@ pub struct OverlayState {
|
|||||||
pub want_visible: bool,
|
pub want_visible: bool,
|
||||||
pub show_hide: bool,
|
pub show_hide: bool,
|
||||||
pub grabbable: bool,
|
pub grabbable: bool,
|
||||||
|
pub dirty: bool,
|
||||||
pub transform: Affine3A,
|
pub transform: Affine3A,
|
||||||
pub spawn_point: Vec3A,
|
pub spawn_point: Vec3A,
|
||||||
pub spawn_rotation: Quat,
|
pub spawn_rotation: Quat,
|
||||||
pub relative_to: RelativeTo,
|
pub relative_to: RelativeTo,
|
||||||
pub primary_pointer: Option<usize>,
|
pub primary_pointer: Option<usize>,
|
||||||
pub interaction_transform: Affine3A,
|
pub interaction_transform: Affine2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for OverlayState {
|
impl Default for OverlayState {
|
||||||
@@ -40,12 +41,13 @@ impl Default for OverlayState {
|
|||||||
want_visible: false,
|
want_visible: false,
|
||||||
show_hide: false,
|
show_hide: false,
|
||||||
grabbable: false,
|
grabbable: false,
|
||||||
|
dirty: false,
|
||||||
relative_to: RelativeTo::None,
|
relative_to: RelativeTo::None,
|
||||||
spawn_point: Vec3A::NEG_Z,
|
spawn_point: Vec3A::NEG_Z,
|
||||||
spawn_rotation: Quat::IDENTITY,
|
spawn_rotation: Quat::IDENTITY,
|
||||||
transform: Affine3A::IDENTITY,
|
transform: Affine3A::IDENTITY,
|
||||||
primary_pointer: None,
|
primary_pointer: None,
|
||||||
interaction_transform: Affine3A::IDENTITY,
|
interaction_transform: Affine2::IDENTITY,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,12 +113,14 @@ impl OverlayRenderer for FallbackRenderer {
|
|||||||
fn resume(&mut self, _app: &mut AppState) {}
|
fn resume(&mut self, _app: &mut AppState) {}
|
||||||
fn render(&mut self, _app: &mut AppState) {}
|
fn render(&mut self, _app: &mut AppState) {}
|
||||||
fn view(&mut self) -> Option<Arc<dyn ImageViewAbstract>> {
|
fn view(&mut self) -> Option<Arc<dyn ImageViewAbstract>> {
|
||||||
unimplemented!()
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Boilerplate and dummies
|
// Boilerplate and dummies
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub enum RelativeTo {
|
pub enum RelativeTo {
|
||||||
|
#[default]
|
||||||
None,
|
None,
|
||||||
Head,
|
Head,
|
||||||
Hand(usize),
|
Hand(usize),
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::{error::Error, io::Cursor, slice::Iter, sync::Arc};
|
use std::{error::Error, io::Cursor, slice::Iter, sync::Arc};
|
||||||
|
|
||||||
use ash::vk::SubmitInfo;
|
use ash::vk::SubmitInfo;
|
||||||
use log::{debug, error, info};
|
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
buffer::{
|
buffer::{
|
||||||
@@ -28,9 +27,9 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{
|
image::{
|
||||||
sys::Image, AttachmentImage, ImageAccess, ImageCreateFlags, ImageDimensions, ImageError,
|
sys::Image, AttachmentImage, ImageCreateFlags, ImageDimensions, ImageError, ImageLayout,
|
||||||
ImageLayout, ImageUsage, ImageViewAbstract, ImmutableImage, MipmapsCount, StorageImage,
|
ImageUsage, ImageViewAbstract, ImmutableImage, MipmapsCount, StorageImage, SubresourceData,
|
||||||
SubresourceData, SwapchainImage,
|
SwapchainImage,
|
||||||
},
|
},
|
||||||
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
|
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
|
||||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||||
@@ -49,8 +48,8 @@ use vulkano::{
|
|||||||
shader::ShaderModule,
|
shader::ShaderModule,
|
||||||
swapchain::{CompositeAlpha, Surface, Swapchain, SwapchainCreateInfo},
|
swapchain::{CompositeAlpha, Surface, Swapchain, SwapchainCreateInfo},
|
||||||
sync::{
|
sync::{
|
||||||
fence::Fence, future::NowFuture, AccessFlags, DependencyInfo, ImageMemoryBarrier,
|
fence::Fence, future::NowFuture, AccessFlags, DependencyInfo, GpuFuture,
|
||||||
PipelineStages,
|
ImageMemoryBarrier, PipelineStages,
|
||||||
},
|
},
|
||||||
Version, VulkanLibrary, VulkanObject,
|
Version, VulkanLibrary, VulkanObject,
|
||||||
};
|
};
|
||||||
@@ -103,8 +102,8 @@ impl WlxGraphics {
|
|||||||
let library_extensions = vulkano_win::required_extensions(&library);
|
let library_extensions = vulkano_win::required_extensions(&library);
|
||||||
let required_extensions = library_extensions.union(&vk_instance_extensions);
|
let required_extensions = library_extensions.union(&vk_instance_extensions);
|
||||||
|
|
||||||
debug!("Instance exts for app: {:?}", &required_extensions);
|
log::debug!("Instance exts for app: {:?}", &required_extensions);
|
||||||
debug!("Instance exts for runtime: {:?}", &vk_instance_extensions);
|
log::debug!("Instance exts for runtime: {:?}", &vk_instance_extensions);
|
||||||
|
|
||||||
let instance = Instance::new(
|
let instance = Instance::new(
|
||||||
library,
|
library,
|
||||||
@@ -126,7 +125,7 @@ impl WlxGraphics {
|
|||||||
..DeviceExtensions::empty()
|
..DeviceExtensions::empty()
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("Device exts for app: {:?}", &device_extensions);
|
log::debug!("Device exts for app: {:?}", &device_extensions);
|
||||||
|
|
||||||
// TODO headless
|
// TODO headless
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
@@ -142,7 +141,7 @@ impl WlxGraphics {
|
|||||||
})
|
})
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
let runtime_extensions = vk_device_extensions_fn(&p);
|
let runtime_extensions = vk_device_extensions_fn(&p);
|
||||||
debug!(
|
log::debug!(
|
||||||
"Device exts for {}: {:?}",
|
"Device exts for {}: {:?}",
|
||||||
p.properties().device_name,
|
p.properties().device_name,
|
||||||
&runtime_extensions
|
&runtime_extensions
|
||||||
@@ -174,7 +173,7 @@ impl WlxGraphics {
|
|||||||
})
|
})
|
||||||
.expect("no suitable physical device found");
|
.expect("no suitable physical device found");
|
||||||
|
|
||||||
info!(
|
log::info!(
|
||||||
"Using vkPhysicalDevice: {}",
|
"Using vkPhysicalDevice: {}",
|
||||||
physical_device.properties().device_name,
|
physical_device.properties().device_name,
|
||||||
);
|
);
|
||||||
@@ -271,6 +270,7 @@ impl WlxGraphics {
|
|||||||
(Arc::new(me), event_loop)
|
(Arc::new(me), event_loop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn create_swapchain(
|
pub fn create_swapchain(
|
||||||
&self,
|
&self,
|
||||||
format: Option<Format>,
|
format: Option<Format>,
|
||||||
@@ -541,32 +541,7 @@ pub struct WlxCommandBuffer<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> WlxCommandBuffer<T> {
|
impl<T> WlxCommandBuffer<T> {
|
||||||
pub fn inner(&self) -> &AutoCommandBufferBuilder<T, Arc<StandardCommandBufferAllocator>> {
|
pub fn begin(mut self, render_target: Arc<dyn ImageViewAbstract>) -> Self {
|
||||||
&self.command_buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn inner_mut(
|
|
||||||
&mut self,
|
|
||||||
) -> &mut AutoCommandBufferBuilder<T, Arc<StandardCommandBufferAllocator>> {
|
|
||||||
&mut self.command_buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_inner(self) -> AutoCommandBufferBuilder<T, Arc<StandardCommandBufferAllocator>> {
|
|
||||||
self.command_buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn begin(
|
|
||||||
mut self,
|
|
||||||
render_target: Arc<dyn ImageViewAbstract>,
|
|
||||||
want_layout: Option<ImageLayout>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(want_layout) = want_layout {
|
|
||||||
let mut barrier =
|
|
||||||
ImageMemoryBarrier::image(render_target.image().inner().image.clone());
|
|
||||||
barrier.old_layout = ImageLayout::ColorAttachmentOptimal;
|
|
||||||
barrier.new_layout = want_layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.command_buffer
|
self.command_buffer
|
||||||
.begin_rendering(RenderingInfo {
|
.begin_rendering(RenderingInfo {
|
||||||
contents: SubpassContents::SecondaryCommandBuffers,
|
contents: SubpassContents::SecondaryCommandBuffers,
|
||||||
@@ -590,13 +565,6 @@ impl<T> WlxCommandBuffer<T> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(mut self, pass: &WlxPass) -> Self {
|
|
||||||
let _ = self
|
|
||||||
.command_buffer
|
|
||||||
.execute_commands(pass.command_buffer.clone());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn texture2d(
|
pub fn texture2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
width: u32,
|
width: u32,
|
||||||
@@ -614,13 +582,14 @@ impl<T> WlxCommandBuffer<T> {
|
|||||||
&self.graphics.memory_allocator,
|
&self.graphics.memory_allocator,
|
||||||
data,
|
data,
|
||||||
dimensions,
|
dimensions,
|
||||||
MipmapsCount::One,
|
MipmapsCount::Log2, // required for TRANSFER_SRC
|
||||||
format,
|
format,
|
||||||
&mut self.command_buffer,
|
&mut self.command_buffer,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn texture2d_png(&mut self, bytes: Vec<u8>) -> Arc<ImmutableImage> {
|
pub fn texture2d_png(&mut self, bytes: Vec<u8>) -> Arc<ImmutableImage> {
|
||||||
let cursor = Cursor::new(bytes);
|
let cursor = Cursor::new(bytes);
|
||||||
let decoder = png::Decoder::new(cursor);
|
let decoder = png::Decoder::new(cursor);
|
||||||
@@ -636,32 +605,24 @@ impl<T> WlxCommandBuffer<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WlxCommandBuffer<PrimaryAutoCommandBuffer> {
|
impl WlxCommandBuffer<PrimaryAutoCommandBuffer> {
|
||||||
pub fn end_render_and_continue(&mut self) {
|
pub fn end_render(mut self) -> Self {
|
||||||
self.command_buffer.end_rendering().unwrap();
|
self.command_buffer.end_rendering().unwrap();
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn end_render(self) -> PrimaryAutoCommandBuffer {
|
pub fn build(self) -> PrimaryAutoCommandBuffer {
|
||||||
let mut buf = self.command_buffer;
|
|
||||||
buf.end_rendering().unwrap();
|
|
||||||
|
|
||||||
buf.build().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn end(self) -> PrimaryAutoCommandBuffer {
|
|
||||||
self.command_buffer.build().unwrap()
|
self.command_buffer.build().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn end_render_and_execute(self) -> CommandBufferExecFuture<NowFuture> {
|
pub fn build_and_execute(self) -> CommandBufferExecFuture<NowFuture> {
|
||||||
let mut buf = self.command_buffer;
|
let queue = self.graphics.queue.clone();
|
||||||
buf.end_rendering().unwrap();
|
self.build().execute(queue).unwrap()
|
||||||
let buf = buf.build().unwrap();
|
|
||||||
buf.execute(self.graphics.queue.clone()).unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn end_and_execute(self) -> CommandBufferExecFuture<NowFuture> {
|
pub fn build_and_execute_now(self) {
|
||||||
let buf = self.command_buffer;
|
let mut exec = self.build_and_execute();
|
||||||
let buf = buf.build().unwrap();
|
exec.flush().unwrap();
|
||||||
buf.execute(self.graphics.queue.clone()).unwrap()
|
exec.cleanup_finished();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,10 +666,6 @@ impl WlxPipeline {
|
|||||||
self.pipeline.clone()
|
self.pipeline.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn graphics(&self) -> Arc<WlxGraphics> {
|
|
||||||
self.graphics.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn uniform_sampler(
|
pub fn uniform_sampler(
|
||||||
&self,
|
&self,
|
||||||
set: usize,
|
set: usize,
|
||||||
@@ -780,6 +737,7 @@ impl WlxPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct WlxPass {
|
pub struct WlxPass {
|
||||||
pipeline: Arc<WlxPipeline>,
|
pipeline: Arc<WlxPipeline>,
|
||||||
vertex_buffer: Subbuffer<[Vert2Uv]>,
|
vertex_buffer: Subbuffer<[Vert2Uv]>,
|
||||||
@@ -833,7 +791,7 @@ impl WlxPass {
|
|||||||
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)
|
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)
|
||||||
.or_else(|err| {
|
.or_else(|err| {
|
||||||
if let Some(source) = err.source() {
|
if let Some(source) = err.source() {
|
||||||
error!("Failed to draw: {}", source);
|
log::error!("Failed to draw: {}", source);
|
||||||
}
|
}
|
||||||
Err(err)
|
Err(err)
|
||||||
})
|
})
|
||||||
|
|||||||
1197
src/graphics.rs.bak2
1197
src/graphics.rs.bak2
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@ use std::{rc::Rc, str::FromStr, sync::Arc};
|
|||||||
use fontconfig::{FontConfig, OwnedPattern};
|
use fontconfig::{FontConfig, OwnedPattern};
|
||||||
use freetype::{bitmap::PixelMode, face::LoadFlag, Face, Library};
|
use freetype::{bitmap::PixelMode, face::LoadFlag, Face, Library};
|
||||||
use idmap::IdMap;
|
use idmap::IdMap;
|
||||||
use log::debug;
|
|
||||||
use vulkano::{command_buffer::CommandBufferUsage, format::Format, image::ImmutableImage};
|
use vulkano::{command_buffer::CommandBufferUsage, format::Format, image::ImmutableImage};
|
||||||
|
|
||||||
use crate::graphics::WlxGraphics;
|
use crate::graphics::WlxGraphics;
|
||||||
@@ -116,7 +115,7 @@ impl FontCache {
|
|||||||
let pattern = pattern.font_match(&mut self.fc);
|
let pattern = pattern.font_match(&mut self.fc);
|
||||||
|
|
||||||
if let Some(path) = pattern.filename() {
|
if let Some(path) = pattern.filename() {
|
||||||
debug!(
|
log::debug!(
|
||||||
"Loading font: {} {}pt",
|
"Loading font: {} {}pt",
|
||||||
pattern.name().unwrap_or(path),
|
pattern.name().unwrap_or(path),
|
||||||
size
|
size
|
||||||
@@ -203,7 +202,7 @@ impl FontCache {
|
|||||||
|
|
||||||
let mut cmd_buffer = graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit);
|
let mut cmd_buffer = graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit);
|
||||||
let texture = cmd_buffer.texture2d(bmp.width() as _, bmp.rows() as _, format, buf);
|
let texture = cmd_buffer.texture2d(bmp.width() as _, bmp.rows() as _, format, buf);
|
||||||
let _ = cmd_buffer.end_and_execute();
|
cmd_buffer.build_and_execute_now();
|
||||||
|
|
||||||
let g = Glyph {
|
let g = Glyph {
|
||||||
tex: Some(texture),
|
tex: Some(texture),
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ impl<D, S> CanvasBuilder<D, S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creates a label with fg_color, font_size inherited from the canvas
|
// Creates a label with fg_color, font_size inherited from the canvas
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn label_centered(
|
pub fn label_centered(
|
||||||
&mut self,
|
&mut self,
|
||||||
x: f32,
|
x: f32,
|
||||||
@@ -320,13 +321,13 @@ impl<D, S> Canvas<D, S> {
|
|||||||
.canvas
|
.canvas
|
||||||
.graphics
|
.graphics
|
||||||
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
||||||
.begin(self.view_bg.clone(), None);
|
.begin(self.view_bg.clone());
|
||||||
for c in self.controls.iter_mut() {
|
for c in self.controls.iter_mut() {
|
||||||
if let Some(fun) = c.on_render_bg {
|
if let Some(fun) = c.on_render_bg {
|
||||||
fun(c, &self.canvas, app, &mut cmd_buffer);
|
fun(c, &self.canvas, app, &mut cmd_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _ = cmd_buffer.end_render_and_execute();
|
cmd_buffer.end_render().build_and_execute_now()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_fg(&mut self, app: &mut AppState) {
|
fn render_fg(&mut self, app: &mut AppState) {
|
||||||
@@ -334,17 +335,13 @@ impl<D, S> Canvas<D, S> {
|
|||||||
.canvas
|
.canvas
|
||||||
.graphics
|
.graphics
|
||||||
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
||||||
.begin(self.view_fg.clone(), None);
|
.begin(self.view_fg.clone());
|
||||||
for c in self.controls.iter_mut() {
|
for c in self.controls.iter_mut() {
|
||||||
if let Some(fun) = c.on_render_fg {
|
if let Some(fun) = c.on_render_fg {
|
||||||
fun(c, &self.canvas, app, &mut cmd_buffer);
|
fun(c, &self.canvas, app, &mut cmd_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _ = cmd_buffer.end_render_and_execute();
|
cmd_buffer.end_render().build_and_execute_now()
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render_view(&self) -> Arc<ImageView<AttachmentImage>> {
|
|
||||||
self.view_final.clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +382,6 @@ impl<D, S> InteractionHandler for Canvas<D, S> {
|
|||||||
impl<D, S> OverlayRenderer for Canvas<D, S> {
|
impl<D, S> OverlayRenderer for Canvas<D, S> {
|
||||||
fn init(&mut self, app: &mut AppState) {
|
fn init(&mut self, app: &mut AppState) {
|
||||||
self.render_bg(app);
|
self.render_bg(app);
|
||||||
|
|
||||||
self.render_fg(app);
|
self.render_fg(app);
|
||||||
}
|
}
|
||||||
fn pause(&mut self, _app: &mut AppState) {}
|
fn pause(&mut self, _app: &mut AppState) {}
|
||||||
@@ -423,10 +419,7 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
|
|||||||
.canvas
|
.canvas
|
||||||
.graphics
|
.graphics
|
||||||
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
||||||
.begin(
|
.begin(self.view_final.clone());
|
||||||
self.view_final.clone(),
|
|
||||||
Some(ImageLayout::TransferSrcOptimal),
|
|
||||||
);
|
|
||||||
|
|
||||||
if dirty {
|
if dirty {
|
||||||
self.render_fg(app);
|
self.render_fg(app);
|
||||||
@@ -451,7 +444,7 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
|
|||||||
// mostly static text
|
// mostly static text
|
||||||
cmd_buffer.run_ref(&self.pass_fg);
|
cmd_buffer.run_ref(&self.pass_fg);
|
||||||
{
|
{
|
||||||
let _ = cmd_buffer.end_render_and_execute();
|
let _ = cmd_buffer.end_render().build_and_execute();
|
||||||
}
|
}
|
||||||
self.canvas
|
self.canvas
|
||||||
.graphics
|
.graphics
|
||||||
@@ -478,7 +471,6 @@ pub struct Control<D, S> {
|
|||||||
text: Arc<str>,
|
text: Arc<str>,
|
||||||
size: isize,
|
size: isize,
|
||||||
dirty: bool,
|
dirty: bool,
|
||||||
pass_hl: Option<(WlxPass, WlxPass)>,
|
|
||||||
|
|
||||||
pub on_update: Option<fn(&mut Self, &mut D, &mut AppState)>,
|
pub on_update: Option<fn(&mut Self, &mut D, &mut AppState)>,
|
||||||
pub on_press: Option<fn(&mut Self, &mut D, &mut AppState)>,
|
pub on_press: Option<fn(&mut Self, &mut D, &mut AppState)>,
|
||||||
@@ -524,7 +516,6 @@ impl<D, S> Control<D, S> {
|
|||||||
test_highlight: None,
|
test_highlight: None,
|
||||||
on_press: None,
|
on_press: None,
|
||||||
on_release: None,
|
on_release: None,
|
||||||
pass_hl: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,11 +528,6 @@ impl<D, S> Control<D, S> {
|
|||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn get_text(&self) -> &str {
|
|
||||||
&self.text
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_rect(
|
fn render_rect(
|
||||||
&self,
|
&self,
|
||||||
canvas: &CanvasData<D>,
|
canvas: &CanvasData<D>,
|
||||||
|
|||||||
21
src/input.rs
21
src/input.rs
@@ -6,7 +6,6 @@ use input_linux::{
|
|||||||
UInputHandle,
|
UInputHandle,
|
||||||
};
|
};
|
||||||
use libc::{input_event, timeval};
|
use libc::{input_event, timeval};
|
||||||
use log::{error, info};
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
@@ -14,11 +13,11 @@ use strum::{EnumIter, EnumString, IntoEnumIterator};
|
|||||||
|
|
||||||
pub fn initialize_input() -> Box<dyn InputProvider> {
|
pub fn initialize_input() -> Box<dyn InputProvider> {
|
||||||
if let Some(uinput) = UInputProvider::try_new() {
|
if let Some(uinput) = UInputProvider::try_new() {
|
||||||
info!("Initialized uinput.");
|
log::info!("Initialized uinput.");
|
||||||
return Box::new(uinput);
|
return Box::new(uinput);
|
||||||
}
|
}
|
||||||
error!("Could not create uinput provider. Keyboard/Mouse input will not work!");
|
log::error!("Could not create uinput provider. Keyboard/Mouse input will not work!");
|
||||||
error!("Check if you're in `input` group: `id -nG`");
|
log::error!("Check if you're in `input` group: `id -nG`");
|
||||||
Box::new(DummyProvider {})
|
Box::new(DummyProvider {})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +63,7 @@ impl UInputProvider {
|
|||||||
version: 5,
|
version: 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
let name = b"WlxOverlay Keyboard-Mouse Hybrid Thing\0";
|
let name = b"WlxOverlay-S Keyboard-Mouse Hybrid Thing\0";
|
||||||
|
|
||||||
let abs_info = vec![
|
let abs_info = vec![
|
||||||
AbsoluteInfoSetup {
|
AbsoluteInfoSetup {
|
||||||
@@ -145,6 +144,8 @@ impl InputProvider for UInputProvider {
|
|||||||
}
|
}
|
||||||
self.mouse_moved = true;
|
self.mouse_moved = true;
|
||||||
|
|
||||||
|
log::info!("Mouse move: {:?}", pos);
|
||||||
|
|
||||||
let pos = pos * (MOUSE_EXTENT / self.desktop_extent);
|
let pos = pos * (MOUSE_EXTENT / self.desktop_extent);
|
||||||
|
|
||||||
let time = get_time();
|
let time = get_time();
|
||||||
@@ -154,7 +155,7 @@ impl InputProvider for UInputProvider {
|
|||||||
new_event(time, EV_SYN, 0, 0),
|
new_event(time, EV_SYN, 0, 0),
|
||||||
];
|
];
|
||||||
if let Err(res) = self.handle.write(&events) {
|
if let Err(res) = self.handle.write(&events) {
|
||||||
error!("{}", res.to_string());
|
log::error!("{}", res.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn send_button(&self, button: u16, down: bool) {
|
fn send_button(&self, button: u16, down: bool) {
|
||||||
@@ -164,7 +165,7 @@ impl InputProvider for UInputProvider {
|
|||||||
new_event(time, EV_SYN, 0, 0),
|
new_event(time, EV_SYN, 0, 0),
|
||||||
];
|
];
|
||||||
if let Err(res) = self.handle.write(&events) {
|
if let Err(res) = self.handle.write(&events) {
|
||||||
error!("{}", res.to_string());
|
log::error!("send_button: {}", res.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn wheel(&self, delta: i32) {
|
fn wheel(&self, delta: i32) {
|
||||||
@@ -174,7 +175,7 @@ impl InputProvider for UInputProvider {
|
|||||||
new_event(time, EV_SYN, 0, 0),
|
new_event(time, EV_SYN, 0, 0),
|
||||||
];
|
];
|
||||||
if let Err(res) = self.handle.write(&events) {
|
if let Err(res) = self.handle.write(&events) {
|
||||||
error!("{}", res.to_string());
|
log::error!("wheel: {}", res.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn set_modifiers(&mut self, modifiers: u8) {
|
fn set_modifiers(&mut self, modifiers: u8) {
|
||||||
@@ -195,11 +196,11 @@ impl InputProvider for UInputProvider {
|
|||||||
new_event(time, EV_SYN, 0, 0),
|
new_event(time, EV_SYN, 0, 0),
|
||||||
];
|
];
|
||||||
if let Err(res) = self.handle.write(&events) {
|
if let Err(res) = self.handle.write(&events) {
|
||||||
error!("{}", res.to_string());
|
log::error!("send_key: {}", res.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn set_desktop_extent(&mut self, extent: Vec2) {
|
fn set_desktop_extent(&mut self, extent: Vec2) {
|
||||||
info!("Desktop extent: {:?}", extent);
|
log::info!("Desktop extent: {:?}", extent);
|
||||||
self.desktop_extent = extent;
|
self.desktop_extent = extent;
|
||||||
}
|
}
|
||||||
fn on_new_frame(&mut self) {
|
fn on_new_frame(&mut self) {
|
||||||
|
|||||||
@@ -9,11 +9,10 @@ mod state;
|
|||||||
|
|
||||||
use crate::backend::openvr::openvr_run;
|
use crate::backend::openvr::openvr_run;
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
use log::info;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||||
info!(
|
log::info!(
|
||||||
"Welcome to {} version {}!",
|
"Welcome to {} version {}!",
|
||||||
env!("CARGO_PKG_NAME"),
|
env!("CARGO_PKG_NAME"),
|
||||||
env!("CARGO_PKG_VERSION")
|
env!("CARGO_PKG_VERSION")
|
||||||
|
|||||||
159
src/main.rs.bak2
159
src/main.rs.bak2
@@ -1,159 +0,0 @@
|
|||||||
#[allow(dead_code)]
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
|
|
||||||
mod graphics;
|
|
||||||
//mod gui;
|
|
||||||
//mod interactions;
|
|
||||||
//mod overlay;
|
|
||||||
//mod state;
|
|
||||||
|
|
||||||
use core::slice;
|
|
||||||
|
|
||||||
use ash::vk;
|
|
||||||
use env_logger::Env;
|
|
||||||
use glam::f32::Vec4;
|
|
||||||
use log::{info, warn};
|
|
||||||
use wlx_capture::{wlr::WlrDmabufCapture, wayland::WlxClient, WlxCapture, frame::WlxFrame};
|
|
||||||
|
|
||||||
use crate::{graphics::{VkGraphics, VkDescriptor}};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
|
||||||
info!("Welcome to {} version {}!", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
|
|
||||||
|
|
||||||
// let mut app = AppState {
|
|
||||||
// fc: gui::font::FontCache::new(),
|
|
||||||
// session: state::AppSession::load(),
|
|
||||||
// };
|
|
||||||
|
|
||||||
let wl = WlxClient::new().unwrap();
|
|
||||||
let output_id = wl.outputs[0].id;
|
|
||||||
let mut capture = WlrDmabufCapture::new(wl, output_id).unwrap();
|
|
||||||
let rx = capture.init();
|
|
||||||
|
|
||||||
let gfx = VkGraphics::new();
|
|
||||||
let vert = gfx.create_shader(include_bytes!("shaders/vert-common.spv"), None);
|
|
||||||
let frag_sprite = gfx.create_shader(
|
|
||||||
include_bytes!("shaders/frag-sprite.spv"),
|
|
||||||
Some(vec![vk::DescriptorType::COMBINED_IMAGE_SAMPLER])
|
|
||||||
);
|
|
||||||
let frag_srgb = gfx.create_shader(
|
|
||||||
include_bytes!("shaders/frag-srgb.spv"),
|
|
||||||
Some(vec![vk::DescriptorType::COMBINED_IMAGE_SAMPLER])
|
|
||||||
);
|
|
||||||
let frag_glyph = gfx.create_shader(
|
|
||||||
include_bytes!("shaders/frag-glyph.spv"),
|
|
||||||
Some(vec![vk::DescriptorType::COMBINED_IMAGE_SAMPLER, vk::DescriptorType::UNIFORM_BUFFER])
|
|
||||||
);
|
|
||||||
let frag_color = gfx.create_shader(
|
|
||||||
include_bytes!("shaders/frag-color.spv"),
|
|
||||||
Some(vec![vk::DescriptorType::UNIFORM_BUFFER])
|
|
||||||
);
|
|
||||||
|
|
||||||
let pipeline = gfx.create_pipeline(vert, frag_color, gfx.swapchain_format);
|
|
||||||
|
|
||||||
let color_buf = gfx.create_buffer(vk::BufferUsageFlags::UNIFORM_BUFFER, &[Vec4::new(1.0, 0.0, 1.0, 1.0); 16]);
|
|
||||||
|
|
||||||
gfx.render_loop(|| {
|
|
||||||
let frame = gfx.create_frame();
|
|
||||||
|
|
||||||
unsafe { gfx.device.reset_command_pool(frame.command_pool, vk::CommandPoolResetFlags::RELEASE_RESOURCES) }.unwrap();
|
|
||||||
|
|
||||||
let (present_index, _) = unsafe {
|
|
||||||
gfx.swapchain_loader.acquire_next_image(
|
|
||||||
gfx.swapchain,
|
|
||||||
std::u64::MAX,
|
|
||||||
frame.present_semaphore,
|
|
||||||
vk::Fence::null()
|
|
||||||
).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder()
|
|
||||||
.flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
unsafe { gfx.device.begin_command_buffer(frame.command_buffer, &command_buffer_begin_info) }.unwrap();
|
|
||||||
|
|
||||||
let image = gfx.present_images[present_index as usize];
|
|
||||||
|
|
||||||
let image_memory_barrier = vk::ImageMemoryBarrier2::builder()
|
|
||||||
.src_stage_mask(vk::PipelineStageFlags2::TOP_OF_PIPE)
|
|
||||||
.dst_stage_mask(vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT)
|
|
||||||
.dst_access_mask(vk::AccessFlags2::COLOR_ATTACHMENT_WRITE)
|
|
||||||
.old_layout(vk::ImageLayout::UNDEFINED)
|
|
||||||
.new_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
|
||||||
.image(image)
|
|
||||||
.subresource_range(vk::ImageSubresourceRange::builder().aspect_mask(vk::ImageAspectFlags::COLOR).level_count(1).layer_count(1).build())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
unsafe { gfx.device.cmd_pipeline_barrier2(frame.command_buffer, &vk::DependencyInfo::builder().image_memory_barriers(slice::from_ref(&image_memory_barrier)).build()) };
|
|
||||||
|
|
||||||
let color_attachment = vk::RenderingAttachmentInfo::builder()
|
|
||||||
.image_view(gfx.present_image_views[present_index as usize])
|
|
||||||
.image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
|
||||||
.load_op(vk::AttachmentLoadOp::CLEAR)
|
|
||||||
.store_op(vk::AttachmentStoreOp::STORE)
|
|
||||||
.clear_value(vk::ClearValue {
|
|
||||||
color: vk::ClearColorValue {
|
|
||||||
float32: [0.0, 0.0, 0.0, 1.0]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let rendering_info = vk::RenderingInfo::builder()
|
|
||||||
.render_area(vk::Rect2D::builder().extent(vk::Extent2D::builder().width(1600).height(900).build()).build())
|
|
||||||
.layer_count(1)
|
|
||||||
.color_attachments(slice::from_ref(&color_attachment))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
|
|
||||||
unsafe { gfx.device.cmd_begin_rendering(frame.command_buffer, &rendering_info) };
|
|
||||||
|
|
||||||
let descriptor = VkDescriptor::Buffer(color_buf.clone());
|
|
||||||
pipeline.bind_descriptors(slice::from_ref(&descriptor));
|
|
||||||
pipeline.render(&frame, vk::Rect2D {
|
|
||||||
offset: vk::Offset2D { x: 0, y: 0 },
|
|
||||||
extent: vk::Extent2D { width: 1600, height: 900 }
|
|
||||||
});
|
|
||||||
|
|
||||||
unsafe { gfx.device.cmd_end_rendering(frame.command_buffer) };
|
|
||||||
|
|
||||||
|
|
||||||
let image_memory_barrier = vk::ImageMemoryBarrier2::builder()
|
|
||||||
.src_stage_mask(vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT)
|
|
||||||
.src_access_mask(vk::AccessFlags2::COLOR_ATTACHMENT_WRITE)
|
|
||||||
.dst_stage_mask(vk::PipelineStageFlags2::BOTTOM_OF_PIPE)
|
|
||||||
.old_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
|
||||||
.new_layout(vk::ImageLayout::PRESENT_SRC_KHR)
|
|
||||||
.image(image)
|
|
||||||
.subresource_range(vk::ImageSubresourceRange::builder().aspect_mask(vk::ImageAspectFlags::COLOR).level_count(1).layer_count(1).build())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
gfx.device.cmd_pipeline_barrier2(frame.command_buffer, &vk::DependencyInfo::builder().image_memory_barriers(slice::from_ref(&image_memory_barrier)).build());
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe { gfx.device.end_command_buffer(frame.command_buffer) }.unwrap();
|
|
||||||
|
|
||||||
let wait_semaphores = [frame.present_semaphore];
|
|
||||||
let wait_dst_stage_mask = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
|
|
||||||
|
|
||||||
let submit_info = vk::SubmitInfo::builder()
|
|
||||||
.wait_semaphores(&wait_semaphores)
|
|
||||||
.wait_dst_stage_mask(&wait_dst_stage_mask)
|
|
||||||
.command_buffers(slice::from_ref(&frame.command_buffer))
|
|
||||||
.signal_semaphores(slice::from_ref(&frame.render_semaphore));
|
|
||||||
|
|
||||||
unsafe { gfx.device.queue_submit(gfx.present_queue, slice::from_ref(&submit_info), frame.fence) }.unwrap();
|
|
||||||
|
|
||||||
let present_info = vk::PresentInfoKHR::builder()
|
|
||||||
.wait_semaphores(slice::from_ref(&frame.present_semaphore))
|
|
||||||
.swapchains(slice::from_ref(&gfx.swapchain))
|
|
||||||
.image_indices(slice::from_ref(&present_index))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
unsafe { gfx.swapchain_loader.queue_present(gfx.present_queue, &present_info).unwrap() };
|
|
||||||
});
|
|
||||||
|
|
||||||
unsafe { gfx.device.device_wait_idle().unwrap() };
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -16,7 +16,6 @@ use crate::{
|
|||||||
state::AppState,
|
state::AppState,
|
||||||
};
|
};
|
||||||
use glam::{vec2, vec3a};
|
use glam::{vec2, vec3a};
|
||||||
use log::error;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rodio::{Decoder, OutputStream, Source};
|
use rodio::{Decoder, OutputStream, Source};
|
||||||
@@ -88,7 +87,7 @@ where
|
|||||||
args: exec_args.iter().skip(1).cloned().collect(),
|
args: exec_args.iter().skip(1).cloned().collect(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
error!("Unknown key: {}", key);
|
log::error!("Unknown key: {}", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(state) = maybe_state {
|
if let Some(state) = maybe_state {
|
||||||
@@ -109,7 +108,7 @@ where
|
|||||||
|
|
||||||
OverlayData {
|
OverlayData {
|
||||||
state: OverlayState {
|
state: OverlayState {
|
||||||
name: Arc::from("Kbd"),
|
name: Arc::from("kbd"),
|
||||||
show_hide: true,
|
show_hide: true,
|
||||||
width: LAYOUT.row_size * 0.05,
|
width: LAYOUT.row_size * 0.05,
|
||||||
size: (size.x as _, size.y as _),
|
size: (size.x as _, size.y as _),
|
||||||
@@ -217,7 +216,7 @@ impl KeyboardData {
|
|||||||
let _ = handle.play_raw(source.convert_samples());
|
let _ = handle.play_raw(source.convert_samples());
|
||||||
self.audio_stream = Some(stream);
|
self.audio_stream = Some(stream);
|
||||||
} else {
|
} else {
|
||||||
error!("Failed to play key click");
|
log::error!("Failed to play key click");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,7 +338,7 @@ fn key_events_for_macro(macro_verbs: &Vec<String>) -> Vec<(VirtualKey, bool)> {
|
|||||||
} else if state.as_str() == "DOWN" {
|
} else if state.as_str() == "DOWN" {
|
||||||
key_events.push((virtual_key, true));
|
key_events.push((virtual_key, true));
|
||||||
} else {
|
} else {
|
||||||
error!(
|
log::error!(
|
||||||
"Unknown key state in macro: {}, looking for UP or DOWN.",
|
"Unknown key state in macro: {}, looking for UP or DOWN.",
|
||||||
state.as_str()
|
state.as_str()
|
||||||
);
|
);
|
||||||
@@ -350,7 +349,7 @@ fn key_events_for_macro(macro_verbs: &Vec<String>) -> Vec<(VirtualKey, bool)> {
|
|||||||
key_events.push((virtual_key, false));
|
key_events.push((virtual_key, false));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error!("Unknown virtual key: {}", &caps[1]);
|
log::error!("Unknown virtual key: {}", &caps[1]);
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use log::{info, warn};
|
|
||||||
use std::{
|
use std::{
|
||||||
f32::consts::PI,
|
f32::consts::PI,
|
||||||
path::Path,
|
path::Path,
|
||||||
@@ -6,9 +5,14 @@ use std::{
|
|||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
|
buffer::Subbuffer,
|
||||||
command_buffer::CommandBufferUsage,
|
command_buffer::CommandBufferUsage,
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, ImageAccess, ImageLayout, ImageViewAbstract, ImmutableImage},
|
image::{
|
||||||
|
view::ImageView, AttachmentImage, ImageAccess, ImageLayout, ImageViewAbstract, StorageImage,
|
||||||
|
},
|
||||||
|
sampler::Filter,
|
||||||
|
sync::GpuFuture,
|
||||||
Handle, VulkanObject,
|
Handle, VulkanObject,
|
||||||
};
|
};
|
||||||
use wlx_capture::{
|
use wlx_capture::{
|
||||||
@@ -26,7 +30,9 @@ use crate::{
|
|||||||
input::{InteractionHandler, PointerHit, PointerMode},
|
input::{InteractionHandler, PointerHit, PointerMode},
|
||||||
overlay::{OverlayData, OverlayRenderer, OverlayState, SplitOverlayBackend},
|
overlay::{OverlayData, OverlayRenderer, OverlayState, SplitOverlayBackend},
|
||||||
},
|
},
|
||||||
|
graphics::{Vert2Uv, WlxGraphics, WlxPipeline},
|
||||||
input::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT},
|
input::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT},
|
||||||
|
shaders::{frag_sprite, vert_common},
|
||||||
state::{AppSession, AppState},
|
state::{AppSession, AppState},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,6 +72,7 @@ impl ScreenInteractionHandler {
|
|||||||
|
|
||||||
impl InteractionHandler for ScreenInteractionHandler {
|
impl InteractionHandler for ScreenInteractionHandler {
|
||||||
fn on_hover(&mut self, app: &mut AppState, hit: &PointerHit) {
|
fn on_hover(&mut self, app: &mut AppState, hit: &PointerHit) {
|
||||||
|
log::info!("Hover: {:?}", hit.uv);
|
||||||
if self.next_move < Instant::now() {
|
if self.next_move < Instant::now() {
|
||||||
let pos = self.mouse_transform.transform_point2(hit.uv);
|
let pos = self.mouse_transform.transform_point2(hit.uv);
|
||||||
app.input.mouse_move(pos);
|
app.input.mouse_move(pos);
|
||||||
@@ -82,7 +89,8 @@ impl InteractionHandler for ScreenInteractionHandler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if pressed {
|
if pressed {
|
||||||
self.next_move = Instant::now() + Duration::from_millis(300);
|
self.next_move =
|
||||||
|
Instant::now() + Duration::from_millis(app.session.click_freeze_time_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.input.send_button(btn, pressed);
|
app.input.send_button(btn, pressed);
|
||||||
@@ -97,11 +105,106 @@ impl InteractionHandler for ScreenInteractionHandler {
|
|||||||
fn on_left(&mut self, _app: &mut AppState, _hand: usize) {}
|
fn on_left(&mut self, _app: &mut AppState, _hand: usize) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ScreenPipeline {
|
||||||
|
graphics: Arc<WlxGraphics>,
|
||||||
|
pipeline: Arc<WlxPipeline>,
|
||||||
|
vertex_buffer: Subbuffer<[Vert2Uv]>,
|
||||||
|
target_layout: ImageLayout,
|
||||||
|
pub view: Arc<ImageView<AttachmentImage>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScreenPipeline {
|
||||||
|
fn new(graphics: Arc<WlxGraphics>, image: &StorageImage) -> Self {
|
||||||
|
let pipeline = graphics.create_pipeline(
|
||||||
|
vert_common::load(graphics.device.clone()).unwrap(),
|
||||||
|
frag_sprite::load(graphics.device.clone()).unwrap(),
|
||||||
|
Format::R8G8B8A8_UNORM,
|
||||||
|
);
|
||||||
|
|
||||||
|
let dim = image.dimensions().width_height();
|
||||||
|
|
||||||
|
let vertex_buffer =
|
||||||
|
graphics.upload_verts(dim[0] as _, dim[1] as _, 0.0, 0.0, dim[0] as _, dim[1] as _);
|
||||||
|
|
||||||
|
let render_texture = graphics.render_texture(dim[0], dim[1], Format::R8G8B8A8_UNORM);
|
||||||
|
|
||||||
|
let view = ImageView::new_default(render_texture).unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
graphics,
|
||||||
|
pipeline,
|
||||||
|
vertex_buffer,
|
||||||
|
view,
|
||||||
|
target_layout: ImageLayout::Undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&mut self, image: Arc<StorageImage>) {
|
||||||
|
if image.inner().image.handle().as_raw()
|
||||||
|
== self.view.image().inner().image.handle().as_raw()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut command_buffer = self
|
||||||
|
.graphics
|
||||||
|
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
||||||
|
.begin(self.view.clone());
|
||||||
|
|
||||||
|
let set0 = self.pipeline.uniform_sampler(
|
||||||
|
0,
|
||||||
|
ImageView::new_default(image).unwrap(),
|
||||||
|
Filter::Linear,
|
||||||
|
);
|
||||||
|
|
||||||
|
let dim = self.view.dimensions().width_height();
|
||||||
|
let dim = [dim[0] as f32, dim[1] as f32];
|
||||||
|
|
||||||
|
let pass = self.pipeline.create_pass(
|
||||||
|
dim,
|
||||||
|
self.vertex_buffer.clone(),
|
||||||
|
self.graphics.quad_indices.clone(),
|
||||||
|
vec![set0],
|
||||||
|
);
|
||||||
|
command_buffer.run_ref(&pass);
|
||||||
|
|
||||||
|
let image = self.view.image().inner().image.clone();
|
||||||
|
|
||||||
|
if self.target_layout == ImageLayout::TransferSrcOptimal {
|
||||||
|
self.graphics
|
||||||
|
.transition_layout(
|
||||||
|
image.clone(),
|
||||||
|
ImageLayout::TransferSrcOptimal,
|
||||||
|
ImageLayout::ColorAttachmentOptimal,
|
||||||
|
)
|
||||||
|
.wait(None)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut exec = command_buffer.end_render().build_and_execute();
|
||||||
|
exec.flush().unwrap();
|
||||||
|
exec.cleanup_finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.graphics
|
||||||
|
.transition_layout(
|
||||||
|
image,
|
||||||
|
ImageLayout::ColorAttachmentOptimal,
|
||||||
|
ImageLayout::TransferSrcOptimal,
|
||||||
|
)
|
||||||
|
.wait(None)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
self.target_layout = ImageLayout::TransferSrcOptimal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ScreenRenderer {
|
pub struct ScreenRenderer {
|
||||||
capture: Box<dyn WlxCapture>,
|
capture: Box<dyn WlxCapture>,
|
||||||
resolution: (i32, i32),
|
|
||||||
receiver: Option<Receiver<WlxFrame>>,
|
receiver: Option<Receiver<WlxFrame>>,
|
||||||
view: Option<Arc<dyn ImageViewAbstract>>,
|
pipeline: Option<ScreenPipeline>,
|
||||||
|
last_frame: Option<Arc<dyn ImageViewAbstract>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScreenRenderer {
|
impl ScreenRenderer {
|
||||||
@@ -114,9 +217,9 @@ impl ScreenRenderer {
|
|||||||
};
|
};
|
||||||
Some(ScreenRenderer {
|
Some(ScreenRenderer {
|
||||||
capture: Box::new(capture),
|
capture: Box::new(capture),
|
||||||
resolution: output.size,
|
|
||||||
receiver: None,
|
receiver: None,
|
||||||
view: None,
|
pipeline: None,
|
||||||
|
last_frame: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,15 +235,11 @@ impl ScreenRenderer {
|
|||||||
|
|
||||||
Some(ScreenRenderer {
|
Some(ScreenRenderer {
|
||||||
capture: Box::new(capture),
|
capture: Box::new(capture),
|
||||||
resolution: output.size,
|
|
||||||
receiver: None,
|
receiver: None,
|
||||||
view: None,
|
pipeline: None,
|
||||||
|
last_frame: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_xshm() -> ScreenRenderer {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OverlayRenderer for ScreenRenderer {
|
impl OverlayRenderer for ScreenRenderer {
|
||||||
@@ -157,28 +256,18 @@ impl OverlayRenderer for ScreenRenderer {
|
|||||||
match frame {
|
match frame {
|
||||||
WlxFrame::Dmabuf(frame) => {
|
WlxFrame::Dmabuf(frame) => {
|
||||||
if let Ok(new) = app.graphics.dmabuf_texture(frame) {
|
if let Ok(new) = app.graphics.dmabuf_texture(frame) {
|
||||||
if let Some(current) = self.view.as_ref() {
|
let pipeline = self
|
||||||
if current.image().inner().image.handle().as_raw()
|
.pipeline
|
||||||
== new.inner().image.handle().as_raw()
|
.get_or_insert_with(|| ScreenPipeline::new(app.graphics.clone(), &new));
|
||||||
{
|
|
||||||
return;
|
pipeline.render(new);
|
||||||
|
self.last_frame = Some(pipeline.view.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.graphics
|
WlxFrame::MemFd(_frame) => {
|
||||||
.transition_layout(
|
|
||||||
new.inner().image.clone(),
|
|
||||||
ImageLayout::Undefined,
|
|
||||||
ImageLayout::TransferSrcOptimal,
|
|
||||||
)
|
|
||||||
.wait(None)
|
|
||||||
.unwrap();
|
|
||||||
self.view = Some(ImageView::new_default(new).unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WlxFrame::MemFd(frame) => {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
WlxFrame::MemPtr(frame) => {
|
WlxFrame::MemPtr(_frame) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -193,7 +282,7 @@ impl OverlayRenderer for ScreenRenderer {
|
|||||||
self.capture.resume();
|
self.capture.resume();
|
||||||
}
|
}
|
||||||
fn view(&mut self) -> Option<Arc<dyn ImageViewAbstract>> {
|
fn view(&mut self) -> Option<Arc<dyn ImageViewAbstract>> {
|
||||||
self.view.as_ref().and_then(|v| Some(v.clone()))
|
self.last_frame.take()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,21 +291,25 @@ where
|
|||||||
O: Default,
|
O: Default,
|
||||||
{
|
{
|
||||||
let output = &wl.outputs[idx];
|
let output = &wl.outputs[idx];
|
||||||
info!(
|
log::info!(
|
||||||
"{}: Res {}x{} Size {:?} Pos {:?}",
|
"{}: Res {}x{} Size {:?} Pos {:?}",
|
||||||
output.name, output.size.0, output.size.1, output.logical_size, output.logical_pos,
|
output.name,
|
||||||
|
output.size.0,
|
||||||
|
output.size.1,
|
||||||
|
output.logical_size,
|
||||||
|
output.logical_pos,
|
||||||
);
|
);
|
||||||
|
|
||||||
let size = (output.size.0, output.size.1);
|
let size = (output.size.0, output.size.1);
|
||||||
let mut capture: Option<ScreenRenderer> = None;
|
let mut capture: Option<ScreenRenderer> = None;
|
||||||
|
|
||||||
if session.capture_method == "auto" && wl.maybe_wlr_dmabuf_mgr.is_some() {
|
if session.capture_method == "auto" && wl.maybe_wlr_dmabuf_mgr.is_some() {
|
||||||
info!("{}: Using Wlr DMA-Buf", &output.name);
|
log::info!("{}: Using Wlr DMA-Buf", &output.name);
|
||||||
capture = ScreenRenderer::new_wlr(output);
|
capture = ScreenRenderer::new_wlr(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if capture.is_none() {
|
if capture.is_none() {
|
||||||
info!("{}: Using Pipewire capture", &output.name);
|
log::info!("{}: Using Pipewire capture", &output.name);
|
||||||
let file_name = format!("{}.token", &output.name);
|
let file_name = format!("{}.token", &output.name);
|
||||||
let full_path = Path::new(&session.config_path).join(file_name);
|
let full_path = Path::new(&session.config_path).join(file_name);
|
||||||
let token = std::fs::read_to_string(full_path).ok();
|
let token = std::fs::read_to_string(full_path).ok();
|
||||||
@@ -246,6 +339,20 @@ where
|
|||||||
_ => 0.,
|
_ => 0.,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let interaction_transform = if output.size.0 >= output.size.1 {
|
||||||
|
Affine2::from_translation(Vec2 { x: 0.5, y: 0.5 })
|
||||||
|
* Affine2::from_scale(Vec2 {
|
||||||
|
x: 1.,
|
||||||
|
y: output.size.0 as f32 / output.size.1 as f32,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Affine2::from_translation(Vec2 { x: 0.5, y: 0.5 })
|
||||||
|
* Affine2::from_scale(Vec2 {
|
||||||
|
x: output.size.1 as f32 / output.size.0 as f32,
|
||||||
|
y: 1.,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
Some(OverlayData {
|
Some(OverlayData {
|
||||||
state: OverlayState {
|
state: OverlayState {
|
||||||
name: output.name.clone(),
|
name: output.name.clone(),
|
||||||
@@ -254,13 +361,14 @@ where
|
|||||||
show_hide: true,
|
show_hide: true,
|
||||||
grabbable: true,
|
grabbable: true,
|
||||||
spawn_rotation: Quat::from_axis_angle(axis, angle),
|
spawn_rotation: Quat::from_axis_angle(axis, angle),
|
||||||
|
interaction_transform,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
backend,
|
backend,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
warn!("{}: Will not be used", &output.name);
|
log::warn!("{}: Will not be used", &output.name);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ where
|
|||||||
let button_width = 360. / num_buttons as f32;
|
let button_width = 360. / num_buttons as f32;
|
||||||
let mut button_x = 40.;
|
let mut button_x = 40.;
|
||||||
|
|
||||||
let keyboard = canvas.button(button_x + 2., 162., button_width - 4., 36., "Kbd".into());
|
let keyboard = canvas.button(button_x + 2., 162., button_width - 4., 36., "kbd".into());
|
||||||
keyboard.state = Some(WatchButtonState {
|
keyboard.state = Some(WatchButtonState {
|
||||||
pressed_at: Instant::now(),
|
pressed_at: Instant::now(),
|
||||||
scr_idx: 0,
|
scr_idx: 0,
|
||||||
@@ -95,14 +95,14 @@ where
|
|||||||
< 2000
|
< 2000
|
||||||
{
|
{
|
||||||
app.tasks.enqueue(TaskType::Overlay(
|
app.tasks.enqueue(TaskType::Overlay(
|
||||||
OverlaySelector::Name("Kbd".into()),
|
OverlaySelector::Name("kbd".into()),
|
||||||
Box::new(|_app, o| {
|
Box::new(|_app, o| {
|
||||||
o.want_visible = !o.want_visible;
|
o.want_visible = !o.want_visible;
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
app.tasks.enqueue(TaskType::Overlay(
|
app.tasks.enqueue(TaskType::Overlay(
|
||||||
OverlaySelector::Name("Kbd".into()),
|
OverlaySelector::Name("kbd".into()),
|
||||||
Box::new(|app, o| {
|
Box::new(|app, o| {
|
||||||
o.reset(app);
|
o.reset(app);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::{env::VarError, path::Path, sync::Arc};
|
use std::{env::VarError, path::Path, sync::Arc};
|
||||||
|
|
||||||
use glam::{Quat, Vec3};
|
use glam::{Quat, Vec3};
|
||||||
use log::warn;
|
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
device::{physical::PhysicalDevice, DeviceExtensions},
|
device::{physical::PhysicalDevice, DeviceExtensions},
|
||||||
format::Format,
|
format::Format,
|
||||||
@@ -55,6 +54,7 @@ pub struct AppSession {
|
|||||||
pub screen_flip_h: bool,
|
pub screen_flip_h: bool,
|
||||||
pub screen_flip_v: bool,
|
pub screen_flip_v: bool,
|
||||||
pub screen_invert_color: bool,
|
pub screen_invert_color: bool,
|
||||||
|
pub screen_max_res: [u32; 2],
|
||||||
|
|
||||||
pub watch_hand: usize,
|
pub watch_hand: usize,
|
||||||
pub watch_pos: Vec3,
|
pub watch_pos: Vec3,
|
||||||
@@ -77,7 +77,7 @@ impl AppSession {
|
|||||||
let config_path = std::env::var("XDG_CONFIG_HOME")
|
let config_path = std::env::var("XDG_CONFIG_HOME")
|
||||||
.or_else(|_| std::env::var("HOME").map(|home| format!("{}/.config", home)))
|
.or_else(|_| std::env::var("HOME").map(|home| format!("{}/.config", home)))
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
warn!("Err: $XDG_CONFIG_HOME and $HOME are not set, using /tmp/wlxoverlay");
|
log::warn!("Err: $XDG_CONFIG_HOME and $HOME are not set, using /tmp/wlxoverlay");
|
||||||
Ok::<String, VarError>("/tmp".to_string())
|
Ok::<String, VarError>("/tmp".to_string())
|
||||||
})
|
})
|
||||||
.map(|config| Path::new(&config).join("wlxoverlay"))
|
.map(|config| Path::new(&config).join("wlxoverlay"))
|
||||||
@@ -95,6 +95,7 @@ impl AppSession {
|
|||||||
screen_flip_h: false,
|
screen_flip_h: false,
|
||||||
screen_flip_v: false,
|
screen_flip_v: false,
|
||||||
screen_invert_color: false,
|
screen_invert_color: false,
|
||||||
|
screen_max_res: [2560, 1440],
|
||||||
capture_method: "auto".to_string(),
|
capture_method: "auto".to_string(),
|
||||||
primary_hand: 1,
|
primary_hand: 1,
|
||||||
watch_hand: 1,
|
watch_hand: 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user