mirror of
https://github.com/yairm210/Unciv.git
synced 2025-03-03 22:22:51 +07:00
Performance optimization: fast and smooth zoom (#8549)
Co-authored-by: tunerzinc@gmail.com <vfylfhby>
This commit is contained in:
parent
38f544a35d
commit
9a35f4a283
80
core/src/com/unciv/ui/utils/ZoomGestureListener.kt
Normal file
80
core/src/com/unciv/ui/utils/ZoomGestureListener.kt
Normal file
@ -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() {}
|
||||
}
|
@ -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) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user