自分が今回やりたかったケースは、スマホゲームによくある、ボタン系をそのままに後ろのマップをスクロールできるような感じ
UIをStageで定義していて、StageはInputAdapterを継承している
これに対して後ろのレイヤをタッチ操作でスクロールする処理を施そうと思い、
GestureDetectorを使おうと考えた
しかしこちらもInputAdapterを継承している為、UIの入力との同時設定が直にはできない
こんな時に、Gdx.input.inputProcessorへ複数を登録する為に使えるのがInputMultiplexer
InputMultiplexer自体の使い方は単純で、インスタンス化して上位レイヤから順にInputProcessorを登録していくだけ
以下、サンプルコード
val im = InputMultiplexer()
// uiのステージを先に登録
im.addProcessor(ui.stage)
im.addProcessor(GestureDetector(CameraScroller()))
Gdx.input.inputProcessor = im
// pan操作でcameraを動かすだけのリスナー
private inner class CameraScroller : GestureDetector.GestureListener {
override fun pan(x: Float, y: Float, deltaX: Float, deltaY: Float): Boolean {
camera.translate(-deltaX, deltaY)
return true
}
override fun panStop(x: Float, y: Float, pointer: Int, button: Int): Boolean = true
override fun pinch(initialPointer1: Vector2?, initialPointer2: Vector2?, pointer1: Vector2?, pointer2: Vector2?): Boolean = false
override fun pinchStop() {}
override fun longPress(x: Float, y: Float): Boolean = false
override fun fling(velocityX: Float, velocityY: Float, button: Int): Boolean = false
override fun touchDown(x: Float, y: Float, pointer: Int, button: Int): Boolean = false
override fun zoom(initialDistance: Float, distance: Float): Boolean = false
override fun tap(x: Float, y: Float, count: Int, button: Int): Boolean = false
}
// あんまりオーバーライドしないならアダプター版もあるヨ
private inner class CameraScroller : GestureDetector.GestureAdapter() {
override fun pan(x: Float, y: Float, deltaX: Float, deltaY: Float): Boolean {
camera.translate(-deltaX, deltaY)
return true
}
override fun panStop(x: Float, y: Float, pointer: Int, button: Int): Boolean = true
}
登録されたInputProcessorは登録順で呼び出される
同じイベントが順次発火するようにしていた場合に重要になるのが各イベントの戻り値で、先に実行されたInputProcessorがtrueを返すと後のInputProcessorのイベントが呼び出されなくなるっぽい
いわゆるstopPropagation(cancelBubble)みたいな使い方ができるわけだ(けど若干クセがある)
この辺はInputMultiplexerのソースを見るとわかりやすいかも