mirror of https://github.com/wayvr-org/wayvr.git
done: grabbable resize corner
This commit is contained in:
parent
4f76a4abfb
commit
21749e22ed
|
|
@ -24,7 +24,7 @@
|
|||
<sprite src_builtin="dashboard/welcome.svg" width="32" height="32" margin="16"/>
|
||||
</Button>
|
||||
|
||||
<Button id="btn_website" macro="home_button" tooltip="wayvr.org">
|
||||
<Button id="btn_website" macro="home_button" tooltip_str="wayvr.org">
|
||||
<sprite src_builtin="dashboard/globe.svg" width="32" height="32" margin="16"/>
|
||||
</Button>
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@
|
|||
|
||||
<elements>
|
||||
<div width="100%" height="100%">
|
||||
<rectangle id="shadow" width="100%" height="100%" padding="4" gap="4" align_items="center" justify_content="center" color="#000000c0" flex_direction="row">
|
||||
<rectangle id="shadow" width="100%" height="100%" padding="4" gap="4" align_items="center" justify_content="space_between" color="#000000c0" flex_direction="column">
|
||||
<div />
|
||||
<div flex_direction="column">
|
||||
<rectangle padding="16" gap="8" round="32" color="~color_bg" border="2" border_color="~color_accent" justify_content="center">
|
||||
<div flex_direction="column" gap="8">
|
||||
|
|
@ -126,9 +127,13 @@
|
|||
</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>
|
||||
<div width="100%" justify_content="end" flex_direction="row">
|
||||
<div>
|
||||
<Button id="resize_corner" macro="button_style" tooltip="EDIT_MODE.RESIZE_CORNER" tooltip_side="left" _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>
|
||||
</div>
|
||||
</div>
|
||||
</rectangle>
|
||||
</div>
|
||||
</elements>
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@
|
|||
"POS_STATIC": "Static: Not part of any set, no recenter.",
|
||||
"POSITIONING": "Positioning",
|
||||
"RESIZE_PRESS_AND_DRAG": "Resize (press & drag)",
|
||||
"RESIZE_CORNER": "Click & hold to resize",
|
||||
"STEREO_3D_MODE": {
|
||||
"ADJUST_MOUSE": "Adjust mouse",
|
||||
"FULL_FRAME": "Full 3D",
|
||||
|
|
|
|||
|
|
@ -735,7 +735,9 @@ where
|
|||
};
|
||||
|
||||
if uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0 {
|
||||
continue;
|
||||
if !overlay.config.resizing {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let pointer_hit = PointerHit {
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ pub enum OverlayTask {
|
|||
SwitchSet(Option<usize>),
|
||||
ToggleOverlay(OverlaySelector, ToggleMode),
|
||||
ResetOverlay(OverlaySelector),
|
||||
ResizeOverlay(OverlaySelector, [u32; 2]),
|
||||
DeleteActiveSet,
|
||||
ToggleEditMode,
|
||||
ToggleDashboard,
|
||||
|
|
|
|||
|
|
@ -392,6 +392,7 @@ impl WvrServerState {
|
|||
let window_handle = wvr_server.wm.create_window(
|
||||
toplevel.clone(),
|
||||
process_handle,
|
||||
output_bounds,
|
||||
min_size,
|
||||
max_size,
|
||||
fallback_size.w as _,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use crate::{backend::wayvr::process, gen_id};
|
|||
pub struct Window {
|
||||
pub min_size: Size<i32, Logical>,
|
||||
pub max_size: Size<i32, Logical>,
|
||||
pub bounds: Size<i32, Logical>,
|
||||
pub size_x: u32,
|
||||
pub size_y: u32,
|
||||
pub visible: bool,
|
||||
|
|
@ -21,10 +22,12 @@ impl Window {
|
|||
const fn new(
|
||||
toplevel: Rc<ToplevelSurface>,
|
||||
process: process::ProcessHandle,
|
||||
bounds: Size<i32, Logical>,
|
||||
min_size: Size<i32, Logical>,
|
||||
max_size: Size<i32, Logical>,
|
||||
) -> Self {
|
||||
Self {
|
||||
bounds,
|
||||
min_size,
|
||||
max_size,
|
||||
size_x: 0,
|
||||
|
|
@ -39,6 +42,17 @@ impl Window {
|
|||
self.min_size != self.max_size
|
||||
}
|
||||
|
||||
pub fn checked_configure_size(&mut self, size: Size<i32, Logical>) {
|
||||
let clamped_size = size.clamp(self.min_size, self.max_size);
|
||||
|
||||
self.toplevel.with_pending_state(|state| {
|
||||
state.bounds = Some(self.bounds);
|
||||
state.size = Some(clamped_size);
|
||||
});
|
||||
self.toplevel.send_configure();
|
||||
self.remember_committed_size(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);
|
||||
|
|
@ -46,6 +60,7 @@ impl Window {
|
|||
});
|
||||
self.toplevel.send_configure();
|
||||
|
||||
self.bounds = bounds;
|
||||
if let Some(size) = size {
|
||||
self.remember_committed_size(size);
|
||||
}
|
||||
|
|
@ -106,12 +121,13 @@ impl WindowManager {
|
|||
&mut self,
|
||||
toplevel: Rc<ToplevelSurface>,
|
||||
process: process::ProcessHandle,
|
||||
bounds: Size<i32, Logical>,
|
||||
min_size: Size<i32, Logical>,
|
||||
max_size: Size<i32, Logical>,
|
||||
size_x: u32,
|
||||
size_y: u32,
|
||||
) -> WindowHandle {
|
||||
let mut window = Window::new(toplevel, process, min_size, max_size);
|
||||
let mut window = Window::new(toplevel, process, bounds, min_size, max_size);
|
||||
window.remember_committed_size(Size::new(size_x as i32, size_y as i32));
|
||||
self.windows.add(window)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||
let e = WguiEvent::MouseWheel(MouseWheelEvent {
|
||||
delta: vec2(delta.x, delta.y) / 8.0,
|
||||
pos: hit.uv * self.layout.content_size,
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
});
|
||||
self.push_event(app, &e);
|
||||
}
|
||||
|
|
@ -375,7 +375,7 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||
fn on_hover(&mut self, app: &mut AppState, hit: &PointerHit) -> HoverResult {
|
||||
let e = &WguiEvent::MouseMotion(MouseMotionEvent {
|
||||
pos: hit.uv * self.layout.content_size,
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
});
|
||||
|
||||
self.has_focus[hit.pointer] = true;
|
||||
|
|
@ -397,7 +397,7 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||
|
||||
fn on_left(&mut self, app: &mut AppState, pointer: usize) {
|
||||
let e = WguiEvent::MouseLeave(MouseLeaveEvent {
|
||||
device: DeviceBitmask::from_usize(pointer),
|
||||
device: DeviceBitmask::from_index(pointer),
|
||||
});
|
||||
self.has_focus[pointer] = false;
|
||||
self.push_event(app, &e);
|
||||
|
|
@ -415,13 +415,13 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||
WguiEvent::MouseDown(MouseButtonEvent {
|
||||
pos: hit.uv * self.layout.content_size,
|
||||
index,
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
})
|
||||
} else {
|
||||
WguiEvent::MouseUp(MouseButtonEvent {
|
||||
pos: hit.uv * self.layout.content_size,
|
||||
index,
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
})
|
||||
};
|
||||
self.push_event(app, &e);
|
||||
|
|
@ -430,11 +430,11 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||
if !pressed && !self.has_focus[hit.pointer] {
|
||||
let e = WguiEvent::MouseMotion(MouseMotionEvent {
|
||||
pos: vec2(-1., -1.),
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
});
|
||||
self.push_event(app, &e);
|
||||
let e = WguiEvent::MouseLeave(MouseLeaveEvent {
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
});
|
||||
self.push_event(app, &e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ impl OverlayBackend for DashFrontend {
|
|||
let e = WguiEvent::MouseWheel(MouseWheelEvent {
|
||||
delta: vec2(delta.x, delta.y) / 8.0,
|
||||
pos: hit.uv * self.inner.layout.content_size,
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
});
|
||||
self.push_event(&e);
|
||||
}
|
||||
|
|
@ -241,7 +241,7 @@ impl OverlayBackend for DashFrontend {
|
|||
fn on_hover(&mut self, _app: &mut AppState, hit: &PointerHit) -> HoverResult {
|
||||
let e = &WguiEvent::MouseMotion(MouseMotionEvent {
|
||||
pos: hit.uv * self.inner.layout.content_size,
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
});
|
||||
|
||||
self.has_focus[hit.pointer] = true;
|
||||
|
|
@ -264,7 +264,7 @@ impl OverlayBackend for DashFrontend {
|
|||
|
||||
fn on_left(&mut self, _app: &mut AppState, pointer: usize) {
|
||||
let e = WguiEvent::MouseLeave(MouseLeaveEvent {
|
||||
device: DeviceBitmask::from_usize(pointer),
|
||||
device: DeviceBitmask::from_index(pointer),
|
||||
});
|
||||
self.has_focus[pointer] = false;
|
||||
self.push_event(&e);
|
||||
|
|
@ -282,13 +282,13 @@ impl OverlayBackend for DashFrontend {
|
|||
WguiEvent::MouseDown(MouseButtonEvent {
|
||||
pos: hit.uv * self.inner.layout.content_size,
|
||||
index,
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
})
|
||||
} else {
|
||||
WguiEvent::MouseUp(MouseButtonEvent {
|
||||
pos: hit.uv * self.inner.layout.content_size,
|
||||
index,
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
})
|
||||
};
|
||||
self.push_event(&e);
|
||||
|
|
@ -297,11 +297,11 @@ impl OverlayBackend for DashFrontend {
|
|||
if !pressed && !self.has_focus[hit.pointer] {
|
||||
let e = WguiEvent::MouseMotion(MouseMotionEvent {
|
||||
pos: vec2(-1., -1.),
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
});
|
||||
self.push_event(&e);
|
||||
let e = WguiEvent::MouseLeave(MouseLeaveEvent {
|
||||
device: DeviceBitmask::from_usize(hit.pointer),
|
||||
device: DeviceBitmask::from_index(hit.pointer),
|
||||
});
|
||||
self.push_event(&e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,19 @@ mod sprite_tab;
|
|||
mod stereo;
|
||||
pub mod tab;
|
||||
|
||||
enum ResizeState {
|
||||
None,
|
||||
Start {
|
||||
overlay_id: OverlayID,
|
||||
},
|
||||
Active {
|
||||
overlay_id: OverlayID,
|
||||
pointer: usize,
|
||||
start_uv: Vec2,
|
||||
last_uv: Vec2,
|
||||
},
|
||||
}
|
||||
|
||||
struct EditModeState {
|
||||
tasks: Rc<RefCell<TaskContainer>>,
|
||||
id: Rc<RefCell<OverlayID>>,
|
||||
|
|
@ -60,7 +73,23 @@ struct EditModeState {
|
|||
pos: SpriteTabHandler<PosTabState>,
|
||||
stereo: SpriteTabHandler<StereoMode>,
|
||||
mouse: SpriteTabHandler<MouseTransform>,
|
||||
resize_uv: Option<Vec2>,
|
||||
resize: ResizeState,
|
||||
}
|
||||
|
||||
impl EditModeState {
|
||||
fn resize_end(&mut self, app: &mut AppState) {
|
||||
match std::mem::replace(&mut self.resize, ResizeState::None) {
|
||||
ResizeState::Active { overlay_id, .. } => {
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(overlay_id),
|
||||
Box::new(|_app, owc| {
|
||||
owc.resizing = false;
|
||||
}),
|
||||
)));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type EditModeWrapPanel = GuiPanel<EditModeState>;
|
||||
|
|
@ -96,7 +125,7 @@ impl EditWrapperManager {
|
|||
owc.backend = Box::new(EditModeBackendWrapper {
|
||||
inner: ManuallyDrop::new(inner),
|
||||
panel: ManuallyDrop::new(panel),
|
||||
last_extent: [0, 0],
|
||||
extent: [0, 0],
|
||||
last_render: Instant::now(),
|
||||
can_render_inner: false,
|
||||
});
|
||||
|
|
@ -138,7 +167,7 @@ pub struct EditModeBackendWrapper {
|
|||
panel: ManuallyDrop<EditModeWrapPanel>,
|
||||
inner: ManuallyDrop<Box<dyn OverlayBackend>>,
|
||||
|
||||
last_extent: [u32; 2],
|
||||
extent: [u32; 2],
|
||||
last_render: Instant,
|
||||
can_render_inner: bool,
|
||||
}
|
||||
|
|
@ -217,7 +246,7 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||
rdr.cmd_bufs.reverse();
|
||||
}
|
||||
|
||||
self.last_extent = rdr.extent;
|
||||
self.extent = rdr.extent;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -233,23 +262,32 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||
let _ = self.inner.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);
|
||||
match &mut self.panel.state.resize {
|
||||
ResizeState::Active {
|
||||
overlay_id,
|
||||
pointer,
|
||||
start_uv,
|
||||
last_uv,
|
||||
} if *pointer == hit.pointer => {
|
||||
// freshest extent we can get is from last frame, so use uv from that frame
|
||||
let new_extent = resize_centered_from_uv(*start_uv, *last_uv, self.extent);
|
||||
|
||||
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:?}");
|
||||
app.tasks
|
||||
.enqueue(TaskType::Overlay(OverlayTask::ResizeOverlay(
|
||||
OverlaySelector::Id(*overlay_id),
|
||||
new_extent,
|
||||
)));
|
||||
|
||||
*last_uv = hit.uv;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
fn on_left(&mut self, app: &mut crate::state::AppState, pointer: usize) {
|
||||
self.panel.state.resize_end(app);
|
||||
|
||||
self.inner.on_left(app, pointer);
|
||||
self.panel.on_left(app, pointer);
|
||||
}
|
||||
|
|
@ -260,6 +298,26 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||
pressed: bool,
|
||||
) {
|
||||
self.panel.on_pointer(app, hit, pressed);
|
||||
|
||||
match &mut self.panel.state.resize {
|
||||
ResizeState::Start { overlay_id } => {
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(*overlay_id),
|
||||
Box::new(|_app, owc| {
|
||||
owc.resizing = true;
|
||||
}),
|
||||
)));
|
||||
|
||||
let last_uv = hit.uv;
|
||||
self.panel.state.resize = ResizeState::Active {
|
||||
overlay_id: *overlay_id,
|
||||
pointer: hit.pointer,
|
||||
start_uv: last_uv,
|
||||
last_uv: last_uv,
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
fn on_scroll(
|
||||
&mut self,
|
||||
|
|
@ -270,7 +328,8 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||
self.panel.on_scroll(app, hit, delta);
|
||||
}
|
||||
fn notify(&mut self, app: &mut AppState, event_data: OverlayEventData) -> anyhow::Result<()> {
|
||||
self.panel.notify(app, event_data)
|
||||
self.panel.notify(app, event_data.clone())?;
|
||||
self.inner.notify(app, event_data)
|
||||
}
|
||||
fn get_interaction_transform(&mut self) -> Option<glam::Affine2> {
|
||||
self.inner.get_interaction_transform()
|
||||
|
|
@ -293,7 +352,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
|||
pos: SpriteTabHandler::default(),
|
||||
stereo: SpriteTabHandler::default(),
|
||||
mouse: SpriteTabHandler::default(),
|
||||
resize_uv: None,
|
||||
resize: ResizeState::None,
|
||||
};
|
||||
|
||||
let anim_mult = app.wgui_theme.animation_mult;
|
||||
|
|
@ -434,14 +493,16 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
|||
if !test_button(data) || !test_duration(&button, app) {
|
||||
return Ok(EventResult::Pass);
|
||||
}
|
||||
state.resize_uv = data.metadata.get_mouse_pos_absolute();
|
||||
state.resize = ResizeState::Start {
|
||||
overlay_id: state.id.borrow().clone(),
|
||||
};
|
||||
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;
|
||||
state.resize_end(app);
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
_ => return,
|
||||
|
|
@ -742,3 +803,25 @@ fn set_up_checkbox(
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn resize_centered_from_uv(grab_uv: Vec2, cur_uv: Vec2, cur_extent: [u32; 2]) -> [u32; 2] {
|
||||
const MIN_SIZE: Vec2 = Vec2::new(160.0, 160.0);
|
||||
const CENTER_DEADZONE: f32 = 0.1;
|
||||
|
||||
let cur_extent_v = Vec2::new(cur_extent[0] as f32, cur_extent[1] as f32);
|
||||
let grab_from_center = grab_uv - Vec2::splat(0.5);
|
||||
let cur_from_center = (cur_uv - Vec2::splat(0.5)) * cur_extent_v;
|
||||
|
||||
let mut out = cur_extent_v;
|
||||
if grab_from_center.x.abs() > CENTER_DEADZONE {
|
||||
out.x = (cur_from_center.x / grab_from_center.x).abs();
|
||||
}
|
||||
|
||||
if grab_from_center.y.abs() > CENTER_DEADZONE {
|
||||
out.y = (cur_from_center.y / grab_from_center.y).abs();
|
||||
}
|
||||
|
||||
out = out.max(MIN_SIZE);
|
||||
|
||||
[out.x.round() as u32, out.y.round() as u32]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ use crate::{
|
|||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum WvrCommand {
|
||||
CloseWindow,
|
||||
KillProcess(KillSignal),
|
||||
|
|
@ -800,6 +801,15 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
};
|
||||
wvr_server.terminate_process(p.process, signal);
|
||||
}
|
||||
OverlayEventData::ResizeRequest(new_size) => {
|
||||
let wvr_server = app.wvr_server.as_mut().unwrap();
|
||||
let Some(win) = wvr_server.wm.windows.get_mut(&self.window) else {
|
||||
log::warn!("Could not process resize request: window not found");
|
||||
return Ok(());
|
||||
};
|
||||
let size: Size<i32, Logical> = Size::new(new_size[0] as i32, new_size[1] as i32);
|
||||
win.checked_configure_size(size);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ pub struct OverlayMeta {
|
|||
}
|
||||
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
#[derive(Clone)]
|
||||
pub enum OverlayEventData {
|
||||
/// Notifies a newly added overlay of its ID, even before the overlay is shown.
|
||||
IdAssigned(OverlayID),
|
||||
|
|
@ -128,6 +129,7 @@ pub enum OverlayEventData {
|
|||
command: ModifyPanelCommand,
|
||||
},
|
||||
WvrCommand(WvrCommand),
|
||||
ResizeRequest([u32; 2]),
|
||||
}
|
||||
|
||||
pub trait OverlayBackend: Any {
|
||||
|
|
|
|||
|
|
@ -193,6 +193,18 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
OverlayTask::ResizeOverlay(sel, size) => {
|
||||
let Some(id) = self.id_by_selector(&sel) else {
|
||||
log::warn!("Overlay not found for task: {sel:?}");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let o = &mut self.overlays[id];
|
||||
|
||||
o.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::ResizeRequest(size))?;
|
||||
}
|
||||
OverlayTask::ToggleOverlay(sel, mode) => {
|
||||
let Some(id) = self.id_by_selector(&sel) else {
|
||||
log::warn!("Overlay not found for task: {sel:?}");
|
||||
|
|
@ -230,8 +242,6 @@ where
|
|||
o.config.activate(app);
|
||||
}
|
||||
self.visible_overlays_changed(app)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
OverlayTask::ToggleEditMode => {
|
||||
self.set_edit_mode(!self.edit_mode, app)?;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ pub struct OverlayWindowConfig {
|
|||
pub dirty: bool,
|
||||
/// True if the window is showing the edit overlay
|
||||
pub editing: bool,
|
||||
/// True if the window is being resized. Captures pointer hits even if not directly hit.
|
||||
pub resizing: bool,
|
||||
/// Used by grab to pause following of HMD or other devices
|
||||
pub pause_movement: bool,
|
||||
}
|
||||
|
|
@ -108,6 +110,7 @@ impl OverlayWindowConfig {
|
|||
global: false,
|
||||
dirty: true,
|
||||
editing: false,
|
||||
resizing: false,
|
||||
pause_movement: false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,13 @@ use crate::{
|
|||
pub struct DeviceBitmask(pub u8);
|
||||
|
||||
impl DeviceBitmask {
|
||||
pub fn from_usize(mask: usize) -> Self {
|
||||
// more than 8 input devices?
|
||||
debug_assert!(mask & !0xff == 0);
|
||||
Self(mask as u8)
|
||||
}
|
||||
pub fn from_index(index: usize) -> Self {
|
||||
debug_assert!(index < 8);
|
||||
Self(1u8 << index)
|
||||
}
|
||||
pub fn to_index(self) -> Option<usize> {
|
||||
(self.0 != 0).then(|| self.0.trailing_zeros() as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue