mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-26 05:14:32 -04:00
TileMapHolder refactor & Map Editor update (#1584)
* TileMapHolder renamed to MapHolder * EditorMapHolder and WorldMapHolder inherits from ZoomableScrollPane * MapEditor Brush Size (from 1 to 5) * MapEditor painting mode (dragging the pointer on screen paints continuously)
This commit is contained in:
parent
908c6ad54a
commit
a1b0c1dcd4
@ -945,6 +945,7 @@ Clear improvements = Elimina miglioramenti
|
|||||||
Clear resource = Elimina risorsa
|
Clear resource = Elimina risorsa
|
||||||
Requires = Richiede
|
Requires = Richiede
|
||||||
Menu = Menu
|
Menu = Menu
|
||||||
|
Brush Size = Dimensione pennello
|
||||||
|
|
||||||
# Civilopedia Tutorials names
|
# Civilopedia Tutorials names
|
||||||
|
|
||||||
|
@ -945,6 +945,7 @@ Clear improvements =
|
|||||||
Clear resource =
|
Clear resource =
|
||||||
Requires =
|
Requires =
|
||||||
Menu =
|
Menu =
|
||||||
|
Brush Size =
|
||||||
|
|
||||||
# Civilopedia Tutorials names
|
# Civilopedia Tutorials names
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package com.unciv.logic
|
package com.unciv.logic
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
import java.util.*
|
import com.badlogic.gdx.math.Vector3
|
||||||
import kotlin.math.abs
|
import kotlin.math.*
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.sqrt
|
|
||||||
|
|
||||||
class HexMath {
|
class HexMath {
|
||||||
|
|
||||||
@ -16,6 +14,18 @@ class HexMath {
|
|||||||
return getVectorForAngle((2 * Math.PI * (hour / 12f)).toFloat())
|
return getVectorForAngle((2 * Math.PI * (hour / 12f)).toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getAdjacentVectors(origin: Vector2): ArrayList<Vector2> {
|
||||||
|
val vectors = ArrayList<Vector2>()
|
||||||
|
vectors += Vector2(1f, 0f)
|
||||||
|
vectors += Vector2(1f, 1f)
|
||||||
|
vectors += Vector2(0f, 1f)
|
||||||
|
vectors += Vector2(-1f, 0f)
|
||||||
|
vectors += Vector2(-1f, -1f)
|
||||||
|
vectors += Vector2(0f, -1f)
|
||||||
|
for (vector in vectors) vector.add(origin)
|
||||||
|
return vectors
|
||||||
|
}
|
||||||
|
|
||||||
// HexCoordinates are a (x,y) vector, where x is the vector getting us to the top-left hex (e.g. 10 o'clock)
|
// HexCoordinates are a (x,y) vector, where x is the vector getting us to the top-left hex (e.g. 10 o'clock)
|
||||||
// and y is the vector getting us to the top-right hex (e.g. 2 o'clock)
|
// and y is the vector getting us to the top-right hex (e.g. 2 o'clock)
|
||||||
|
|
||||||
@ -30,16 +40,45 @@ class HexMath {
|
|||||||
return xVector.scl(hexCoord.x).add(yVector.scl(hexCoord.y))
|
return xVector.scl(hexCoord.x).add(yVector.scl(hexCoord.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAdjacentVectors(origin: Vector2): ArrayList<Vector2> {
|
fun world2HexCoords(worldCoord: Vector2): Vector2 {
|
||||||
val vectors = ArrayList<Vector2>()
|
// D: diagonal, A: antidiagonal versors
|
||||||
vectors += Vector2(1f, 0f)
|
val D = getVectorByClockHour(10).scl(sqrt(3.0).toFloat())
|
||||||
vectors += Vector2(1f, 1f)
|
val A = getVectorByClockHour(2).scl(sqrt(3.0).toFloat())
|
||||||
vectors += Vector2(0f, 1f)
|
val den = D.x * A.y - D.y * A.x
|
||||||
vectors += Vector2(-1f, 0f)
|
val x = (worldCoord.x * A.y - worldCoord.y * A.x) / den
|
||||||
vectors += Vector2(-1f, -1f)
|
val y = (worldCoord.y * D.x - worldCoord.x * D.y) / den
|
||||||
vectors += Vector2(0f, -1f)
|
return Vector2(x, y)
|
||||||
for (vector in vectors) vector.add(origin)
|
}
|
||||||
return vectors
|
|
||||||
|
fun hex2CubicCoords(hexCoord: Vector2): Vector3 {
|
||||||
|
return Vector3(hexCoord.y - hexCoord.x, hexCoord.x, -hexCoord.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cubic2HexCoords(cubicCoord: Vector3): Vector2 {
|
||||||
|
return Vector2(cubicCoord.y, -cubicCoord.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun roundCubicCoords(cubicCoords: Vector3): Vector3 {
|
||||||
|
var rx = round(cubicCoords.x)
|
||||||
|
var ry = round(cubicCoords.y)
|
||||||
|
var rz = round(cubicCoords.z)
|
||||||
|
|
||||||
|
val deltaX = abs(rx - cubicCoords.x)
|
||||||
|
val deltaY = abs(ry - cubicCoords.y)
|
||||||
|
val deltaZ = abs(rz - cubicCoords.z)
|
||||||
|
|
||||||
|
if (deltaX > deltaY && deltaX > deltaZ)
|
||||||
|
rx = -ry-rz
|
||||||
|
else if (deltaY > deltaZ)
|
||||||
|
ry = -rx-rz
|
||||||
|
else
|
||||||
|
rz = -rx-ry
|
||||||
|
|
||||||
|
return Vector3(rx, ry, rz)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun roundHexCoords(hexCoord: Vector2): Vector2 {
|
||||||
|
return cubic2HexCoords(roundCubicCoords(hex2CubicCoords(hexCoord)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getVectorsAtDistance(origin: Vector2, distance: Int): List<Vector2> {
|
fun getVectorsAtDistance(origin: Vector2, distance: Int): List<Vector2> {
|
||||||
|
@ -29,9 +29,9 @@ data class LocationAction(var locations: ArrayList<Vector2> = ArrayList()) : Not
|
|||||||
|
|
||||||
override fun execute(worldScreen: WorldScreen) {
|
override fun execute(worldScreen: WorldScreen) {
|
||||||
if (locations.isNotEmpty()) {
|
if (locations.isNotEmpty()) {
|
||||||
var index = locations.indexOf(worldScreen.tileMapHolder.selectedTile?.position)
|
var index = locations.indexOf(worldScreen.mapHolder.selectedTile?.position)
|
||||||
index = ++index % locations.size // cycle through tiles
|
index = ++index % locations.size // cycle through tiles
|
||||||
worldScreen.tileMapHolder.setCenterPosition(locations[index], selectUnit = false)
|
worldScreen.mapHolder.setCenterPosition(locations[index], selectUnit = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ class TechAction(val techName: String = "") : NotificationAction {
|
|||||||
data class CityAction(val city: Vector2 = Vector2.Zero): NotificationAction {
|
data class CityAction(val city: Vector2 = Vector2.Zero): NotificationAction {
|
||||||
|
|
||||||
override fun execute(worldScreen: WorldScreen) {
|
override fun execute(worldScreen: WorldScreen) {
|
||||||
worldScreen.tileMapHolder.tileMap[city].getCity()?.let {
|
worldScreen.mapHolder.tileMap[city].getCity()?.let {
|
||||||
worldScreen.game.setScreen(CityScreen(it))
|
worldScreen.game.setScreen(CityScreen(it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ class EmpireOverviewScreen(val viewingPlayer:CivilizationInfo) : CameraStageBase
|
|||||||
val button = TextButton(unit.name.tr(), skin)
|
val button = TextButton(unit.name.tr(), skin)
|
||||||
button.onClick {
|
button.onClick {
|
||||||
UncivGame.Current.setWorldScreen()
|
UncivGame.Current.setWorldScreen()
|
||||||
UncivGame.Current.worldScreen.tileMapHolder.setCenterPosition(unit.currentTile.position)
|
UncivGame.Current.worldScreen.mapHolder.setCenterPosition(unit.currentTile.position)
|
||||||
}
|
}
|
||||||
table.add(button).left()
|
table.add(button).left()
|
||||||
val mapUnitAction = unit.mapUnitAction
|
val mapUnitAction = unit.mapUnitAction
|
||||||
|
@ -17,7 +17,7 @@ import com.unciv.models.stats.Stats
|
|||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.tilegroups.TileSetStrings
|
import com.unciv.ui.tilegroups.TileSetStrings
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
import com.unciv.ui.worldscreen.TileGroupMap
|
import com.unciv.ui.map.TileGroupMap
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
@ -87,7 +87,7 @@ class CityScreenCityPickerTable(val cityScreen: CityScreen) : Table(){
|
|||||||
exitCityButton.onClick {
|
exitCityButton.onClick {
|
||||||
val game = cityScreen.game
|
val game = cityScreen.game
|
||||||
game.setWorldScreen()
|
game.setWorldScreen()
|
||||||
game.worldScreen.tileMapHolder.setCenterPosition(city.location)
|
game.worldScreen.mapHolder.setCenterPosition(city.location)
|
||||||
game.worldScreen.bottomUnitTable.selectedUnit=null
|
game.worldScreen.bottomUnitTable.selectedUnit=null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
package com.unciv.ui.worldscreen
|
package com.unciv.ui.map
|
||||||
|
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.badlogic.gdx.scenes.scene2d.Group
|
import com.badlogic.gdx.scenes.scene2d.Group
|
||||||
import com.unciv.logic.HexMath
|
import com.unciv.logic.HexMath
|
||||||
import com.unciv.ui.tilegroups.TileGroup
|
import com.unciv.ui.tilegroups.TileGroup
|
||||||
|
|
||||||
class TileGroupMap<T: TileGroup>(val tileGroups:Collection<T>, padding:Float): Group(){
|
class TileGroupMap<T: TileGroup>(val tileGroups: Collection<T>, val padding: Float): Group(){
|
||||||
|
var topX = -Float.MAX_VALUE
|
||||||
|
var topY = -Float.MAX_VALUE
|
||||||
|
var bottomX = Float.MAX_VALUE
|
||||||
|
var bottomY = Float.MAX_VALUE
|
||||||
|
val groupSize = 50
|
||||||
init{
|
init{
|
||||||
var topX = -Float.MAX_VALUE
|
|
||||||
var topY = -Float.MAX_VALUE
|
|
||||||
var bottomX = Float.MAX_VALUE
|
|
||||||
var bottomY = Float.MAX_VALUE
|
|
||||||
|
|
||||||
for(tileGroup in tileGroups){
|
for(tileGroup in tileGroups){
|
||||||
val positionalVector = HexMath().hex2WorldCoords(tileGroup.tileInfo.position)
|
val positionalVector = HexMath().hex2WorldCoords(tileGroup.tileInfo.position)
|
||||||
val groupSize = 50
|
|
||||||
tileGroup.setPosition(positionalVector.x * 0.8f * groupSize.toFloat(),
|
tileGroup.setPosition(positionalVector.x * 0.8f * groupSize.toFloat(),
|
||||||
positionalVector.y * 0.8f * groupSize.toFloat())
|
positionalVector.y * 0.8f * groupSize.toFloat())
|
||||||
|
|
||||||
@ -56,6 +57,16 @@ class TileGroupMap<T: TileGroup>(val tileGroups:Collection<T>, padding:Float): G
|
|||||||
// there are tiles "below the zero",
|
// there are tiles "below the zero",
|
||||||
// so we zero out the starting position of the whole board so they will be displayed as well
|
// so we zero out the starting position of the whole board so they will be displayed as well
|
||||||
setSize(topX - bottomX + padding*2, topY - bottomY + padding*2)
|
setSize(topX - bottomX + padding*2, topY - bottomY + padding*2)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the positional coordinates of the TileGroupMap center.
|
||||||
|
*/
|
||||||
|
fun getPositionalVector(stageCoords: Vector2): Vector2 {
|
||||||
|
val trueGroupSize = 0.8f * groupSize.toFloat()
|
||||||
|
return Vector2(bottomX - padding, bottomY - padding)
|
||||||
|
.add(stageCoords)
|
||||||
|
.sub(groupSize.toFloat() / 2f, groupSize.toFloat() / 2f)
|
||||||
|
.scl(1f / trueGroupSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
73
core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt
Normal file
73
core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package com.unciv.ui.mapeditor
|
||||||
|
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.unciv.logic.map.TileMap
|
||||||
|
import com.unciv.logic.map.TileInfo
|
||||||
|
import com.unciv.ui.tilegroups.TileGroup
|
||||||
|
import com.unciv.ui.tilegroups.TileSetStrings
|
||||||
|
import com.unciv.ui.utils.onClick
|
||||||
|
import com.unciv.ui.map.TileGroupMap
|
||||||
|
import com.unciv.ui.utils.*
|
||||||
|
import com.unciv.logic.HexMath
|
||||||
|
|
||||||
|
class EditorMapHolder(internal val mapEditorScreen: MapEditorScreen, internal val tileMap: TileMap): ZoomableScrollPane() {
|
||||||
|
val tileGroups = HashMap<TileInfo, TileGroup>()
|
||||||
|
lateinit var tileGroupMap: TileGroupMap<TileGroup>
|
||||||
|
|
||||||
|
internal fun addTiles() {
|
||||||
|
|
||||||
|
val tileSetStrings = TileSetStrings()
|
||||||
|
for (tileGroup in tileMap.values.map { TileGroup(it, tileSetStrings) })
|
||||||
|
tileGroups[tileGroup.tileInfo] = tileGroup
|
||||||
|
|
||||||
|
tileGroupMap = TileGroupMap(tileGroups.values, mapEditorScreen.stage.width)
|
||||||
|
actor = tileGroupMap
|
||||||
|
|
||||||
|
for (tileGroup in tileGroups.values) {
|
||||||
|
tileGroup.showEntireMap = true
|
||||||
|
tileGroup.update()
|
||||||
|
tileGroup.onClick {
|
||||||
|
|
||||||
|
val distance = mapEditorScreen.tileEditorOptions.brushSize - 1
|
||||||
|
|
||||||
|
for (tileInfo in mapEditorScreen.tileMap.getTilesInDistance(tileGroup.tileInfo.position, distance)) {
|
||||||
|
mapEditorScreen.tileEditorOptions.updateTileWhenClicked(tileInfo)
|
||||||
|
|
||||||
|
tileInfo.setTransients()
|
||||||
|
tileGroups[tileInfo]!!.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setSize(mapEditorScreen.stage.width * 2, mapEditorScreen.stage.height * 2)
|
||||||
|
setOrigin(width / 2,height / 2)
|
||||||
|
center(mapEditorScreen.stage)
|
||||||
|
|
||||||
|
layout()
|
||||||
|
|
||||||
|
scrollPercentX = .5f
|
||||||
|
scrollPercentY = .5f
|
||||||
|
updateVisualScroll()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateTileGroups() {
|
||||||
|
for (tileGroup in tileGroups.values)
|
||||||
|
tileGroup.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTransients() {
|
||||||
|
for (tileInfo in tileGroups.keys)
|
||||||
|
tileInfo.setTransients()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getClosestTileTo(stageCoords: Vector2): TileInfo? {
|
||||||
|
val positionalCoords = tileGroupMap.getPositionalVector(stageCoords)
|
||||||
|
val hexPosition = HexMath().world2HexCoords(positionalCoords)
|
||||||
|
val rounded = HexMath().roundHexCoords(hexPosition)
|
||||||
|
|
||||||
|
if (tileMap.contains(rounded))
|
||||||
|
return tileMap.get(rounded)
|
||||||
|
else
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ class MapEditorMenuPopup(mapEditorScreen: MapEditorScreen): PopupTable(mapEditor
|
|||||||
|
|
||||||
val clearCurrentMapButton = TextButton("Clear current map".tr(),skin)
|
val clearCurrentMapButton = TextButton("Clear current map".tr(),skin)
|
||||||
clearCurrentMapButton.onClick {
|
clearCurrentMapButton.onClick {
|
||||||
for(tileGroup in mapEditorScreen.mapHolder.tileGroups)
|
for(tileGroup in mapEditorScreen.mapHolder.tileGroups.values)
|
||||||
{
|
{
|
||||||
val tile = tileGroup.tileInfo
|
val tile = tileGroup.tileInfo
|
||||||
tile.baseTerrain=Constants.ocean
|
tile.baseTerrain=Constants.ocean
|
||||||
|
@ -1,51 +1,59 @@
|
|||||||
package com.unciv.ui.mapeditor
|
package com.unciv.ui.mapeditor
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
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.Actions
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.MapSaver
|
import com.unciv.logic.MapSaver
|
||||||
import com.unciv.logic.map.TileMap
|
import com.unciv.logic.map.TileMap
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.tilegroups.TileGroup
|
|
||||||
import com.unciv.ui.tilegroups.TileSetStrings
|
|
||||||
import com.unciv.ui.utils.CameraStageBaseScreen
|
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||||
import com.unciv.ui.utils.onClick
|
import com.unciv.ui.utils.onClick
|
||||||
import com.unciv.ui.utils.setFontSize
|
import com.unciv.ui.utils.setFontSize
|
||||||
import com.unciv.ui.worldscreen.TileGroupMap
|
|
||||||
|
|
||||||
class MapEditorScreen(): CameraStageBaseScreen(){
|
class MapEditorScreen(): CameraStageBaseScreen() {
|
||||||
var tileMap = TileMap()
|
val ruleset = UncivGame.Current.ruleset
|
||||||
var mapName = "My first map"
|
var mapName = "My first map"
|
||||||
lateinit var mapHolder: TileGroupMap<TileGroup>
|
|
||||||
private val showHideEditorOptionsButton = TextButton(">",skin)
|
|
||||||
val ruleSet = UncivGame.Current.ruleset
|
|
||||||
private val tileEditorOptions = TileEditorOptionsTable(this)
|
|
||||||
|
|
||||||
constructor(mapNameToLoad:String?):this(){
|
var tileMap = TileMap()
|
||||||
|
lateinit var mapHolder: EditorMapHolder
|
||||||
|
|
||||||
|
val tileEditorOptions = TileEditorOptionsTable(this)
|
||||||
|
|
||||||
|
private val showHideEditorOptionsButton = TextButton(">", skin)
|
||||||
|
|
||||||
|
|
||||||
|
constructor(mapNameToLoad: String?): this() {
|
||||||
var mapToLoad = mapNameToLoad
|
var mapToLoad = mapNameToLoad
|
||||||
if (mapToLoad == null) {
|
if (mapToLoad == null) {
|
||||||
val existingSaves = MapSaver().getMaps()
|
val existingSaves = MapSaver().getMaps()
|
||||||
if(existingSaves.isNotEmpty())
|
if(existingSaves.isNotEmpty())
|
||||||
mapToLoad = existingSaves.first()
|
mapToLoad = existingSaves.first()
|
||||||
}
|
}
|
||||||
if(mapToLoad!=null){
|
|
||||||
mapName=mapToLoad
|
if(mapToLoad != null){
|
||||||
tileMap= MapSaver().loadMap(mapName)
|
mapName = mapToLoad
|
||||||
|
tileMap = MapSaver().loadMap(mapName)
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize()
|
initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(map: TileMap):this(){
|
constructor(map: TileMap): this() {
|
||||||
tileMap = map
|
tileMap = map
|
||||||
initialize()
|
initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initialize() {
|
fun initialize() {
|
||||||
tileMap.setTransients(ruleSet)
|
tileMap.setTransients(ruleset)
|
||||||
val mapHolder = getMapHolder(tileMap)
|
|
||||||
|
|
||||||
|
mapHolder = EditorMapHolder(this, tileMap)
|
||||||
|
mapHolder.addTiles()
|
||||||
stage.addActor(mapHolder)
|
stage.addActor(mapHolder)
|
||||||
|
|
||||||
stage.addActor(tileEditorOptions)
|
stage.addActor(tileEditorOptions)
|
||||||
tileEditorOptions.setPosition(stage.width - tileEditorOptions.width, 0f)
|
tileEditorOptions.setPosition(stage.width - tileEditorOptions.width, 0f)
|
||||||
|
|
||||||
@ -76,35 +84,60 @@ class MapEditorScreen(): CameraStageBaseScreen(){
|
|||||||
optionsMenuButton.pack()
|
optionsMenuButton.pack()
|
||||||
optionsMenuButton.x = 30f
|
optionsMenuButton.x = 30f
|
||||||
optionsMenuButton.y = 30f
|
optionsMenuButton.y = 30f
|
||||||
|
|
||||||
stage.addActor(optionsMenuButton)
|
stage.addActor(optionsMenuButton)
|
||||||
}
|
|
||||||
|
|
||||||
private fun getMapHolder(tileMap: TileMap): ScrollPane {
|
mapHolder.addCaptureListener(object: InputListener() {
|
||||||
val tileSetStrings = TileSetStrings()
|
var isDragging = false
|
||||||
val tileGroups = tileMap.values.map { TileGroup(it, tileSetStrings) }
|
var isPainting = false
|
||||||
for (tileGroup in tileGroups) {
|
var touchDownTime = System.currentTimeMillis()
|
||||||
tileGroup.showEntireMap = true
|
|
||||||
tileGroup.update()
|
|
||||||
tileGroup.onClick {
|
|
||||||
val tileInfo = tileGroup.tileInfo
|
|
||||||
|
|
||||||
tileEditorOptions.updateTileWhenClicked(tileInfo)
|
override fun touchDown(event: InputEvent?, x: Float, y: Float, pointer: Int, button: Int): Boolean {
|
||||||
tileGroup.tileInfo.setTransients()
|
touchDownTime = System.currentTimeMillis()
|
||||||
tileGroup.update()
|
return true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mapHolder = TileGroupMap(tileGroups, 300f)
|
override fun touchDragged(event: InputEvent?, x: Float, y: Float, pointer: Int) {
|
||||||
val scrollPane = ScrollPane(mapHolder)
|
if (!isDragging) {
|
||||||
scrollPane.setSize(stage.width, stage.height)
|
isDragging = true
|
||||||
scrollPane.layout()
|
val deltaTime = System.currentTimeMillis() - touchDownTime
|
||||||
scrollPane.scrollPercentX=0.5f
|
if (deltaTime > 400) {
|
||||||
scrollPane.scrollPercentY=0.5f
|
isPainting = true
|
||||||
scrollPane.updateVisualScroll()
|
stage.cancelTouchFocusExcept(this, mapHolder)
|
||||||
return scrollPane
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPainting) {
|
||||||
|
mapHolder.updateTileGroups()
|
||||||
|
mapHolder.setTransients()
|
||||||
|
|
||||||
|
val stageCoords = mapHolder.actor.stageToLocalCoordinates(Vector2(event!!.stageX, event.stageY))
|
||||||
|
val centerTileInfo = mapHolder.getClosestTileTo(stageCoords)
|
||||||
|
if (centerTileInfo != null) {
|
||||||
|
val distance = tileEditorOptions.brushSize - 1
|
||||||
|
|
||||||
|
for (tileInfo in tileMap.getTilesInDistance(centerTileInfo.position, distance)) {
|
||||||
|
|
||||||
|
tileEditorOptions.updateTileWhenClicked(tileInfo)
|
||||||
|
|
||||||
|
tileInfo.setTransients()
|
||||||
|
mapHolder.tileGroups[tileInfo]!!.update()
|
||||||
|
mapHolder.tileGroups[tileInfo]!!.showCircle(Color.WHITE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun touchUp(event: InputEvent?, x: Float, y: Float, pointer: Int, button: Int) {
|
||||||
|
// Reset tile overlays
|
||||||
|
if (isPainting) {
|
||||||
|
mapHolder.updateTileGroups()
|
||||||
|
mapHolder.setTransients()
|
||||||
|
}
|
||||||
|
|
||||||
|
isDragging = false
|
||||||
|
isPainting = false
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,10 @@ import com.badlogic.gdx.graphics.Color
|
|||||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.Group
|
import com.badlogic.gdx.scenes.scene2d.Group
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.Slider
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.map.RoadStatus
|
import com.unciv.logic.map.RoadStatus
|
||||||
@ -19,6 +21,7 @@ import com.unciv.ui.tilegroups.TileGroup
|
|||||||
import com.unciv.ui.tilegroups.TileSetStrings
|
import com.unciv.ui.tilegroups.TileSetStrings
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
|
|
||||||
|
|
||||||
class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(CameraStageBaseScreen.skin){
|
class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(CameraStageBaseScreen.skin){
|
||||||
val tileSetLocation = "TileSets/"+ UncivGame.Current.settings.tileSet +"/"
|
val tileSetLocation = "TileSets/"+ UncivGame.Current.settings.tileSet +"/"
|
||||||
|
|
||||||
@ -37,13 +40,14 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
|
|
||||||
val editorPickTable = Table()
|
val editorPickTable = Table()
|
||||||
|
|
||||||
|
var brushSize = 1
|
||||||
private var currentHex: Actor = Group()
|
private var currentHex: Actor = Group()
|
||||||
|
|
||||||
val ruleSet = mapEditorScreen.ruleSet
|
val ruleset = mapEditorScreen.ruleset
|
||||||
|
|
||||||
init{
|
init{
|
||||||
height=mapEditorScreen.stage.height
|
height = mapEditorScreen.stage.height
|
||||||
width=mapEditorScreen.stage.width/3
|
width = mapEditorScreen.stage.width/3
|
||||||
|
|
||||||
setTerrainsAndResources()
|
setTerrainsAndResources()
|
||||||
|
|
||||||
@ -52,10 +56,28 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
.onClick { setTerrainsAndResources() }
|
.onClick { setTerrainsAndResources() }
|
||||||
tabPickerTable.add(terrainsAndResourcesTabButton)
|
tabPickerTable.add(terrainsAndResourcesTabButton)
|
||||||
|
|
||||||
val civLocationsButton = TextButton("Improvements".tr(),skin)
|
val civLocationsButton = TextButton("Improvements".tr(), skin)
|
||||||
.onClick { setImprovements() }
|
.onClick { setImprovements() }
|
||||||
tabPickerTable.add(civLocationsButton)
|
tabPickerTable.add(civLocationsButton)
|
||||||
tabPickerTable.pack()
|
tabPickerTable.pack()
|
||||||
|
|
||||||
|
val sliderTab = Table()
|
||||||
|
|
||||||
|
val slider = Slider(1f,5f,1f, false, skin)
|
||||||
|
val sliderLabel = "{Brush Size} $brushSize".toLabel()
|
||||||
|
|
||||||
|
slider.addListener(object : ChangeListener() {
|
||||||
|
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
||||||
|
brushSize = slider.getValue().toInt()
|
||||||
|
sliderLabel.setText("{Brush Size} $brushSize".tr())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
sliderTab.defaults().pad(5f)
|
||||||
|
sliderTab.add(sliderLabel)
|
||||||
|
sliderTab.add(slider)
|
||||||
|
|
||||||
|
add(sliderTab).row()
|
||||||
add(ScrollPane(tabPickerTable).apply { this.width= mapEditorScreen.stage.width/3}).row()
|
add(ScrollPane(tabPickerTable).apply { this.width= mapEditorScreen.stage.width/3}).row()
|
||||||
|
|
||||||
add(editorPickTable).row()
|
add(editorPickTable).row()
|
||||||
@ -74,7 +96,7 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
}
|
}
|
||||||
}).row()
|
}).row()
|
||||||
|
|
||||||
for(improvement in ruleSet.tileImprovements.values){
|
for(improvement in ruleset.tileImprovements.values){
|
||||||
if(improvement.name.startsWith("Remove")) continue
|
if(improvement.name.startsWith("Remove")) continue
|
||||||
val improvementImage = getHex(Color.WHITE,ImageGetter.getImprovementIcon(improvement.name,40f))
|
val improvementImage = getHex(Color.WHITE,ImageGetter.getImprovementIcon(improvement.name,40f))
|
||||||
improvementImage.onClick {
|
improvementImage.onClick {
|
||||||
@ -88,7 +110,7 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
editorPickTable.add(ScrollPane(improvementsTable)).height(mapEditorScreen.stage.height*0.7f)
|
editorPickTable.add(ScrollPane(improvementsTable)).height(mapEditorScreen.stage.height*0.7f)
|
||||||
|
|
||||||
val nationsTable = Table()
|
val nationsTable = Table()
|
||||||
for(nation in ruleSet.nations.values){
|
for(nation in ruleset.nations.values){
|
||||||
val nationImage = getHex(Color.WHITE,ImageGetter.getNationIndicator(nation,40f))
|
val nationImage = getHex(Color.WHITE,ImageGetter.getNationIndicator(nation,40f))
|
||||||
nationImage.onClick {
|
nationImage.onClick {
|
||||||
clearSelection()
|
clearSelection()
|
||||||
@ -151,16 +173,16 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
for (resource in ruleSet.tileResources.values) {
|
for (resource in ruleset.tileResources.values) {
|
||||||
val resourceHex = getHex(Color.WHITE, ImageGetter.getResourceImage(resource.name, 40f))
|
val resourceHex = getHex(Color.WHITE, ImageGetter.getResourceImage(resource.name, 40f))
|
||||||
resourceHex.onClick {
|
resourceHex.onClick {
|
||||||
clearSelection()
|
clearSelection()
|
||||||
selectedResource = resource
|
selectedResource = resource
|
||||||
val tileInfo = TileInfo()
|
val tileInfo = TileInfo()
|
||||||
tileInfo.ruleset = mapEditorScreen.ruleSet
|
tileInfo.ruleset = mapEditorScreen.ruleset
|
||||||
|
|
||||||
val terrain = resource.terrainsCanBeFoundOn.first()
|
val terrain = resource.terrainsCanBeFoundOn.first()
|
||||||
val terrainObject = ruleSet.terrains[terrain]!!
|
val terrainObject = ruleset.terrains[terrain]!!
|
||||||
if (terrainObject.type == TerrainType.TerrainFeature) {
|
if (terrainObject.type == TerrainType.TerrainFeature) {
|
||||||
tileInfo.baseTerrain = when {
|
tileInfo.baseTerrain = when {
|
||||||
terrainObject.occursOn == null -> terrainObject.occursOn!!.first()
|
terrainObject.occursOn == null -> terrainObject.occursOn!!.first()
|
||||||
@ -179,9 +201,9 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addTerrainOptions(terrainFeaturesTable: Table, baseTerrainTable: Table) {
|
private fun addTerrainOptions(terrainFeaturesTable: Table, baseTerrainTable: Table) {
|
||||||
for (terrain in ruleSet.terrains.values) {
|
for (terrain in ruleset.terrains.values) {
|
||||||
val tileInfo = TileInfo()
|
val tileInfo = TileInfo()
|
||||||
tileInfo.ruleset = mapEditorScreen.ruleSet
|
tileInfo.ruleset = mapEditorScreen.ruleset
|
||||||
if (terrain.type == TerrainType.TerrainFeature) {
|
if (terrain.type == TerrainType.TerrainFeature) {
|
||||||
tileInfo.baseTerrain = when {
|
tileInfo.baseTerrain = when {
|
||||||
terrain.occursOn != null -> terrain.occursOn.first()
|
terrain.occursOn != null -> terrain.occursOn.first()
|
||||||
@ -318,7 +340,7 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
else tileInfo.improvement = improvement.name
|
else tileInfo.improvement = improvement.name
|
||||||
|
|
||||||
if(improvement.name.startsWith("StartingLocation"))
|
if(improvement.name.startsWith("StartingLocation"))
|
||||||
for(tileGroup in mapEditorScreen.mapHolder.tileGroups){
|
for(tileGroup in mapEditorScreen.mapHolder.tileGroups.values){
|
||||||
val tile = tileGroup.tileInfo
|
val tile = tileGroup.tileInfo
|
||||||
if(tile.improvement==improvement.name && tile!=tileInfo)
|
if(tile.improvement==improvement.name && tile!=tileInfo)
|
||||||
tile.improvement=null
|
tile.improvement=null
|
||||||
@ -332,7 +354,6 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
}
|
}
|
||||||
|
|
||||||
normalizeTile(tileInfo)
|
normalizeTile(tileInfo)
|
||||||
tileInfo.setTransients()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun normalizeTile(tileInfo: TileInfo){
|
fun normalizeTile(tileInfo: TileInfo){
|
||||||
|
48
core/src/com/unciv/ui/utils/ZoomableScrollPane.kt
Normal file
48
core/src/com/unciv/ui/utils/ZoomableScrollPane.kt
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package com.unciv.ui.utils
|
||||||
|
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.InputEvent
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.InputListener
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
|
||||||
|
open class ZoomableScrollPane: ScrollPane(null) {
|
||||||
|
init{
|
||||||
|
// Remove the existing inputListener
|
||||||
|
// which defines that mouse scroll = vertical movement
|
||||||
|
val zoomListener = listeners.last { it is InputListener && it !in captureListeners }
|
||||||
|
removeListener(zoomListener)
|
||||||
|
addZoomListeners()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun zoom(zoomScale: Float) {
|
||||||
|
if (zoomScale < 0.5f) return
|
||||||
|
setScale(zoomScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addZoomListeners() {
|
||||||
|
|
||||||
|
addListener(object: InputListener() {
|
||||||
|
override fun scrolled(event: InputEvent?, x: Float, y: Float, amount: Int): Boolean {
|
||||||
|
if(amount > 0) zoom(scaleX * 0.8f)
|
||||||
|
else zoom(scaleX / 0.8f)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
addListener(object : ActorGestureListener() {
|
||||||
|
var lastScale = 1f
|
||||||
|
var lastInitialDistance = 0f
|
||||||
|
|
||||||
|
override fun zoom(event: InputEvent?, initialDistance: Float, distance: Float) {
|
||||||
|
if (lastInitialDistance != initialDistance) {
|
||||||
|
lastInitialDistance = initialDistance
|
||||||
|
lastScale = scaleX
|
||||||
|
}
|
||||||
|
val scale: Float = sqrt((distance / initialDistance).toDouble()).toFloat() * lastScale
|
||||||
|
zoom(scale)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -16,14 +16,14 @@ import com.unciv.ui.utils.ImageGetter
|
|||||||
import com.unciv.ui.utils.onClick
|
import com.unciv.ui.utils.onClick
|
||||||
import com.unciv.ui.utils.surroundWithCircle
|
import com.unciv.ui.utils.surroundWithCircle
|
||||||
|
|
||||||
class Minimap(val tileMapHolder: TileMapHolder) : ScrollPane(null){
|
class Minimap(val mapHolder: WorldMapHolder) : ScrollPane(null){
|
||||||
val allTiles = Group()
|
val allTiles = Group()
|
||||||
val tileImages = HashMap<TileInfo, Image>()
|
val tileImages = HashMap<TileInfo, Image>()
|
||||||
|
|
||||||
|
|
||||||
fun setScrollToTileMapHolder(){
|
fun setScrollTomapHolder(){
|
||||||
scrollPercentX = tileMapHolder.scrollPercentX
|
scrollPercentX = mapHolder.scrollPercentX
|
||||||
scrollPercentY = tileMapHolder.scrollPercentY
|
scrollPercentY = mapHolder.scrollPercentY
|
||||||
}
|
}
|
||||||
|
|
||||||
init{
|
init{
|
||||||
@ -32,7 +32,7 @@ class Minimap(val tileMapHolder: TileMapHolder) : ScrollPane(null){
|
|||||||
var bottomX = 0f
|
var bottomX = 0f
|
||||||
var bottomY = 0f
|
var bottomY = 0f
|
||||||
|
|
||||||
for (tileInfo in tileMapHolder.tileMap.values) {
|
for (tileInfo in mapHolder.tileMap.values) {
|
||||||
val hex = ImageGetter.getImage("OtherIcons/Hexagon")
|
val hex = ImageGetter.getImage("OtherIcons/Hexagon")
|
||||||
|
|
||||||
val positionalVector = HexMath().hex2WorldCoords(tileInfo.position)
|
val positionalVector = HexMath().hex2WorldCoords(tileInfo.position)
|
||||||
@ -41,8 +41,8 @@ class Minimap(val tileMapHolder: TileMapHolder) : ScrollPane(null){
|
|||||||
hex.setPosition(positionalVector.x * 0.5f * groupSize,
|
hex.setPosition(positionalVector.x * 0.5f * groupSize,
|
||||||
positionalVector.y * 0.5f * groupSize)
|
positionalVector.y * 0.5f * groupSize)
|
||||||
hex.onClick {
|
hex.onClick {
|
||||||
tileMapHolder.setCenterPosition(tileInfo.position)
|
mapHolder.setCenterPosition(tileInfo.position)
|
||||||
setScrollToTileMapHolder()
|
setScrollTomapHolder()
|
||||||
}
|
}
|
||||||
allTiles.addActor(hex)
|
allTiles.addActor(hex)
|
||||||
tileImages[tileInfo] = hex
|
tileImages[tileInfo] = hex
|
||||||
@ -61,19 +61,19 @@ class Minimap(val tileMapHolder: TileMapHolder) : ScrollPane(null){
|
|||||||
// so we zero out the starting position of the whole board so they will be displayed as well
|
// so we zero out the starting position of the whole board so they will be displayed as well
|
||||||
allTiles.setSize(10 + topX - bottomX, 10 + topY - bottomY)
|
allTiles.setSize(10 + topX - bottomX, 10 + topY - bottomY)
|
||||||
|
|
||||||
widget = allTiles
|
actor = allTiles
|
||||||
layout()
|
layout()
|
||||||
updateVisualScroll()
|
updateVisualScroll()
|
||||||
tileMapHolder.addListener(object : InputListener(){
|
mapHolder.addListener(object : InputListener(){
|
||||||
override fun handle(e: Event?): Boolean {
|
override fun handle(e: Event?): Boolean {
|
||||||
setScrollToTileMapHolder()
|
setScrollTomapHolder()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(cloneCivilization: CivilizationInfo) {
|
fun update(cloneCivilization: CivilizationInfo) {
|
||||||
for(tileInfo in tileMapHolder.tileMap.values) {
|
for(tileInfo in mapHolder.tileMap.values) {
|
||||||
val hex = tileImages[tileInfo]!!
|
val hex = tileImages[tileInfo]!!
|
||||||
if (!(UncivGame.Current.viewEntireMapForDebug || cloneCivilization.exploredTiles.contains(tileInfo.position)))
|
if (!(UncivGame.Current.viewEntireMapForDebug || cloneCivilization.exploredTiles.contains(tileInfo.position)))
|
||||||
hex.color = Color.DARK_GRAY
|
hex.color = Color.DARK_GRAY
|
||||||
@ -86,9 +86,9 @@ class Minimap(val tileMapHolder: TileMapHolder) : ScrollPane(null){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MinimapHolder(tileMapHolder: TileMapHolder): Table(){
|
class MinimapHolder(mapHolder: WorldMapHolder): Table(){
|
||||||
val minimap = Minimap(tileMapHolder)
|
val minimap = Minimap(mapHolder)
|
||||||
val worldScreen = tileMapHolder.worldScreen
|
val worldScreen = mapHolder.worldScreen
|
||||||
|
|
||||||
init{
|
init{
|
||||||
add(getToggleIcons()).align(Align.bottom)
|
add(getToggleIcons()).align(Align.bottom)
|
||||||
|
@ -6,9 +6,7 @@ import com.badlogic.gdx.math.Interpolation
|
|||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.badlogic.gdx.scenes.scene2d.*
|
import com.badlogic.gdx.scenes.scene2d.*
|
||||||
import com.badlogic.gdx.scenes.scene2d.actions.FloatAction
|
import com.badlogic.gdx.scenes.scene2d.actions.FloatAction
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener
|
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.automation.UnitAutomation
|
import com.unciv.logic.automation.UnitAutomation
|
||||||
@ -21,26 +19,18 @@ import com.unciv.models.UncivSound
|
|||||||
import com.unciv.models.ruleset.unit.UnitType
|
import com.unciv.models.ruleset.unit.UnitType
|
||||||
import com.unciv.ui.tilegroups.TileSetStrings
|
import com.unciv.ui.tilegroups.TileSetStrings
|
||||||
import com.unciv.ui.tilegroups.WorldTileGroup
|
import com.unciv.ui.tilegroups.WorldTileGroup
|
||||||
|
import com.unciv.ui.map.TileGroupMap
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
import com.unciv.ui.worldscreen.unit.UnitContextMenu
|
import com.unciv.ui.worldscreen.unit.UnitContextMenu
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
import kotlin.math.sqrt
|
|
||||||
|
|
||||||
|
|
||||||
|
class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: TileMap): ZoomableScrollPane() {
|
||||||
class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: TileMap) : ScrollPane(null) {
|
|
||||||
internal var selectedTile: TileInfo? = null
|
internal var selectedTile: TileInfo? = null
|
||||||
val tileGroups = HashMap<TileInfo, WorldTileGroup>()
|
val tileGroups = HashMap<TileInfo, WorldTileGroup>()
|
||||||
|
|
||||||
var unitActionOverlay :Actor?=null
|
var unitActionOverlay :Actor?=null
|
||||||
|
|
||||||
init{
|
|
||||||
// Remove the existing inputListener
|
|
||||||
// which defines that mouse scroll = vertical movement
|
|
||||||
val zoomListener = listeners.last { it is InputListener && it !in captureListeners }
|
|
||||||
removeListener (zoomListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to transfer data on the "move here" button that should be created, from the side thread to the main thread
|
// Used to transfer data on the "move here" button that should be created, from the side thread to the main thread
|
||||||
class MoveHereButtonDto(val unit: MapUnit, val tileInfo: TileInfo, val turnsToGetThere: Int)
|
class MoveHereButtonDto(val unit: MapUnit, val tileInfo: TileInfo, val turnsToGetThere: Int)
|
||||||
|
|
||||||
@ -65,46 +55,9 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
setOrigin(width/2,height/2)
|
setOrigin(width/2,height/2)
|
||||||
center(worldScreen.stage)
|
center(worldScreen.stage)
|
||||||
|
|
||||||
addGestureListener()
|
|
||||||
|
|
||||||
addListener(object :InputListener(){
|
|
||||||
override fun scrolled(event: InputEvent?, x: Float, y: Float, amount: Int): Boolean {
|
|
||||||
if(amount>0) zoom(scaleX*0.8f)
|
|
||||||
else zoom(scaleX/0.8f)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
layout() // Fit the scroll pane to the contents - otherwise, setScroll won't work!
|
layout() // Fit the scroll pane to the contents - otherwise, setScroll won't work!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun zoom(zoomScale:Float){
|
|
||||||
if (zoomScale < 0.5f) return
|
|
||||||
setScale(zoomScale)
|
|
||||||
for (tilegroup in tileGroups.values.filter { it.cityButton != null })
|
|
||||||
tilegroup.cityButton!!.setScale(1 / zoomScale)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addGestureListener() {
|
|
||||||
addListener(object : ActorGestureListener() {
|
|
||||||
var lastScale = 1f
|
|
||||||
var lastInitialDistance = 0f
|
|
||||||
|
|
||||||
override fun zoom(event: InputEvent?, initialDistance: Float, distance: Float) {
|
|
||||||
// deselect any unit, as zooming occasionally forwards clicks on to the map
|
|
||||||
worldScreen.bottomUnitTable.selectedUnit = null
|
|
||||||
worldScreen.shouldUpdate = true
|
|
||||||
if (lastInitialDistance != initialDistance) {
|
|
||||||
lastInitialDistance = initialDistance
|
|
||||||
lastScale = scaleX
|
|
||||||
}
|
|
||||||
val scale: Float = sqrt((distance / initialDistance).toDouble()).toFloat() * lastScale
|
|
||||||
zoom(scale)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onTileClicked(tileInfo: TileInfo) {
|
private fun onTileClicked(tileInfo: TileInfo) {
|
||||||
unitActionOverlay?.remove()
|
unitActionOverlay?.remove()
|
||||||
selectedTile = tileInfo
|
selectedTile = tileInfo
|
||||||
@ -357,5 +310,4 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
|
|
||||||
worldScreen.shouldUpdate=true
|
worldScreen.shouldUpdate=true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -48,8 +48,8 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
var isPlayersTurn = viewingCiv == gameInfo.currentPlayerCiv // todo this should be updated when passing turns
|
var isPlayersTurn = viewingCiv == gameInfo.currentPlayerCiv // todo this should be updated when passing turns
|
||||||
var waitingForAutosave = false
|
var waitingForAutosave = false
|
||||||
|
|
||||||
val tileMapHolder: TileMapHolder = TileMapHolder(this, gameInfo.tileMap)
|
val mapHolder = WorldMapHolder(this, gameInfo.tileMap)
|
||||||
val minimapWrapper = MinimapHolder(tileMapHolder)
|
val minimapWrapper = MinimapHolder(mapHolder)
|
||||||
|
|
||||||
private val topBar = WorldScreenTopBar(this)
|
private val topBar = WorldScreenTopBar(this)
|
||||||
val bottomUnitTable = UnitTable(this)
|
val bottomUnitTable = UnitTable(this)
|
||||||
@ -76,7 +76,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
|
|
||||||
minimapWrapper.x = stage.width - minimapWrapper.width
|
minimapWrapper.x = stage.width - minimapWrapper.width
|
||||||
|
|
||||||
tileMapHolder.addTiles()
|
mapHolder.addTiles()
|
||||||
|
|
||||||
techButtonHolder.touchable=Touchable.enabled
|
techButtonHolder.touchable=Touchable.enabled
|
||||||
techButtonHolder.onClick(UncivSound.Paper) {
|
techButtonHolder.onClick(UncivSound.Paper) {
|
||||||
@ -92,7 +92,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
techPolicyAndVictoryHolder.add(policyScreenButton).pad(10f)
|
techPolicyAndVictoryHolder.add(policyScreenButton).pad(10f)
|
||||||
}
|
}
|
||||||
|
|
||||||
stage.addActor(tileMapHolder)
|
stage.addActor(mapHolder)
|
||||||
stage.addActor(minimapWrapper)
|
stage.addActor(minimapWrapper)
|
||||||
stage.addActor(topBar)
|
stage.addActor(topBar)
|
||||||
stage.addActor(nextTurnButton)
|
stage.addActor(nextTurnButton)
|
||||||
@ -119,7 +119,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
viewingCiv.getCivUnits().isNotEmpty() -> viewingCiv.getCivUnits().first().getTile().position
|
viewingCiv.getCivUnits().isNotEmpty() -> viewingCiv.getCivUnits().first().getTile().position
|
||||||
else -> Vector2.Zero
|
else -> Vector2.Zero
|
||||||
}
|
}
|
||||||
tileMapHolder.setCenterPosition(tileToCenterOn,true)
|
mapHolder.setCenterPosition(tileToCenterOn,true)
|
||||||
|
|
||||||
|
|
||||||
if(gameInfo.gameParameters.isOnlineMultiplayer && !gameInfo.isUpToDate)
|
if(gameInfo.gameParameters.isOnlineMultiplayer && !gameInfo.isUpToDate)
|
||||||
@ -173,7 +173,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
displayTutorialsOnUpdate()
|
displayTutorialsOnUpdate()
|
||||||
|
|
||||||
bottomUnitTable.update()
|
bottomUnitTable.update()
|
||||||
bottomTileInfoTable.updateTileTable(tileMapHolder.selectedTile!!)
|
bottomTileInfoTable.updateTileTable(mapHolder.selectedTile!!)
|
||||||
bottomTileInfoTable.x = stage.width - bottomTileInfoTable.width
|
bottomTileInfoTable.x = stage.width - bottomTileInfoTable.width
|
||||||
bottomTileInfoTable.y = if (UncivGame.Current.settings.showMinimap) minimapWrapper.height else 0f
|
bottomTileInfoTable.y = if (UncivGame.Current.settings.showMinimap) minimapWrapper.height else 0f
|
||||||
battleTable.update()
|
battleTable.update()
|
||||||
@ -198,7 +198,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
// if we use the clone, then when we update viewable tiles
|
// if we use the clone, then when we update viewable tiles
|
||||||
// it doesn't update the explored tiles of the civ... need to think about that harder
|
// it doesn't update the explored tiles of the civ... need to think about that harder
|
||||||
// it causes a bug when we move a unit to an unexplored tile (for instance a cavalry unit which can move far)
|
// it causes a bug when we move a unit to an unexplored tile (for instance a cavalry unit which can move far)
|
||||||
tileMapHolder.updateTiles(viewingCiv)
|
mapHolder.updateTiles(viewingCiv)
|
||||||
|
|
||||||
topBar.update(viewingCiv)
|
topBar.update(viewingCiv)
|
||||||
|
|
||||||
@ -344,7 +344,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
if (viewingCiv.shouldGoToDueUnit()) {
|
if (viewingCiv.shouldGoToDueUnit()) {
|
||||||
val nextDueUnit = viewingCiv.getNextDueUnit()
|
val nextDueUnit = viewingCiv.getNextDueUnit()
|
||||||
if(nextDueUnit!=null) {
|
if(nextDueUnit!=null) {
|
||||||
tileMapHolder.setCenterPosition(nextDueUnit.currentTile.position, false, false)
|
mapHolder.setCenterPosition(nextDueUnit.currentTile.position, false, false)
|
||||||
bottomUnitTable.selectedUnit = nextDueUnit
|
bottomUnitTable.selectedUnit = nextDueUnit
|
||||||
shouldUpdate=true
|
shouldUpdate=true
|
||||||
}
|
}
|
||||||
@ -413,11 +413,11 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
|
|
||||||
fun createNewWorldScreen(){
|
fun createNewWorldScreen(){
|
||||||
val newWorldScreen = WorldScreen(gameInfoClone.getPlayerToViewAs())
|
val newWorldScreen = WorldScreen(gameInfoClone.getPlayerToViewAs())
|
||||||
newWorldScreen.tileMapHolder.scrollX = tileMapHolder.scrollX
|
newWorldScreen.mapHolder.scrollX = mapHolder.scrollX
|
||||||
newWorldScreen.tileMapHolder.scrollY = tileMapHolder.scrollY
|
newWorldScreen.mapHolder.scrollY = mapHolder.scrollY
|
||||||
newWorldScreen.tileMapHolder.scaleX = tileMapHolder.scaleX
|
newWorldScreen.mapHolder.scaleX = mapHolder.scaleX
|
||||||
newWorldScreen.tileMapHolder.scaleY = tileMapHolder.scaleY
|
newWorldScreen.mapHolder.scaleY = mapHolder.scaleY
|
||||||
newWorldScreen.tileMapHolder.updateVisualScroll()
|
newWorldScreen.mapHolder.updateVisualScroll()
|
||||||
game.worldScreen = newWorldScreen
|
game.worldScreen = newWorldScreen
|
||||||
game.setWorldScreen()
|
game.setWorldScreen()
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,8 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
|||||||
|
|
||||||
private fun tryGetDefender(): ICombatant? {
|
private fun tryGetDefender(): ICombatant? {
|
||||||
val attackerCiv = worldScreen.viewingCiv
|
val attackerCiv = worldScreen.viewingCiv
|
||||||
if (worldScreen.tileMapHolder.selectedTile == null) return null // no selected tile
|
if (worldScreen.mapHolder.selectedTile == null) return null // no selected tile
|
||||||
val selectedTile = worldScreen.tileMapHolder.selectedTile!!
|
val selectedTile = worldScreen.mapHolder.selectedTile!!
|
||||||
|
|
||||||
val defender: ICombatant? = Battle(worldScreen.gameInfo).getMapCombatantOfTile(selectedTile)
|
val defender: ICombatant? = Battle(worldScreen.gameInfo).getMapCombatantOfTile(selectedTile)
|
||||||
|
|
||||||
@ -197,7 +197,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
|||||||
attackButton.onClick {
|
attackButton.onClick {
|
||||||
try {
|
try {
|
||||||
battle.moveAndAttack(attacker, attackableEnemy)
|
battle.moveAndAttack(attacker, attackableEnemy)
|
||||||
worldScreen.tileMapHolder.unitActionOverlay?.remove() // the overlay was one of attacking
|
worldScreen.mapHolder.unitActionOverlay?.remove() // the overlay was one of attacking
|
||||||
worldScreen.shouldUpdate = true
|
worldScreen.shouldUpdate = true
|
||||||
}
|
}
|
||||||
catch (ex:Exception){
|
catch (ex:Exception){
|
||||||
|
@ -7,11 +7,11 @@ import com.badlogic.gdx.utils.Align
|
|||||||
import com.unciv.logic.map.MapUnit
|
import com.unciv.logic.map.MapUnit
|
||||||
import com.unciv.ui.utils.ImageGetter
|
import com.unciv.ui.utils.ImageGetter
|
||||||
import com.unciv.ui.utils.onClick
|
import com.unciv.ui.utils.onClick
|
||||||
import com.unciv.ui.worldscreen.TileMapHolder
|
import com.unciv.ui.worldscreen.WorldMapHolder
|
||||||
|
|
||||||
class IdleUnitButton (
|
class IdleUnitButton (
|
||||||
internal val unitTable: UnitTable,
|
internal val unitTable: UnitTable,
|
||||||
val tileMapHolder: TileMapHolder,
|
val tileMapHolder: WorldMapHolder,
|
||||||
val previous:Boolean
|
val previous:Boolean
|
||||||
) : Table() {
|
) : Table() {
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ import com.unciv.ui.utils.CameraStageBaseScreen
|
|||||||
import com.unciv.ui.utils.ImageGetter
|
import com.unciv.ui.utils.ImageGetter
|
||||||
import com.unciv.ui.utils.Sounds
|
import com.unciv.ui.utils.Sounds
|
||||||
import com.unciv.ui.utils.onClick
|
import com.unciv.ui.utils.onClick
|
||||||
import com.unciv.ui.worldscreen.TileMapHolder
|
import com.unciv.ui.worldscreen.WorldMapHolder
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class UnitContextMenu(val tileMapHolder: TileMapHolder, val selectedUnit: MapUnit, val targetTile: TileInfo) : VerticalGroup() {
|
class UnitContextMenu(val tileMapHolder: WorldMapHolder, val selectedUnit: MapUnit, val targetTile: TileInfo) : VerticalGroup() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ import com.unciv.ui.utils.*
|
|||||||
import com.unciv.ui.worldscreen.WorldScreen
|
import com.unciv.ui.worldscreen.WorldScreen
|
||||||
|
|
||||||
class UnitTable(val worldScreen: WorldScreen) : Table(){
|
class UnitTable(val worldScreen: WorldScreen) : Table(){
|
||||||
private val prevIdleUnitButton = IdleUnitButton(this,worldScreen.tileMapHolder,true)
|
private val prevIdleUnitButton = IdleUnitButton(this,worldScreen.mapHolder,true)
|
||||||
private val nextIdleUnitButton = IdleUnitButton(this,worldScreen.tileMapHolder,false)
|
private val nextIdleUnitButton = IdleUnitButton(this,worldScreen.mapHolder,false)
|
||||||
private val unitIconHolder=Table()
|
private val unitIconHolder=Table()
|
||||||
private val unitNameLabel = "".toLabel()
|
private val unitNameLabel = "".toLabel()
|
||||||
private val promotionsTable = Table()
|
private val promotionsTable = Table()
|
||||||
@ -64,7 +64,7 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
|
|||||||
touchable = Touchable.enabled
|
touchable = Touchable.enabled
|
||||||
onClick {
|
onClick {
|
||||||
selectedUnit?.currentTile?.position?.let {
|
selectedUnit?.currentTile?.position?.let {
|
||||||
worldScreen.tileMapHolder.setCenterPosition(it, false, false)
|
worldScreen.mapHolder.setCenterPosition(it, false, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).expand()
|
}).expand()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user