Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic multi touch support (issue #279) #306

Merged
merged 36 commits into from
May 6, 2021
Merged
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3cae7c5
translate touch events from glium to egui
quadruple-output Apr 9, 2021
9dbda04
translate touch events from web_sys to egui
quadruple-output Apr 10, 2021
7c1c01a
introduce `TouchState` and `Gesture`
quadruple-output Apr 11, 2021
69dafcc
add method InputState::zoom()
quadruple-output Apr 11, 2021
7d30aa1
manage one `TouchState` per individual device
quadruple-output Apr 11, 2021
2d8406b
implement control loop for gesture detection
quadruple-output Apr 11, 2021
c2908ab
streamline `Gesture` trait, simplifying impl's
quadruple-output Apr 12, 2021
a5da37d
implement first version of Zoom gesture
quadruple-output Apr 12, 2021
45e59e7
fix failing doctest
quadruple-output Apr 13, 2021
c348c6c
Merge remote-tracking branch 'upstream/master' into issue-279-touch-g…
quadruple-output Apr 17, 2021
9e841d5
get rid of `Gesture`s
quadruple-output Apr 17, 2021
dfc4f20
Provide a Zoom/Rotate window in the demo app
quadruple-output Apr 18, 2021
286e4d5
fix comments and non-idiomatic code
quadruple-output Apr 18, 2021
39d93e1
update touch state *each frame*
quadruple-output Apr 18, 2021
99176c3
Merge remote-tracking branch 'upstream/master' into issue-279-touch-g…
quadruple-output Apr 18, 2021
de4b4cd
Merge remote-tracking branch 'upstream/master' into issue-279-touch-g…
quadruple-output Apr 21, 2021
211972e
change egui_demo to use *relative* touch data
quadruple-output Apr 22, 2021
ca846e5
support more than two fingers
quadruple-output Apr 23, 2021
0882300
Merge remote-tracking branch 'upstream/master' into issue-279-touch-g…
quadruple-output Apr 23, 2021
0d7d20a
Merge remote-tracking branch 'upstream/master' into issue-279-touch-g…
quadruple-output Apr 26, 2021
bd5b909
cleanup code and comments for review
quadruple-output Apr 26, 2021
cc054b8
minor code simplifications
quadruple-output Apr 28, 2021
fee8ed8
oops – forgot the changelog
quadruple-output Apr 28, 2021
0687b82
Merge remote-tracking branch 'upstream/master' into issue-279-touch-g…
quadruple-output Apr 29, 2021
ce8f3a8
resolve comment https://github.com/emilk/egui/pull/306/files/fee8ed83…
quadruple-output Apr 29, 2021
9c6c6b1
accept suggestion https://github.com/emilk/egui/pull/306#discussion_r…
quadruple-output Apr 29, 2021
5c27120
fix syntax error (dough!)
quadruple-output Apr 29, 2021
612069a
remove `dbg!` (why didnt clippy see this?)
quadruple-output Apr 29, 2021
e3cc56e
apply suggested diffs from review
quadruple-output Apr 29, 2021
e4c9a65
fix conversion of physical location to Pos2
quadruple-output Apr 29, 2021
67b5a88
Merge remote-tracking branch 'upstream/master' into issue-279-touch-g…
quadruple-output May 1, 2021
3918653
remove redundanct type `TouchAverages`
quadruple-output May 1, 2021
9161b12
Merge remote-tracking branch 'upstream' into issue-279-touch-gesture-…
quadruple-output May 3, 2021
b38e225
remove trailing space
quadruple-output May 3, 2021
acbefda
avoid initial translation jump in plot demo
quadruple-output May 3, 2021
755ca30
extend the demo so it shows off translation
quadruple-output May 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
remove redundanct type TouchAverages
  • Loading branch information
quadruple-output committed May 1, 2021
commit 3918653979261912606a2a6d184c0c964fdcc1ce
68 changes: 27 additions & 41 deletions egui/src/input_state/touch_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,17 @@ pub(crate) struct TouchState {
struct GestureState {
start_time: f64,
start_pointer_pos: Pos2,
force: f32,
previous: Option<DynGestureState>,
current: DynGestureState,
}

/// Gesture data which can change over time
/// Gesture data that can change over time
#[derive(Clone, Copy, Debug)]
struct DynGestureState {
quadruple-output marked this conversation as resolved.
Show resolved Hide resolved
avg_pos: Pos2,
avg_distance: f32,
direction: f32,
avg_pos: Pos2,
avg_force: f32,
heading: f32,
}

/// Describes an individual touch (finger or digitizer) on the touch surface. Instances exist as
Expand Down Expand Up @@ -159,34 +159,26 @@ impl TouchState {
start_pos: state.start_pointer_pos,
num_touches: self.active_touches.len(),
zoom_delta: state.current.avg_distance / state_previous.avg_distance,
rotation_delta: normalized_angle(state.current.direction, state_previous.direction),
rotation_delta: normalized_angle(state.current.heading, state_previous.heading),
translation_delta: state.current.avg_pos - state_previous.avg_pos,
force: state.force,
force: state.current.avg_force,
}
})
}

fn update_gesture(&mut self, time: f64, pointer_pos: Option<Pos2>) {
if let Some(avg) = self.calc_averages() {
if let Some(dyn_state) = self.calc_dynamic_state() {
if let Some(ref mut state) = &mut self.gesture_state {
// updating an ongoing gesture
state.force = avg.force;
state.previous = Some(state.current);
state.current.avg_pos = avg.pos;
state.current.direction = avg.direction;
state.current.avg_distance = avg.distance;
state.current = dyn_state;
} else if let Some(pointer_pos) = pointer_pos {
// starting a new gesture
self.gesture_state = Some(GestureState {
start_time: time,
start_pointer_pos: pointer_pos,
force: avg.force,
previous: None,
current: DynGestureState {
avg_pos: avg.pos,
avg_distance: avg.distance,
direction: avg.direction,
},
current: dyn_state,
});
}
} else {
Expand All @@ -195,34 +187,34 @@ impl TouchState {
}
}

fn calc_averages(&self) -> Option<TouchAverages> {
fn calc_dynamic_state(&self) -> Option<DynGestureState> {
let num_touches = self.active_touches.len();
if num_touches < 2 {
None
} else {
let mut avg = TouchAverages {
pos: Pos2::ZERO,
force: 0.,
distance: 0.,
direction: 0.,
let mut state = DynGestureState {
avg_distance: 0.,
avg_pos: Pos2::ZERO,
avg_force: 0.,
heading: 0.,
};
let num_touches_rezip = 1. / num_touches as f32;
let num_touches_recip = 1. / num_touches as f32;

// first pass: calculate force, and center position:
// first pass: calculate force and center of touch positions:
for touch in self.active_touches.values() {
avg.force += touch.force;
avg.pos.x += touch.pos.x;
avg.pos.y += touch.pos.y;
state.avg_force += touch.force;
state.avg_pos.x += touch.pos.x;
state.avg_pos.y += touch.pos.y;
}
avg.force *= num_touches_rezip;
avg.pos.x *= num_touches_rezip;
avg.pos.y *= num_touches_rezip;
state.avg_force *= num_touches_recip;
state.avg_pos.x *= num_touches_recip;
state.avg_pos.y *= num_touches_recip;

// second pass: calculate distances from center:
for touch in self.active_touches.values() {
avg.distance += avg.pos.distance(touch.pos);
state.avg_distance += state.avg_pos.distance(touch.pos);
}
avg.distance *= num_touches_rezip;
state.avg_distance *= num_touches_recip;

// Calculate the direction from the first touch to the center position.
// This is not the perfect way of calculating the direction if more than two fingers
Expand All @@ -235,18 +227,12 @@ impl TouchState {
// direction. But this approach cannot be implemented locally in this method, making
// everything a bit more complicated.
let first_touch = self.active_touches.values().next().unwrap();
avg.direction = (avg.pos - first_touch.pos).angle();
state.heading = (state.avg_pos - first_touch.pos).angle();

Some(avg)
Some(state)
}
}
}
struct TouchAverages {
pos: Pos2,
force: f32,
distance: f32,
direction: f32,
}

impl TouchState {
pub fn ui(&self, ui: &mut crate::Ui) {
Expand Down