Skip to content

Commit

Permalink
multi touch handling on android
Browse files Browse the repository at this point in the history
  • Loading branch information
regb committed Sep 30, 2016
1 parent ae45dce commit 7804a72
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
24 changes: 21 additions & 3 deletions android/src/main/scala/sgl/android/AndroidInputProvider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,26 @@ trait AndroidInputProvider extends InputProvider with Lifecycle {
override def onTouch(view: View, event: MotionEvent): Boolean = {
gestureDetector.onTouchEvent(event)

/*
* Multi-touch on android starts with a first ACTION_DOWN event for the
* very first pointer, then following down are ACTION_POINTER_DOWN, and
* first up (as long as one finger is still left) is ACTION_POINTER_UP.
* Seems like we don't need that level of precision in the engine, so we
* only have the notion of Up and Down, relying on the pointer id if we
* need to track a multitouch gesture
*/

val action = event.getActionMasked
for(p <- 0 until event.getPointerCount()) {
if(event.getAction == MotionEvent.ACTION_DOWN) {
if(action == MotionEvent.ACTION_DOWN) {
val x = event.getX(p).toInt
val y = event.getY(p).toInt
Input.newEvent(Input.TouchDownEvent(x, y, event.getPointerId(p)))
} else if(event.getAction == MotionEvent.ACTION_MOVE) {
} else if(action == MotionEvent.ACTION_POINTER_DOWN) {
val x = event.getX(p).toInt
val y = event.getY(p).toInt
Input.newEvent(Input.TouchDownEvent(x, y, event.getPointerId(p)))
} else if(action == MotionEvent.ACTION_MOVE) {

//ACTION_MOVE is sometimes batched, meaning that we need to consume
//historical data from the event, that shows intermediate position
Expand All @@ -38,7 +52,11 @@ trait AndroidInputProvider extends InputProvider with Lifecycle {
val x = event.getX(p).toInt
val y = event.getY(p).toInt
Input.newEvent(Input.TouchMovedEvent(x, y, event.getPointerId(p)))
} else if(event.getAction == MotionEvent.ACTION_UP) {
} else if(action == MotionEvent.ACTION_POINTER_UP) {
val x = event.getX(p).toInt
val y = event.getY(p).toInt
Input.newEvent(Input.TouchUpEvent(x, y, event.getPointerId(p)))
} else if(action == MotionEvent.ACTION_UP) {
val x = event.getX(p).toInt
val y = event.getY(p).toInt
Input.newEvent(Input.TouchUpEvent(x, y, event.getPointerId(p)))
Expand Down
12 changes: 12 additions & 0 deletions core/src/main/scala/sgl/InputHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,17 @@ trait InputHelpersComponent extends Lifecycle {
ev foreach processEvent
ev
}
def processEvents(function: (InputEvent) => Unit): Unit = {
var oev = Input.pollEvent()
while(!oev.isEmpty) {
val ev = oev.get
processEvent(ev)
function(ev)
oev = pollEvent()
}
}

//TODO: not a good name, confusing with processEvents
/** Process an input event to maintain state of inputs */
def processEvent(event: InputEvent): Unit = event match {
case KeyDownEvent(key) => setKeyboardState(key, true)
Expand Down Expand Up @@ -185,6 +195,8 @@ trait InputHelpersComponent extends Lifecycle {
/** is defined if at least one pointer is pressed */
def pressed: Option[(Int, Int)] = pointerPressed.toSeq.headOption.map(_._2)
def pressed(pointer: Int): Option[(Int, Int)] = pointerPressed.get(pointer)

def allPressed: Seq[(Int, (Int, Int))] = pointerPressed.toSeq
}

object Mouse {
Expand Down

0 comments on commit 7804a72

Please sign in to comment.