diff --git a/core/src/com/unciv/ui/utils/ZoomGestureListener.kt b/core/src/com/unciv/ui/utils/ZoomGestureListener.kt new file mode 100644 index 0000000000..4e729f455f --- /dev/null +++ b/core/src/com/unciv/ui/utils/ZoomGestureListener.kt @@ -0,0 +1,80 @@ +package com.unciv.ui.utils + +import com.badlogic.gdx.input.GestureDetector +import com.badlogic.gdx.math.Vector2 +import com.badlogic.gdx.scenes.scene2d.Event +import com.badlogic.gdx.scenes.scene2d.EventListener +import com.badlogic.gdx.scenes.scene2d.InputEvent + +open class ZoomGestureListener( + halfTapSquareSize: Float, tapCountInterval: Float, longPressDuration: Float, maxFlingDelay: Float +) : EventListener { + + val detector: GestureDetector + var event: InputEvent? = null + + constructor() : this(20f, 0.4f, 1.1f, Int.MAX_VALUE.toFloat()) + + init { + detector = GestureDetector( + halfTapSquareSize, + tapCountInterval, + longPressDuration, + maxFlingDelay, + object : GestureDetector.GestureAdapter() { + + override fun zoom(initialDistance: Float, distance: Float): Boolean { + this@ZoomGestureListener.zoom(event, initialDistance, distance) + return true + } + + override fun pinch( + stageInitialPointer1: Vector2, + stageInitialPointer2: Vector2, + stagePointer1: Vector2, + stagePointer2: Vector2 + ): Boolean { + this@ZoomGestureListener.pinch() + return true + } + + override fun pinchStop() { + this@ZoomGestureListener.pinchStop() + } + }) + } + + + override fun handle(event: Event?): Boolean { + if (event !is InputEvent) + return false + when (event.type) { + InputEvent.Type.touchDown -> { + detector.touchDown(event.stageX, event.stageY, event.pointer, event.button) + if (event.touchFocus) event.stage.addTouchFocus( + this, event.listenerActor, event.target, + event.pointer, event.button + ) + return true + } + InputEvent.Type.touchUp -> { + if (event.isTouchFocusCancel) { + detector.reset() + return false + } + this.event = event + detector.touchUp(event.stageX, event.stageY, event.pointer, event.button) + return true + } + InputEvent.Type.touchDragged -> { + this.event = event + detector.touchDragged(event.stageX, event.stageY, event.pointer) + return true + } + else -> return false + } + } + open fun zoom(event: InputEvent?, initialDistance: Float, distance: Float) {} + open fun pinch() {} + open fun pinchStop() {} +} diff --git a/core/src/com/unciv/ui/utils/ZoomableScrollPane.kt b/core/src/com/unciv/ui/utils/ZoomableScrollPane.kt index a8bf08a7fd..4258f4901f 100644 --- a/core/src/com/unciv/ui/utils/ZoomableScrollPane.kt +++ b/core/src/com/unciv/ui/utils/ZoomableScrollPane.kt @@ -29,6 +29,8 @@ open class ZoomableScrollPane( var onViewportChangedListener: ((width: Float, height: Float, viewport: Rectangle) -> Unit)? = null var onPanStopListener: (() -> Unit)? = null var onPanStartListener: (() -> Unit)? = null + var onZoomStopListener: (() -> Unit)? = null + var onZoomStartListener: (() -> Unit)? = null private val horizontalPadding get() = width / 2 private val verticalPadding get() = height / 2 @@ -154,9 +156,23 @@ open class ZoomableScrollPane( } } - class ZoomListener(private val zoomableScrollPane: ZoomableScrollPane):ActorGestureListener(){ + class ZoomListener(private val zoomableScrollPane: ZoomableScrollPane): ZoomGestureListener(){ + + private var isZooming = false + private var lastInitialDistance = 0f var lastScale = 1f - var lastInitialDistance = 0f + + override fun pinch() { + if (!isZooming) { + isZooming = true + zoomableScrollPane.onZoomStartListener?.invoke() + } + } + + override fun pinchStop() { + isZooming = false + zoomableScrollPane.onZoomStopListener?.invoke() + } override fun zoom(event: InputEvent?, initialDistance: Float, distance: Float) { if (lastInitialDistance != initialDistance) { diff --git a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt index da438ddad4..c0401b5134 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt @@ -76,24 +76,33 @@ class WorldMapHolder( } /** - * When scrolling the world map, there are two unnecessary (at least currently) things happening that take a decent amount of time: + * When scrolling or zooming the world map, there are two unnecessary (at least currently) things happening that take a decent amount of time: * * 1. Checking which [Actor]'s bounds the pointer (mouse/finger) entered+exited and sending appropriate events to these actors * 2. Running all [Actor.act] methods of all child [Actor]s + * 3. Running all [Actor.hit] methode of all chikld [Actor]s * * Disabling them while panning increases the frame rate while panning by approximately 100%. */ private fun disablePointerEventsAndActionsOnPan() { onPanStartListener = { - Log.debug("Disable pointer enter/exit events & TileGroupMap.act()") (stage as UncivStage).performPointerEnterExitEvents = false tileGroupMap.shouldAct = false } onPanStopListener = { - Log.debug("Enable pointer enter/exit events & TileGroupMap.act()") (stage as UncivStage).performPointerEnterExitEvents = true tileGroupMap.shouldAct = true } + onZoomStartListener = { + (stage as UncivStage).performPointerEnterExitEvents = false + tileGroupMap.shouldAct = false + tileGroupMap.touchable = Touchable.disabled + } + onZoomStopListener = { + (stage as UncivStage).performPointerEnterExitEvents = true + tileGroupMap.shouldAct = true + tileGroupMap.touchable = Touchable.enabled + } } // Interface for classes that contain the data required to draw a button