diff --git a/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt b/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt index 46ffc3d4be..064a6b8290 100644 --- a/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt +++ b/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt @@ -23,6 +23,7 @@ import com.unciv.ui.utils.extensions.colorFromRGB import com.unciv.ui.utils.extensions.darken import com.unciv.ui.utils.extensions.disable import com.unciv.ui.utils.extensions.onClick +import com.unciv.ui.utils.extensions.onDoubleClick import com.unciv.ui.utils.extensions.toLabel import com.unciv.utils.concurrency.Concurrency import kotlin.math.abs @@ -80,19 +81,7 @@ class TechPickerScreen( pickerPane.bottomTable.background = skinStrings.getUiBackground("TechPickerScreen/BottomTable", tintColor = skinStrings.skinConfig.clearColor) rightSideButton.setText("Pick a tech".tr()) - rightSideButton.onClick(UncivSound.Paper) { - if (freeTechPick) { - val freeTech = selectedTech!!.name - // More evil people fast-clicking to cheat - #4977 - if (!researchableTechs.contains(freeTech)) return@onClick - civTech.getFreeTechnology(selectedTech!!.name) - } - else civTech.techsToResearch = tempTechsToResearch - - game.settings.addCompletedTutorialTask("Pick technology") - - game.popScreen() - } + rightSideButton.onClick(UncivSound.Paper) { tryExit() } // per default show current/recent technology, // and possibly select it to show description, @@ -112,6 +101,20 @@ class TechPickerScreen( } } + private fun tryExit() { + if (freeTechPick) { + val freeTech = selectedTech!!.name + // More evil people fast-clicking to cheat - #4977 + if (!researchableTechs.contains(freeTech)) return + civTech.getFreeTechnology(selectedTech!!.name) + } + else civTech.techsToResearch = tempTechsToResearch + + game.settings.addCompletedTutorialTask("Pick technology") + + game.popScreen() + } + private fun createTechTable() { for (label in eraLabels) label.remove() @@ -182,6 +185,7 @@ class TechPickerScreen( table.add(techButton) techNameToButton[tech.name] = techButton techButton.onClick { selectTechnology(tech, false) } + techButton.onDoubleClick(UncivSound.Paper) { tryExit() } techTable.add(table).fillX() } } diff --git a/core/src/com/unciv/ui/utils/extensions/Scene2dExtensions.kt b/core/src/com/unciv/ui/utils/extensions/Scene2dExtensions.kt index 5283b5144c..a0b53dc21c 100644 --- a/core/src/com/unciv/ui/utils/extensions/Scene2dExtensions.kt +++ b/core/src/com/unciv/ui/utils/extensions/Scene2dExtensions.kt @@ -276,25 +276,62 @@ fun Actor.centerX(parent: Stage) { x = parent.width / 2 - width / 2 } fun Actor.centerY(parent: Stage) { y = parent.height / 2 - height / 2 } fun Actor.center(parent: Stage) { centerX(parent); centerY(parent) } -class OnClickListener(val sound: UncivSound = UncivSound.Click, val function: (event: InputEvent?, x: Float, y: Float) -> Unit):ClickListener(){ +class ClickListenerInstance(val sound: UncivSound, val function: (event: InputEvent?, x: Float, y: Float) -> Unit, val tapCount: Int) + +class OnClickListener(val sound: UncivSound = UncivSound.Click, + val function: (event: InputEvent?, x: Float, y: Float) -> Unit, + tapCount: Int = 1, + tapInterval: Float = 0.0f): ClickListener() { + + private val clickFunctions = mutableMapOf() + + init { + setTapCountInterval(tapInterval) + clickFunctions[tapCount] = ClickListenerInstance(sound, function, tapCount) + } + + fun addClickFunction(sound: UncivSound = UncivSound.Click, tapCount: Int, function: (event: InputEvent?, x: Float, y: Float) -> Unit) { + clickFunctions[tapCount] = ClickListenerInstance(sound, function, tapCount) + } + override fun clicked(event: InputEvent?, x: Float, y: Float) { - Concurrency.run("Sound") { SoundPlayer.play(sound) } - function(event, x, y) + var effectiveTapCount = tapCount + if (clickFunctions[effectiveTapCount] == null) { + effectiveTapCount = clickFunctions.keys.filter { it < tapCount }.maxOrNull() ?: return // happens if there's a double (or more) click function but no single click + } + val clickInstance = clickFunctions[effectiveTapCount]!! + Concurrency.run("Sound") { SoundPlayer.play(clickInstance.sound) } + val func = clickInstance.function + func(event, x, y) } } /** same as [onClick], but sends the [InputEvent] and coordinates along */ -fun Actor.onClickEvent(sound: UncivSound = UncivSound.Click, function: (event: InputEvent?, x: Float, y: Float) -> Unit) { - this.addListener(OnClickListener(sound, function)) +fun Actor.onClickEvent(sound: UncivSound = UncivSound.Click, + tapCount: Int = 1, + tapInterval: Float = 0.0f, + function: (event: InputEvent?, x: Float, y: Float) -> Unit) { + val previousListener = this.listeners.firstOrNull { it is OnClickListener } + if (previousListener != null && previousListener is OnClickListener) { + previousListener.addClickFunction(sound, tapCount, function) + previousListener.setTapCountInterval(tapInterval) + } else { + this.addListener(OnClickListener(sound, function, tapCount, tapInterval)) + } } // If there are other buttons that require special clicks then we'll have an onclick that will accept a string parameter, no worries -fun Actor.onClick(sound: UncivSound = UncivSound.Click, function: () -> Unit) { - onClickEvent(sound) { _, _, _ -> function() } +fun Actor.onClick(sound: UncivSound = UncivSound.Click, tapCount: Int = 1, tapInterval: Float = 0.0f, function: () -> Unit) { + onClickEvent(sound, tapCount, tapInterval) { _, _, _ -> function() } } fun Actor.onClick(function: () -> Unit): Actor { - onClick(UncivSound.Click, function) + onClick(UncivSound.Click, 1, 0f, function) + return this +} + +fun Actor.onDoubleClick(sound: UncivSound = UncivSound.Click, tapInterval: Float = 0.25f, function: () -> Unit): Actor { + onClick(sound, 2, tapInterval, function) return this }