mirror of https://github.com/wayvr-org/wayvr.git
wip: grabbable resize corner
This commit is contained in:
parent
137570f548
commit
4f76a4abfb
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="white" d="M3 21v-2h16V3h2v16q0 .825-.587 1.413T19 21zm12-4q-.825 0-1.412-.587T13 15t.588-1.412T15 13t1.413.588T17 15t-.587 1.413T15 17M5 12v-2h3.6L3 4.4L4.4 3L10 8.6V5h2v7z"/></svg>
|
||||
|
After Width: | Height: | Size: 392 B |
|
|
@ -126,6 +126,9 @@
|
|||
</div>
|
||||
</rectangle>
|
||||
</div>
|
||||
<Button id="resize_corner" macro="button_style" tooltip="EDIT_MODE.RESIZE" _press="::EditModeResizeStart" _release="::EditModeResizeStop" border_color="~color_accent_translucent" color="~color_accent_50" color2="~color_accent_10">
|
||||
<sprite width="48" height="48" src="edit/resize-corner.svg" />
|
||||
</Button>
|
||||
</rectangle>
|
||||
</div>
|
||||
</elements>
|
||||
|
|
|
|||
|
|
@ -392,6 +392,8 @@ impl WvrServerState {
|
|||
let window_handle = wvr_server.wm.create_window(
|
||||
toplevel.clone(),
|
||||
process_handle,
|
||||
min_size,
|
||||
max_size,
|
||||
fallback_size.w as _,
|
||||
fallback_size.h as _,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ use crate::{backend::wayvr::process, gen_id};
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Window {
|
||||
pub min_size: Size<i32, Logical>,
|
||||
pub max_size: Size<i32, Logical>,
|
||||
pub size_x: u32,
|
||||
pub size_y: u32,
|
||||
pub visible: bool,
|
||||
|
|
@ -16,8 +18,15 @@ pub struct Window {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
const fn new(toplevel: Rc<ToplevelSurface>, process: process::ProcessHandle) -> Self {
|
||||
const fn new(
|
||||
toplevel: Rc<ToplevelSurface>,
|
||||
process: process::ProcessHandle,
|
||||
min_size: Size<i32, Logical>,
|
||||
max_size: Size<i32, Logical>,
|
||||
) -> Self {
|
||||
Self {
|
||||
min_size,
|
||||
max_size,
|
||||
size_x: 0,
|
||||
size_y: 0,
|
||||
visible: true,
|
||||
|
|
@ -26,6 +35,10 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn resizable(&self) -> bool {
|
||||
self.min_size != self.max_size
|
||||
}
|
||||
|
||||
pub fn configure_size(&mut self, size: Option<Size<i32, Logical>>, bounds: Size<i32, Logical>) {
|
||||
self.toplevel.with_pending_state(|state| {
|
||||
state.bounds = Some(bounds);
|
||||
|
|
@ -93,10 +106,12 @@ impl WindowManager {
|
|||
&mut self,
|
||||
toplevel: Rc<ToplevelSurface>,
|
||||
process: process::ProcessHandle,
|
||||
min_size: Size<i32, Logical>,
|
||||
max_size: Size<i32, Logical>,
|
||||
size_x: u32,
|
||||
size_y: u32,
|
||||
) -> WindowHandle {
|
||||
let mut window = Window::new(toplevel, process);
|
||||
let mut window = Window::new(toplevel, process, min_size, max_size);
|
||||
window.remember_committed_size(Size::new(size_x as i32, size_y as i32));
|
||||
self.windows.add(window)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@ use std::{
|
|||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use glam::vec2;
|
||||
use glam::{Vec2, vec2};
|
||||
use slotmap::Key;
|
||||
use wgui::{
|
||||
components::{button::ComponentButton, checkbox::ComponentCheckbox, slider::ComponentSlider},
|
||||
event::EventCallback,
|
||||
event::{CallbackDataCommon, EventCallback, StyleSetRequest},
|
||||
i18n::Translation,
|
||||
parser::Fetchable,
|
||||
taffy::Display,
|
||||
widget::EventResult,
|
||||
};
|
||||
use wlx_common::overlays::{BackendAttrib, BackendAttribValue, MouseTransform, StereoMode};
|
||||
|
|
@ -59,6 +60,7 @@ struct EditModeState {
|
|||
pos: SpriteTabHandler<PosTabState>,
|
||||
stereo: SpriteTabHandler<StereoMode>,
|
||||
mouse: SpriteTabHandler<MouseTransform>,
|
||||
resize_uv: Option<Vec2>,
|
||||
}
|
||||
|
||||
type EditModeWrapPanel = GuiPanel<EditModeState>;
|
||||
|
|
@ -94,6 +96,7 @@ impl EditWrapperManager {
|
|||
owc.backend = Box::new(EditModeBackendWrapper {
|
||||
inner: ManuallyDrop::new(inner),
|
||||
panel: ManuallyDrop::new(panel),
|
||||
last_extent: [0, 0],
|
||||
last_render: Instant::now(),
|
||||
can_render_inner: false,
|
||||
});
|
||||
|
|
@ -135,6 +138,7 @@ pub struct EditModeBackendWrapper {
|
|||
panel: ManuallyDrop<EditModeWrapPanel>,
|
||||
inner: ManuallyDrop<Box<dyn OverlayBackend>>,
|
||||
|
||||
last_extent: [u32; 2],
|
||||
last_render: Instant,
|
||||
can_render_inner: bool,
|
||||
}
|
||||
|
|
@ -213,6 +217,8 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||
rdr.cmd_bufs.reverse();
|
||||
}
|
||||
|
||||
self.last_extent = rdr.extent;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn frame_meta(&mut self) -> Option<crate::windowing::backend::FrameMeta> {
|
||||
|
|
@ -225,7 +231,23 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||
) -> 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)
|
||||
let res = self.panel.on_hover(app, hit);
|
||||
|
||||
if let Some(start_uv) = self.panel.state.resize_uv.as_mut() {
|
||||
let extent_f32 = vec2(self.last_extent[0] as f32, self.last_extent[1] as f32);
|
||||
|
||||
if start_uv.length_squared() > 10.0 {
|
||||
// at first this is raw position in pixels, transform to UV here
|
||||
*start_uv /= extent_f32;
|
||||
} else {
|
||||
// actually do resize
|
||||
let new_res = extent_f32 * hit.uv / *start_uv;
|
||||
let new_extent = [new_res.x as u32, new_res.y as u32];
|
||||
log::warn!("NEW SIZE: {new_extent:?}");
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
fn on_left(&mut self, app: &mut crate::state::AppState, pointer: usize) {
|
||||
self.inner.on_left(app, pointer);
|
||||
|
|
@ -271,6 +293,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
|||
pos: SpriteTabHandler::default(),
|
||||
stereo: SpriteTabHandler::default(),
|
||||
mouse: SpriteTabHandler::default(),
|
||||
resize_uv: None,
|
||||
};
|
||||
|
||||
let anim_mult = app.wgui_theme.animation_mult;
|
||||
|
|
@ -407,6 +430,20 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
|||
)));
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
"::EditModeResizeStart" => Box::new(move |_common, data, app, state| {
|
||||
if !test_button(data) || !test_duration(&button, app) {
|
||||
return Ok(EventResult::Pass);
|
||||
}
|
||||
state.resize_uv = data.metadata.get_mouse_pos_absolute();
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
"::EditModeResizeStop" => Box::new(move |_common, data, app, state| {
|
||||
if !test_button(data) || !test_duration(&button, app) {
|
||||
return Ok(EventResult::Pass);
|
||||
}
|
||||
state.resize_uv = None;
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
|
|
@ -564,6 +601,27 @@ fn reset_panel(
|
|||
c.set_checked(&mut com, adjust_mouse);
|
||||
}
|
||||
|
||||
let resizable = attrib_value!(
|
||||
owc.backend.get_attrib(BackendAttrib::Resizable),
|
||||
BackendAttribValue::Resizable
|
||||
)
|
||||
.unwrap_or(false);
|
||||
let c = panel
|
||||
.parser_state
|
||||
.fetch_component_as::<ComponentButton>("resize_corner")?;
|
||||
let common = CallbackDataCommon {
|
||||
state: &panel.layout.state,
|
||||
alterables: &mut panel.layout.alterables,
|
||||
};
|
||||
common.alterables.set_style(
|
||||
c.get_rect(),
|
||||
StyleSetRequest::Display(if resizable {
|
||||
Display::Block
|
||||
} else {
|
||||
Display::None
|
||||
}),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,13 @@ pub fn create_wl_window_overlay(
|
|||
-0.95
|
||||
};
|
||||
|
||||
let resizable = app
|
||||
.wvr_server
|
||||
.as_mut()
|
||||
.and_then(|wvr| wvr.wm.windows.get(&window))
|
||||
.map(|w| w.resizable())
|
||||
.unwrap_or(false);
|
||||
|
||||
Ok(OverlayWindowConfig {
|
||||
name: name.clone(),
|
||||
default_state: OverlayWindowState {
|
||||
|
|
@ -113,6 +120,7 @@ pub fn create_wl_window_overlay(
|
|||
window,
|
||||
icon,
|
||||
(scale, curve_scale),
|
||||
resizable,
|
||||
)?))
|
||||
})
|
||||
}
|
||||
|
|
@ -175,6 +183,7 @@ pub struct WvrWindowBackend {
|
|||
scrolling: bool,
|
||||
overlay_id: OverlayID,
|
||||
scale: (f32, f32),
|
||||
resizable: bool,
|
||||
}
|
||||
|
||||
impl WvrWindowBackend {
|
||||
|
|
@ -184,6 +193,7 @@ impl WvrWindowBackend {
|
|||
window: wayvr::window::WindowHandle,
|
||||
icon: Arc<str>,
|
||||
scale: (f32, f32),
|
||||
resizable: bool,
|
||||
) -> anyhow::Result<Self> {
|
||||
let subsurface_pipeline = app.gfx.create_pipeline(
|
||||
app.gfx_extras.shaders.get("vert_quad").unwrap(), // want panic
|
||||
|
|
@ -285,6 +295,7 @@ impl WvrWindowBackend {
|
|||
scrolling: false,
|
||||
overlay_id: OverlayID::null(),
|
||||
scale,
|
||||
resizable,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -300,6 +311,13 @@ impl WvrWindowBackend {
|
|||
if (scale_delta - 1.0).abs() > f32::EPSILON
|
||||
|| (curve_scale_delta - 1.0).abs() > f32::EPSILON
|
||||
{
|
||||
self.resizable = app
|
||||
.wvr_server
|
||||
.as_mut()
|
||||
.and_then(|wvr| wvr.wm.windows.get(&self.window))
|
||||
.map(|w| w.resizable())
|
||||
.unwrap_or(false);
|
||||
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(self.overlay_id),
|
||||
Box::new(move |_app, owc| {
|
||||
|
|
@ -978,6 +996,8 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
BackendAttrib::StereoAdjustMouse => Some(BackendAttribValue::StereoAdjustMouse(
|
||||
self.stereo_adjust_mouse,
|
||||
)),
|
||||
BackendAttrib::Resizable => Some(BackendAttribValue::Resizable(self.resizable)),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ pub enum BackendAttrib {
|
|||
StereoAdjustMouse,
|
||||
MouseTransform,
|
||||
Icon,
|
||||
Resizable,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
|
@ -36,9 +37,12 @@ pub enum BackendAttribValue {
|
|||
MouseTransform(MouseTransform),
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
Icon(Arc<str>),
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
Resizable(bool),
|
||||
}
|
||||
|
||||
impl BackendAttribValue {
|
||||
/// Used to determine if value should be saved
|
||||
pub fn is_default(&self) -> bool {
|
||||
match self {
|
||||
Self::Stereo(val) => *val == StereoMode::default(),
|
||||
|
|
@ -46,6 +50,7 @@ impl BackendAttribValue {
|
|||
Self::StereoAdjustMouse(val) => !*val,
|
||||
Self::MouseTransform(val) => *val == MouseTransform::default(),
|
||||
Self::Icon(_) => false,
|
||||
Self::Resizable(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue