Multitouch Level Panning
Add multi-touch gesture support so that the player can scroll the level in the editor (and title screen) by treating a two finger swipe to be equivalent to a middle click drag. Fun quirks found with SDL2's MultiGestureEvent: * They don't begin sending us the event until motion is detected after two fingers have touched the screen; not the moment the second finger touches it. * It spams us with events when it detects any tiny change and a lot of cool details like rotate/pinch deltas, but it never tells us when the multitouch STOPS! The game has to block left clicks while multitouch happens so the user doesn't draw all over their level, so it needs to know when touch has ended. * The workaround is to track the mouse cursor position at the first touch and each delta thereafter; if the deltas stop changing tick to tick, unset the "is touching" variable.
This commit is contained in:
parent
cc16a472af
commit
a24c94a161
|
@ -95,10 +95,11 @@ type Canvas struct {
|
||||||
lastPixel *level.Pixel
|
lastPixel *level.Pixel
|
||||||
|
|
||||||
// We inherit the ui.Widget which manages the width and height.
|
// We inherit the ui.Widget which manages the width and height.
|
||||||
Scroll render.Point // Scroll offset for which parts of canvas are visible.
|
Scroll render.Point // Scroll offset for which parts of canvas are visible.
|
||||||
scrollDragging bool // Middle-click to pan scroll
|
scrollDragging bool // Middle-click to pan scroll
|
||||||
scrollStartAt render.Point // Cursor point at beginning of pan
|
scrollStartAt render.Point // Cursor point at beginning of pan
|
||||||
scrollWasAt render.Point // copy of Scroll at beginning of pan
|
scrollWasAt render.Point // copy of Scroll at beginning of pan
|
||||||
|
scrollLastDelta render.Point // multitouch spam
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCanvas initializes a Canvas widget.
|
// NewCanvas initializes a Canvas widget.
|
||||||
|
|
|
@ -54,8 +54,41 @@ func (w *Canvas) loopEditorScroll(ev *event.State) error {
|
||||||
w.ScrollBy(scrollBy)
|
w.ScrollBy(scrollBy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multitouch events to pan the level, like middle click on desktop.
|
||||||
|
if ev.Touching {
|
||||||
|
// Intention: user drags with 2 fingers to scroll the canvas.
|
||||||
|
// SDL2 will register one finger also as a Button1 mouse click.
|
||||||
|
// We need to record the "mouse cursor" as start point but then
|
||||||
|
// fake that no click occurs so we don't nick the drawing.
|
||||||
|
if !w.scrollDragging {
|
||||||
|
w.scrollDragging = true
|
||||||
|
w.scrollStartAt = shmem.Cursor
|
||||||
|
w.scrollWasAt = w.Scroll
|
||||||
|
w.scrollLastDelta = render.Point{}
|
||||||
|
} else {
|
||||||
|
delta := shmem.Cursor.Compare(w.scrollStartAt)
|
||||||
|
w.Scroll = w.scrollWasAt
|
||||||
|
w.Scroll.Subtract(delta)
|
||||||
|
|
||||||
|
// So, SDL2 spams us with events for every subtle movement of 2+ fingers
|
||||||
|
// on the screen, but we don't know when that STOPS. As a heuristic, it
|
||||||
|
// seems we can tell by if the delta stops updating.
|
||||||
|
if !w.scrollLastDelta.IsZero() {
|
||||||
|
if w.scrollLastDelta == delta {
|
||||||
|
ev.Touching = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.scrollLastDelta = delta
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lift the mouse button.
|
||||||
|
ev.Button1 = false
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Middle click of the mouse to pan the level.
|
// Middle click of the mouse to pan the level.
|
||||||
// NOTE: returns are below!
|
|
||||||
if keybind.MiddleClick(ev) {
|
if keybind.MiddleClick(ev) {
|
||||||
if !w.scrollDragging {
|
if !w.scrollDragging {
|
||||||
w.scrollDragging = true
|
w.scrollDragging = true
|
||||||
|
|
Loading…
Reference in New Issue
Block a user