screens & basic interactions
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
use std::{collections::VecDeque, time::Instant};
|
||||
|
||||
use glam::{Affine3A, Vec2, Vec3A};
|
||||
use log::warn;
|
||||
use ovr_overlay::TrackedDeviceIndex;
|
||||
use tinyvec::array_vec;
|
||||
|
||||
@@ -42,6 +41,39 @@ impl<TState, THand> InputState<TState, THand> {
|
||||
|
||||
pub fn post_update(&mut self) {
|
||||
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 {
|
||||
hand.interaction.mode = PointerMode::Right;
|
||||
continue;
|
||||
@@ -176,7 +208,7 @@ pub enum PointerMode {
|
||||
}
|
||||
|
||||
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
|
||||
O: Default,
|
||||
{
|
||||
@@ -184,10 +216,10 @@ impl<THand> Pointer<THand> {
|
||||
if let Some(grabbed) = overlays.mut_by_id(grab_data.grabbed_id) {
|
||||
self.handle_grabbed(grabbed, grab_data.offset);
|
||||
} 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;
|
||||
}
|
||||
return;
|
||||
return grab_data.offset.length(); // grab interaction
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
return;
|
||||
return 0.0; // no hit
|
||||
};
|
||||
|
||||
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 {
|
||||
warn!("Hit overlay {} does not exist", hit.overlay);
|
||||
return;
|
||||
log::warn!("Hit overlay {} does not exist", hit.overlay);
|
||||
return 0.0; // no hit
|
||||
};
|
||||
|
||||
self.interaction.hovered_id = Some(hit.overlay);
|
||||
|
||||
if let Some(primary_pointer) = hovered.primary_pointer {
|
||||
if hit.pointer < primary_pointer {
|
||||
if hit.pointer <= primary_pointer {
|
||||
hovered.primary_pointer = Some(hit.pointer);
|
||||
hit.primary = true;
|
||||
}
|
||||
@@ -237,6 +269,14 @@ impl<THand> Pointer<THand> {
|
||||
hovered.primary_pointer = Some(hit.pointer);
|
||||
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);
|
||||
|
||||
if self.now.scroll.abs() > 0.1 {
|
||||
@@ -255,6 +295,7 @@ impl<THand> Pointer<THand> {
|
||||
hovered.backend.on_pointer(app, &hit, false);
|
||||
}
|
||||
}
|
||||
hit.dist
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
for hit in hits.iter() {
|
||||
let uv = overlays
|
||||
.get_by_id(hit.overlay)
|
||||
.unwrap() // this is safe
|
||||
let overlay = overlays.get_by_id(hit.overlay).unwrap(); // this is safe
|
||||
|
||||
let uv = overlay
|
||||
.state
|
||||
.transform
|
||||
.inverse()
|
||||
.transform_point3a(hit.hit_pos)
|
||||
.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 {
|
||||
continue;
|
||||
}
|
||||
@@ -315,7 +358,9 @@ impl<THand> Pointer<THand> {
|
||||
offset,
|
||||
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)
|
||||
where
|
||||
O: Default,
|
||||
@@ -324,7 +369,7 @@ impl<THand> Pointer<THand> {
|
||||
overlay.state.transform.translation = self.pose.transform_point3a(offset);
|
||||
|
||||
if self.now.click && !self.before.click {
|
||||
warn!("todo: click-while-grabbed");
|
||||
log::warn!("todo: click-while-grabbed");
|
||||
}
|
||||
|
||||
match self.interaction.mode {
|
||||
@@ -339,11 +384,14 @@ impl<THand> Pointer<THand> {
|
||||
.mul_scalar(1.0 + 0.01 * self.now.scroll);
|
||||
}
|
||||
}
|
||||
overlay.state.dirty = true;
|
||||
} else {
|
||||
overlay.state.spawn_point = overlay.state.transform.translation;
|
||||
self.interaction.grabbed = None;
|
||||
log::info!("Hand {}: dropped {}", self.idx, overlay.state.name);
|
||||
}
|
||||
}
|
||||
|
||||
fn ray_test(&self, overlay: usize, plane: &Affine3A) -> Option<RayHit> {
|
||||
let plane_normal = plane.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) line_id: usize,
|
||||
has_pose: bool,
|
||||
input_hnd: InputValueHandle,
|
||||
pose_hnd: ActionHandle,
|
||||
@@ -103,6 +104,7 @@ impl InputState<OpenVrInputState, OpenVrHandState> {
|
||||
pose: Affine3A::IDENTITY,
|
||||
interaction: InteractionState::default(),
|
||||
data: OpenVrHandState {
|
||||
line_id: 0,
|
||||
has_pose: false,
|
||||
input_hnd: input_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::{
|
||||
collections::VecDeque,
|
||||
path::Path,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use log::{error, info};
|
||||
use ovr_overlay::{
|
||||
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
|
||||
TrackedDeviceIndex,
|
||||
@@ -15,7 +14,7 @@ use vulkano::{
|
||||
Handle, VulkanObject,
|
||||
};
|
||||
|
||||
use crate::state::AppState;
|
||||
use crate::{backend::openvr::lines::LinePool, state::AppState};
|
||||
|
||||
use self::{input::action_manifest_path, overlay::OpenVrOverlayData};
|
||||
|
||||
@@ -25,12 +24,13 @@ use super::{
|
||||
};
|
||||
|
||||
pub mod input;
|
||||
pub mod lines;
|
||||
pub mod overlay;
|
||||
|
||||
pub fn openvr_run() {
|
||||
let app_type = EVRApplicationType::VRApplication_Overlay;
|
||||
let Ok(context) = ovr_overlay::Context::init(app_type) else {
|
||||
error!("Failed to initialize OpenVR");
|
||||
log::error!("Failed to initialize OpenVR");
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -56,12 +56,12 @@ pub fn openvr_run() {
|
||||
let mut overlays = OverlayContainer::<OpenVrOverlayData>::new(&mut state);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
let Ok(mut input) = InputState::new(&mut input_mngr) else {
|
||||
error!("Failed to initialize input");
|
||||
log::error!("Failed to initialize input");
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -69,21 +69,25 @@ pub fn openvr_run() {
|
||||
TrackedDeviceIndex::HMD,
|
||||
ETrackedDeviceProperty::Prop_DisplayFrequency_Float,
|
||||
) else {
|
||||
error!("Failed to get display refresh rate");
|
||||
log::error!("Failed to get display refresh rate");
|
||||
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 mut next_device_update = Instant::now();
|
||||
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 {
|
||||
while let Some(event) = system_mngr.poll_next_event() {
|
||||
match event.event_type {
|
||||
EVREventType::VREvent_Quit => {
|
||||
info!("Received quit event, shutting down.");
|
||||
log::info!("Received quit event, shutting down.");
|
||||
return;
|
||||
}
|
||||
EVREventType::VREvent_TrackedDeviceActivated
|
||||
@@ -93,64 +97,73 @@ pub fn openvr_run() {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if next_device_update <= Instant::now() {
|
||||
input.update_devices(&mut system_mngr);
|
||||
next_device_update = Instant::now() + Duration::from_secs(30);
|
||||
}
|
||||
if next_device_update <= Instant::now() {
|
||||
input.update_devices(&mut system_mngr);
|
||||
next_device_update = Instant::now() + Duration::from_secs(30);
|
||||
}
|
||||
|
||||
state.tasks.retrieve_due(&mut due_tasks);
|
||||
while let Some(task) = due_tasks.pop_front() {
|
||||
match task {
|
||||
TaskType::Global(f) => f(&mut state),
|
||||
TaskType::Overlay(sel, f) => {
|
||||
if let Some(o) = overlays.mut_by_selector(&sel) {
|
||||
f(&mut state, &mut o.state);
|
||||
}
|
||||
state.tasks.retrieve_due(&mut due_tasks);
|
||||
while let Some(task) = due_tasks.pop_front() {
|
||||
match task {
|
||||
TaskType::Global(f) => f(&mut state),
|
||||
TaskType::Overlay(sel, f) => {
|
||||
if let Some(o) = overlays.mut_by_selector(&sel) {
|
||||
f(&mut state, &mut o.state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.pre_update();
|
||||
input.update(&mut input_mngr, &mut system_mngr);
|
||||
input.post_update();
|
||||
|
||||
input
|
||||
.pointers
|
||||
.iter_mut()
|
||||
.for_each(|p| p.interact(&mut overlays, &mut state));
|
||||
|
||||
overlays
|
||||
.iter_mut()
|
||||
.for_each(|o| o.after_input(&mut overlay_mngr, &mut state));
|
||||
|
||||
log::debug!("Rendering frame");
|
||||
|
||||
overlays
|
||||
.iter_mut()
|
||||
.filter(|o| o.state.want_visible)
|
||||
.for_each(|o| o.render(&mut state));
|
||||
|
||||
log::debug!("Rendering overlays");
|
||||
|
||||
overlays
|
||||
.iter_mut()
|
||||
.for_each(|o| o.after_render(&mut overlay_mngr, &state.graphics));
|
||||
|
||||
// chaperone
|
||||
|
||||
// close font handles?
|
||||
|
||||
// playspace moved end frame
|
||||
|
||||
let mut seconds_since_vsync = 0f32;
|
||||
std::thread::sleep(Duration::from_secs_f32(
|
||||
if system_mngr.get_time_since_last_vsync(&mut seconds_since_vsync, &mut 0u64) {
|
||||
(frame_time - seconds_since_vsync).max(0.0)
|
||||
} else {
|
||||
0.011
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
input.pre_update();
|
||||
input.update(&mut input_mngr, &mut system_mngr);
|
||||
input.post_update();
|
||||
|
||||
input.pointers.iter_mut().for_each(|p| {
|
||||
let dist = p.interact(&mut overlays, &mut state);
|
||||
if dist > 0.001 {
|
||||
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
|
||||
.iter_mut()
|
||||
.for_each(|o| o.after_input(&mut overlay_mngr, &mut state));
|
||||
|
||||
log::debug!("Rendering frame");
|
||||
|
||||
overlays
|
||||
.iter_mut()
|
||||
.filter(|o| o.state.want_visible)
|
||||
.for_each(|o| o.render(&mut state));
|
||||
|
||||
log::debug!("Rendering overlays");
|
||||
|
||||
overlays
|
||||
.iter_mut()
|
||||
.for_each(|o| o.after_render(&mut overlay_mngr, &state.graphics));
|
||||
|
||||
// chaperone
|
||||
|
||||
// close font handles?
|
||||
|
||||
// playspace moved end frame
|
||||
|
||||
state.input.on_new_frame();
|
||||
|
||||
let mut seconds_since_vsync = 0f32;
|
||||
std::thread::sleep(Duration::from_secs_f32(
|
||||
if system_mngr.get_time_since_last_vsync(&mut seconds_since_vsync, &mut 0u64) {
|
||||
frame_time - (seconds_since_vsync % frame_time)
|
||||
} else {
|
||||
frame_time
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,11 @@ use ovr_overlay::{
|
||||
};
|
||||
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)]
|
||||
pub(super) struct OpenVrOverlayData {
|
||||
@@ -16,10 +20,11 @@ pub(super) struct OpenVrOverlayData {
|
||||
pub(super) color: Vec4,
|
||||
pub(super) curvature: f32,
|
||||
pub(super) sort_order: u32,
|
||||
pub(super) relative_to: RelativeTo,
|
||||
}
|
||||
|
||||
impl OverlayData<OpenVrOverlayData> {
|
||||
pub fn initialize(
|
||||
pub(super) fn initialize(
|
||||
&mut self,
|
||||
overlay: &mut OverlayManager,
|
||||
app: &mut AppState,
|
||||
@@ -33,6 +38,11 @@ impl OverlayData<OpenVrOverlayData> {
|
||||
};
|
||||
log::debug!("{}: initialize", self.state.name);
|
||||
|
||||
//watch
|
||||
if self.state.id == 0 {
|
||||
self.data.sort_order = 68;
|
||||
}
|
||||
|
||||
self.data.handle = Some(handle);
|
||||
self.data.color = Vec4::ONE;
|
||||
|
||||
@@ -41,11 +51,12 @@ impl OverlayData<OpenVrOverlayData> {
|
||||
self.upload_width(overlay);
|
||||
self.upload_color(overlay);
|
||||
self.upload_curvature(overlay);
|
||||
self.upload_sort_order(overlay);
|
||||
|
||||
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 {
|
||||
self.show(overlay, app);
|
||||
} 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 {
|
||||
self.upload_transform(overlay);
|
||||
if self.state.dirty {
|
||||
self.upload_transform(overlay);
|
||||
self.state.dirty = false;
|
||||
}
|
||||
self.upload_texture(overlay, graphics);
|
||||
}
|
||||
}
|
||||
@@ -83,7 +97,7 @@ impl OverlayData<OpenVrOverlayData> {
|
||||
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 {
|
||||
log::debug!("{}: No overlay handle", self.state.name);
|
||||
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 {
|
||||
log::debug!("{}: No overlay handle", self.state.name);
|
||||
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 {
|
||||
log::debug!("{}: No overlay handle", self.state.name);
|
||||
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 {
|
||||
log::debug!("{}: No overlay handle", self.state.name);
|
||||
return;
|
||||
@@ -210,8 +224,13 @@ impl OverlayData<OpenVrOverlayData> {
|
||||
m_nQueueFamilyIndex: graphics.queue.queue_family_index(),
|
||||
};
|
||||
|
||||
log::info!("Usages: {:?}", image.usage());
|
||||
log::info!("nImage: {}, nFormat: {:?}, nWidth: {}, nHeight: {}, nSampleCount: {}, nQueueFamilyIndex: {}", texture.m_nImage, format, texture.m_nWidth, texture.m_nHeight, texture.m_nSampleCount, texture.m_nQueueFamilyIndex);
|
||||
log::debug!(
|
||||
"UploadTex: {:?}, {}x{}, {:?}",
|
||||
format,
|
||||
texture.m_nWidth,
|
||||
texture.m_nHeight,
|
||||
image.usage()
|
||||
);
|
||||
if let Err(e) = overlay.set_image_vulkan(handle, &mut texture) {
|
||||
panic!("Failed to set overlay texture: {}", e);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::sync::{
|
||||
Arc,
|
||||
};
|
||||
|
||||
use glam::{Affine3A, Quat, Vec3A};
|
||||
use glam::{Affine2, Affine3A, Quat, Vec3A};
|
||||
use vulkano::image::ImageViewAbstract;
|
||||
|
||||
use crate::state::AppState;
|
||||
@@ -22,12 +22,13 @@ pub struct OverlayState {
|
||||
pub want_visible: bool,
|
||||
pub show_hide: bool,
|
||||
pub grabbable: bool,
|
||||
pub dirty: bool,
|
||||
pub transform: Affine3A,
|
||||
pub spawn_point: Vec3A,
|
||||
pub spawn_rotation: Quat,
|
||||
pub relative_to: RelativeTo,
|
||||
pub primary_pointer: Option<usize>,
|
||||
pub interaction_transform: Affine3A,
|
||||
pub interaction_transform: Affine2,
|
||||
}
|
||||
|
||||
impl Default for OverlayState {
|
||||
@@ -40,12 +41,13 @@ impl Default for OverlayState {
|
||||
want_visible: false,
|
||||
show_hide: false,
|
||||
grabbable: false,
|
||||
dirty: false,
|
||||
relative_to: RelativeTo::None,
|
||||
spawn_point: Vec3A::NEG_Z,
|
||||
spawn_rotation: Quat::IDENTITY,
|
||||
transform: Affine3A::IDENTITY,
|
||||
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 render(&mut self, _app: &mut AppState) {}
|
||||
fn view(&mut self) -> Option<Arc<dyn ImageViewAbstract>> {
|
||||
unimplemented!()
|
||||
None
|
||||
}
|
||||
}
|
||||
// Boilerplate and dummies
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub enum RelativeTo {
|
||||
#[default]
|
||||
None,
|
||||
Head,
|
||||
Hand(usize),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::{error::Error, io::Cursor, slice::Iter, sync::Arc};
|
||||
|
||||
use ash::vk::SubmitInfo;
|
||||
use log::{debug, error, info};
|
||||
use smallvec::smallvec;
|
||||
use vulkano::{
|
||||
buffer::{
|
||||
@@ -28,9 +27,9 @@ use vulkano::{
|
||||
},
|
||||
format::Format,
|
||||
image::{
|
||||
sys::Image, AttachmentImage, ImageAccess, ImageCreateFlags, ImageDimensions, ImageError,
|
||||
ImageLayout, ImageUsage, ImageViewAbstract, ImmutableImage, MipmapsCount, StorageImage,
|
||||
SubresourceData, SwapchainImage,
|
||||
sys::Image, AttachmentImage, ImageCreateFlags, ImageDimensions, ImageError, ImageLayout,
|
||||
ImageUsage, ImageViewAbstract, ImmutableImage, MipmapsCount, StorageImage, SubresourceData,
|
||||
SwapchainImage,
|
||||
},
|
||||
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||
@@ -49,8 +48,8 @@ use vulkano::{
|
||||
shader::ShaderModule,
|
||||
swapchain::{CompositeAlpha, Surface, Swapchain, SwapchainCreateInfo},
|
||||
sync::{
|
||||
fence::Fence, future::NowFuture, AccessFlags, DependencyInfo, ImageMemoryBarrier,
|
||||
PipelineStages,
|
||||
fence::Fence, future::NowFuture, AccessFlags, DependencyInfo, GpuFuture,
|
||||
ImageMemoryBarrier, PipelineStages,
|
||||
},
|
||||
Version, VulkanLibrary, VulkanObject,
|
||||
};
|
||||
@@ -103,8 +102,8 @@ impl WlxGraphics {
|
||||
let library_extensions = vulkano_win::required_extensions(&library);
|
||||
let required_extensions = library_extensions.union(&vk_instance_extensions);
|
||||
|
||||
debug!("Instance exts for app: {:?}", &required_extensions);
|
||||
debug!("Instance exts for runtime: {:?}", &vk_instance_extensions);
|
||||
log::debug!("Instance exts for app: {:?}", &required_extensions);
|
||||
log::debug!("Instance exts for runtime: {:?}", &vk_instance_extensions);
|
||||
|
||||
let instance = Instance::new(
|
||||
library,
|
||||
@@ -126,7 +125,7 @@ impl WlxGraphics {
|
||||
..DeviceExtensions::empty()
|
||||
};
|
||||
|
||||
debug!("Device exts for app: {:?}", &device_extensions);
|
||||
log::debug!("Device exts for app: {:?}", &device_extensions);
|
||||
|
||||
// TODO headless
|
||||
let event_loop = EventLoop::new();
|
||||
@@ -142,7 +141,7 @@ impl WlxGraphics {
|
||||
})
|
||||
.filter_map(|p| {
|
||||
let runtime_extensions = vk_device_extensions_fn(&p);
|
||||
debug!(
|
||||
log::debug!(
|
||||
"Device exts for {}: {:?}",
|
||||
p.properties().device_name,
|
||||
&runtime_extensions
|
||||
@@ -174,7 +173,7 @@ impl WlxGraphics {
|
||||
})
|
||||
.expect("no suitable physical device found");
|
||||
|
||||
info!(
|
||||
log::info!(
|
||||
"Using vkPhysicalDevice: {}",
|
||||
physical_device.properties().device_name,
|
||||
);
|
||||
@@ -271,6 +270,7 @@ impl WlxGraphics {
|
||||
(Arc::new(me), event_loop)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn create_swapchain(
|
||||
&self,
|
||||
format: Option<Format>,
|
||||
@@ -541,32 +541,7 @@ pub struct WlxCommandBuffer<T> {
|
||||
}
|
||||
|
||||
impl<T> WlxCommandBuffer<T> {
|
||||
pub fn inner(&self) -> &AutoCommandBufferBuilder<T, Arc<StandardCommandBufferAllocator>> {
|
||||
&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;
|
||||
}
|
||||
|
||||
pub fn begin(mut self, render_target: Arc<dyn ImageViewAbstract>) -> Self {
|
||||
self.command_buffer
|
||||
.begin_rendering(RenderingInfo {
|
||||
contents: SubpassContents::SecondaryCommandBuffers,
|
||||
@@ -590,13 +565,6 @@ impl<T> WlxCommandBuffer<T> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn run(mut self, pass: &WlxPass) -> Self {
|
||||
let _ = self
|
||||
.command_buffer
|
||||
.execute_commands(pass.command_buffer.clone());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn texture2d(
|
||||
&mut self,
|
||||
width: u32,
|
||||
@@ -614,13 +582,14 @@ impl<T> WlxCommandBuffer<T> {
|
||||
&self.graphics.memory_allocator,
|
||||
data,
|
||||
dimensions,
|
||||
MipmapsCount::One,
|
||||
MipmapsCount::Log2, // required for TRANSFER_SRC
|
||||
format,
|
||||
&mut self.command_buffer,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn texture2d_png(&mut self, bytes: Vec<u8>) -> Arc<ImmutableImage> {
|
||||
let cursor = Cursor::new(bytes);
|
||||
let decoder = png::Decoder::new(cursor);
|
||||
@@ -636,32 +605,24 @@ impl<T> WlxCommandBuffer<T> {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
pub fn end_render(self) -> PrimaryAutoCommandBuffer {
|
||||
let mut buf = self.command_buffer;
|
||||
buf.end_rendering().unwrap();
|
||||
|
||||
buf.build().unwrap()
|
||||
}
|
||||
|
||||
pub fn end(self) -> PrimaryAutoCommandBuffer {
|
||||
pub fn build(self) -> PrimaryAutoCommandBuffer {
|
||||
self.command_buffer.build().unwrap()
|
||||
}
|
||||
|
||||
pub fn end_render_and_execute(self) -> CommandBufferExecFuture<NowFuture> {
|
||||
let mut buf = self.command_buffer;
|
||||
buf.end_rendering().unwrap();
|
||||
let buf = buf.build().unwrap();
|
||||
buf.execute(self.graphics.queue.clone()).unwrap()
|
||||
pub fn build_and_execute(self) -> CommandBufferExecFuture<NowFuture> {
|
||||
let queue = self.graphics.queue.clone();
|
||||
self.build().execute(queue).unwrap()
|
||||
}
|
||||
|
||||
pub fn end_and_execute(self) -> CommandBufferExecFuture<NowFuture> {
|
||||
let buf = self.command_buffer;
|
||||
let buf = buf.build().unwrap();
|
||||
buf.execute(self.graphics.queue.clone()).unwrap()
|
||||
pub fn build_and_execute_now(self) {
|
||||
let mut exec = self.build_and_execute();
|
||||
exec.flush().unwrap();
|
||||
exec.cleanup_finished();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -705,10 +666,6 @@ impl WlxPipeline {
|
||||
self.pipeline.clone()
|
||||
}
|
||||
|
||||
pub fn graphics(&self) -> Arc<WlxGraphics> {
|
||||
self.graphics.clone()
|
||||
}
|
||||
|
||||
pub fn uniform_sampler(
|
||||
&self,
|
||||
set: usize,
|
||||
@@ -780,6 +737,7 @@ impl WlxPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct WlxPass {
|
||||
pipeline: Arc<WlxPipeline>,
|
||||
vertex_buffer: Subbuffer<[Vert2Uv]>,
|
||||
@@ -833,7 +791,7 @@ impl WlxPass {
|
||||
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)
|
||||
.or_else(|err| {
|
||||
if let Some(source) = err.source() {
|
||||
error!("Failed to draw: {}", source);
|
||||
log::error!("Failed to draw: {}", source);
|
||||
}
|
||||
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 freetype::{bitmap::PixelMode, face::LoadFlag, Face, Library};
|
||||
use idmap::IdMap;
|
||||
use log::debug;
|
||||
use vulkano::{command_buffer::CommandBufferUsage, format::Format, image::ImmutableImage};
|
||||
|
||||
use crate::graphics::WlxGraphics;
|
||||
@@ -116,7 +115,7 @@ impl FontCache {
|
||||
let pattern = pattern.font_match(&mut self.fc);
|
||||
|
||||
if let Some(path) = pattern.filename() {
|
||||
debug!(
|
||||
log::debug!(
|
||||
"Loading font: {} {}pt",
|
||||
pattern.name().unwrap_or(path),
|
||||
size
|
||||
@@ -203,7 +202,7 @@ impl FontCache {
|
||||
|
||||
let mut cmd_buffer = graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit);
|
||||
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 {
|
||||
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
|
||||
#[allow(dead_code)]
|
||||
pub fn label_centered(
|
||||
&mut self,
|
||||
x: f32,
|
||||
@@ -320,13 +321,13 @@ impl<D, S> Canvas<D, S> {
|
||||
.canvas
|
||||
.graphics
|
||||
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
||||
.begin(self.view_bg.clone(), None);
|
||||
.begin(self.view_bg.clone());
|
||||
for c in self.controls.iter_mut() {
|
||||
if let Some(fun) = c.on_render_bg {
|
||||
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) {
|
||||
@@ -334,17 +335,13 @@ impl<D, S> Canvas<D, S> {
|
||||
.canvas
|
||||
.graphics
|
||||
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
||||
.begin(self.view_fg.clone(), None);
|
||||
.begin(self.view_fg.clone());
|
||||
for c in self.controls.iter_mut() {
|
||||
if let Some(fun) = c.on_render_fg {
|
||||
fun(c, &self.canvas, app, &mut cmd_buffer);
|
||||
}
|
||||
}
|
||||
let _ = cmd_buffer.end_render_and_execute();
|
||||
}
|
||||
|
||||
pub fn render_view(&self) -> Arc<ImageView<AttachmentImage>> {
|
||||
self.view_final.clone()
|
||||
cmd_buffer.end_render().build_and_execute_now()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +382,6 @@ impl<D, S> InteractionHandler for Canvas<D, S> {
|
||||
impl<D, S> OverlayRenderer for Canvas<D, S> {
|
||||
fn init(&mut self, app: &mut AppState) {
|
||||
self.render_bg(app);
|
||||
|
||||
self.render_fg(app);
|
||||
}
|
||||
fn pause(&mut self, _app: &mut AppState) {}
|
||||
@@ -423,10 +419,7 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
|
||||
.canvas
|
||||
.graphics
|
||||
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
||||
.begin(
|
||||
self.view_final.clone(),
|
||||
Some(ImageLayout::TransferSrcOptimal),
|
||||
);
|
||||
.begin(self.view_final.clone());
|
||||
|
||||
if dirty {
|
||||
self.render_fg(app);
|
||||
@@ -451,7 +444,7 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
|
||||
// mostly static text
|
||||
cmd_buffer.run_ref(&self.pass_fg);
|
||||
{
|
||||
let _ = cmd_buffer.end_render_and_execute();
|
||||
let _ = cmd_buffer.end_render().build_and_execute();
|
||||
}
|
||||
self.canvas
|
||||
.graphics
|
||||
@@ -478,7 +471,6 @@ pub struct Control<D, S> {
|
||||
text: Arc<str>,
|
||||
size: isize,
|
||||
dirty: bool,
|
||||
pass_hl: Option<(WlxPass, WlxPass)>,
|
||||
|
||||
pub on_update: 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,
|
||||
on_press: None,
|
||||
on_release: None,
|
||||
pass_hl: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,11 +528,6 @@ impl<D, S> Control<D, S> {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_text(&self) -> &str {
|
||||
&self.text
|
||||
}
|
||||
|
||||
fn render_rect(
|
||||
&self,
|
||||
canvas: &CanvasData<D>,
|
||||
|
||||
21
src/input.rs
21
src/input.rs
@@ -6,7 +6,6 @@ use input_linux::{
|
||||
UInputHandle,
|
||||
};
|
||||
use libc::{input_event, timeval};
|
||||
use log::{error, info};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::fs::File;
|
||||
use std::mem::transmute;
|
||||
@@ -14,11 +13,11 @@ use strum::{EnumIter, EnumString, IntoEnumIterator};
|
||||
|
||||
pub fn initialize_input() -> Box<dyn InputProvider> {
|
||||
if let Some(uinput) = UInputProvider::try_new() {
|
||||
info!("Initialized uinput.");
|
||||
log::info!("Initialized uinput.");
|
||||
return Box::new(uinput);
|
||||
}
|
||||
error!("Could not create uinput provider. Keyboard/Mouse input will not work!");
|
||||
error!("Check if you're in `input` group: `id -nG`");
|
||||
log::error!("Could not create uinput provider. Keyboard/Mouse input will not work!");
|
||||
log::error!("Check if you're in `input` group: `id -nG`");
|
||||
Box::new(DummyProvider {})
|
||||
}
|
||||
|
||||
@@ -64,7 +63,7 @@ impl UInputProvider {
|
||||
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![
|
||||
AbsoluteInfoSetup {
|
||||
@@ -145,6 +144,8 @@ impl InputProvider for UInputProvider {
|
||||
}
|
||||
self.mouse_moved = true;
|
||||
|
||||
log::info!("Mouse move: {:?}", pos);
|
||||
|
||||
let pos = pos * (MOUSE_EXTENT / self.desktop_extent);
|
||||
|
||||
let time = get_time();
|
||||
@@ -154,7 +155,7 @@ impl InputProvider for UInputProvider {
|
||||
new_event(time, EV_SYN, 0, 0),
|
||||
];
|
||||
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) {
|
||||
@@ -164,7 +165,7 @@ impl InputProvider for UInputProvider {
|
||||
new_event(time, EV_SYN, 0, 0),
|
||||
];
|
||||
if let Err(res) = self.handle.write(&events) {
|
||||
error!("{}", res.to_string());
|
||||
log::error!("send_button: {}", res.to_string());
|
||||
}
|
||||
}
|
||||
fn wheel(&self, delta: i32) {
|
||||
@@ -174,7 +175,7 @@ impl InputProvider for UInputProvider {
|
||||
new_event(time, EV_SYN, 0, 0),
|
||||
];
|
||||
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) {
|
||||
@@ -195,11 +196,11 @@ impl InputProvider for UInputProvider {
|
||||
new_event(time, EV_SYN, 0, 0),
|
||||
];
|
||||
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) {
|
||||
info!("Desktop extent: {:?}", extent);
|
||||
log::info!("Desktop extent: {:?}", extent);
|
||||
self.desktop_extent = extent;
|
||||
}
|
||||
fn on_new_frame(&mut self) {
|
||||
|
||||
@@ -9,11 +9,10 @@ mod state;
|
||||
|
||||
use crate::backend::openvr::openvr_run;
|
||||
use env_logger::Env;
|
||||
use log::info;
|
||||
|
||||
fn main() {
|
||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||
info!(
|
||||
log::info!(
|
||||
"Welcome to {} version {}!",
|
||||
env!("CARGO_PKG_NAME"),
|
||||
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,
|
||||
};
|
||||
use glam::{vec2, vec3a};
|
||||
use log::error;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use rodio::{Decoder, OutputStream, Source};
|
||||
@@ -88,7 +87,7 @@ where
|
||||
args: exec_args.iter().skip(1).cloned().collect(),
|
||||
});
|
||||
} else {
|
||||
error!("Unknown key: {}", key);
|
||||
log::error!("Unknown key: {}", key);
|
||||
}
|
||||
|
||||
if let Some(state) = maybe_state {
|
||||
@@ -109,7 +108,7 @@ where
|
||||
|
||||
OverlayData {
|
||||
state: OverlayState {
|
||||
name: Arc::from("Kbd"),
|
||||
name: Arc::from("kbd"),
|
||||
show_hide: true,
|
||||
width: LAYOUT.row_size * 0.05,
|
||||
size: (size.x as _, size.y as _),
|
||||
@@ -217,7 +216,7 @@ impl KeyboardData {
|
||||
let _ = handle.play_raw(source.convert_samples());
|
||||
self.audio_stream = Some(stream);
|
||||
} 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" {
|
||||
key_events.push((virtual_key, true));
|
||||
} else {
|
||||
error!(
|
||||
log::error!(
|
||||
"Unknown key state in macro: {}, looking for UP or DOWN.",
|
||||
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));
|
||||
}
|
||||
} else {
|
||||
error!("Unknown virtual key: {}", &caps[1]);
|
||||
log::error!("Unknown virtual key: {}", &caps[1]);
|
||||
return vec![];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use log::{info, warn};
|
||||
use std::{
|
||||
f32::consts::PI,
|
||||
path::Path,
|
||||
@@ -6,9 +5,14 @@ use std::{
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use vulkano::{
|
||||
buffer::Subbuffer,
|
||||
command_buffer::CommandBufferUsage,
|
||||
format::Format,
|
||||
image::{view::ImageView, ImageAccess, ImageLayout, ImageViewAbstract, ImmutableImage},
|
||||
image::{
|
||||
view::ImageView, AttachmentImage, ImageAccess, ImageLayout, ImageViewAbstract, StorageImage,
|
||||
},
|
||||
sampler::Filter,
|
||||
sync::GpuFuture,
|
||||
Handle, VulkanObject,
|
||||
};
|
||||
use wlx_capture::{
|
||||
@@ -26,7 +30,9 @@ use crate::{
|
||||
input::{InteractionHandler, PointerHit, PointerMode},
|
||||
overlay::{OverlayData, OverlayRenderer, OverlayState, SplitOverlayBackend},
|
||||
},
|
||||
graphics::{Vert2Uv, WlxGraphics, WlxPipeline},
|
||||
input::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT},
|
||||
shaders::{frag_sprite, vert_common},
|
||||
state::{AppSession, AppState},
|
||||
};
|
||||
|
||||
@@ -66,6 +72,7 @@ impl ScreenInteractionHandler {
|
||||
|
||||
impl InteractionHandler for ScreenInteractionHandler {
|
||||
fn on_hover(&mut self, app: &mut AppState, hit: &PointerHit) {
|
||||
log::info!("Hover: {:?}", hit.uv);
|
||||
if self.next_move < Instant::now() {
|
||||
let pos = self.mouse_transform.transform_point2(hit.uv);
|
||||
app.input.mouse_move(pos);
|
||||
@@ -82,7 +89,8 @@ impl InteractionHandler for ScreenInteractionHandler {
|
||||
};
|
||||
|
||||
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);
|
||||
@@ -97,11 +105,106 @@ impl InteractionHandler for ScreenInteractionHandler {
|
||||
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 {
|
||||
capture: Box<dyn WlxCapture>,
|
||||
resolution: (i32, i32),
|
||||
receiver: Option<Receiver<WlxFrame>>,
|
||||
view: Option<Arc<dyn ImageViewAbstract>>,
|
||||
pipeline: Option<ScreenPipeline>,
|
||||
last_frame: Option<Arc<dyn ImageViewAbstract>>,
|
||||
}
|
||||
|
||||
impl ScreenRenderer {
|
||||
@@ -114,9 +217,9 @@ impl ScreenRenderer {
|
||||
};
|
||||
Some(ScreenRenderer {
|
||||
capture: Box::new(capture),
|
||||
resolution: output.size,
|
||||
receiver: None,
|
||||
view: None,
|
||||
pipeline: None,
|
||||
last_frame: None,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -132,15 +235,11 @@ impl ScreenRenderer {
|
||||
|
||||
Some(ScreenRenderer {
|
||||
capture: Box::new(capture),
|
||||
resolution: output.size,
|
||||
receiver: None,
|
||||
view: None,
|
||||
pipeline: None,
|
||||
last_frame: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_xshm() -> ScreenRenderer {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl OverlayRenderer for ScreenRenderer {
|
||||
@@ -157,28 +256,18 @@ impl OverlayRenderer for ScreenRenderer {
|
||||
match frame {
|
||||
WlxFrame::Dmabuf(frame) => {
|
||||
if let Ok(new) = app.graphics.dmabuf_texture(frame) {
|
||||
if let Some(current) = self.view.as_ref() {
|
||||
if current.image().inner().image.handle().as_raw()
|
||||
== new.inner().image.handle().as_raw()
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
app.graphics
|
||||
.transition_layout(
|
||||
new.inner().image.clone(),
|
||||
ImageLayout::Undefined,
|
||||
ImageLayout::TransferSrcOptimal,
|
||||
)
|
||||
.wait(None)
|
||||
.unwrap();
|
||||
self.view = Some(ImageView::new_default(new).unwrap());
|
||||
let pipeline = self
|
||||
.pipeline
|
||||
.get_or_insert_with(|| ScreenPipeline::new(app.graphics.clone(), &new));
|
||||
|
||||
pipeline.render(new);
|
||||
self.last_frame = Some(pipeline.view.clone());
|
||||
}
|
||||
}
|
||||
WlxFrame::MemFd(frame) => {
|
||||
WlxFrame::MemFd(_frame) => {
|
||||
todo!()
|
||||
}
|
||||
WlxFrame::MemPtr(frame) => {
|
||||
WlxFrame::MemPtr(_frame) => {
|
||||
todo!()
|
||||
}
|
||||
_ => {}
|
||||
@@ -193,7 +282,7 @@ impl OverlayRenderer for ScreenRenderer {
|
||||
self.capture.resume();
|
||||
}
|
||||
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,
|
||||
{
|
||||
let output = &wl.outputs[idx];
|
||||
info!(
|
||||
log::info!(
|
||||
"{}: 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 mut capture: Option<ScreenRenderer> = None;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 full_path = Path::new(&session.config_path).join(file_name);
|
||||
let token = std::fs::read_to_string(full_path).ok();
|
||||
@@ -246,6 +339,20 @@ where
|
||||
_ => 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 {
|
||||
state: OverlayState {
|
||||
name: output.name.clone(),
|
||||
@@ -254,13 +361,14 @@ where
|
||||
show_hide: true,
|
||||
grabbable: true,
|
||||
spawn_rotation: Quat::from_axis_angle(axis, angle),
|
||||
interaction_transform,
|
||||
..Default::default()
|
||||
},
|
||||
backend,
|
||||
..Default::default()
|
||||
})
|
||||
} else {
|
||||
warn!("{}: Will not be used", &output.name);
|
||||
log::warn!("{}: Will not be used", &output.name);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ where
|
||||
let button_width = 360. / num_buttons as f32;
|
||||
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 {
|
||||
pressed_at: Instant::now(),
|
||||
scr_idx: 0,
|
||||
@@ -95,14 +95,14 @@ where
|
||||
< 2000
|
||||
{
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
OverlaySelector::Name("Kbd".into()),
|
||||
OverlaySelector::Name("kbd".into()),
|
||||
Box::new(|_app, o| {
|
||||
o.want_visible = !o.want_visible;
|
||||
}),
|
||||
));
|
||||
} else {
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
OverlaySelector::Name("Kbd".into()),
|
||||
OverlaySelector::Name("kbd".into()),
|
||||
Box::new(|app, o| {
|
||||
o.reset(app);
|
||||
}),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::{env::VarError, path::Path, sync::Arc};
|
||||
|
||||
use glam::{Quat, Vec3};
|
||||
use log::warn;
|
||||
use vulkano::{
|
||||
device::{physical::PhysicalDevice, DeviceExtensions},
|
||||
format::Format,
|
||||
@@ -55,6 +54,7 @@ pub struct AppSession {
|
||||
pub screen_flip_h: bool,
|
||||
pub screen_flip_v: bool,
|
||||
pub screen_invert_color: bool,
|
||||
pub screen_max_res: [u32; 2],
|
||||
|
||||
pub watch_hand: usize,
|
||||
pub watch_pos: Vec3,
|
||||
@@ -77,7 +77,7 @@ impl AppSession {
|
||||
let config_path = std::env::var("XDG_CONFIG_HOME")
|
||||
.or_else(|_| std::env::var("HOME").map(|home| format!("{}/.config", home)))
|
||||
.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())
|
||||
})
|
||||
.map(|config| Path::new(&config).join("wlxoverlay"))
|
||||
@@ -95,6 +95,7 @@ impl AppSession {
|
||||
screen_flip_h: false,
|
||||
screen_flip_v: false,
|
||||
screen_invert_color: false,
|
||||
screen_max_res: [2560, 1440],
|
||||
capture_method: "auto".to_string(),
|
||||
primary_hand: 1,
|
||||
watch_hand: 1,
|
||||
|
||||
Reference in New Issue
Block a user