diff --git a/core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt b/core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt index 99f60dff3f..487014c9de 100644 --- a/core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt +++ b/core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt @@ -1,6 +1,5 @@ package com.unciv.ui.mapeditor -import com.badlogic.gdx.math.Interpolation import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.scenes.scene2d.Action import com.badlogic.gdx.scenes.scene2d.EventListener @@ -9,7 +8,6 @@ import com.badlogic.gdx.scenes.scene2d.InputListener import com.badlogic.gdx.scenes.scene2d.Stage import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.actions.Actions -import com.badlogic.gdx.scenes.scene2d.actions.FloatAction import com.unciv.UncivGame import com.unciv.logic.HexMath import com.unciv.logic.map.TileInfo @@ -131,25 +129,9 @@ class EditorMapHolder( fun setCenterPosition(vector: Vector2, blink: Boolean = false) { val tileGroup = allTileGroups.firstOrNull { it.tileInfo.position == vector } ?: return - val originalScrollX = scrollX - val originalScrollY = scrollY - - val finalScrollX = tileGroup.x + tileGroup.width / 2 - - /** The Y axis of [scrollY] is inverted - when at 0 we're at the top, not bottom - so we invert it back. */ - val finalScrollY = maxY - (tileGroup.y + tileGroup.width / 2) - - if (finalScrollX == originalScrollX && finalScrollY == originalScrollY) return - - val action = object : FloatAction(0f, 1f, 0.4f) { - override fun update(percent: Float) { - scrollX = finalScrollX * percent + originalScrollX * (1 - percent) - scrollY = finalScrollY * percent + originalScrollY * (1 - percent) - updateVisualScroll() - } - } - action.interpolation = Interpolation.sine - addAction(action) + // The Y axis of [scrollY] is inverted - when at 0 we're at the top, not bottom - so we invert it back. + if (!scrollTo(tileGroup.x + tileGroup.width / 2, maxY - (tileGroup.y + tileGroup.width / 2))) + return if (!blink) return diff --git a/core/src/com/unciv/ui/utils/ZoomableScrollPane.kt b/core/src/com/unciv/ui/utils/ZoomableScrollPane.kt index cd71282c07..41913526cf 100644 --- a/core/src/com/unciv/ui/utils/ZoomableScrollPane.kt +++ b/core/src/com/unciv/ui/utils/ZoomableScrollPane.kt @@ -1,10 +1,15 @@ package com.unciv.ui.utils +import com.badlogic.gdx.math.Interpolation import com.badlogic.gdx.math.Rectangle +import com.badlogic.gdx.math.Vector2 +import com.badlogic.gdx.scenes.scene2d.Action import com.badlogic.gdx.scenes.scene2d.Actor import com.badlogic.gdx.scenes.scene2d.Group import com.badlogic.gdx.scenes.scene2d.InputEvent import com.badlogic.gdx.scenes.scene2d.InputListener +import com.badlogic.gdx.scenes.scene2d.actions.Actions +import com.badlogic.gdx.scenes.scene2d.actions.FloatAction import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener import com.badlogic.gdx.scenes.scene2d.utils.Cullable @@ -189,6 +194,51 @@ open class ZoomableScrollPane( } } + private var scrollingTo: Vector2? = null + private var scrollingAction: Action? = null + + fun isScrolling(): Boolean = scrollingAction != null && actions.any { it == scrollingAction } + + /** Get the scrolling destination if currently scrolling, else the current scroll position. */ + fun scrollingDestination(): Vector2 { + if (isScrolling()) + return scrollingTo!! + else + return Vector2(scrollX, scrollY) + } + + /** Scroll the pane to specified coordinates. + * @return `true` if scroll position got changed or started being changed, `false` + * if already centered there or already scrolling there + */ + fun scrollTo(x: Float, y: Float, immediately: Boolean = false): Boolean { + if (scrollingDestination() == Vector2(x, y)) return false + + removeAction(scrollingAction) + + if (immediately) { + scrollX = x + scrollY = y + updateVisualScroll() + } else { + val originalScrollX = scrollX + val originalScrollY = scrollY + scrollingTo = Vector2(x, y) + val action = object : FloatAction(0f, 1f, 0.4f) { + override fun update(percent: Float) { + scrollX = scrollingTo!!.x * percent + originalScrollX * (1 - percent) + scrollY = scrollingTo!!.y * percent + originalScrollY * (1 - percent) + updateVisualScroll() + } + } + action.interpolation = Interpolation.sine + addAction(action) + scrollingAction = action + } + + return true + } + /** @return the currently scrolled-to viewport of the whole scrollable area */ fun getViewport(): Rectangle { val viewportFromLeft = scrollX diff --git a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt index 528cfcebc0..74b8237e90 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt @@ -5,7 +5,6 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.Input import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.Batch -import com.badlogic.gdx.math.Interpolation import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.scenes.scene2d.Action import com.badlogic.gdx.scenes.scene2d.Actor @@ -13,7 +12,6 @@ import com.badlogic.gdx.scenes.scene2d.Group import com.badlogic.gdx.scenes.scene2d.InputEvent import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.actions.Actions -import com.badlogic.gdx.scenes.scene2d.actions.FloatAction import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.utils.ClickListener import com.badlogic.gdx.utils.Align @@ -723,31 +721,9 @@ class WorldMapHolder( if (selectUnit || forceSelectUnit != null) worldScreen.bottomUnitTable.tileSelected(selectedTile!!, forceSelectUnit) - val originalScrollX = scrollX - val originalScrollY = scrollY - - val finalScrollX = tileGroup.x + tileGroup.width / 2 - - /** The Y axis of [scrollY] is inverted - when at 0 we're at the top, not bottom - so we invert it back. */ - val finalScrollY = maxY - (tileGroup.y + tileGroup.width / 2) - - if (finalScrollX == originalScrollX && finalScrollY == originalScrollY) return false - - if (immediately) { - scrollX = finalScrollX - scrollY = finalScrollY - updateVisualScroll() - } else { - val action = object : FloatAction(0f, 1f, 0.4f) { - override fun update(percent: Float) { - scrollX = finalScrollX * percent + originalScrollX * (1 - percent) - scrollY = finalScrollY * percent + originalScrollY * (1 - percent) - updateVisualScroll() - } - } - action.interpolation = Interpolation.sine - addAction(action) - } + // The Y axis of [scrollY] is inverted - when at 0 we're at the top, not bottom - so we invert it back. + if (!scrollTo(tileGroup.x + tileGroup.width / 2, maxY - (tileGroup.y + tileGroup.width / 2), immediately)) + return false removeAction(blinkAction) // so we don't have multiple blinks at once blinkAction = Actions.repeat(3, Actions.sequence(