mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-24 03:53:12 -04: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 onViewportChangedListener: ((width: Float, height: Float, viewport: Rectangle) -> Unit)? = null
|
||||||
var onPanStopListener: (() -> Unit)? = null
|
var onPanStopListener: (() -> Unit)? = null
|
||||||
var onPanStartListener: (() -> Unit)? = null
|
var onPanStartListener: (() -> Unit)? = null
|
||||||
|
var onZoomStopListener: (() -> Unit)? = null
|
||||||
|
var onZoomStartListener: (() -> Unit)? = null
|
||||||
|
|
||||||
private val horizontalPadding get() = width / 2
|
private val horizontalPadding get() = width / 2
|
||||||
private val verticalPadding get() = height / 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 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) {
|
override fun zoom(event: InputEvent?, initialDistance: Float, distance: Float) {
|
||||||
if (lastInitialDistance != initialDistance) {
|
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
|
* 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
|
* 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%.
|
* Disabling them while panning increases the frame rate while panning by approximately 100%.
|
||||||
*/
|
*/
|
||||||
private fun disablePointerEventsAndActionsOnPan() {
|
private fun disablePointerEventsAndActionsOnPan() {
|
||||||
onPanStartListener = {
|
onPanStartListener = {
|
||||||
Log.debug("Disable pointer enter/exit events & TileGroupMap.act()")
|
|
||||||
(stage as UncivStage).performPointerEnterExitEvents = false
|
(stage as UncivStage).performPointerEnterExitEvents = false
|
||||||
tileGroupMap.shouldAct = false
|
tileGroupMap.shouldAct = false
|
||||||
}
|
}
|
||||||
onPanStopListener = {
|
onPanStopListener = {
|
||||||
Log.debug("Enable pointer enter/exit events & TileGroupMap.act()")
|
|
||||||
(stage as UncivStage).performPointerEnterExitEvents = true
|
(stage as UncivStage).performPointerEnterExitEvents = true
|
||||||
tileGroupMap.shouldAct = 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
|
// Interface for classes that contain the data required to draw a button
|
||||||
|
Loading…
x
Reference in New Issue
Block a user