refactor rendering interface, working edit overlay
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
use std::{marker::PhantomData, sync::Arc};
|
use std::{marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
DeviceSize,
|
|
||||||
buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer},
|
buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer},
|
||||||
command_buffer::{
|
command_buffer::{
|
||||||
AutoCommandBufferBuilder, ClearColorImageInfo, CommandBufferExecFuture, CopyBufferToImageInfo, CopyImageInfo,
|
AutoCommandBufferBuilder, ClearColorImageInfo, CommandBufferExecFuture, CopyBufferToImageInfo, CopyImageInfo,
|
||||||
@@ -9,13 +8,14 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::Queue,
|
device::Queue,
|
||||||
format::{ClearColorValue, ClearValue, Format},
|
format::{ClearColorValue, ClearValue, Format},
|
||||||
image::{Image, ImageCreateInfo, ImageType, ImageUsage, view::ImageView},
|
image::{view::ImageView, Image, ImageCreateInfo, ImageType, ImageUsage},
|
||||||
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter},
|
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter},
|
||||||
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
|
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
|
||||||
sync::{GpuFuture, future::NowFuture},
|
sync::{future::NowFuture, GpuFuture},
|
||||||
|
DeviceSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{WGfx, pass::WGfxPass};
|
use super::{pass::WGfxPass, WGfx};
|
||||||
|
|
||||||
pub type GfxCommandBuffer = WCommandBuffer<CmdBufGfx>;
|
pub type GfxCommandBuffer = WCommandBuffer<CmdBufGfx>;
|
||||||
pub type XferCommandBuffer = WCommandBuffer<CmdBufXfer>;
|
pub type XferCommandBuffer = WCommandBuffer<CmdBufXfer>;
|
||||||
@@ -44,13 +44,24 @@ impl<T> WCommandBuffer<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Default, Clone, Copy)]
|
||||||
pub enum WGfxClearMode {
|
pub enum WGfxClearMode {
|
||||||
Keep,
|
#[default]
|
||||||
DontCare,
|
DontCare,
|
||||||
|
Keep,
|
||||||
Clear([f32; 4]),
|
Clear([f32; 4]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
impl WGfxClearMode {
|
||||||
|
pub fn or_default(self, def: WGfxClearMode) -> WGfxClearMode {
|
||||||
|
match self {
|
||||||
|
Self::DontCare => def,
|
||||||
|
s => s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl WCommandBuffer<CmdBufGfx> {
|
impl WCommandBuffer<CmdBufGfx> {
|
||||||
pub fn begin_rendering(&mut self, render_target: Arc<ImageView>, clear_mode: WGfxClearMode) -> anyhow::Result<()> {
|
pub fn begin_rendering(&mut self, render_target: Arc<ImageView>, clear_mode: WGfxClearMode) -> anyhow::Result<()> {
|
||||||
self.command_buffer.begin_rendering(RenderingInfo {
|
self.command_buffer.begin_rendering(RenderingInfo {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical" />
|
border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical" />
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<div width="600" height="600">
|
<div width="100%" height="100%">
|
||||||
<rectangle width="100%" height="100%" padding="4" gap="4" align_items="center" justify_content="center" color="#000000DD" flex_direction="row">
|
<rectangle width="100%" height="100%" padding="4" gap="4" align_items="center" justify_content="center" color="#000000DD" flex_direction="row">
|
||||||
<div></div>
|
<div></div>
|
||||||
<div flex_direction="column">
|
<div flex_direction="column">
|
||||||
35
wlx-overlay-s/src/assets/gui/toolbox.xml
Normal file
35
wlx-overlay-s/src/assets/gui/toolbox.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<layout>
|
||||||
|
<theme>
|
||||||
|
<var key="border" value="2" />
|
||||||
|
</theme>
|
||||||
|
|
||||||
|
<macro name="button_style"
|
||||||
|
margin="2" overflow="hidden" box_sizing="border_box" align_items="center" justify_content="center"
|
||||||
|
border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical" />
|
||||||
|
|
||||||
|
<template name="Set">
|
||||||
|
<Button macro="button_style" _press="::SetToggle ${handle}">
|
||||||
|
<sprite width="40" height="40" color="~set_color" src="watch/set2.svg" />
|
||||||
|
<div position="absolute" margin_top="9">
|
||||||
|
<label text="${display}" size="24" color="#00050F" weight="bold" />
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<elements>
|
||||||
|
<div width="400" height="200">
|
||||||
|
<rectangle width="100%" height="100%" padding="4" box_sizing="content_box" flex_wrap="wrap" flex_direction="column" gap="4" color="~bg_color">
|
||||||
|
<label text="Select set to edit" size="48" color="#ffffff" weight="bold" />
|
||||||
|
<div width="100%" flex_direction="row">
|
||||||
|
<div id="sets">
|
||||||
|
<!-- Will populate <Set> tags at runtime -->
|
||||||
|
</div>
|
||||||
|
<Button macro="button_style" _press="::EditToggle">
|
||||||
|
<sprite color="~set_color" width="40" height="40" src="watch/edit.svg" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<label text="" size="48" color="#ffffff" weight="bold" />
|
||||||
|
</rectangle>
|
||||||
|
</div>
|
||||||
|
</elements>
|
||||||
|
</layout>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ash::vk::SubmitInfo;
|
use ash::vk::SubmitInfo;
|
||||||
use glam::{Affine3A, Vec3, Vec3A, Vec4};
|
use glam::{Affine3A, Vec3, Vec3A, Vec4};
|
||||||
@@ -8,7 +8,6 @@ use idmap::IdMap;
|
|||||||
use ovr_overlay::overlay::OverlayManager;
|
use ovr_overlay::overlay::OverlayManager;
|
||||||
use ovr_overlay::sys::ETrackingUniverseOrigin;
|
use ovr_overlay::sys::ETrackingUniverseOrigin;
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
VulkanObject,
|
|
||||||
command_buffer::{
|
command_buffer::{
|
||||||
CommandBufferBeginInfo, CommandBufferLevel, CommandBufferUsage, RecordingCommandBuffer,
|
CommandBufferBeginInfo, CommandBufferLevel, CommandBufferUsage, RecordingCommandBuffer,
|
||||||
},
|
},
|
||||||
@@ -16,19 +15,19 @@ use vulkano::{
|
|||||||
image::view::ImageView,
|
image::view::ImageView,
|
||||||
image::{Image, ImageLayout},
|
image::{Image, ImageLayout},
|
||||||
sync::{
|
sync::{
|
||||||
AccessFlags, DependencyInfo, ImageMemoryBarrier, PipelineStages,
|
|
||||||
fence::{Fence, FenceCreateInfo},
|
fence::{Fence, FenceCreateInfo},
|
||||||
|
AccessFlags, DependencyInfo, ImageMemoryBarrier, PipelineStages,
|
||||||
},
|
},
|
||||||
|
VulkanObject,
|
||||||
};
|
};
|
||||||
use wgui::gfx::WGfx;
|
use wgui::gfx::WGfx;
|
||||||
|
|
||||||
use crate::backend::input::{HoverResult, PointerHit};
|
use crate::backend::input::{HoverResult, PointerHit};
|
||||||
use crate::graphics::CommandBuffers;
|
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
use crate::subsystem::hid::WheelDelta;
|
use crate::subsystem::hid::WheelDelta;
|
||||||
use crate::windowing::Z_ORDER_LINES;
|
use crate::windowing::backend::{FrameMeta, OverlayBackend, RenderResources, ShouldRender};
|
||||||
use crate::windowing::backend::{FrameMeta, OverlayBackend, ShouldRender};
|
|
||||||
use crate::windowing::window::{OverlayWindowConfig, OverlayWindowData};
|
use crate::windowing::window::{OverlayWindowConfig, OverlayWindowData};
|
||||||
|
use crate::windowing::Z_ORDER_LINES;
|
||||||
|
|
||||||
use super::overlay::OpenVrOverlayData;
|
use super::overlay::OpenVrOverlayData;
|
||||||
|
|
||||||
@@ -189,14 +188,8 @@ impl OverlayBackend for LineBackend {
|
|||||||
fn should_render(&mut self, _: &mut AppState) -> anyhow::Result<ShouldRender> {
|
fn should_render(&mut self, _: &mut AppState) -> anyhow::Result<ShouldRender> {
|
||||||
Ok(ShouldRender::Unable)
|
Ok(ShouldRender::Unable)
|
||||||
}
|
}
|
||||||
fn render(
|
fn render(&mut self, _: &mut AppState, _: &mut RenderResources) -> anyhow::Result<()> {
|
||||||
&mut self,
|
unreachable!()
|
||||||
_: &mut AppState,
|
|
||||||
_: Arc<ImageView>,
|
|
||||||
_: &mut CommandBuffers,
|
|
||||||
_: f32,
|
|
||||||
) -> anyhow::Result<bool> {
|
|
||||||
Ok(false)
|
|
||||||
}
|
}
|
||||||
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
||||||
Some(FrameMeta {
|
Some(FrameMeta {
|
||||||
|
|||||||
@@ -29,14 +29,18 @@ use crate::{
|
|||||||
BackendError,
|
BackendError,
|
||||||
},
|
},
|
||||||
config::save_state,
|
config::save_state,
|
||||||
graphics::{init_openvr_graphics, CommandBuffers},
|
graphics::{init_openvr_graphics, GpuFutures},
|
||||||
overlays::{
|
overlays::{
|
||||||
toast::{Toast, ToastTopic},
|
toast::{Toast, ToastTopic},
|
||||||
watch::{watch_fade, WATCH_NAME},
|
watch::{watch_fade, WATCH_NAME},
|
||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::notifications::NotificationManager,
|
subsystem::notifications::NotificationManager,
|
||||||
windowing::{backend::ShouldRender, manager::OverlayWindowManager, window::OverlayWindowData},
|
windowing::{
|
||||||
|
backend::{RenderResources, ShouldRender},
|
||||||
|
manager::OverlayWindowManager,
|
||||||
|
window::OverlayWindowData,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
@@ -311,7 +315,7 @@ pub fn openvr_run(
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.hid_provider.inner.commit();
|
app.hid_provider.inner.commit();
|
||||||
let mut buffers = CommandBuffers::default();
|
let mut futures = GpuFutures::default();
|
||||||
|
|
||||||
lines.update(universe.clone(), &mut overlay_mgr, &mut app)?;
|
lines.update(universe.clone(), &mut overlay_mgr, &mut app)?;
|
||||||
|
|
||||||
@@ -338,26 +342,17 @@ pub fn openvr_run(
|
|||||||
let ShouldRender::Should = o.should_render(&mut app)? else {
|
let ShouldRender::Should = o.should_render(&mut app)? else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if !o.ensure_image_allocated(&mut app)? {
|
let meta = o.config.backend.frame_meta().unwrap();
|
||||||
continue;
|
let tgt = o.ensure_staging_image(&mut app, meta.extent)?;
|
||||||
}
|
let mut rdr = RenderResources::new(app.gfx.clone(), tgt, &meta, 1.0)?;
|
||||||
o.data.image_dirty = o.render(
|
o.render(&mut app, &mut rdr)?;
|
||||||
&mut app,
|
o.data.image_dirty = true;
|
||||||
o.data.image_view.as_ref().unwrap().clone(),
|
futures.execute(rdr.end()?)?;
|
||||||
&mut buffers,
|
|
||||||
1.0, // alpha is instead set using OVR API
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!("Rendering overlays");
|
log::trace!("Rendering overlays");
|
||||||
|
futures.wait()?;
|
||||||
if let Some(mut future) = buffers.execute_now(app.gfx.queue_gfx.clone())? {
|
|
||||||
if let Err(e) = future.flush() {
|
|
||||||
return Err(BackendError::Fatal(e.into()));
|
|
||||||
}
|
|
||||||
future.cleanup_finished();
|
|
||||||
}
|
|
||||||
|
|
||||||
overlays
|
overlays
|
||||||
.values_mut()
|
.values_mut()
|
||||||
|
|||||||
@@ -62,21 +62,33 @@ impl OverlayWindowData<OpenVrOverlayData> {
|
|||||||
Ok(handle)
|
Ok(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn ensure_image_allocated(&mut self, app: &mut AppState) -> anyhow::Result<bool> {
|
pub(super) fn ensure_staging_image(
|
||||||
if self.data.image_view.is_some() {
|
&mut self,
|
||||||
return Ok(true);
|
app: &mut AppState,
|
||||||
|
extent: [u32; 3],
|
||||||
|
) -> anyhow::Result<Arc<ImageView>> {
|
||||||
|
if let Some(image_view) = self.data.image_view.as_ref()
|
||||||
|
&& image_view.image().extent() == extent
|
||||||
|
{
|
||||||
|
return Ok(image_view.clone());
|
||||||
}
|
}
|
||||||
let Some(meta) = self.config.backend.frame_meta() else {
|
|
||||||
return Ok(false);
|
log::debug!(
|
||||||
};
|
"{}: recreating staging image at {}x{}",
|
||||||
|
self.config.name,
|
||||||
|
extent[0],
|
||||||
|
extent[1],
|
||||||
|
);
|
||||||
|
|
||||||
let image = app.gfx.new_image(
|
let image = app.gfx.new_image(
|
||||||
meta.extent[0],
|
extent[0],
|
||||||
meta.extent[1],
|
extent[1],
|
||||||
app.gfx.surface_format,
|
app.gfx.surface_format,
|
||||||
ImageUsage::TRANSFER_SRC | ImageUsage::COLOR_ATTACHMENT | ImageUsage::SAMPLED,
|
ImageUsage::TRANSFER_SRC | ImageUsage::COLOR_ATTACHMENT | ImageUsage::SAMPLED,
|
||||||
)?;
|
)?;
|
||||||
self.data.image_view = Some(ImageView::new_default(image)?);
|
let image_view = ImageView::new_default(image)?;
|
||||||
Ok(true)
|
self.data.image_view = Some(image_view.clone());
|
||||||
|
Ok(image_view)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn after_input(
|
pub(super) fn after_input(
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use wgui::gfx::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::openxr::helpers,
|
backend::openxr::helpers,
|
||||||
graphics::{CommandBuffers, Vert2Uv},
|
graphics::{GpuFutures, Vert2Uv},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
};
|
};
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
@@ -152,7 +152,7 @@ impl LinePool {
|
|||||||
pub(super) fn render(
|
pub(super) fn render(
|
||||||
&mut self,
|
&mut self,
|
||||||
app: &AppState,
|
app: &AppState,
|
||||||
buf: &mut CommandBuffers,
|
futures: &mut GpuFutures,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
for line in self.lines.values_mut() {
|
for line in self.lines.values_mut() {
|
||||||
if let Some(inner) = line.maybe_line.as_mut() {
|
if let Some(inner) = line.maybe_line.as_mut() {
|
||||||
@@ -167,7 +167,7 @@ impl LinePool {
|
|||||||
cmd_buffer.run_ref(&self.pass)?;
|
cmd_buffer.run_ref(&self.pass)?;
|
||||||
cmd_buffer.end_rendering()?;
|
cmd_buffer.end_rendering()?;
|
||||||
|
|
||||||
buf.push(cmd_buffer.build()?);
|
futures.execute((cmd_buffer.queue.clone(), cmd_buffer.build()?))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,14 +23,18 @@ use crate::{
|
|||||||
BackendError,
|
BackendError,
|
||||||
},
|
},
|
||||||
config::save_state,
|
config::save_state,
|
||||||
graphics::{init_openxr_graphics, CommandBuffers},
|
graphics::{init_openxr_graphics, GpuFutures},
|
||||||
overlays::{
|
overlays::{
|
||||||
toast::{Toast, ToastTopic},
|
toast::{Toast, ToastTopic},
|
||||||
watch::{watch_fade, WATCH_NAME},
|
watch::{watch_fade, WATCH_NAME},
|
||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::notifications::NotificationManager,
|
subsystem::notifications::NotificationManager,
|
||||||
windowing::{backend::ShouldRender, manager::OverlayWindowManager, window::OverlayWindowData},
|
windowing::{
|
||||||
|
backend::{RenderResources, ShouldRender},
|
||||||
|
manager::OverlayWindowManager,
|
||||||
|
window::OverlayWindowData,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
@@ -378,10 +382,10 @@ pub fn openxr_run(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Begin rendering
|
// Begin rendering
|
||||||
let mut buffers = CommandBuffers::default();
|
let mut futures = GpuFutures::default();
|
||||||
|
|
||||||
if !main_session_visible && let Some(skybox) = skybox.as_mut() {
|
if !main_session_visible && let Some(skybox) = skybox.as_mut() {
|
||||||
skybox.render(&xr_state, &app, &mut buffers)?;
|
skybox.render(&xr_state, &app, &mut futures)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for o in overlays.values_mut() {
|
for o in overlays.values_mut() {
|
||||||
@@ -402,30 +406,20 @@ pub fn openxr_run(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if should_render {
|
if should_render {
|
||||||
if !o.ensure_swapchain(&app, &xr_state)? {
|
let meta = o.config.backend.frame_meta().unwrap(); // want panic
|
||||||
continue;
|
let tgt = o.ensure_swapchain_acquire(&app, &xr_state, meta.extent)?;
|
||||||
}
|
let mut rdr = RenderResources::new(app.gfx.clone(), tgt, &meta, alpha)?;
|
||||||
let tgt = o.data.swapchain.as_mut().unwrap().acquire_wait_image()?; // want
|
o.render(&mut app, &mut rdr)?;
|
||||||
if !o.render(&mut app, tgt, &mut buffers, alpha)? {
|
|
||||||
o.data.swapchain.as_mut().unwrap().ensure_image_released()?; // want
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
o.data.last_alpha = alpha;
|
o.data.last_alpha = alpha;
|
||||||
|
futures.execute(rdr.end()?)?;
|
||||||
} else if o.data.swapchain.is_none() {
|
} else if o.data.swapchain.is_none() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
o.data.cur_visible = true;
|
o.data.cur_visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lines.render(&app, &mut buffers)?;
|
lines.render(&app, &mut futures)?;
|
||||||
|
futures.wait()?;
|
||||||
let future = buffers.execute_now(app.gfx.queue_gfx.clone())?;
|
|
||||||
if let Some(mut future) = future {
|
|
||||||
if let Err(e) = future.flush() {
|
|
||||||
return Err(BackendError::Fatal(e.into()));
|
|
||||||
}
|
|
||||||
future.cleanup_finished();
|
|
||||||
}
|
|
||||||
// End rendering
|
// End rendering
|
||||||
|
|
||||||
// Layer composition
|
// Layer composition
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
use glam::Vec3A;
|
use glam::Vec3A;
|
||||||
use openxr::{self as xr, CompositionLayerFlags};
|
use openxr::{self as xr, CompositionLayerFlags};
|
||||||
use std::f32::consts::PI;
|
use std::{f32::consts::PI, sync::Arc};
|
||||||
|
use vulkano::image::view::ImageView;
|
||||||
use xr::EyeVisibility;
|
use xr::EyeVisibility;
|
||||||
|
|
||||||
use super::{CompositionLayer, XrState, helpers, swapchain::WlxSwapchain};
|
use super::{helpers, swapchain::WlxSwapchain, CompositionLayer, XrState};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::openxr::swapchain::{SwapchainOpts, create_swapchain},
|
backend::openxr::swapchain::{create_swapchain, SwapchainOpts},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
windowing::window::OverlayWindowData,
|
windowing::window::OverlayWindowData,
|
||||||
};
|
};
|
||||||
@@ -20,41 +21,28 @@ pub struct OpenXrOverlayData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl OverlayWindowData<OpenXrOverlayData> {
|
impl OverlayWindowData<OpenXrOverlayData> {
|
||||||
pub(super) fn ensure_swapchain<'a>(
|
pub(super) fn ensure_swapchain_acquire<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
app: &AppState,
|
app: &AppState,
|
||||||
xr: &'a XrState,
|
xr: &'a XrState,
|
||||||
) -> anyhow::Result<bool> {
|
extent: [u32; 3],
|
||||||
let Some(meta) = self.frame_meta() else {
|
) -> anyhow::Result<Arc<ImageView>> {
|
||||||
log::warn!(
|
if let Some(swapchain) = self.data.swapchain.as_mut()
|
||||||
"{}: swapchain cannot be created due to missing metadata",
|
&& swapchain.extent == extent
|
||||||
self.config.name
|
|
||||||
);
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
if self
|
|
||||||
.data
|
|
||||||
.swapchain
|
|
||||||
.as_ref()
|
|
||||||
.is_some_and(|s| s.extent == meta.extent)
|
|
||||||
{
|
{
|
||||||
return Ok(true);
|
return Ok(swapchain.acquire_wait_image()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"{}: recreating swapchain at {}x{}",
|
"{}: recreating swapchain at {}x{}",
|
||||||
self.config.name,
|
self.config.name,
|
||||||
meta.extent[0],
|
extent[0],
|
||||||
meta.extent[1],
|
extent[1],
|
||||||
);
|
);
|
||||||
self.data.swapchain = Some(create_swapchain(
|
let mut swapchain = create_swapchain(xr, app.gfx.clone(), extent, SwapchainOpts::new())?;
|
||||||
xr,
|
let tgt = swapchain.acquire_wait_image()?;
|
||||||
app.gfx.clone(),
|
self.data.swapchain = Some(swapchain);
|
||||||
meta.extent,
|
Ok(tgt)
|
||||||
SwapchainOpts::new(),
|
|
||||||
)?);
|
|
||||||
Ok(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn present<'a>(
|
pub(super) fn present<'a>(
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use wgui::gfx::{cmd::WGfxClearMode, pipeline::WPipelineCreateInfo};
|
|||||||
use crate::{
|
use crate::{
|
||||||
backend::openxr::{helpers::translation_rotation_to_posef, swapchain::SwapchainOpts},
|
backend::openxr::{helpers::translation_rotation_to_posef, swapchain::SwapchainOpts},
|
||||||
config_io,
|
config_io,
|
||||||
graphics::{dds::WlxCommandBufferDds, CommandBuffers, ExtentExt},
|
graphics::{dds::WlxCommandBufferDds, ExtentExt, GpuFutures},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ impl Skybox {
|
|||||||
&'a mut self,
|
&'a mut self,
|
||||||
xr: &'a XrState,
|
xr: &'a XrState,
|
||||||
app: &AppState,
|
app: &AppState,
|
||||||
buf: &mut CommandBuffers,
|
futures: &mut GpuFutures,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if self.sky.is_some() {
|
if self.sky.is_some() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -119,7 +119,7 @@ impl Skybox {
|
|||||||
cmd_buffer.run_ref(&pass)?;
|
cmd_buffer.run_ref(&pass)?;
|
||||||
cmd_buffer.end_rendering()?;
|
cmd_buffer.end_rendering()?;
|
||||||
|
|
||||||
buf.push(cmd_buffer.build()?);
|
futures.execute((cmd_buffer.queue.clone(), cmd_buffer.build()?))?;
|
||||||
|
|
||||||
self.sky = Some(swapchain);
|
self.sky = Some(swapchain);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -129,7 +129,7 @@ impl Skybox {
|
|||||||
&'a mut self,
|
&'a mut self,
|
||||||
xr: &'a XrState,
|
xr: &'a XrState,
|
||||||
app: &AppState,
|
app: &AppState,
|
||||||
buf: &mut CommandBuffers,
|
futures: &mut GpuFutures,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if self.grid.is_some() {
|
if self.grid.is_some() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -165,7 +165,7 @@ impl Skybox {
|
|||||||
cmd_buffer.run_ref(&pass)?;
|
cmd_buffer.run_ref(&pass)?;
|
||||||
cmd_buffer.end_rendering()?;
|
cmd_buffer.end_rendering()?;
|
||||||
|
|
||||||
buf.push(cmd_buffer.build()?);
|
futures.execute((cmd_buffer.queue.clone(), cmd_buffer.build()?))?;
|
||||||
|
|
||||||
self.grid = Some(swapchain);
|
self.grid = Some(swapchain);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -175,7 +175,7 @@ impl Skybox {
|
|||||||
&mut self,
|
&mut self,
|
||||||
xr: &XrState,
|
xr: &XrState,
|
||||||
app: &AppState,
|
app: &AppState,
|
||||||
buf: &mut CommandBuffers,
|
buf: &mut GpuFutures,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
self.prepare_sky(xr, app, buf)?;
|
self.prepare_sky(xr, app, buf)?;
|
||||||
self.prepare_grid(xr, app, buf)?;
|
self.prepare_grid(xr, app, buf)?;
|
||||||
|
|||||||
@@ -636,28 +636,32 @@ fn queue_families_priorities(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct CommandBuffers {
|
pub struct GpuFutures {
|
||||||
inner: Vec<Arc<PrimaryAutoCommandBuffer>>,
|
futures: Vec<Box<dyn GpuFuture>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandBuffers {
|
impl GpuFutures {
|
||||||
pub fn push(&mut self, buffer: Arc<PrimaryAutoCommandBuffer>) {
|
pub fn execute(
|
||||||
self.inner.push(buffer);
|
&mut self,
|
||||||
|
cmd: (Arc<Queue>, Arc<PrimaryAutoCommandBuffer>),
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
self.futures.push(cmd.1.execute(cmd.0)?.boxed());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn execute_now(self, queue: Arc<Queue>) -> anyhow::Result<Option<Box<dyn GpuFuture>>> {
|
pub fn wait(self) -> anyhow::Result<()> {
|
||||||
let mut buffers = self.inner.into_iter();
|
let mut it = self.futures.into_iter();
|
||||||
let Some(first) = buffers.next() else {
|
let Some(mut all) = it.next() else {
|
||||||
return Ok(None);
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
for f in it {
|
||||||
let future = first.execute(queue)?;
|
all = all.join(f).boxed();
|
||||||
let mut future: Box<dyn GpuFuture> = Box::new(future);
|
|
||||||
|
|
||||||
for buf in buffers {
|
|
||||||
future = Box::new(future.then_execute_same_queue(buf)?);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(future))
|
let finished = all.then_signal_fence_and_flush()?;
|
||||||
|
finished.wait(None)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
use std::{cell::RefCell, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use button::setup_custom_button;
|
use button::setup_custom_button;
|
||||||
use glam::{Affine2, Vec2, vec2};
|
use glam::{vec2, Affine2, Vec2};
|
||||||
use label::setup_custom_label;
|
use label::setup_custom_label;
|
||||||
use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView};
|
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
drawing,
|
drawing,
|
||||||
@@ -16,15 +15,14 @@ use wgui::{
|
|||||||
layout::{Layout, LayoutParams, WidgetID},
|
layout::{Layout, LayoutParams, WidgetID},
|
||||||
parser::ParserState,
|
parser::ParserState,
|
||||||
renderer_vk::context::Context as WguiContext,
|
renderer_vk::context::Context as WguiContext,
|
||||||
widget::{EventResult, label::WidgetLabel, rectangle::WidgetRectangle},
|
widget::{label::WidgetLabel, rectangle::WidgetRectangle, EventResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::input::{Haptics, HoverResult, PointerHit, PointerMode},
|
backend::input::{Haptics, HoverResult, PointerHit, PointerMode},
|
||||||
graphics::{CommandBuffers, ExtentExt},
|
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::WheelDelta,
|
subsystem::hid::WheelDelta,
|
||||||
windowing::backend::{FrameMeta, OverlayBackend, ShouldRender, ui_transform},
|
windowing::backend::{ui_transform, FrameMeta, OverlayBackend, RenderResources, ShouldRender},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{timer::GuiTimer, timestep::Timestep};
|
use super::{timer::GuiTimer, timestep::Timestep};
|
||||||
@@ -222,31 +220,11 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(
|
fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> {
|
||||||
&mut self,
|
|
||||||
app: &mut AppState,
|
|
||||||
tgt: Arc<ImageView>,
|
|
||||||
buf: &mut CommandBuffers,
|
|
||||||
mut alpha: f32,
|
|
||||||
) -> anyhow::Result<bool> {
|
|
||||||
self.context
|
self.context
|
||||||
.update_viewport(&mut app.wgui_shared, tgt.extent_u32arr(), 1.0)?;
|
.update_viewport(&mut app.wgui_shared, rdr.extent, 1.0)?;
|
||||||
self.layout.update(self.max_size, self.timestep.alpha)?;
|
self.layout.update(self.max_size, self.timestep.alpha)?;
|
||||||
|
|
||||||
// FIXME: pass this properly
|
|
||||||
let mut clear = WGfxClearMode::Clear([0., 0., 0., 0.]);
|
|
||||||
if alpha < 0. {
|
|
||||||
alpha *= -1.;
|
|
||||||
clear = WGfxClearMode::Keep;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut cmd_buf = app
|
|
||||||
.gfx
|
|
||||||
.create_gfx_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
|
||||||
.unwrap(); // want panic
|
|
||||||
|
|
||||||
cmd_buf.begin_rendering(tgt, clear)?;
|
|
||||||
|
|
||||||
let globals = self.layout.state.globals.clone(); // sorry
|
let globals = self.layout.state.globals.clone(); // sorry
|
||||||
let mut globals = globals.get();
|
let mut globals = globals.get();
|
||||||
|
|
||||||
@@ -254,22 +232,20 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||||||
globals: &mut globals,
|
globals: &mut globals,
|
||||||
layout: &mut self.layout,
|
layout: &mut self.layout,
|
||||||
debug_draw: false,
|
debug_draw: false,
|
||||||
alpha,
|
alpha: rdr.alpha,
|
||||||
})?;
|
})?;
|
||||||
self.context.draw(
|
self.context.draw(
|
||||||
&globals.font_system,
|
&globals.font_system,
|
||||||
&mut app.wgui_shared,
|
&mut app.wgui_shared,
|
||||||
&mut cmd_buf,
|
&mut rdr.cmd_buf,
|
||||||
&primitives,
|
&primitives,
|
||||||
)?;
|
)?;
|
||||||
cmd_buf.end_rendering()?;
|
Ok(())
|
||||||
buf.push(cmd_buf.build()?);
|
|
||||||
|
|
||||||
Ok(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
||||||
Some(FrameMeta {
|
Some(FrameMeta {
|
||||||
|
clear: WGfxClearMode::Clear([0., 0., 0., 0.]),
|
||||||
extent: [
|
extent: [
|
||||||
self.max_size.x.min(self.layout.content_size.x) as _,
|
self.max_size.x.min(self.layout.content_size.x) as _,
|
||||||
self.max_size.y.min(self.layout.content_size.y) as _,
|
self.max_size.y.min(self.layout.content_size.y) as _,
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use glam::vec2;
|
use glam::vec2;
|
||||||
use vulkano::image::{view::ImageView, ImageUsage};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::input::HoverResult,
|
backend::input::HoverResult,
|
||||||
gui::panel::GuiPanel,
|
gui::panel::GuiPanel,
|
||||||
state::AppState,
|
state::AppState,
|
||||||
|
subsystem::hid::WheelDelta,
|
||||||
windowing::{
|
windowing::{
|
||||||
backend::{DummyBackend, OverlayBackend, ShouldRender},
|
backend::{DummyBackend, OverlayBackend, RenderResources, ShouldRender},
|
||||||
window::OverlayWindowConfig,
|
window::OverlayWindowConfig,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -38,15 +38,13 @@ impl EditModeManager {
|
|||||||
let inner = mem::replace(&mut owc.backend, Box::new(DummyBackend {}));
|
let inner = mem::replace(&mut owc.backend, Box::new(DummyBackend {}));
|
||||||
let mut panel = self.panel_pool.pop();
|
let mut panel = self.panel_pool.pop();
|
||||||
if panel.is_none() {
|
if panel.is_none() {
|
||||||
panel = Some(make_adjustment_panel(app)?);
|
panel = Some(make_edit_panel(app)?);
|
||||||
}
|
}
|
||||||
let mut panel = panel.unwrap();
|
let mut panel = panel.unwrap();
|
||||||
panel.state = owc.name.clone();
|
panel.state = owc.name.clone();
|
||||||
owc.backend = Box::new(EditModeBackendWrapper {
|
owc.backend = Box::new(EditModeBackendWrapper {
|
||||||
inner: ManuallyDrop::new(inner),
|
inner: ManuallyDrop::new(inner),
|
||||||
panel: ManuallyDrop::new(panel),
|
panel: ManuallyDrop::new(panel),
|
||||||
can_render_inner: false,
|
|
||||||
image: None,
|
|
||||||
});
|
});
|
||||||
owc.editing = true;
|
owc.editing = true;
|
||||||
|
|
||||||
@@ -79,8 +77,6 @@ impl EditModeManager {
|
|||||||
pub struct EditModeBackendWrapper {
|
pub struct EditModeBackendWrapper {
|
||||||
panel: ManuallyDrop<EditModeWrapPanel>,
|
panel: ManuallyDrop<EditModeWrapPanel>,
|
||||||
inner: ManuallyDrop<Box<dyn OverlayBackend>>,
|
inner: ManuallyDrop<Box<dyn OverlayBackend>>,
|
||||||
image: Option<Arc<ImageView>>,
|
|
||||||
can_render_inner: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OverlayBackend for EditModeBackendWrapper {
|
impl OverlayBackend for EditModeBackendWrapper {
|
||||||
@@ -99,8 +95,7 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||||||
fn should_render(&mut self, app: &mut crate::state::AppState) -> anyhow::Result<ShouldRender> {
|
fn should_render(&mut self, app: &mut crate::state::AppState) -> anyhow::Result<ShouldRender> {
|
||||||
let i = self.inner.should_render(app)?;
|
let i = self.inner.should_render(app)?;
|
||||||
|
|
||||||
self.can_render_inner = !matches!(i, ShouldRender::Unable);
|
if !matches!(i, ShouldRender::Unable)
|
||||||
if self.can_render_inner
|
|
||||||
&& let Some(ref frame_meta) = self.inner.frame_meta()
|
&& let Some(ref frame_meta) = self.inner.frame_meta()
|
||||||
{
|
{
|
||||||
let new_size = vec2(frame_meta.extent[0] as _, frame_meta.extent[1] as _);
|
let new_size = vec2(frame_meta.extent[0] as _, frame_meta.extent[1] as _);
|
||||||
@@ -109,6 +104,8 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||||||
self.panel.max_size = new_size;
|
self.panel.max_size = new_size;
|
||||||
self.panel.update_layout()?;
|
self.panel.update_layout()?;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return Ok(ShouldRender::Unable);
|
||||||
}
|
}
|
||||||
|
|
||||||
let p = self.panel.should_render(app)?;
|
let p = self.panel.should_render(app)?;
|
||||||
@@ -118,39 +115,19 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||||||
(ShouldRender::Should, ShouldRender::Can) => ShouldRender::Should,
|
(ShouldRender::Should, ShouldRender::Can) => ShouldRender::Should,
|
||||||
(ShouldRender::Can, ShouldRender::Should) => ShouldRender::Should,
|
(ShouldRender::Can, ShouldRender::Should) => ShouldRender::Should,
|
||||||
(ShouldRender::Can, ShouldRender::Can) => ShouldRender::Can,
|
(ShouldRender::Can, ShouldRender::Can) => ShouldRender::Can,
|
||||||
// (ShouldRender::Unable, ShouldRender::Should) if self.image.is_some() => {
|
|
||||||
// ShouldRender::Should
|
|
||||||
// }
|
|
||||||
// (ShouldRender::Unable, ShouldRender::Can) if self.image.is_some() => ShouldRender::Can,
|
|
||||||
_ => ShouldRender::Unable,
|
_ => ShouldRender::Unable,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn render(
|
fn render(
|
||||||
&mut self,
|
&mut self,
|
||||||
app: &mut crate::state::AppState,
|
app: &mut crate::state::AppState,
|
||||||
tgt: std::sync::Arc<vulkano::image::view::ImageView>,
|
rdr: &mut RenderResources,
|
||||||
buf: &mut crate::graphics::CommandBuffers,
|
) -> anyhow::Result<()> {
|
||||||
alpha: f32,
|
self.inner.render(app, rdr)?;
|
||||||
) -> anyhow::Result<bool> {
|
self.panel.render(app, rdr)
|
||||||
if self.can_render_inner {
|
|
||||||
if self.image.is_none()
|
|
||||||
&& let Some(ref meta) = self.inner.frame_meta()
|
|
||||||
{
|
|
||||||
let image = app.gfx.new_image(
|
|
||||||
meta.extent[0],
|
|
||||||
meta.extent[1],
|
|
||||||
app.gfx.surface_format,
|
|
||||||
ImageUsage::COLOR_ATTACHMENT | ImageUsage::SAMPLED,
|
|
||||||
)?;
|
|
||||||
self.image = Some(ImageView::new_default(image)?);
|
|
||||||
}
|
|
||||||
self.inner.render(app, tgt.clone(), buf, alpha)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.panel.render(app, tgt, buf, -1.)
|
|
||||||
}
|
}
|
||||||
fn frame_meta(&mut self) -> Option<crate::windowing::backend::FrameMeta> {
|
fn frame_meta(&mut self) -> Option<crate::windowing::backend::FrameMeta> {
|
||||||
self.inner.frame_meta().or_else(|| self.panel.frame_meta())
|
self.inner.frame_meta()
|
||||||
}
|
}
|
||||||
fn on_hover(
|
fn on_hover(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -177,19 +154,17 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||||||
&mut self,
|
&mut self,
|
||||||
app: &mut crate::state::AppState,
|
app: &mut crate::state::AppState,
|
||||||
hit: &crate::backend::input::PointerHit,
|
hit: &crate::backend::input::PointerHit,
|
||||||
delta_y: f32,
|
delta: WheelDelta,
|
||||||
delta_x: f32,
|
|
||||||
) {
|
) {
|
||||||
self.panel.on_scroll(app, hit, delta_y, delta_x);
|
self.panel.on_scroll(app, hit, delta);
|
||||||
}
|
}
|
||||||
fn get_interaction_transform(&mut self) -> Option<glam::Affine2> {
|
fn get_interaction_transform(&mut self) -> Option<glam::Affine2> {
|
||||||
self.inner.get_interaction_transform()
|
self.inner.get_interaction_transform()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_adjustment_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
||||||
let mut panel = GuiPanel::new_from_template(app, "gui/adjust.xml", "".into(), None, true)?;
|
let panel = GuiPanel::new_from_template(app, "gui/edit.xml", "".into(), None, true)?;
|
||||||
panel.update_layout()?;
|
|
||||||
|
|
||||||
Ok(panel)
|
Ok(panel)
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ use wgui::{
|
|||||||
layout::LayoutParams,
|
layout::LayoutParams,
|
||||||
parser::Fetchable,
|
parser::Fetchable,
|
||||||
renderer_vk::util,
|
renderer_vk::util,
|
||||||
taffy::{self, prelude::length, BoxSizing},
|
taffy::{self, prelude::length},
|
||||||
widget::{
|
widget::{
|
||||||
div::WidgetDiv,
|
div::WidgetDiv,
|
||||||
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
process::{Child, Command},
|
process::{Child, Command},
|
||||||
sync::Arc,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use vulkano::image::view::ImageView;
|
|
||||||
use wgui::{
|
use wgui::{
|
||||||
drawing,
|
drawing,
|
||||||
event::{InternalStateChangeEvent, MouseButton, MouseButtonIndex},
|
event::{InternalStateChangeEvent, MouseButton, MouseButtonIndex},
|
||||||
@@ -12,11 +10,10 @@ use wgui::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::input::{HoverResult, PointerHit},
|
backend::input::{HoverResult, PointerHit},
|
||||||
graphics::CommandBuffers,
|
|
||||||
gui::panel::GuiPanel,
|
gui::panel::GuiPanel,
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::{ALT, CTRL, KeyModifier, META, SHIFT, SUPER, VirtualKey, WheelDelta},
|
subsystem::hid::{KeyModifier, VirtualKey, WheelDelta, ALT, CTRL, META, SHIFT, SUPER},
|
||||||
windowing::backend::{FrameMeta, OverlayBackend, ShouldRender},
|
windowing::backend::{FrameMeta, OverlayBackend, RenderResources, ShouldRender},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
@@ -36,14 +33,8 @@ impl OverlayBackend for KeyboardBackend {
|
|||||||
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
|
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
|
||||||
self.panel.should_render(app)
|
self.panel.should_render(app)
|
||||||
}
|
}
|
||||||
fn render(
|
fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> {
|
||||||
&mut self,
|
self.panel.render(app, rdr)
|
||||||
app: &mut AppState,
|
|
||||||
tgt: Arc<ImageView>,
|
|
||||||
buf: &mut CommandBuffers,
|
|
||||||
alpha: f32,
|
|
||||||
) -> anyhow::Result<bool> {
|
|
||||||
self.panel.render(app, tgt, buf, alpha)
|
|
||||||
}
|
}
|
||||||
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
||||||
self.panel.frame_meta()
|
self.panel.frame_meta()
|
||||||
|
|||||||
@@ -5,21 +5,19 @@ use std::{
|
|||||||
|
|
||||||
use futures::{Future, FutureExt};
|
use futures::{Future, FutureExt};
|
||||||
use glam::{Affine2, Affine3A, Vec3};
|
use glam::{Affine2, Affine3A, Vec3};
|
||||||
use vulkano::image::view::ImageView;
|
use wlx_capture::pipewire::{pipewire_select_screen, PipewireCapture, PipewireSelectScreenResult};
|
||||||
use wlx_capture::pipewire::{PipewireCapture, PipewireSelectScreenResult, pipewire_select_screen};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
input::{HoverResult, PointerHit},
|
input::{HoverResult, PointerHit},
|
||||||
task::TaskType,
|
task::TaskType,
|
||||||
},
|
},
|
||||||
graphics::CommandBuffers,
|
|
||||||
state::{AppSession, AppState},
|
state::{AppSession, AppState},
|
||||||
subsystem::hid::WheelDelta,
|
subsystem::hid::WheelDelta,
|
||||||
windowing::{
|
windowing::{
|
||||||
OverlaySelector,
|
backend::{ui_transform, FrameMeta, OverlayBackend, RenderResources, ShouldRender},
|
||||||
backend::{FrameMeta, OverlayBackend, ShouldRender, ui_transform},
|
|
||||||
window::{OverlayWindowConfig, OverlayWindowState},
|
window::{OverlayWindowConfig, OverlayWindowState},
|
||||||
|
OverlaySelector,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -93,16 +91,12 @@ impl OverlayBackend for MirrorBackend {
|
|||||||
.as_mut()
|
.as_mut()
|
||||||
.map_or(Ok(ShouldRender::Unable), |r| r.should_render(app))
|
.map_or(Ok(ShouldRender::Unable), |r| r.should_render(app))
|
||||||
}
|
}
|
||||||
fn render(
|
fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> {
|
||||||
&mut self,
|
let Some(renderer) = self.renderer.as_mut() else {
|
||||||
app: &mut AppState,
|
anyhow::bail!("render failed after should_render passed");
|
||||||
tgt: Arc<ImageView>,
|
};
|
||||||
buf: &mut CommandBuffers,
|
|
||||||
alpha: f32,
|
renderer.render(app, rdr)?;
|
||||||
) -> anyhow::Result<bool> {
|
|
||||||
let mut result = false;
|
|
||||||
if let Some(renderer) = self.renderer.as_mut() {
|
|
||||||
result = renderer.render(app, tgt, buf, alpha)?;
|
|
||||||
if let Some(meta) = renderer.frame_meta() {
|
if let Some(meta) = renderer.frame_meta() {
|
||||||
let extent = meta.extent;
|
let extent = meta.extent;
|
||||||
if self.last_extent != extent {
|
if self.last_extent != extent {
|
||||||
@@ -110,9 +104,8 @@ impl OverlayBackend for MirrorBackend {
|
|||||||
self.interaction_transform = Some(ui_transform([extent[0], extent[1]]));
|
self.interaction_transform = Some(ui_transform([extent[0], extent[1]]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(result)
|
Ok(())
|
||||||
}
|
}
|
||||||
fn pause(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
fn pause(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||||
if let Some(renderer) = self.renderer.as_mut() {
|
if let Some(renderer) = self.renderer.as_mut() {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
pub mod adjust;
|
|
||||||
pub mod anchor;
|
pub mod anchor;
|
||||||
pub mod bar;
|
pub mod bar;
|
||||||
pub mod custom;
|
pub mod custom;
|
||||||
//pub mod edit;
|
pub mod edit;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub mod mirror;
|
pub mod mirror;
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
use std::{
|
use std::{
|
||||||
sync::{Arc, LazyLock, atomic::AtomicU64},
|
sync::{atomic::AtomicU64, Arc, LazyLock},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
use glam::{Affine2, Vec2, vec2};
|
use glam::{vec2, Affine2, Vec2};
|
||||||
use vulkano::image::view::ImageView;
|
use wlx_capture::{frame::Transform, WlxCapture};
|
||||||
use wlx_capture::{WlxCapture, frame::Transform};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::input::{HoverResult, PointerHit, PointerMode},
|
backend::input::{HoverResult, PointerHit, PointerMode},
|
||||||
graphics::{CommandBuffers, ExtentExt},
|
graphics::ExtentExt,
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT, WheelDelta},
|
subsystem::hid::{WheelDelta, MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT},
|
||||||
windowing::backend::{FrameMeta, OverlayBackend, ShouldRender},
|
windowing::backend::{FrameMeta, OverlayBackend, RenderResources, ShouldRender},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::capture::{ScreenPipeline, WlxCaptureIn, WlxCaptureOut, receive_callback};
|
use super::capture::{receive_callback, ScreenPipeline, WlxCaptureIn, WlxCaptureOut};
|
||||||
|
|
||||||
const CURSOR_SIZE: f32 = 16. / 1440.;
|
const CURSOR_SIZE: f32 = 16. / 1440.;
|
||||||
|
|
||||||
@@ -179,25 +178,14 @@ impl OverlayBackend for ScreenBackend {
|
|||||||
Ok(ShouldRender::Unable)
|
Ok(ShouldRender::Unable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn render(
|
fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> {
|
||||||
&mut self,
|
// want panic; must be some if should_render was not Unable
|
||||||
app: &mut AppState,
|
let capture = self.cur_frame.take().unwrap();
|
||||||
tgt: Arc<ImageView>,
|
|
||||||
buf: &mut CommandBuffers,
|
|
||||||
alpha: f32,
|
|
||||||
) -> anyhow::Result<bool> {
|
|
||||||
let Some(capture) = self.cur_frame.take() else {
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// want panic; must be Some if cur_frame is also Some
|
// want panic; must be Some if cur_frame is also Some
|
||||||
self.pipeline
|
self.pipeline.as_mut().unwrap().render(&capture, app, rdr)?;
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.render(&capture, app, tgt, buf, alpha)?;
|
|
||||||
|
|
||||||
self.capture.request_new_frame();
|
self.capture.request_new_frame();
|
||||||
Ok(true)
|
Ok(())
|
||||||
}
|
}
|
||||||
fn pause(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
fn pause(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||||
self.capture.pause();
|
self.capture.pause();
|
||||||
|
|||||||
@@ -7,29 +7,28 @@ use vulkano::{
|
|||||||
command_buffer::CommandBufferUsage,
|
command_buffer::CommandBufferUsage,
|
||||||
device::Queue,
|
device::Queue,
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{Image, sampler::Filter, view::ImageView},
|
image::{sampler::Filter, view::ImageView, Image},
|
||||||
pipeline::graphics::color_blend::AttachmentBlend,
|
pipeline::graphics::color_blend::AttachmentBlend,
|
||||||
};
|
};
|
||||||
use wgui::gfx::{
|
use wgui::gfx::{
|
||||||
WGfx,
|
|
||||||
cmd::WGfxClearMode,
|
cmd::WGfxClearMode,
|
||||||
pass::WGfxPass,
|
pass::WGfxPass,
|
||||||
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
||||||
|
WGfx,
|
||||||
};
|
};
|
||||||
use wlx_capture::{
|
use wlx_capture::{
|
||||||
WlxCapture,
|
|
||||||
frame::{self as wlx_frame, DrmFormat, FrameFormat, MouseMeta, Transform, WlxFrame},
|
frame::{self as wlx_frame, DrmFormat, FrameFormat, MouseMeta, Transform, WlxFrame},
|
||||||
|
WlxCapture,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::GeneralConfig,
|
config::GeneralConfig,
|
||||||
graphics::{
|
graphics::{
|
||||||
CommandBuffers, Vert2Uv,
|
dmabuf::{fourcc_to_vk, WGfxDmabuf},
|
||||||
dmabuf::{WGfxDmabuf, fourcc_to_vk},
|
upload_quad_vertices, Vert2Uv,
|
||||||
upload_quad_vertices,
|
|
||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
windowing::backend::FrameMeta,
|
windowing::backend::{FrameMeta, RenderResources},
|
||||||
};
|
};
|
||||||
|
|
||||||
const CURSOR_SIZE: f32 = 16. / 1440.;
|
const CURSOR_SIZE: f32 = 16. / 1440.;
|
||||||
@@ -147,20 +146,14 @@ impl ScreenPipeline {
|
|||||||
&mut self,
|
&mut self,
|
||||||
capture: &WlxCaptureOut,
|
capture: &WlxCaptureOut,
|
||||||
app: &mut AppState,
|
app: &mut AppState,
|
||||||
tgt: Arc<ImageView>,
|
rdr: &mut RenderResources,
|
||||||
buf: &mut CommandBuffers,
|
|
||||||
alpha: f32,
|
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let view = ImageView::new_default(capture.image.clone())?;
|
let view = ImageView::new_default(capture.image.clone())?;
|
||||||
|
|
||||||
self.pass.update_sampler(0, view, app.gfx.texture_filter)?;
|
self.pass.update_sampler(0, view, app.gfx.texture_filter)?;
|
||||||
self.buf_alpha.write()?[0] = alpha;
|
self.buf_alpha.write()?[0] = rdr.alpha;
|
||||||
|
|
||||||
let mut cmd = app
|
rdr.cmd_buf.run_ref(&self.pass)?;
|
||||||
.gfx
|
|
||||||
.create_gfx_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
|
||||||
cmd.begin_rendering(tgt, WGfxClearMode::DontCare)?;
|
|
||||||
cmd.run_ref(&self.pass)?;
|
|
||||||
|
|
||||||
if let Some(mouse) = capture.mouse.as_ref() {
|
if let Some(mouse) = capture.mouse.as_ref() {
|
||||||
let size = CURSOR_SIZE * self.extentf[1];
|
let size = CURSOR_SIZE * self.extentf[1];
|
||||||
@@ -176,11 +169,9 @@ impl ScreenPipeline {
|
|||||||
size,
|
size,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
cmd.run_ref(&self.mouse.pass)?;
|
rdr.cmd_buf.run_ref(&self.mouse.pass)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.end_rendering()?;
|
|
||||||
buf.push(cmd.build()?);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,6 +208,7 @@ pub struct WlxCaptureOut {
|
|||||||
impl WlxCaptureOut {
|
impl WlxCaptureOut {
|
||||||
pub(super) fn get_frame_meta(&self, config: &GeneralConfig) -> FrameMeta {
|
pub(super) fn get_frame_meta(&self, config: &GeneralConfig) -> FrameMeta {
|
||||||
FrameMeta {
|
FrameMeta {
|
||||||
|
clear: WGfxClearMode::DontCare,
|
||||||
extent: extent_from_format(self.format, config),
|
extent: extent_from_format(self.format, config),
|
||||||
transform: affine_from_format(&self.format),
|
transform: affine_from_format(&self.format),
|
||||||
format: self.image.format(),
|
format: self.image.format(),
|
||||||
|
|||||||
80
wlx-overlay-s/src/overlays/toolbox.rs
Normal file
80
wlx-overlay-s/src/overlays/toolbox.rs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use glam::{Affine3A, Vec3};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
gui::{panel::GuiPanel, timer::GuiTimer},
|
||||||
|
state::AppState,
|
||||||
|
windowing::{
|
||||||
|
window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
||||||
|
Z_ORDER_WATCH,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const EDIT_NAME: &str = "edit";
|
||||||
|
|
||||||
|
struct EditState {
|
||||||
|
num_sets: usize,
|
||||||
|
current_set: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::significant_drop_tightening)]
|
||||||
|
pub fn create_edit(
|
||||||
|
app: &mut AppState,
|
||||||
|
num_sets: usize,
|
||||||
|
current_set: usize,
|
||||||
|
) -> anyhow::Result<OverlayWindowConfig> {
|
||||||
|
let state = EditState {
|
||||||
|
num_sets,
|
||||||
|
current_set,
|
||||||
|
};
|
||||||
|
let mut panel = GuiPanel::new_from_template(
|
||||||
|
app,
|
||||||
|
"gui/watch.xml",
|
||||||
|
state,
|
||||||
|
Some(Box::new(
|
||||||
|
move |id, widget, doc_params, layout, parser_state| {
|
||||||
|
if &*id != "sets" {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx in 0..num_sets {
|
||||||
|
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
|
||||||
|
params.insert("display".into(), (idx + 1).to_string().into());
|
||||||
|
params.insert("handle".into(), idx.to_string().into());
|
||||||
|
parser_state.instantiate_template(doc_params, "Set", layout, widget, params)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
panel
|
||||||
|
.timers
|
||||||
|
.push(GuiTimer::new(Duration::from_millis(100), 0));
|
||||||
|
|
||||||
|
let positioning = Positioning::FollowHand {
|
||||||
|
hand: app.session.config.watch_hand as _,
|
||||||
|
lerp: 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
panel.update_layout()?;
|
||||||
|
|
||||||
|
Ok(OverlayWindowConfig {
|
||||||
|
name: EDIT_NAME.into(),
|
||||||
|
z_order: Z_ORDER_WATCH,
|
||||||
|
default_state: OverlayWindowState {
|
||||||
|
interactable: true,
|
||||||
|
positioning,
|
||||||
|
transform: Affine3A::from_scale_rotation_translation(
|
||||||
|
Vec3::ONE * 0.115,
|
||||||
|
app.session.config.watch_rot,
|
||||||
|
app.session.config.watch_pos,
|
||||||
|
) * Affine3A::from_translation(Vec3::Y * 0.075),
|
||||||
|
..OverlayWindowState::default()
|
||||||
|
},
|
||||||
|
show_on_spawn: true,
|
||||||
|
global: true,
|
||||||
|
..OverlayWindowConfig::from_backend(Box::new(panel))
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
use glam::{Affine2, Affine3A, Quat, Vec3, vec3};
|
use glam::{vec3, Affine2, Affine3A, Quat, Vec3};
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
buffer::{BufferUsage, Subbuffer},
|
buffer::{BufferUsage, Subbuffer},
|
||||||
command_buffer::CommandBufferUsage,
|
command_buffer::CommandBufferUsage,
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{Image, ImageTiling, SubresourceLayout, view::ImageView},
|
image::{view::ImageView, Image, ImageTiling, SubresourceLayout},
|
||||||
};
|
};
|
||||||
use wayvr_ipc::packet_server::{self, PacketServer, WvrStateChanged};
|
use wayvr_ipc::packet_server::{self, PacketServer, WvrStateChanged};
|
||||||
use wgui::gfx::{
|
use wgui::gfx::{
|
||||||
WGfx,
|
|
||||||
pass::WGfxPass,
|
pass::WGfxPass,
|
||||||
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
||||||
|
WGfx,
|
||||||
};
|
};
|
||||||
use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
|
use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
|
||||||
|
|
||||||
@@ -20,19 +20,20 @@ use crate::{
|
|||||||
input::{self, HoverResult},
|
input::{self, HoverResult},
|
||||||
task::TaskType,
|
task::TaskType,
|
||||||
wayvr::{
|
wayvr::{
|
||||||
self, WayVR, WayVRAction, WayVRDisplayClickAction, display,
|
self, display,
|
||||||
server_ipc::{gen_args_vec, gen_env_vec},
|
server_ipc::{gen_args_vec, gen_env_vec},
|
||||||
|
WayVR, WayVRAction, WayVRDisplayClickAction,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config_wayvr,
|
config_wayvr,
|
||||||
graphics::{CommandBuffers, Vert2Uv, dmabuf::WGfxDmabuf},
|
graphics::{dmabuf::WGfxDmabuf, Vert2Uv},
|
||||||
state::{self, AppState},
|
state::{self, AppState},
|
||||||
subsystem::{hid::WheelDelta, input::KeyboardFocus},
|
subsystem::{hid::WheelDelta, input::KeyboardFocus},
|
||||||
windowing::{
|
windowing::{
|
||||||
OverlayID, OverlaySelector, Z_ORDER_DASHBOARD,
|
backend::{ui_transform, FrameMeta, OverlayBackend, RenderResources, ShouldRender},
|
||||||
backend::{FrameMeta, OverlayBackend, ShouldRender, ui_transform},
|
|
||||||
manager::OverlayWindowManager,
|
manager::OverlayWindowManager,
|
||||||
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState},
|
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState},
|
||||||
|
OverlayID, OverlaySelector, Z_ORDER_DASHBOARD,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -660,11 +661,9 @@ impl OverlayBackend for WayVRBackend {
|
|||||||
|
|
||||||
fn render(
|
fn render(
|
||||||
&mut self,
|
&mut self,
|
||||||
app: &mut state::AppState,
|
_app: &mut state::AppState,
|
||||||
tgt: Arc<ImageView>,
|
rdr: &mut RenderResources,
|
||||||
buf: &mut CommandBuffers,
|
) -> anyhow::Result<()> {
|
||||||
alpha: f32,
|
|
||||||
) -> anyhow::Result<bool> {
|
|
||||||
let ctx = self.context.borrow();
|
let ctx = self.context.borrow();
|
||||||
let wayvr = ctx.wayvr.borrow_mut();
|
let wayvr = ctx.wayvr.borrow_mut();
|
||||||
|
|
||||||
@@ -689,26 +688,12 @@ impl OverlayBackend for WayVRBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(image) = self.image.as_ref() else {
|
let image = self.image.as_ref().unwrap();
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
self.pass
|
self.pass
|
||||||
.update_sampler(0, image.vk_image_view.clone(), self.graphics.texture_filter)?;
|
.update_sampler(0, image.vk_image_view.clone(), self.graphics.texture_filter)?;
|
||||||
self.buf_alpha.write()?[0] = alpha;
|
self.buf_alpha.write()?[0] = rdr.alpha;
|
||||||
|
rdr.cmd_buf.run_ref(&self.pass)?;
|
||||||
let mut cmd_buffer = app
|
Ok(())
|
||||||
.gfx
|
|
||||||
.create_gfx_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
|
||||||
cmd_buffer.begin_rendering(
|
|
||||||
tgt,
|
|
||||||
wgui::gfx::cmd::WGfxClearMode::Clear([0.0, 0.0, 0.0, 1.0]),
|
|
||||||
)?;
|
|
||||||
cmd_buffer.run_ref(&self.pass)?;
|
|
||||||
cmd_buffer.end_rendering()?;
|
|
||||||
buf.push(cmd_buffer.build()?);
|
|
||||||
|
|
||||||
Ok(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use idmap::{IdMap, idmap};
|
use idmap::{idmap, IdMap};
|
||||||
use idmap_derive::IntegerId;
|
use idmap_derive::IntegerId;
|
||||||
use input_linux::{
|
use input_linux::{
|
||||||
AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind, InputId, Key, RelativeAxis,
|
AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind, InputId, Key, RelativeAxis,
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
use glam::{Affine2, Affine3A, Vec2};
|
use glam::{Affine2, Affine3A, Vec2};
|
||||||
use std::{any::Any, sync::Arc};
|
use std::{any::Any, sync::Arc};
|
||||||
use vulkano::{format::Format, image::view::ImageView};
|
use vulkano::{
|
||||||
|
command_buffer::{CommandBufferUsage, PrimaryAutoCommandBuffer},
|
||||||
|
device::Queue,
|
||||||
|
format::Format,
|
||||||
|
image::view::ImageView,
|
||||||
|
};
|
||||||
|
use wgui::gfx::{
|
||||||
|
cmd::{GfxCommandBuffer, WGfxClearMode},
|
||||||
|
WGfx,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::input::{HoverResult, PointerHit},
|
backend::input::{HoverResult, PointerHit},
|
||||||
graphics::CommandBuffers,
|
graphics::ExtentExt,
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::WheelDelta,
|
subsystem::hid::WheelDelta,
|
||||||
};
|
};
|
||||||
@@ -14,6 +23,7 @@ pub struct FrameMeta {
|
|||||||
pub extent: [u32; 3],
|
pub extent: [u32; 3],
|
||||||
pub transform: Affine3A,
|
pub transform: Affine3A,
|
||||||
pub format: Format,
|
pub format: Format,
|
||||||
|
pub clear: WGfxClearMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ShouldRender {
|
pub enum ShouldRender {
|
||||||
@@ -25,6 +35,35 @@ pub enum ShouldRender {
|
|||||||
Unable,
|
Unable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RenderResources {
|
||||||
|
pub alpha: f32,
|
||||||
|
pub cmd_buf: GfxCommandBuffer,
|
||||||
|
pub extent: [u32; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderResources {
|
||||||
|
pub fn new(
|
||||||
|
gfx: Arc<WGfx>,
|
||||||
|
tgt: Arc<ImageView>,
|
||||||
|
meta: &FrameMeta,
|
||||||
|
alpha: f32,
|
||||||
|
) -> anyhow::Result<Self> {
|
||||||
|
let mut cmd_buf = gfx.create_gfx_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
||||||
|
cmd_buf.begin_rendering(tgt, meta.clear)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
cmd_buf,
|
||||||
|
alpha,
|
||||||
|
extent: meta.extent.extent_u32arr(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end(mut self) -> anyhow::Result<(Arc<Queue>, Arc<PrimaryAutoCommandBuffer>)> {
|
||||||
|
self.cmd_buf.end_rendering()?;
|
||||||
|
Ok((self.cmd_buf.queue.clone(), self.cmd_buf.build()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait OverlayBackend: Any {
|
pub trait OverlayBackend: Any {
|
||||||
/// Called once, before the first frame is rendered
|
/// Called once, before the first frame is rendered
|
||||||
fn init(&mut self, app: &mut AppState) -> anyhow::Result<()>;
|
fn init(&mut self, app: &mut AppState) -> anyhow::Result<()>;
|
||||||
@@ -35,13 +74,7 @@ pub trait OverlayBackend: Any {
|
|||||||
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender>;
|
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender>;
|
||||||
|
|
||||||
/// Called when the contents need to be rendered to the swapchain
|
/// Called when the contents need to be rendered to the swapchain
|
||||||
fn render(
|
fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()>;
|
||||||
&mut self,
|
|
||||||
app: &mut AppState,
|
|
||||||
tgt: Arc<ImageView>,
|
|
||||||
buf: &mut CommandBuffers,
|
|
||||||
alpha: f32,
|
|
||||||
) -> anyhow::Result<bool>;
|
|
||||||
|
|
||||||
/// Called to retrieve the effective extent of the image
|
/// Called to retrieve the effective extent of the image
|
||||||
/// Used for creating swapchains.
|
/// Used for creating swapchains.
|
||||||
@@ -85,17 +118,11 @@ impl OverlayBackend for DummyBackend {
|
|||||||
fn should_render(&mut self, _: &mut AppState) -> anyhow::Result<ShouldRender> {
|
fn should_render(&mut self, _: &mut AppState) -> anyhow::Result<ShouldRender> {
|
||||||
Ok(ShouldRender::Unable)
|
Ok(ShouldRender::Unable)
|
||||||
}
|
}
|
||||||
fn render(
|
fn render(&mut self, _: &mut AppState, _: &mut RenderResources) -> anyhow::Result<()> {
|
||||||
&mut self,
|
unreachable!()
|
||||||
_: &mut AppState,
|
|
||||||
_: Arc<ImageView>,
|
|
||||||
_: &mut CommandBuffers,
|
|
||||||
_: f32,
|
|
||||||
) -> anyhow::Result<bool> {
|
|
||||||
Ok(false)
|
|
||||||
}
|
}
|
||||||
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
||||||
None
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_hover(&mut self, _: &mut AppState, _: &PointerHit) -> HoverResult {
|
fn on_hover(&mut self, _: &mut AppState, _: &PointerHit) -> HoverResult {
|
||||||
@@ -103,7 +130,7 @@ impl OverlayBackend for DummyBackend {
|
|||||||
}
|
}
|
||||||
fn on_left(&mut self, _: &mut AppState, _: usize) {}
|
fn on_left(&mut self, _: &mut AppState, _: usize) {}
|
||||||
fn on_pointer(&mut self, _: &mut AppState, _: &PointerHit, _: bool) {}
|
fn on_pointer(&mut self, _: &mut AppState, _: &PointerHit, _: bool) {}
|
||||||
fn on_scroll(&mut self, _: &mut AppState, _: &PointerHit, _: f32, _: f32) {}
|
fn on_scroll(&mut self, _: &mut AppState, _: &PointerHit, _: WheelDelta) {}
|
||||||
fn get_interaction_transform(&mut self) -> Option<glam::Affine2> {
|
fn get_interaction_transform(&mut self) -> Option<glam::Affine2> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use slotmap::{HopSlotMap, Key, SecondaryMap};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
overlays::{
|
overlays::{
|
||||||
adjust::EditModeManager, anchor::create_anchor, keyboard::builder::create_keyboard,
|
anchor::create_anchor, edit::EditModeManager, keyboard::builder::create_keyboard,
|
||||||
screen::create_screens, watch::create_watch,
|
screen::create_screens, watch::create_watch,
|
||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
use glam::{Affine3A, Mat3A, Quat, Vec3, Vec3A};
|
use glam::{Affine3A, Mat3A, Quat, Vec3, Vec3A};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{f32::consts::PI, sync::Arc};
|
use std::{f32::consts::PI, sync::Arc};
|
||||||
use vulkano::image::view::ImageView;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
graphics::CommandBuffers,
|
|
||||||
state::{AppState, LeftRight},
|
state::{AppState, LeftRight},
|
||||||
subsystem::input::KeyboardFocus,
|
subsystem::input::KeyboardFocus,
|
||||||
windowing::{
|
windowing::{
|
||||||
backend::{FrameMeta, OverlayBackend, ShouldRender},
|
backend::{FrameMeta, OverlayBackend, RenderResources, ShouldRender},
|
||||||
snap_upright,
|
snap_upright,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -68,14 +66,8 @@ impl<T> OverlayWindowData<T> {
|
|||||||
pub fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
|
pub fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
|
||||||
self.config.backend.should_render(app)
|
self.config.backend.should_render(app)
|
||||||
}
|
}
|
||||||
pub fn render(
|
pub fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> {
|
||||||
&mut self,
|
self.config.backend.render(app, rdr)
|
||||||
app: &mut AppState,
|
|
||||||
tgt: Arc<ImageView>,
|
|
||||||
buf: &mut CommandBuffers,
|
|
||||||
alpha: f32,
|
|
||||||
) -> anyhow::Result<bool> {
|
|
||||||
self.config.backend.render(app, tgt, buf, alpha)
|
|
||||||
}
|
}
|
||||||
pub fn frame_meta(&mut self) -> Option<FrameMeta> {
|
pub fn frame_meta(&mut self) -> Option<FrameMeta> {
|
||||||
self.config.backend.frame_meta()
|
self.config.backend.frame_meta()
|
||||||
|
|||||||
Reference in New Issue
Block a user