Automated screenshots! :D
@ -3,7 +3,11 @@ package com.unciv.ui.options
|
|||||||
import com.badlogic.gdx.Application
|
import com.badlogic.gdx.Application
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.Input
|
import com.badlogic.gdx.Input
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
|
import com.badlogic.gdx.graphics.PixmapIO
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
||||||
@ -11,6 +15,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
|||||||
import com.badlogic.gdx.utils.Array
|
import com.badlogic.gdx.utils.Array
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.models.metadata.GameSettings
|
import com.unciv.models.metadata.GameSettings
|
||||||
|
import com.unciv.models.metadata.ScreenSize
|
||||||
import com.unciv.models.translations.TranslationFileWriter
|
import com.unciv.models.translations.TranslationFileWriter
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.popup.ConfirmPopup
|
import com.unciv.ui.popup.ConfirmPopup
|
||||||
@ -27,9 +32,14 @@ import com.unciv.ui.utils.extensions.onClick
|
|||||||
import com.unciv.ui.utils.extensions.setFontColor
|
import com.unciv.ui.utils.extensions.setFontColor
|
||||||
import com.unciv.ui.utils.extensions.toLabel
|
import com.unciv.ui.utils.extensions.toLabel
|
||||||
import com.unciv.ui.utils.extensions.toTextButton
|
import com.unciv.ui.utils.extensions.toTextButton
|
||||||
|
import com.unciv.ui.utils.extensions.withoutItem
|
||||||
import com.unciv.utils.concurrency.Concurrency
|
import com.unciv.utils.concurrency.Concurrency
|
||||||
import com.unciv.utils.concurrency.launchOnGLThread
|
import com.unciv.utils.concurrency.launchOnGLThread
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.zip.Deflater
|
||||||
|
|
||||||
fun advancedTab(
|
fun advancedTab(
|
||||||
optionsPopup: OptionsPopup,
|
optionsPopup: OptionsPopup,
|
||||||
@ -188,6 +198,73 @@ private fun addTranslationGeneration(table: Table, optionsPopup: OptionsPopup) {
|
|||||||
generateTranslationsButton.keyShortcuts.add(Input.Keys.F12)
|
generateTranslationsButton.keyShortcuts.add(Input.Keys.F12)
|
||||||
generateTranslationsButton.addTooltip("F12", 18f)
|
generateTranslationsButton.addTooltip("F12", 18f)
|
||||||
table.add(generateTranslationsButton).colspan(2).row()
|
table.add(generateTranslationsButton).colspan(2).row()
|
||||||
|
|
||||||
|
|
||||||
|
val generateScreenshotsButton = "Generate screenshots".toTextButton()
|
||||||
|
|
||||||
|
generateScreenshotsButton.onActivation {
|
||||||
|
optionsPopup.tabs.selectPage("Advanced")
|
||||||
|
generateScreenshotsButton.setText("Working...".tr())
|
||||||
|
Concurrency.run("GenerateScreenshot") {
|
||||||
|
val extraImagesLocation = "../../extraImages"
|
||||||
|
generateScreenshots(arrayListOf(
|
||||||
|
ScreenshotConfig(630, 500, ScreenSize.Medium, "$extraImagesLocation/itch.io image.png", Vector2(-2f, 2f),false),
|
||||||
|
ScreenshotConfig(1280, 640, ScreenSize.Medium, "$extraImagesLocation/GithubPreviewImage.png", Vector2(-2f, 4f)),
|
||||||
|
ScreenshotConfig(1024, 500, ScreenSize.Medium, "$extraImagesLocation/Feature graphic - Google Play.png",Vector2(-2f, 6f))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.add(generateScreenshotsButton).colspan(2).row()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ScreenshotConfig(val width: Int, val height: Int, val screenSize: ScreenSize, var fileLocation:String, var centerTile:Vector2, var attackCity:Boolean=true)
|
||||||
|
|
||||||
|
private fun CoroutineScope.generateScreenshots(configs:ArrayList<ScreenshotConfig>) {
|
||||||
|
val currentConfig = configs.first()
|
||||||
|
launchOnGLThread {
|
||||||
|
val screenshotGame =
|
||||||
|
UncivGame.Current.files.loadGameByName("ScreenshotGenerationGame")
|
||||||
|
UncivGame.Current.settings.screenSize = currentConfig.screenSize
|
||||||
|
val newScreen = UncivGame.Current.loadGame(screenshotGame)
|
||||||
|
|
||||||
|
|
||||||
|
newScreen.stage.viewport.update(currentConfig.width, currentConfig.height, true)
|
||||||
|
|
||||||
|
// Reposition mapholder and minimap whose position was based on the previous stage size...
|
||||||
|
newScreen.mapHolder.setSize(newScreen.stage.width, newScreen.stage.height)
|
||||||
|
newScreen.mapHolder.layout()
|
||||||
|
newScreen.minimapWrapper.x = newScreen.stage.width - newScreen.minimapWrapper.width
|
||||||
|
|
||||||
|
newScreen.mapHolder.setCenterPosition( // Center on the city
|
||||||
|
currentConfig.centerTile,
|
||||||
|
immediately = true,
|
||||||
|
selectUnit = true
|
||||||
|
)
|
||||||
|
|
||||||
|
newScreen.mapHolder.onTileClicked(newScreen.mapHolder.tileMap[-2, 3]) // Then click on Keshik
|
||||||
|
if (currentConfig.attackCity)
|
||||||
|
newScreen.mapHolder.onTileClicked(newScreen.mapHolder.tileMap[-2, 2]) // Then click city again for attack table
|
||||||
|
newScreen.mapHolder.zoomIn()
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
Thread.sleep(300)
|
||||||
|
launchOnGLThread {
|
||||||
|
val pixmap = Pixmap.createFromFrameBuffer(
|
||||||
|
0, 0,
|
||||||
|
currentConfig.width, currentConfig.height
|
||||||
|
)
|
||||||
|
PixmapIO.writePNG(
|
||||||
|
FileHandle(currentConfig.fileLocation),
|
||||||
|
pixmap,
|
||||||
|
Deflater.DEFAULT_COMPRESSION,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
pixmap.dispose()
|
||||||
|
val newConfigs = configs.withoutItem(currentConfig)
|
||||||
|
if (newConfigs.isNotEmpty()) generateScreenshots(newConfigs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addSetUserId(table: Table, settings: GameSettings) {
|
private fun addSetUserId(table: Table, settings: GameSettings) {
|
||||||
|
@ -169,7 +169,7 @@ class WorldMapHolder(
|
|||||||
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!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onTileClicked(tileInfo: TileInfo) {
|
fun onTileClicked(tileInfo: TileInfo) {
|
||||||
|
|
||||||
if (!worldScreen.viewingCiv.hasExplored(tileInfo)
|
if (!worldScreen.viewingCiv.hasExplored(tileInfo)
|
||||||
&& tileInfo.neighbors.all { worldScreen.viewingCiv.hasExplored(it) })
|
&& tileInfo.neighbors.all { worldScreen.viewingCiv.hasExplored(it) })
|
||||||
|
@ -120,7 +120,7 @@ class WorldScreen(
|
|||||||
val bottomUnitTable = UnitTable(this)
|
val bottomUnitTable = UnitTable(this)
|
||||||
private val battleTable = BattleTable(this)
|
private val battleTable = BattleTable(this)
|
||||||
private val zoomController = ZoomButtonPair(mapHolder)
|
private val zoomController = ZoomButtonPair(mapHolder)
|
||||||
private val minimapWrapper = MinimapHolder(mapHolder)
|
internal val minimapWrapper = MinimapHolder(mapHolder)
|
||||||
private val bottomTileInfoTable = TileInfoTable(viewingCiv)
|
private val bottomTileInfoTable = TileInfoTable(viewingCiv)
|
||||||
private val notificationsScroll = NotificationsScroll(this)
|
private val notificationsScroll = NotificationsScroll(this)
|
||||||
private val nextTurnButton = NextTurnButton()
|
private val nextTurnButton = NextTurnButton()
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
# Generating Screenshots
|
|
||||||
|
|
||||||
Images are the first way that a player viscerally connects to the game,
|
|
||||||
and so making our screenshots better leads to a direct increase in interest.
|
|
||||||
|
|
||||||
For us to continue to generate screenshots as the UI improves, we have a saved game named "ScreenshotGenerationGame" in the extraImages folder.
|
|
||||||
|
|
||||||
The easiest way to create screenshots is by:
|
|
||||||
|
|
||||||
- WRITE DOWN which file you're working on! They all look the same!
|
|
||||||
- Editing the gamesettings.json to the required height/width
|
|
||||||
- Loading the ScreenshotGenerationGame
|
|
||||||
- Centering on Elephantine
|
|
||||||
- Selecting the top-right Keshik, then clicking on Elephantine
|
|
||||||
- Screenshotting the entire window
|
|
||||||
- Cropping the area off the top (I use Shutter on Ubuntu for the above 2 steps)
|
|
||||||
- Save!
|
|
||||||
|
|
||||||
Quick dimensions checklist for y'all!
|
|
||||||
|
|
||||||
- Github preview image - 1280*640
|
|
||||||
- Feature Graphic - Google Play - 1024*500 - best in 900x600 resolution (options - display)
|
|
||||||
- Itch.io image - 630*500 - best in 1050x700 resolution
|
|
||||||
|
|
||||||
# Generating Steam images with Gimp
|
|
||||||
|
|
||||||
- Open map editor
|
|
||||||
- Take a screenshot of a nice-looking piece of map in the required dimensions (I use Shutter)
|
|
||||||
- Take the latest Unciv icon, add as another layer, and resize the layer until it's like 90% of the height
|
|
||||||
- Go here: https://text.imageonline.co/ and select color-black, font-Nobile, and Bold.
|
|
||||||
- Generate text in a good size to fit into the rest of your image, screenshot that (with the white background) and paste in a new layer
|
|
||||||
- Use the Bucket Fill, mode-erase, with opacity to get rid of most of the white, this should leave a small outline of white around our black text!
|
|
Before Width: | Height: | Size: 405 KiB After Width: | Height: | Size: 446 KiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 501 KiB After Width: | Height: | Size: 643 KiB |
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 343 KiB |