wip: edit mode overlay
This commit is contained in:
195
wlx-overlay-s/src/overlays/adjust.rs
Normal file
195
wlx-overlay-s/src/overlays/adjust.rs
Normal file
@@ -0,0 +1,195 @@
|
||||
use std::{
|
||||
any::Any,
|
||||
mem::{self, ManuallyDrop},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use glam::vec2;
|
||||
use vulkano::image::{view::ImageView, ImageUsage};
|
||||
|
||||
use crate::{
|
||||
backend::input::HoverResult,
|
||||
gui::panel::GuiPanel,
|
||||
state::AppState,
|
||||
windowing::{
|
||||
backend::{DummyBackend, OverlayBackend, ShouldRender},
|
||||
window::OverlayWindowConfig,
|
||||
},
|
||||
};
|
||||
|
||||
type EditModeWrapPanel = GuiPanel<Arc<str>>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct EditModeManager {
|
||||
panel_pool: Vec<EditModeWrapPanel>,
|
||||
}
|
||||
|
||||
impl EditModeManager {
|
||||
pub fn wrap_edit_mode(
|
||||
&mut self,
|
||||
owc: &mut OverlayWindowConfig,
|
||||
app: &mut AppState,
|
||||
) -> anyhow::Result<()> {
|
||||
if owc.editing {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
log::debug!("EditMode wrap on {}", owc.name);
|
||||
let inner = mem::replace(&mut owc.backend, Box::new(DummyBackend {}));
|
||||
let mut panel = self.panel_pool.pop();
|
||||
if panel.is_none() {
|
||||
panel = Some(make_adjustment_panel(app)?);
|
||||
}
|
||||
let mut panel = panel.unwrap();
|
||||
panel.state = owc.name.clone();
|
||||
owc.backend = Box::new(EditModeBackendWrapper {
|
||||
inner: ManuallyDrop::new(inner),
|
||||
panel: ManuallyDrop::new(panel),
|
||||
can_render_inner: false,
|
||||
image: None,
|
||||
});
|
||||
owc.editing = true;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unwrap_edit_mode(&mut self, owc: &mut OverlayWindowConfig) {
|
||||
if !owc.editing {
|
||||
return;
|
||||
}
|
||||
|
||||
log::debug!("EditMode unwrap on {}", owc.name);
|
||||
let wrapper = mem::replace(&mut owc.backend, Box::new(DummyBackend {}));
|
||||
let mut wrapper: Box<dyn Any> = wrapper;
|
||||
let wrapper = wrapper
|
||||
.downcast_mut::<EditModeBackendWrapper>()
|
||||
.expect("Wrong type to unwrap");
|
||||
|
||||
let panel = unsafe { ManuallyDrop::take(&mut wrapper.panel) };
|
||||
self.panel_pool.push(panel);
|
||||
|
||||
let inner = unsafe { ManuallyDrop::take(&mut wrapper.inner) };
|
||||
owc.backend = inner;
|
||||
owc.editing = false;
|
||||
|
||||
// wrapper is destroyed with nothing left inside
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EditModeBackendWrapper {
|
||||
panel: ManuallyDrop<EditModeWrapPanel>,
|
||||
inner: ManuallyDrop<Box<dyn OverlayBackend>>,
|
||||
image: Option<Arc<ImageView>>,
|
||||
can_render_inner: bool,
|
||||
}
|
||||
|
||||
impl OverlayBackend for EditModeBackendWrapper {
|
||||
fn init(&mut self, app: &mut crate::state::AppState) -> anyhow::Result<()> {
|
||||
self.inner.init(app)?;
|
||||
self.panel.init(app)
|
||||
}
|
||||
fn pause(&mut self, app: &mut crate::state::AppState) -> anyhow::Result<()> {
|
||||
self.inner.pause(app)?;
|
||||
self.panel.pause(app)
|
||||
}
|
||||
fn resume(&mut self, app: &mut crate::state::AppState) -> anyhow::Result<()> {
|
||||
self.inner.resume(app)?;
|
||||
self.panel.resume(app)
|
||||
}
|
||||
fn should_render(&mut self, app: &mut crate::state::AppState) -> anyhow::Result<ShouldRender> {
|
||||
let i = self.inner.should_render(app)?;
|
||||
|
||||
self.can_render_inner = !matches!(i, ShouldRender::Unable);
|
||||
if self.can_render_inner
|
||||
&& let Some(ref frame_meta) = self.inner.frame_meta()
|
||||
{
|
||||
let new_size = vec2(frame_meta.extent[0] as _, frame_meta.extent[1] as _);
|
||||
if self.panel.max_size != new_size {
|
||||
log::debug!("EditWrapperGui size {} → {new_size}", self.panel.max_size);
|
||||
self.panel.max_size = new_size;
|
||||
self.panel.update_layout()?;
|
||||
}
|
||||
}
|
||||
|
||||
let p = self.panel.should_render(app)?;
|
||||
|
||||
Ok(match (i, p) {
|
||||
(ShouldRender::Should, ShouldRender::Should) => ShouldRender::Should,
|
||||
(ShouldRender::Should, ShouldRender::Can) => ShouldRender::Should,
|
||||
(ShouldRender::Can, ShouldRender::Should) => ShouldRender::Should,
|
||||
(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,
|
||||
})
|
||||
}
|
||||
fn render(
|
||||
&mut self,
|
||||
app: &mut crate::state::AppState,
|
||||
tgt: std::sync::Arc<vulkano::image::view::ImageView>,
|
||||
buf: &mut crate::graphics::CommandBuffers,
|
||||
alpha: f32,
|
||||
) -> anyhow::Result<bool> {
|
||||
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> {
|
||||
self.inner.frame_meta().or_else(|| self.panel.frame_meta())
|
||||
}
|
||||
fn on_hover(
|
||||
&mut self,
|
||||
app: &mut crate::state::AppState,
|
||||
hit: &crate::backend::input::PointerHit,
|
||||
) -> HoverResult {
|
||||
// pass through hover events to force pipewire to capture frames for us
|
||||
let _ = self.inner.on_hover(app, hit);
|
||||
self.panel.on_hover(app, hit)
|
||||
}
|
||||
fn on_left(&mut self, app: &mut crate::state::AppState, pointer: usize) {
|
||||
self.inner.on_left(app, pointer);
|
||||
self.panel.on_left(app, pointer);
|
||||
}
|
||||
fn on_pointer(
|
||||
&mut self,
|
||||
app: &mut crate::state::AppState,
|
||||
hit: &crate::backend::input::PointerHit,
|
||||
pressed: bool,
|
||||
) {
|
||||
self.panel.on_pointer(app, hit, pressed);
|
||||
}
|
||||
fn on_scroll(
|
||||
&mut self,
|
||||
app: &mut crate::state::AppState,
|
||||
hit: &crate::backend::input::PointerHit,
|
||||
delta_y: f32,
|
||||
delta_x: f32,
|
||||
) {
|
||||
self.panel.on_scroll(app, hit, delta_y, delta_x);
|
||||
}
|
||||
fn get_interaction_transform(&mut self) -> Option<glam::Affine2> {
|
||||
self.inner.get_interaction_transform()
|
||||
}
|
||||
}
|
||||
|
||||
fn make_adjustment_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
||||
let mut panel = GuiPanel::new_from_template(app, "gui/adjust.xml", "".into(), None, true)?;
|
||||
panel.update_layout()?;
|
||||
|
||||
Ok(panel)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ use crate::windowing::Z_ORDER_ANCHOR;
|
||||
pub static ANCHOR_NAME: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("anchor"));
|
||||
|
||||
pub fn create_anchor(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
let mut panel = GuiPanel::new_from_template(app, "gui/anchor.xml", (), None)?;
|
||||
let mut panel = GuiPanel::new_from_template(app, "gui/anchor.xml", (), None, false)?;
|
||||
panel.update_layout()?;
|
||||
|
||||
Ok(OverlayWindowConfig {
|
||||
|
||||
@@ -15,7 +15,7 @@ struct BarState {}
|
||||
#[allow(clippy::match_same_arms)] // TODO: remove later
|
||||
pub fn create_bar(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
let state = BarState {};
|
||||
let mut panel = GuiPanel::new_from_template(app, "gui/bar.xml", state, None)?;
|
||||
let mut panel = GuiPanel::new_from_template(app, "gui/bar.xml", state, None, false)?;
|
||||
|
||||
for (id, _widget_id) in &panel.parser_state.data.ids {
|
||||
match id.as_ref() {
|
||||
|
||||
@@ -18,7 +18,7 @@ pub fn create_custom(app: &mut AppState, name: Arc<str>) -> Option<OverlayWindow
|
||||
|
||||
unreachable!();
|
||||
|
||||
let panel = GuiPanel::new_blank(app, ()).ok()?;
|
||||
let panel = GuiPanel::new_blank(app, (), false).ok()?;
|
||||
panel.update_layout().ok()?;
|
||||
|
||||
Some(OverlayWindowConfig {
|
||||
|
||||
@@ -9,7 +9,7 @@ use wgui::{
|
||||
layout::LayoutParams,
|
||||
parser::Fetchable,
|
||||
renderer_vk::util,
|
||||
taffy::{self, prelude::length},
|
||||
taffy::{self, prelude::length, BoxSizing},
|
||||
widget::{
|
||||
div::WidgetDiv,
|
||||
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||
@@ -53,7 +53,7 @@ pub fn create_keyboard(
|
||||
processes: vec![],
|
||||
};
|
||||
|
||||
let mut panel = GuiPanel::new_blank(app, state)?;
|
||||
let mut panel = GuiPanel::new_blank(app, state, false)?;
|
||||
|
||||
let (background, _) = panel.layout.add_child(
|
||||
panel.layout.content_root_widget,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod adjust;
|
||||
pub mod anchor;
|
||||
pub mod bar;
|
||||
pub mod custom;
|
||||
|
||||
@@ -170,7 +170,7 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<OverlayWindowConfig> {
|
||||
toast.title
|
||||
};
|
||||
|
||||
let mut panel = GuiPanel::new_blank(app, ()).ok()?;
|
||||
let mut panel = GuiPanel::new_blank(app, (), false).ok()?;
|
||||
|
||||
let globals = panel.layout.state.globals.clone();
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ pub fn create_watch(app: &mut AppState, num_sets: usize) -> anyhow::Result<Overl
|
||||
Ok(())
|
||||
},
|
||||
)),
|
||||
false,
|
||||
)?;
|
||||
|
||||
panel
|
||||
|
||||
Reference in New Issue
Block a user