Skip to content

Commit

Permalink
refactor: split pointer and touch input
Browse files Browse the repository at this point in the history
  • Loading branch information
technobaboo committed Dec 12, 2024
1 parent a08e246 commit dabc3eb
Show file tree
Hide file tree
Showing 3 changed files with 349 additions and 131 deletions.
56 changes: 36 additions & 20 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use initial_panel_placement::InitialPanelPlacement;
use initial_positioner::InitialPositioner;
use panel_ui::PanelUI;
use panel_wrapper::PanelWrapper;
use pointer_input::PointerPlane;
use resize_handles::ResizeHandles;
use rustc_hash::FxHashMap;
use stardust_xr_fusion::{
Expand All @@ -25,7 +26,7 @@ use stardust_xr_fusion::{
values::{color::rgba_linear, Color, Vector2},
};
use std::f32::consts::FRAC_PI_2;
use surface_input::SurfaceInput;
use touch_input::TouchPlane;
use tracing_subscriber::EnvFilter;

pub mod close_button;
Expand All @@ -35,8 +36,9 @@ pub mod initial_positioner;
pub mod panel_shell_transfer;
pub mod panel_ui;
pub mod panel_wrapper;
pub mod pointer_input;
pub mod resize_handles;
pub mod surface_input;
pub mod touch_input;

async fn accent_color() -> color_eyre::eyre::Result<Color> {
let accent_color = Settings::new().await?.accent_color().await?;
Expand Down Expand Up @@ -194,28 +196,13 @@ impl Reify for ToplevelState {
.build();

// input handler
let surface_input = SurfaceInput::<Self>::default()
let pointer_plane = PointerPlane::<Self>::default()
.pos([0.0, 0.0, panel_thickness / 2.0])
.physical_size([
self.info.size.x as f32 / self.density,
self.info.size.y as f32 / self.density,
])
.thickness(panel_thickness)
.on_touch_down(|state, id, position| {
let _ = state.panel_item.touch_down(
SurfaceId::Toplevel(()),
id,
[position.x * state.density, position.y * state.density],
);
})
.on_touch_move(|state, id, position| {
let _ = state
.panel_item
.touch_move(id, [position.x * state.density, position.y * state.density]);
})
.on_touch_up(|state, id| {
let _ = state.panel_item.touch_up(id);
})
.on_mouse_button(|state, button, pressed| {
let _ = state
.panel_item
Expand All @@ -228,7 +215,6 @@ impl Reify for ToplevelState {
);
})
.on_scroll(|state, scroll| {
dbg!(&scroll);
let _ = match (scroll.scroll_continuous, scroll.scroll_discrete) {
(None, None) => state
.panel_item
Expand All @@ -251,6 +237,29 @@ impl Reify for ToplevelState {
};
})
.build();
let touch_plane = TouchPlane::<Self>::default()
.pos([0.0, 0.0, panel_thickness / 2.0])
.physical_size([
self.info.size.x as f32 / self.density,
self.info.size.y as f32 / self.density,
])
.thickness(panel_thickness)
.on_touch_down(|state, id, position| {
let _ = state.panel_item.touch_down(
SurfaceId::Toplevel(()),
id,
[position.x * state.density, position.y * state.density],
);
})
.on_touch_move(|state, id, position| {
let _ = state
.panel_item
.touch_move(id, [position.x * state.density, position.y * state.density]);
})
.on_touch_up(|state, id| {
let _ = state.panel_item.touch_up(id);
})
.build();

// close button
let close_button = ExposureButton::<Self> {
Expand Down Expand Up @@ -324,7 +333,14 @@ impl Reify for ToplevelState {
state.info.size = size.into();
})),
}
.with_children([close_button, text, model, keyboard_handler, surface_input]);
.with_children([
close_button,
text,
model,
keyboard_handler,
pointer_plane,
touch_plane,
]);

let panel_wrapper = PanelWrapper::<Self>::new(self.panel_item.clone())
.on_toplevel_size_changed(|state, size| {
Expand Down
133 changes: 22 additions & 111 deletions src/surface_input.rs → src/pointer_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use stardust_xr_fusion::{
values::{color::rgba_linear, Vector3},
};
use stardust_xr_molecules::{
input_action::{InputQueue, InputQueueable, MultiAction, SimpleAction, SingleAction},
input_action::{InputQueue, InputQueueable, SimpleAction, SingleAction},
lines::{self, LineExt},
DebugSettings, VisualDebug,
};
Expand All @@ -31,74 +31,33 @@ pub struct MouseEvent {
#[derive(Setters)]
#[setters(into, strip_option)]
#[allow(clippy::type_complexity)]
pub struct SurfaceInput<State: ValidState> {
pub struct PointerPlane<State: ValidState> {
pub transform: Transform,
/// Physical size of the input surface in meters
pub physical_size: Vector2<f32>,
/// Thickness of the input volume in meters
pub thickness: f32,

/// Called when a touch starts
/// position: Vector3<f32> in meters relative to top-left corner
/// x: right is positive, y: down is positive, z: forward is positive
#[setters(skip)]
pub on_touch_down: FnWrapper<dyn Fn(&mut State, u32, Vector3<f32>) + Send + Sync>,
/// Called when a touch moves
/// position: Vector3<f32> in meters relative to top-left corner
/// x: right is positive, y: down is positive, z: forward is positive
#[setters(skip)]
pub on_touch_move: FnWrapper<dyn Fn(&mut State, u32, Vector3<f32>) + Send + Sync>,
#[setters(skip)]
pub on_touch_up: FnWrapper<dyn Fn(&mut State, u32) + Send + Sync>,

#[setters(skip)]
pub on_mouse_button: FnWrapper<dyn Fn(&mut State, u32, bool) + Send + Sync>,
/// Called when pointer moves
/// position: Vector3<f32> in meters relative to top-left corner
/// x: right is positive, y: down is positive, z: forward is positive
#[setters(skip)]
pub on_pointer_motion: FnWrapper<dyn Fn(&mut State, Vector3<f32>) + Send + Sync>,
#[setters(skip)]
pub on_scroll: FnWrapper<dyn Fn(&mut State, MouseEvent) + Send + Sync>,
}
impl<State: ValidState> Default for SurfaceInput<State> {

impl<State: ValidState> Default for PointerPlane<State> {
fn default() -> Self {
Self {
transform: Transform::identity(),
physical_size: [1.0; 2].into(),
thickness: 0.0,
on_touch_down: FnWrapper(Box::new(|_, _, _| {})),
on_touch_move: FnWrapper(Box::new(|_, _, _| {})),
on_touch_up: FnWrapper(Box::new(|_, _| {})),
on_mouse_button: FnWrapper(Box::new(|_, _, _| {})),
on_pointer_motion: FnWrapper(Box::new(|_, _| {})),
on_scroll: FnWrapper(Box::new(|_, _| {})),
}
}
}

impl<State: ValidState> SurfaceInput<State> {
pub fn on_touch_down(
mut self,
f: impl Fn(&mut State, u32, Vector3<f32>) + Send + Sync + 'static,
) -> Self {
self.on_touch_down = FnWrapper(Box::new(f));
self
}

pub fn on_touch_move(
mut self,
f: impl Fn(&mut State, u32, Vector3<f32>) + Send + Sync + 'static,
) -> Self {
self.on_touch_move = FnWrapper(Box::new(f));
self
}

pub fn on_touch_up(mut self, f: impl Fn(&mut State, u32) + Send + Sync + 'static) -> Self {
self.on_touch_up = FnWrapper(Box::new(f));
self
}

impl<State: ValidState> PointerPlane<State> {
pub fn on_mouse_button(
mut self,
f: impl Fn(&mut State, u32, bool) + Send + Sync + 'static,
Expand All @@ -121,8 +80,8 @@ impl<State: ValidState> SurfaceInput<State> {
}
}

impl<State: ValidState> ElementTrait<State> for SurfaceInput<State> {
type Inner = SurfaceInputInner;
impl<State: ValidState> ElementTrait<State> for PointerPlane<State> {
type Inner = PointerSurfaceInputInner;
type Error = NodeError;

fn create_inner(
Expand All @@ -140,19 +99,16 @@ impl<State: ValidState> ElementTrait<State> for SurfaceInput<State> {
let hover = SimpleAction::default();
let lines = Lines::create(&field, Transform::identity(), &[])?;

Ok(SurfaceInputInner {
Ok(PointerSurfaceInputInner {
input,
field,
hover,
pointer_hover: None,
left_click: SingleAction::default(),
middle_click: SingleAction::default(),
right_click: SingleAction::default(),
touch: MultiAction::default(),

physical_size: self.physical_size.into(),
thickness: self.thickness,

lines,
debug_line_settings: Some(DebugSettings::default()),
})
Expand All @@ -171,42 +127,40 @@ impl<State: ValidState> ElementTrait<State> for SurfaceInput<State> {
inner.field.clone().as_spatial().as_spatial_ref()
}
}
impl<State: ValidState> Transformable for SurfaceInput<State> {

impl<State: ValidState> Transformable for PointerPlane<State> {
fn transform(&self) -> &Transform {
&self.transform
}
fn transform_mut(&mut self) -> &mut Transform {
&mut self.transform
}
}
pub struct SurfaceInputInner {

pub struct PointerSurfaceInputInner {
input: InputQueue,
field: Field,
hover: SimpleAction,
pointer_hover: Option<Arc<InputData>>,
left_click: SingleAction,
middle_click: SingleAction,
right_click: SingleAction,
touch: MultiAction,

physical_size: Vec2,
thickness: f32,

lines: Lines,
debug_line_settings: Option<DebugSettings>,
}

impl SurfaceInputInner {
impl PointerSurfaceInputInner {
pub fn handle_events<State: ValidState>(
&mut self,
state: &mut State,
decl: &SurfaceInput<State>,
decl: &PointerPlane<State>,
) {
if !self.input.handle_events() {
return;
};
}
self.update_pointer(state, decl);
self.update_touches(state, decl);
self.update_signifiers();
}

Expand All @@ -220,10 +174,7 @@ impl SurfaceInputInner {
pub fn set_enabled(&mut self, enabled: bool) {
let _ = self.input.handler().set_enabled(enabled);
}
}

// Pointer inputs
impl SurfaceInputInner {
fn hovering(size: Vector2<f32>, point: Vector3<f32>, front: bool) -> bool {
point.x.abs() * 2.0 < size.x
&& point.y.abs() * 2.0 < size.y
Expand Down Expand Up @@ -258,7 +209,7 @@ impl SurfaceInputInner {
fn handle_button<State: ValidState>(
state: &mut State,
input: &InputQueue,
decl: &SurfaceInput<State>,
decl: &PointerPlane<State>,
action: &mut SingleAction,
finger: fn(&Hand) -> &Finger,
datamap_key: &str,
Expand Down Expand Up @@ -288,7 +239,7 @@ impl SurfaceInputInner {
}
}

fn update_pointer<State: ValidState>(&mut self, state: &mut State, decl: &SurfaceInput<State>) {
fn update_pointer<State: ValidState>(&mut self, state: &mut State, decl: &PointerPlane<State>) {
self.hover.update(&self.input, &|input| match &input.input {
InputDataType::Pointer(_) => input.distance <= 0.0,
_ => {
Expand Down Expand Up @@ -352,55 +303,14 @@ impl SurfaceInputInner {
.unwrap_or_default();
(decl.on_scroll.0)(state, mouse_event);
}
}

// Touch points
impl SurfaceInputInner {
pub fn update_touches<State: ValidState>(
&mut self,
state: &mut State,
decl: &SurfaceInput<State>,
) {
let physical_size = self.physical_size.into();
self.touch.update(
&self.input,
|input| match &input.input {
InputDataType::Pointer(_) => false,
InputDataType::Hand(h) => Self::hovering(physical_size, h.index.tip.position, true),
InputDataType::Tip(t) => Self::hovering(physical_size, t.origin, true),
},
|input| match &input.input {
InputDataType::Pointer(_) => {
input.datamap.with_data(|d| d.idx("select").as_f32() > 0.5)
}
InputDataType::Hand(h) => {
Self::hovering(physical_size, h.index.tip.position, false)
}
InputDataType::Tip(t) => Self::hovering(physical_size, t.origin, false),
},
);

for input_data in self.touch.interact().added().iter() {
let position = self.to_local_coords(Self::hover_point(input_data));
(decl.on_touch_down.0)(state, input_data.id as u32, position);
}
for input_data in self.touch.interact().current().iter() {
let position = self.to_local_coords(Self::hover_point(input_data));
(decl.on_touch_move.0)(state, input_data.id as u32, position);
}
for input_data in self.touch.interact().removed().iter() {
(decl.on_touch_up.0)(state, input_data.id as u32);
}
}
}

impl SurfaceInputInner {
fn update_signifiers(&mut self) {
let mut lines = self.hover_lines();
lines.extend(self.debug_lines());

self.lines.set_lines(&lines).unwrap();
}

fn debug_lines(&mut self) -> Vec<Line> {
let Some(settings) = &self.debug_line_settings else {
return vec![];
Expand Down Expand Up @@ -428,17 +338,18 @@ impl SurfaceInputInner {
fn hover_lines(&mut self) -> Vec<Line> {
self.pointer_hover
.iter()
.filter(|_| self.touch.interact().current().is_empty())
.filter_map(|p| self.line_from_input(p, p.captured))
.collect::<Vec<_>>()
}

fn line_from_input(&self, input: &InputData, interacting: bool) -> Option<Line> {
if let InputDataType::Pointer(_) = &input.input {
None
} else {
Some(self.line_from_point(SurfaceInputInner::hover_point(input), interacting))
Some(self.line_from_point(PointerSurfaceInputInner::hover_point(input), interacting))
}
}

fn line_from_point(&self, point: Vec3, interacting: bool) -> Line {
let settings = stardust_xr_molecules::hover_plane::HoverPlaneSettings::default();
Line {
Expand Down Expand Up @@ -476,7 +387,7 @@ impl SurfaceInputInner {
}
}

impl VisualDebug for SurfaceInputInner {
impl VisualDebug for PointerSurfaceInputInner {
fn set_debug(&mut self, settings: Option<DebugSettings>) {
self.debug_line_settings = settings;
}
Expand Down
Loading

0 comments on commit dabc3eb

Please sign in to comment.