mirror of
https://github.com/yairm210/Unciv.git
synced 2025-03-03 22:22:51 +07:00
Show a preview of custom maps on new game screen (#9234)
* Show a preview of custom maps on new game screen * Show a preview of custom maps on new game screen - step 2 * Show a preview of custom maps on new game screen V2
This commit is contained in:
parent
43b044740c
commit
b0876935f5
@ -0,0 +1,175 @@
|
||||
package com.unciv.ui.screens.newgamescreen
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.scenes.scene2d.Group
|
||||
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Container
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Array as GdxArray
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.UncivShowableException
|
||||
import com.unciv.logic.files.MapSaver
|
||||
import com.unciv.logic.map.MapParameters
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.ui.components.extensions.onChange
|
||||
import com.unciv.ui.components.extensions.pad
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.popups.Popup
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.victoryscreen.LoadMapPreview
|
||||
import com.unciv.utils.concurrency.Concurrency
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.isActive
|
||||
|
||||
class MapFileSelectTable(
|
||||
private val newGameScreen: NewGameScreen,
|
||||
private val mapParameters: MapParameters
|
||||
) : Table() {
|
||||
|
||||
private val mapFileSelectBox = SelectBox<FileHandleWrapper>(BaseScreen.skin)
|
||||
private val miniMapWrapper = Container<Group?>()
|
||||
private var mapPreviewJob: Job? = null
|
||||
|
||||
private val mapFilesSequence = sequence<FileHandle> {
|
||||
yieldAll(MapSaver.getMaps().asSequence())
|
||||
for (modFolder in RulesetCache.values.mapNotNull { it.folderLocation }) {
|
||||
val mapsFolder = modFolder.child(MapSaver.mapsFolder)
|
||||
if (mapsFolder.exists())
|
||||
yieldAll(mapsFolder.list().asSequence())
|
||||
}
|
||||
}.map { FileHandleWrapper(it) }
|
||||
|
||||
private val columnWidth = newGameScreen.getColumnWidth()
|
||||
|
||||
init {
|
||||
defaults().pad(5f, 10f) // Must stay same as in MapParametersTable
|
||||
val mapFileLabel = "{Map file}:".toLabel()
|
||||
add(mapFileLabel).left()
|
||||
add(mapFileSelectBox)
|
||||
// because SOME people gotta give the hugest names to their maps
|
||||
.maxWidth((columnWidth - mapFileLabel.prefWidth).coerceAtLeast(120f))
|
||||
.right().row()
|
||||
add(miniMapWrapper)
|
||||
.pad(15f)
|
||||
.colspan(2).center().row()
|
||||
|
||||
mapFileSelectBox.onChange { onSelectBoxChange() }
|
||||
}
|
||||
|
||||
// The SelectBox auto displays the text a object.toString(), which on the FileHandle itself includes the folder path.
|
||||
// So we wrap it in another object with a custom toString()
|
||||
private class FileHandleWrapper(val fileHandle: FileHandle) {
|
||||
override fun toString(): String = fileHandle.name()
|
||||
}
|
||||
|
||||
fun isNotEmpty() = mapFilesSequence.any()
|
||||
fun recentlySavedMapExists() = mapFilesSequence.any {
|
||||
it.fileHandle.lastModified() > System.currentTimeMillis() - 900000
|
||||
}
|
||||
|
||||
fun fillMapFileSelectBox() {
|
||||
if (!mapFileSelectBox.items.isEmpty) return
|
||||
|
||||
val mapFiles = GdxArray<FileHandleWrapper>()
|
||||
mapFilesSequence
|
||||
.sortedWith(compareBy(UncivGame.Current.settings.getCollatorFromLocale()) { it.toString() })
|
||||
.forEach { mapFiles.add(it) }
|
||||
mapFileSelectBox.items = mapFiles
|
||||
|
||||
// Pre-select: a) map saved within last 15min or b) map named in mapParameters or c) alphabetically first
|
||||
// This is a kludge - the better way would be to have a "play this map now" menu button in the editor
|
||||
// (which would ideally not even require a save file - which makes implementation non-trivial)
|
||||
val selectedItem =
|
||||
mapFiles.maxByOrNull { it.fileHandle.lastModified() }
|
||||
?.takeIf { it.fileHandle.lastModified() > System.currentTimeMillis() - 900000 }
|
||||
?: mapFiles.firstOrNull { it.fileHandle.name() == mapParameters.name }
|
||||
?: mapFiles.firstOrNull()
|
||||
?: return
|
||||
mapFileSelectBox.selected = selectedItem
|
||||
mapParameters.name = selectedItem.toString()
|
||||
newGameScreen.gameSetupInfo.mapFile = selectedItem.fileHandle
|
||||
}
|
||||
|
||||
private fun onSelectBoxChange() {
|
||||
cancelBackgroundJobs()
|
||||
val mapFile = mapFileSelectBox.selected.fileHandle
|
||||
val mapParams = try {
|
||||
MapSaver.loadMapParameters(mapFile)
|
||||
} catch (ex:Exception){
|
||||
ex.printStackTrace()
|
||||
Popup(newGameScreen).apply {
|
||||
addGoodSizedLabel("Could not load map!").row()
|
||||
if (ex is UncivShowableException)
|
||||
addGoodSizedLabel(ex.message).row()
|
||||
addCloseButton()
|
||||
open()
|
||||
}
|
||||
return
|
||||
}
|
||||
mapParameters.name = mapFile.name()
|
||||
newGameScreen.gameSetupInfo.mapFile = mapFile
|
||||
val mapMods = mapParams.mods.partition { RulesetCache[it]?.modOptions?.isBaseRuleset == true }
|
||||
newGameScreen.gameSetupInfo.gameParameters.mods = LinkedHashSet(mapMods.second)
|
||||
newGameScreen.gameSetupInfo.gameParameters.baseRuleset = mapMods.first.firstOrNull() ?: mapParams.baseRuleset
|
||||
newGameScreen.updateRuleset()
|
||||
newGameScreen.updateTables()
|
||||
hideMiniMap()
|
||||
startMapPreview(mapFile)
|
||||
}
|
||||
|
||||
private fun startMapPreview(mapFile: FileHandle) {
|
||||
mapPreviewJob = Concurrency.run {
|
||||
try {
|
||||
val map = MapSaver.loadMap(mapFile)
|
||||
if (!isActive) return@run
|
||||
map.setTransients(newGameScreen.ruleset, false)
|
||||
if (!isActive) return@run
|
||||
// ReplyMap still paints outside its bounds - so we subtract padding and a little extra
|
||||
val size = (columnWidth - 40f).coerceAtMost(500f)
|
||||
val miniMap = LoadMapPreview(map, size, size)
|
||||
if (!isActive) return@run
|
||||
Concurrency.runOnGLThread {
|
||||
showMinimap(miniMap)
|
||||
}
|
||||
} catch (_: Throwable) {}
|
||||
}.apply {
|
||||
invokeOnCompletion {
|
||||
mapPreviewJob = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun cancelBackgroundJobs() {
|
||||
mapPreviewJob?.cancel()
|
||||
mapPreviewJob = null
|
||||
miniMapWrapper.clearActions()
|
||||
}
|
||||
|
||||
private fun showMinimap(miniMap: LoadMapPreview) {
|
||||
if (miniMapWrapper.actor == miniMap) return
|
||||
miniMapWrapper.clearActions()
|
||||
miniMapWrapper.color.a = 0f
|
||||
miniMapWrapper.actor = miniMap
|
||||
miniMapWrapper.invalidateHierarchy()
|
||||
miniMapWrapper.addAction(Actions.fadeIn(0.2f))
|
||||
}
|
||||
|
||||
private fun hideMiniMap() {
|
||||
if (miniMapWrapper.actor !is LoadMapPreview) return
|
||||
miniMapWrapper.clearActions()
|
||||
miniMapWrapper.addAction(
|
||||
Actions.sequence(
|
||||
Actions.fadeOut(0.4f),
|
||||
Actions.run {
|
||||
// in portrait, simply removing the map preview will cause the layout to "jump".
|
||||
// with a dummy holding the empty space, it jumps later and not as far.
|
||||
val dummy = Group().apply {
|
||||
setSize(miniMapWrapper.actor!!.width, miniMapWrapper.actor!!.height)
|
||||
}
|
||||
miniMapWrapper.actor = dummy
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
@ -1,66 +1,35 @@
|
||||
package com.unciv.ui.screens.newgamescreen
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Array
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.files.MapSaver
|
||||
import com.unciv.logic.UncivShowableException
|
||||
import com.unciv.logic.map.MapGeneratedMainType
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.ui.popups.Popup
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.components.extensions.onChange
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
|
||||
class MapOptionsTable(private val newGameScreen: NewGameScreen): Table() {
|
||||
|
||||
private val mapParameters = newGameScreen.gameSetupInfo.mapParameters
|
||||
private var mapTypeSpecificTable = Table()
|
||||
val generatedMapOptionsTable = MapParametersTable(newGameScreen, mapParameters, MapGeneratedMainType.generated)
|
||||
internal val generatedMapOptionsTable = MapParametersTable(newGameScreen, mapParameters, MapGeneratedMainType.generated)
|
||||
private val randomMapOptionsTable = MapParametersTable(newGameScreen, mapParameters, MapGeneratedMainType.randomGenerated)
|
||||
private val savedMapOptionsTable = Table()
|
||||
lateinit var mapTypeSelectBox: TranslatedSelectBox
|
||||
private val mapFileSelectBox = createMapFileSelectBox()
|
||||
|
||||
private val mapFilesSequence = sequence<FileHandle> {
|
||||
yieldAll(MapSaver.getMaps().asSequence())
|
||||
for (modFolder in RulesetCache.values.mapNotNull { it.folderLocation }) {
|
||||
val mapsFolder = modFolder.child(MapSaver.mapsFolder)
|
||||
if (mapsFolder.exists())
|
||||
yieldAll(mapsFolder.list().asSequence())
|
||||
}
|
||||
}.map { FileHandleWrapper(it) }
|
||||
private val savedMapOptionsTable = MapFileSelectTable(newGameScreen, mapParameters)
|
||||
internal val mapTypeSelectBox: TranslatedSelectBox
|
||||
|
||||
init {
|
||||
//defaults().pad(5f) - each nested table having the same can give 'stairs' effects,
|
||||
// better control directly. Besides, the first Labels/Buttons should have 10f to look nice
|
||||
addMapTypeSelection()
|
||||
background = BaseScreen.skinStrings.getUiBackground("NewGameScreen/MapOptionsTable", tintColor = BaseScreen.skinStrings.skinConfig.clearColor)
|
||||
}
|
||||
|
||||
private fun addMapTypeSelection() {
|
||||
val mapTypes = arrayListOf(MapGeneratedMainType.generated, MapGeneratedMainType.randomGenerated)
|
||||
if (mapFilesSequence.any()) mapTypes.add(MapGeneratedMainType.custom)
|
||||
if (savedMapOptionsTable.isNotEmpty()) mapTypes.add(MapGeneratedMainType.custom)
|
||||
mapTypeSelectBox = TranslatedSelectBox(mapTypes, "Generated", BaseScreen.skin)
|
||||
|
||||
savedMapOptionsTable.defaults().pad(5f)
|
||||
savedMapOptionsTable.add("{Map file}:".toLabel()).left()
|
||||
// because SOME people gotta give the hugest names to their maps
|
||||
val columnWidth = newGameScreen.stage.width / (if (newGameScreen.isNarrowerThan4to3()) 1 else 3)
|
||||
savedMapOptionsTable.add(mapFileSelectBox)
|
||||
.maxWidth((columnWidth - 120f).coerceAtLeast(120f))
|
||||
.right().row()
|
||||
|
||||
|
||||
fun updateOnMapTypeChange() {
|
||||
mapTypeSpecificTable.clear()
|
||||
when (mapTypeSelectBox.selected.value) {
|
||||
MapGeneratedMainType.custom -> {
|
||||
fillMapFileSelectBox()
|
||||
savedMapOptionsTable.fillMapFileSelectBox()
|
||||
mapParameters.type = MapGeneratedMainType.custom
|
||||
mapParameters.name = mapFileSelectBox.selected.toString()
|
||||
mapTypeSpecificTable.add(savedMapOptionsTable)
|
||||
newGameScreen.unlockTables()
|
||||
}
|
||||
@ -82,7 +51,7 @@ class MapOptionsTable(private val newGameScreen: NewGameScreen): Table() {
|
||||
}
|
||||
|
||||
// Pre-select custom if any map saved within last 15 minutes
|
||||
if (mapFilesSequence.any { it.fileHandle.lastModified() > System.currentTimeMillis() - 900000 })
|
||||
if (savedMapOptionsTable.recentlySavedMapExists())
|
||||
mapTypeSelectBox.selected =
|
||||
TranslatedSelectBox.TranslatedString(MapGeneratedMainType.custom)
|
||||
|
||||
@ -98,59 +67,5 @@ class MapOptionsTable(private val newGameScreen: NewGameScreen): Table() {
|
||||
add(mapTypeSpecificTable).row()
|
||||
}
|
||||
|
||||
private fun createMapFileSelectBox(): SelectBox<FileHandleWrapper> {
|
||||
val mapFileSelectBox = SelectBox<FileHandleWrapper>(BaseScreen.skin)
|
||||
mapFileSelectBox.onChange {
|
||||
val mapFile = mapFileSelectBox.selected.fileHandle
|
||||
val mapParams = try {
|
||||
MapSaver.loadMapParameters(mapFile)
|
||||
} catch (ex:Exception){
|
||||
ex.printStackTrace()
|
||||
Popup(newGameScreen).apply {
|
||||
addGoodSizedLabel("Could not load map!").row()
|
||||
if (ex is UncivShowableException)
|
||||
addGoodSizedLabel(ex.message).row()
|
||||
addCloseButton()
|
||||
open()
|
||||
}
|
||||
return@onChange
|
||||
}
|
||||
mapParameters.name = mapFile.name()
|
||||
newGameScreen.gameSetupInfo.mapFile = mapFile
|
||||
val mapMods = mapParams.mods.partition { RulesetCache[it]?.modOptions?.isBaseRuleset == true }
|
||||
newGameScreen.gameSetupInfo.gameParameters.mods = LinkedHashSet(mapMods.second)
|
||||
newGameScreen.gameSetupInfo.gameParameters.baseRuleset = mapMods.first.firstOrNull() ?: mapParams.baseRuleset
|
||||
newGameScreen.updateRuleset()
|
||||
newGameScreen.updateTables()
|
||||
}
|
||||
return mapFileSelectBox
|
||||
}
|
||||
|
||||
private fun fillMapFileSelectBox() {
|
||||
if (!mapFileSelectBox.items.isEmpty) return
|
||||
val mapFiles = Array<FileHandleWrapper>()
|
||||
mapFilesSequence
|
||||
.sortedWith(compareBy(UncivGame.Current.settings.getCollatorFromLocale()) { it.toString() })
|
||||
.forEach { mapFiles.add(it) }
|
||||
mapFileSelectBox.items = mapFiles
|
||||
|
||||
// Pre-select: a) map saved within last 15min or b) map named in mapParameters or c) alphabetically first
|
||||
// This is a kludge - the better way would be to have a "play this map now" menu button in the editor
|
||||
// (which would ideally not even require a save file - which makes implementation non-trivial)
|
||||
val selectedItem =
|
||||
mapFiles.maxByOrNull { it.fileHandle.lastModified() }
|
||||
?.takeIf { it.fileHandle.lastModified() > System.currentTimeMillis() - 900000 }
|
||||
?: mapFiles.firstOrNull { it.fileHandle.name() == mapParameters.name }
|
||||
?: mapFiles.firstOrNull()
|
||||
?: return
|
||||
mapFileSelectBox.selected = selectedItem
|
||||
newGameScreen.gameSetupInfo.mapFile = selectedItem.fileHandle
|
||||
}
|
||||
|
||||
// The SelectBox auto displays the text a object.toString(), which on the FileHandle itself includes the folder path.
|
||||
// So we wrap it in another object with a custom toString()
|
||||
class FileHandleWrapper(val fileHandle: FileHandle) {
|
||||
override fun toString(): String = fileHandle.name()
|
||||
}
|
||||
|
||||
internal fun cancelBackgroundJobs() = savedMapOptionsTable.cancelBackgroundJobs()
|
||||
}
|
||||
|
@ -80,7 +80,12 @@ class MapParametersTable(
|
||||
skin = BaseScreen.skin
|
||||
defaults().pad(5f, 10f)
|
||||
if (mapGeneratedMainType == MapGeneratedMainType.randomGenerated) {
|
||||
add("{Which options should be available to the random selection?}".toLabel()).colspan(2).grow().row()
|
||||
val prompt = "Which options should be available to the random selection?"
|
||||
val width = (previousScreen as? NewGameScreen)?.getColumnWidth() ?: 200f
|
||||
val label = WrappableLabel(prompt, width - 20f) // 20 is the defaults() padding
|
||||
label.setAlignment(Align.center)
|
||||
label.wrap = true
|
||||
add(label).colspan(2).grow().row()
|
||||
}
|
||||
addMapShapeSelectBox()
|
||||
addMapTypeSelectBox()
|
||||
|
@ -20,10 +20,13 @@ import com.unciv.models.metadata.GameSetupInfo
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.ExpanderTab
|
||||
import com.unciv.ui.components.KeyCharAndCode
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.addSeparatorVertical
|
||||
import com.unciv.ui.components.extensions.disable
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
import com.unciv.ui.components.extensions.keyShortcuts
|
||||
import com.unciv.ui.components.extensions.onActivation
|
||||
import com.unciv.ui.components.extensions.onClick
|
||||
import com.unciv.ui.components.extensions.pad
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
@ -76,7 +79,11 @@ class NewGameScreen(
|
||||
updatePlayerPickerRandomLabel = { playerPickerTable.updateRandomNumberLabel() }
|
||||
)
|
||||
mapOptionsTable = MapOptionsTable(this)
|
||||
setDefaultCloseAction()
|
||||
pickerPane.closeButton.onActivation {
|
||||
mapOptionsTable.cancelBackgroundJobs()
|
||||
game.popScreen()
|
||||
}
|
||||
pickerPane.closeButton.keyShortcuts.add(KeyCharAndCode.BACK)
|
||||
|
||||
if (isPortrait) initPortrait()
|
||||
else initLandscape()
|
||||
@ -104,6 +111,7 @@ class NewGameScreen(
|
||||
}
|
||||
|
||||
private fun onStartGameClicked() {
|
||||
mapOptionsTable.cancelBackgroundJobs()
|
||||
if (gameSetupInfo.gameParameters.isOnlineMultiplayer) {
|
||||
if (!checkConnectionToMultiplayerServer()) {
|
||||
val noInternetConnectionPopup = Popup(this)
|
||||
@ -206,6 +214,10 @@ class NewGameScreen(
|
||||
}
|
||||
}
|
||||
|
||||
/** Subtables may need an upper limit to their width - they can ask this function. */
|
||||
// In sync with isPortrait in init, here so UI details need not know about 3-column vs 1-column layout
|
||||
internal fun getColumnWidth() = stage.width / (if (isNarrowerThan4to3()) 1 else 3)
|
||||
|
||||
private fun initLandscape() {
|
||||
scrollPane.setScrollingDisabled(true,true)
|
||||
|
||||
|
@ -2,55 +2,126 @@ package com.unciv.ui.screens.victoryscreen
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.Group
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.logic.map.MapShape
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.ui.screens.worldscreen.minimap.MinimapTile
|
||||
import com.unciv.ui.screens.worldscreen.minimap.MinimapTileUtil
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sqrt
|
||||
|
||||
// Mostly copied from MiniMap
|
||||
class ReplayMap(
|
||||
val tileMap: TileMap,
|
||||
val viewingCiv: Civilization,
|
||||
private val replayMapWidth: Float,
|
||||
private val replayMapHeight: Float
|
||||
|
||||
@Suppress("LeakingThis")
|
||||
/**
|
||||
* Base for a MiniMap not intertwined with a WorldScreen.
|
||||
* For a _minimal_ implementation see [LoadMapPreview]
|
||||
*
|
||||
* TODO: Analyze why MiniMap needs the tight WorldScreen integration and clean up / merge
|
||||
*/
|
||||
abstract class IndependentMiniMap(
|
||||
val tileMap: TileMap
|
||||
) : Group() {
|
||||
private val tileLayer = Group()
|
||||
private val minimapTiles: List<MinimapTile>
|
||||
protected lateinit var minimapTiles: List<MinimapTile>
|
||||
|
||||
init {
|
||||
val tileSize = calcTileSize()
|
||||
/** Call this in the init of derived classes.
|
||||
*
|
||||
* Needs to be deferred only to allow [calcTileSize] or [includeTileFilter] to use class parameters added in the derived class. */
|
||||
protected open fun deferredInit(maxWidth: Float, maxHeight: Float) {
|
||||
val tileSize = calcTileSize(maxWidth, maxHeight)
|
||||
minimapTiles = createReplayMap(tileSize)
|
||||
val tileExtension = MinimapTileUtil.spreadOutMinimapTiles(tileLayer, minimapTiles, tileSize)
|
||||
val tileExtension = MinimapTileUtil.spreadOutMinimapTiles(this, minimapTiles, tileSize)
|
||||
|
||||
for (group in tileLayer.children) {
|
||||
for (group in children) {
|
||||
group.moveBy(-tileExtension.x, -tileExtension.y)
|
||||
}
|
||||
|
||||
// there are tiles "below the zero",
|
||||
// so we zero out the starting position of the whole board so they will be displayed as well
|
||||
tileLayer.setSize(tileExtension.width, tileExtension.height)
|
||||
setSize(tileLayer.width, tileLayer.height)
|
||||
addActor(tileLayer)
|
||||
setSize(tileExtension.width, tileExtension.height)
|
||||
}
|
||||
|
||||
private fun calcTileSize(): Float {
|
||||
/** Calculate a tile radius in screen coordinates so that the resulting map, after distributimg
|
||||
* the tiles using spreadOutMinimapTiles, will not exceed the bounds ([maxWidth],[maxHeight]) */
|
||||
protected abstract fun calcTileSize(maxWidth: Float, maxHeight: Float): Float
|
||||
|
||||
/** Controls which tiles are included */
|
||||
protected open fun includeTileFilter(tile: Tile): Boolean = true
|
||||
|
||||
private fun createReplayMap(tileSize: Float): List<MinimapTile> {
|
||||
val doNothing = fun(){}
|
||||
val tiles = ArrayList<MinimapTile>(tileMap.values.size)
|
||||
for (tile in tileMap.values.filter(::includeTileFilter) ) {
|
||||
val minimapTile = MinimapTile(tile, tileSize, doNothing)
|
||||
minimapTile.updateColor(false, null)
|
||||
tiles.add(minimapTile)
|
||||
}
|
||||
tiles.trimToSize()
|
||||
return tiles
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A minimap with no WorldScreen dependencies, always shows the entire map.
|
||||
*
|
||||
* @param tileMap Map to display minimap-style
|
||||
* @param maxWidth Resulting Group will not exceed this width
|
||||
* @param maxHeight Resulting Group will not exceed this height
|
||||
*/
|
||||
class LoadMapPreview(
|
||||
tileMap: TileMap,
|
||||
maxWidth: Float,
|
||||
maxHeight: Float
|
||||
) : IndependentMiniMap(tileMap) {
|
||||
init {
|
||||
deferredInit(maxWidth, maxHeight)
|
||||
}
|
||||
|
||||
override fun calcTileSize(maxWidth: Float, maxHeight: Float): Float {
|
||||
val height: Float
|
||||
val width: Float
|
||||
val mapSize = tileMap.mapParameters.mapSize
|
||||
if (tileMap.mapParameters.shape != MapShape.rectangular) {
|
||||
height = mapSize.radius * 2 + 1f
|
||||
width = height
|
||||
} else {
|
||||
height = mapSize.height.toFloat()
|
||||
width = mapSize.width.toFloat()
|
||||
}
|
||||
// See HexMath.worldFromLatLong, the 0.6 is empiric to avoid rounding to cause the map to spill over
|
||||
return min(
|
||||
maxWidth / (width + 0.6f) / 1.5f * 2f,
|
||||
maxHeight / (height + 0.6f) / sqrt(3f) * 2f,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A minimap with no WorldScreen dependencies, with the ability to show historical states.
|
||||
*
|
||||
* @param tileMap Map to display minimap-style
|
||||
* @param viewingCiv used to determine tile visibility and explored area
|
||||
* @param maxWidth Resulting Group should not exceed this width
|
||||
* @param maxHeight Resulting Group should not exceed this height
|
||||
*/
|
||||
class ReplayMap(
|
||||
tileMap: TileMap,
|
||||
val viewingCiv: Civilization,
|
||||
maxWidth: Float,
|
||||
maxHeight: Float
|
||||
) : IndependentMiniMap(tileMap) {
|
||||
init {
|
||||
deferredInit(maxWidth, maxHeight)
|
||||
}
|
||||
|
||||
override fun calcTileSize(maxWidth: Float, maxHeight: Float): Float {
|
||||
val height = viewingCiv.exploredRegion.getHeight().toFloat()
|
||||
val width = viewingCiv.exploredRegion.getWidth().toFloat()
|
||||
return min(
|
||||
replayMapHeight / (height + 1.5f) / sqrt(3f) * 4f, // 1.5 - padding, hex height = sqrt(3) / 2 * d / 2 -> d = height / sqrt(3) * 2 * 2
|
||||
replayMapWidth / (width + 0.5f) / 0.75f // 0.5 - padding, hex width = 0.75 * d -> d = width / 0.75
|
||||
return min (
|
||||
maxHeight / (height + 1.5f) / sqrt(3f) * 4f, // 1.5 - padding, hex height = sqrt(3) / 2 * d / 2 -> d = height / sqrt(3) * 2 * 2
|
||||
maxWidth / (width + 0.5f) / 0.75f // 0.5 - padding, hex width = 0.75 * d -> d = width / 0.75
|
||||
)
|
||||
}
|
||||
|
||||
private fun createReplayMap(tileSize: Float): List<MinimapTile> {
|
||||
val tiles = ArrayList<MinimapTile>()
|
||||
for (tile in tileMap.values.filter { it.isExplored(viewingCiv) }) {
|
||||
val minimapTile = MinimapTile(tile, tileSize) {}
|
||||
tiles.add(minimapTile)
|
||||
}
|
||||
return tiles
|
||||
}
|
||||
override fun includeTileFilter(tile: Tile) = tile.isExplored(viewingCiv)
|
||||
|
||||
fun update(turn: Int) {
|
||||
val viewingCivIsDefeated = viewingCiv.gameInfo.victoryData != null || !viewingCiv.isAlive()
|
||||
|
@ -51,7 +51,7 @@ class VictoryScreenReplay(
|
||||
gameInfo.tileMap,
|
||||
worldScreen.viewingCiv,
|
||||
worldScreen.stage.width - 50,
|
||||
worldScreen.stage.height - 250
|
||||
worldScreen.stage.height - 250 // Empiric: `stage.height - pager.contentScroll_field.height` after init is 244.
|
||||
)
|
||||
|
||||
playImage.setSize(24f)
|
||||
|
Loading…
Reference in New Issue
Block a user