mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-08 04:41:51 +09:00
save load screen
This commit is contained in:
@@ -11,3 +11,18 @@ const val MIDDOT = 0xB7.toChar()
|
||||
const val ENDASH = 0x2013.toChar()
|
||||
const val EMDASH = 0x2014.toChar()
|
||||
const val ELLIPSIS = 0x2026.toChar()
|
||||
|
||||
fun getKeycapPC(c: Char) = when (c.uppercaseChar()) {
|
||||
in ' '..'_' -> (0xE000 + c.code - 32).toChar()
|
||||
else -> throw IllegalArgumentException("Not in range: ${c.code - 32}")
|
||||
}
|
||||
fun getKeycapPC(keycode: Int) = getKeycapPC(com.badlogic.gdx.Input.Keys.toString(keycode)[0])
|
||||
fun getKeycapConsole(c: Char) = when (c.uppercaseChar()) {
|
||||
in ' '..'_' -> (0xE040 + c.code - 32).toChar()
|
||||
else -> throw IllegalArgumentException("Not in range: ${c.code - 32}")
|
||||
}
|
||||
fun getKeycapFkeys(n: Int) = when (n) {
|
||||
in 1..9 -> "\uE090${(0xE090 + n).toChar()}"
|
||||
in 10..12 -> "\uE09D${(0xE090 + n).toChar()}"
|
||||
else -> throw IllegalArgumentException("Not in range: $n")
|
||||
}
|
||||
@@ -15,7 +15,6 @@ import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
import com.badlogic.gdx.utils.JsonValue;
|
||||
import com.badlogic.gdx.utils.ScreenUtils;
|
||||
import com.github.strikerx3.jxinput.XInputDevice;
|
||||
import net.torvald.gdx.graphics.PixmapIO2;
|
||||
import net.torvald.getcpuname.GetCpuName;
|
||||
@@ -535,7 +534,7 @@ public class App implements ApplicationListener {
|
||||
screenshotRequested = false;
|
||||
|
||||
try {
|
||||
Pixmap p = ScreenUtils.getFrameBufferPixmap(0, 0, scr.getWidth(), scr.getHeight());
|
||||
Pixmap p = Pixmap.createFromFrameBuffer(0, 0, scr.getWidth(), scr.getHeight());
|
||||
PixmapIO2.writeTGA(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".tga"), p, true);
|
||||
p.dispose();
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import com.badlogic.gdx.Input
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2019-08-11.
|
||||
*/
|
||||
|
||||
private val keyToIcon = hashMapOf(
|
||||
Input.Keys.NUM_0 to 0xE010.toChar(),
|
||||
Input.Keys.NUM_1 to 0xE011.toChar(),
|
||||
Input.Keys.NUM_2 to 0xE012.toChar(),
|
||||
Input.Keys.NUM_3 to 0xE013.toChar(),
|
||||
Input.Keys.NUM_4 to 0xE014.toChar(),
|
||||
Input.Keys.NUM_5 to 0xE015.toChar(),
|
||||
Input.Keys.NUM_6 to 0xE016.toChar(),
|
||||
Input.Keys.NUM_7 to 0xE017.toChar(),
|
||||
Input.Keys.NUM_8 to 0xE018.toChar(),
|
||||
Input.Keys.NUM_9 to 0xE019.toChar(),
|
||||
|
||||
Input.Keys.A to 0xE021.toChar(),
|
||||
Input.Keys.B to 0xE022.toChar(),
|
||||
Input.Keys.C to 0xE023.toChar(),
|
||||
Input.Keys.D to 0xE024.toChar(),
|
||||
Input.Keys.E to 0xE025.toChar(),
|
||||
Input.Keys.F to 0xE026.toChar(),
|
||||
Input.Keys.G to 0xE027.toChar(),
|
||||
Input.Keys.H to 0xE028.toChar(),
|
||||
Input.Keys.I to 0xE029.toChar(),
|
||||
Input.Keys.J to 0xE02A.toChar(),
|
||||
Input.Keys.K to 0xE02B.toChar(),
|
||||
Input.Keys.L to 0xE02C.toChar(),
|
||||
Input.Keys.M to 0xE02D.toChar(),
|
||||
|
||||
Input.Keys.N to 0xE02E.toChar(),
|
||||
Input.Keys.O to 0xE02E.toChar(),
|
||||
Input.Keys.P to 0xE030.toChar(),
|
||||
Input.Keys.Q to 0xE031.toChar(),
|
||||
Input.Keys.R to 0xE032.toChar(),
|
||||
Input.Keys.S to 0xE033.toChar(),
|
||||
Input.Keys.T to 0xE034.toChar(),
|
||||
Input.Keys.U to 0xE035.toChar(),
|
||||
Input.Keys.V to 0xE036.toChar(),
|
||||
Input.Keys.W to 0xE037.toChar(),
|
||||
Input.Keys.X to 0xE038.toChar(),
|
||||
Input.Keys.Y to 0xE039.toChar(),
|
||||
Input.Keys.Z to 0xE03A.toChar()
|
||||
)
|
||||
|
||||
fun keyToIcon(key: Int) = keyToIcon[key]!!
|
||||
|
||||
const val F1 = "${0xE090.toChar()}${0xE091.toChar()}"
|
||||
const val F2 = "${0xE090.toChar()}${0xE092.toChar()}"
|
||||
const val F3 = "${0xE090.toChar()}${0xE093.toChar()}"
|
||||
const val F4 = "${0xE090.toChar()}${0xE094.toChar()}"
|
||||
const val F5 = "${0xE090.toChar()}${0xE095.toChar()}"
|
||||
const val F6 = "${0xE090.toChar()}${0xE096.toChar()}"
|
||||
const val F7 = "${0xE090.toChar()}${0xE097.toChar()}"
|
||||
const val F8 = "${0xE090.toChar()}${0xE098.toChar()}"
|
||||
const val F9 = "${0xE090.toChar()}${0xE099.toChar()}"
|
||||
const val F10 = "${0xE09D.toChar()}${0xE09A.toChar()}"
|
||||
const val F11 = "${0xE09D.toChar()}${0xE09B.toChar()}"
|
||||
const val F12 = "${0xE09D.toChar()}${0xE09C.toChar()}"
|
||||
@@ -62,6 +62,7 @@ object DefaultConfig {
|
||||
"config_keymovementaux" to Input.Keys.A, // movement-auxiliary, or hookshot
|
||||
"config_keyinventory" to Input.Keys.Q,
|
||||
"config_keyinteract" to Input.Keys.R,
|
||||
"config_keydiscard" to Input.Keys.T,
|
||||
"config_keyclose" to Input.Keys.C, // this or hard-coded ESC
|
||||
"config_keyzoom" to Input.Keys.Z,
|
||||
|
||||
|
||||
@@ -375,7 +375,8 @@ infix fun Color.mulAndAssign(other: Color): Color {
|
||||
fun blendMul(batch: SpriteBatch) {
|
||||
// will break if the colour image contains semitransparency
|
||||
batch.enableBlending()
|
||||
batch.setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
||||
// batch.setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
||||
batch.setBlendFunctionSeparate(GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_DST_ALPHA, GL20.GL_SRC_ALPHA)
|
||||
}
|
||||
|
||||
fun blendScreen(batch: SpriteBatch) {
|
||||
@@ -390,7 +391,7 @@ fun blendDisable(batch: SpriteBatch) {
|
||||
|
||||
fun blendNormal(batch: SpriteBatch) {
|
||||
batch.enableBlending()
|
||||
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA, GL20.GL_ONE)
|
||||
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE)
|
||||
|
||||
// ALPHA *MUST BE* PREMULTIPLIED //
|
||||
|
||||
@@ -424,8 +425,8 @@ fun gdxSetBlend() {
|
||||
|
||||
fun gdxSetBlendNormal() {
|
||||
gdxSetBlend()
|
||||
Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA, GL20.GL_ONE)
|
||||
//Gdx.gl.glBlendEquationSeparate(GL20.GL_FUNC_ADD, GL30.GL_MAX) // batch.flush does not touch blend equation
|
||||
Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE)
|
||||
// Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA, GL20.GL_ONE)
|
||||
|
||||
// ALPHA *MUST BE* PREMULTIPLIED //
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ object IngameRenderer : Disposable {
|
||||
|
||||
private var newWorldLoadedLatch = false
|
||||
|
||||
|
||||
// these codes will run regardless of the invocation of the "initialise()" function
|
||||
// the "initialise()" function will also be called
|
||||
init {
|
||||
|
||||
@@ -188,26 +188,7 @@ internal class UIStorageChest : UICanvas(
|
||||
|
||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||
// background fill
|
||||
/*batch.end()
|
||||
gdxSetBlendNormal()
|
||||
|
||||
|
||||
val gradTopStart = (App.scr.height - internalHeight).div(2).toFloat()
|
||||
val gradBottomEnd = App.scr.height - gradTopStart
|
||||
|
||||
shapeRenderer.inUse {
|
||||
shapeRenderer.rect(0f, gradTopStart, App.scr.wf, gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
|
||||
shapeRenderer.rect(0f, gradBottomEnd, App.scr.wf, -gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
|
||||
|
||||
shapeRenderer.rect(0f, gradTopStart + gradHeight, App.scr.wf, internalHeight - (2 * gradHeight), gradEndCol, gradEndCol, gradEndCol, gradEndCol)
|
||||
|
||||
shapeRenderer.rect(0f, 0f, App.scr.wf, gradTopStart, gradStartCol, gradStartCol, gradStartCol, gradStartCol)
|
||||
shapeRenderer.rect(0f, App.scr.hf, App.scr.wf, -(App.scr.hf - gradBottomEnd), gradStartCol, gradStartCol, gradStartCol, gradStartCol)
|
||||
}
|
||||
|
||||
|
||||
|
||||
batch.begin()*/
|
||||
UIInventoryFull.drawBackground(batch, shapeRenderer)
|
||||
|
||||
// UI items
|
||||
batch.color = Color.WHITE
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
||||
import net.torvald.ENDASH
|
||||
import net.torvald.getKeycapPC
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.*
|
||||
import net.torvald.terrarum.blockstats.MinimapComposer
|
||||
@@ -58,6 +59,29 @@ class UIInventoryFull(
|
||||
val gradHeight = 48f
|
||||
|
||||
val controlHelpHeight = App.fontGame.lineHeight
|
||||
|
||||
fun drawBackground(batch: SpriteBatch, shapeRenderer: ShapeRenderer) {
|
||||
batch.end()
|
||||
gdxSetBlendNormal()
|
||||
|
||||
|
||||
val gradTopStart = (App.scr.height - internalHeight).div(2).toFloat()
|
||||
val gradBottomEnd = App.scr.height - gradTopStart
|
||||
|
||||
shapeRenderer.inUse {
|
||||
// shaperender starts at bottom-left!
|
||||
|
||||
shapeRenderer.rect(0f, gradTopStart, App.scr.wf, gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
|
||||
shapeRenderer.rect(0f, gradBottomEnd, App.scr.wf, -gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
|
||||
|
||||
shapeRenderer.rect(0f, gradTopStart + gradHeight, App.scr.wf, internalHeight - (2 * gradHeight), gradEndCol, gradEndCol, gradEndCol, gradEndCol)
|
||||
|
||||
shapeRenderer.rect(0f, 0f, App.scr.wf, gradTopStart, gradStartCol, gradStartCol, gradStartCol, gradStartCol)
|
||||
shapeRenderer.rect(0f, App.scr.hf, App.scr.wf, -(App.scr.hf - gradBottomEnd), gradStartCol, gradStartCol, gradStartCol, gradStartCol)
|
||||
}
|
||||
|
||||
batch.begin()
|
||||
}
|
||||
}
|
||||
|
||||
//val REQUIRED_MARGIN: Int = 138 // hard-coded value. Don't know the details. Range: [91-146]. I chose MAX-8 because cell gap is 8
|
||||
@@ -85,13 +109,13 @@ class UIInventoryFull(
|
||||
CommonResourcePool.loadAll()
|
||||
}
|
||||
|
||||
private val SP = "${0x3000.toChar()} "
|
||||
private val SP = "\u3000 "
|
||||
val listControlHelp: String
|
||||
get() = if (App.environment == RunningEnvironment.PC)
|
||||
"${0xe031.toChar()} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||
"${getKeycapPC(App.getConfigInt("config_keyinventory"))} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||
"${0xe006.toChar()} ${Lang["GAME_INVENTORY_USE"]}$SP" +
|
||||
"${0xe011.toChar()}$ENDASH${0x2009.toChar()}${0xe010.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
|
||||
"${0xe034.toChar()} ${Lang["GAME_INVENTORY_DROP"]}"
|
||||
"${getKeycapPC(App.getConfigInt("config_keydiscard"))} ${Lang["GAME_INVENTORY_DROP"]}"
|
||||
else
|
||||
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||
"$gamepadLabelLT ${Lang["CONTEXT_ITEM_MAP"]}$SP" +
|
||||
@@ -182,26 +206,7 @@ class UIInventoryFull(
|
||||
|
||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||
|
||||
// background fill
|
||||
batch.end()
|
||||
gdxSetBlendNormal()
|
||||
|
||||
|
||||
val gradTopStart = (App.scr.height - internalHeight).div(2).toFloat()
|
||||
val gradBottomEnd = App.scr.height - gradTopStart
|
||||
|
||||
shapeRenderer.inUse {
|
||||
shapeRenderer.rect(0f, gradTopStart, App.scr.wf, gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
|
||||
shapeRenderer.rect(0f, gradBottomEnd, App.scr.wf, -gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
|
||||
|
||||
shapeRenderer.rect(0f, gradTopStart + gradHeight, App.scr.wf, internalHeight - (2 * gradHeight), gradEndCol, gradEndCol, gradEndCol, gradEndCol)
|
||||
|
||||
shapeRenderer.rect(0f, 0f, App.scr.wf, gradTopStart, gradStartCol, gradStartCol, gradStartCol, gradStartCol)
|
||||
shapeRenderer.rect(0f, App.scr.hf, App.scr.wf, -(App.scr.hf - gradBottomEnd), gradStartCol, gradStartCol, gradStartCol, gradStartCol)
|
||||
}
|
||||
|
||||
|
||||
batch.begin()
|
||||
drawBackground(batch, shapeRenderer)
|
||||
|
||||
// UI items
|
||||
catBar.render(batch, camera)
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package net.torvald.terrarum.modulebasegame.ui
|
||||
|
||||
import com.badlogic.gdx.graphics.Camera
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.*
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
||||
import net.torvald.getKeycapConsole
|
||||
import net.torvald.getKeycapPC
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
@@ -14,15 +17,13 @@ import net.torvald.terrarum.serialise.ReadMeta
|
||||
import net.torvald.terrarum.tvda.ByteArray64InputStream
|
||||
import net.torvald.terrarum.tvda.VDUtil
|
||||
import net.torvald.terrarum.tvda.VirtualDisk
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.ui.UIItem
|
||||
import net.torvald.terrarum.ui.UIItemTextButton
|
||||
import net.torvald.terrarum.ui.*
|
||||
import java.io.File
|
||||
import java.time.Instant
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
import java.util.zip.GZIPInputStream
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2021-09-09.
|
||||
@@ -37,6 +38,38 @@ class UILoadDemoSavefiles : UICanvas() {
|
||||
set(value) {}
|
||||
override var openCloseTime: Second = 0f
|
||||
|
||||
|
||||
private val shaderAlfamul = ShaderProgram(vert, frag)
|
||||
|
||||
private val shapeRenderer = ShapeRenderer()
|
||||
private val transparent = Color(1f,1f,1f,0f)
|
||||
private val white = Color(1f, 1f, 1f, 1f)
|
||||
|
||||
|
||||
private val uiWidth = UIItemDemoSaveCells.WIDTH // 480
|
||||
private val uiX = (width - uiWidth) / 2
|
||||
|
||||
private val textH = App.fontGame.lineHeight.toInt()
|
||||
|
||||
private val cellGap = 24
|
||||
private val cellInterval = cellGap + UIItemDemoSaveCells.HEIGHT
|
||||
private val gradAreaHeight = 32
|
||||
|
||||
private val titleTextPosY: Int = App.scr.tvSafeGraphicsHeight + 10
|
||||
private val titleTopGradStart: Int = titleTextPosY + textH
|
||||
private val titleTopGradEnd: Int = titleTopGradStart + gradAreaHeight
|
||||
private val titleBottomGradStart: Int = height - App.scr.tvSafeGraphicsHeight - gradAreaHeight
|
||||
private val titleBottomGradEnd: Int = titleBottomGradStart + gradAreaHeight
|
||||
private val controlHelperY: Int = titleBottomGradStart + gradAreaHeight - textH
|
||||
|
||||
|
||||
private val controlHelp: String
|
||||
get() = if (App.environment == RunningEnvironment.PC)
|
||||
"${getKeycapPC(App.getConfigInt("config_keyup"))}${getKeycapPC(App.getConfigInt("config_keydown"))}" +
|
||||
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||
else
|
||||
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||
|
||||
// read savegames
|
||||
init {
|
||||
File(App.defaultSaveDir).listFiles().map { file ->
|
||||
@@ -48,23 +81,139 @@ class UILoadDemoSavefiles : UICanvas() {
|
||||
null
|
||||
}
|
||||
}.filter { it != null }.sortedByDescending { (it as VirtualDisk).entries[0]!!.modificationDate }.forEachIndexed { index, disk ->
|
||||
val x = (width - UIItemDemoSaveCells.WIDTH) / 2
|
||||
val y = 144 + (24 + UIItemDemoSaveCells.HEIGHT) * index
|
||||
val x = uiX
|
||||
val y = titleTopGradEnd + cellInterval * index
|
||||
addUIitem(UIItemDemoSaveCells(this, x, y, disk as VirtualDisk))
|
||||
}
|
||||
}
|
||||
|
||||
private var scrollAreaHeight = height - 2 * App.scr.tvSafeGraphicsHeight - 64
|
||||
private var listScroll = 0 // only update when animation is finished
|
||||
private var savesVisible = (scrollAreaHeight + cellGap) / cellInterval
|
||||
|
||||
private var uiScroll = 0f
|
||||
private var scrollFrom = 0
|
||||
private var scrollTarget = 0
|
||||
private var scrollAnimCounter = 0f
|
||||
private val scrollAnimLen = 0.1f
|
||||
|
||||
private var sliderFBO = FrameBuffer(Pixmap.Format.RGBA8888, uiWidth + 10, height, true)
|
||||
private var sliderFBO2 = FrameBuffer(Pixmap.Format.RGBA8888, width, height, true)
|
||||
|
||||
override fun updateUI(delta: Float) {
|
||||
uiItems.forEach { it.update(delta) }
|
||||
|
||||
if (scrollTarget != listScroll) {
|
||||
if (scrollAnimCounter < scrollAnimLen) {
|
||||
scrollAnimCounter += delta
|
||||
uiScroll = Movement.fastPullOut(
|
||||
scrollAnimCounter / scrollAnimLen,
|
||||
listScroll * cellInterval.toFloat(),
|
||||
scrollTarget * cellInterval.toFloat()
|
||||
)
|
||||
}
|
||||
else {
|
||||
scrollAnimCounter = 0f
|
||||
listScroll = scrollTarget
|
||||
uiScroll = cellInterval.toFloat() * scrollTarget
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uiItems.forEachIndexed { index, it ->
|
||||
if (index in listScroll - 2 until listScroll + savesVisible + 2) {
|
||||
// re-position
|
||||
it.posY = (it.initialY - uiScroll).roundToInt()
|
||||
it.update(delta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||
uiItems.forEach { it.render(batch, camera) }
|
||||
|
||||
val loadGameTitleStr = Lang["MENU_IO_LOAD_GAME"]
|
||||
App.fontGame.draw(batch, loadGameTitleStr, (width - App.fontGame.getWidth(loadGameTitleStr)).div(2).toFloat(), 62f)
|
||||
|
||||
|
||||
batch.end()
|
||||
|
||||
lateinit var savePixmap: Pixmap
|
||||
sliderFBO.inAction(camera as OrthographicCamera, batch) {
|
||||
gdxClearAndSetBlend(0f,0f,0f,0f)
|
||||
|
||||
setCameraPosition(batch, camera, 0f, 0f)
|
||||
batch.color = Color.WHITE
|
||||
batch.inUse {
|
||||
uiItems.forEachIndexed { index, it ->
|
||||
if (index in listScroll - 2 until listScroll + savesVisible + 2) {
|
||||
it.render(batch, camera)
|
||||
}
|
||||
}
|
||||
}
|
||||
savePixmap = Pixmap.createFromFrameBuffer(0, 0, sliderFBO.width, sliderFBO.height)
|
||||
savePixmap.blending = Pixmap.Blending.None
|
||||
}
|
||||
|
||||
|
||||
// implement "wipe-out" by CPU-rendering (*deep exhale*)
|
||||
//savePixmap.setColor(1f,1f,1f,0f)
|
||||
savePixmap.setColor(0f,0f,0f,0f)
|
||||
savePixmap.fillRectangle(0, savePixmap.height - titleTopGradStart, savePixmap.width, titleTopGradStart)
|
||||
// top grad
|
||||
for (y in titleTopGradStart until titleTopGradEnd) {
|
||||
val alpha = (y - titleTopGradStart).toFloat() / gradAreaHeight
|
||||
for (x in 0 until savePixmap.width) {
|
||||
val col = savePixmap.getPixel(x, savePixmap.height - y)
|
||||
val blendAlpha = (col.and(0xFF) * alpha).roundToInt()
|
||||
savePixmap.drawPixel(x, savePixmap.height - y, col.and(0xFFFFFF00.toInt()) or blendAlpha)
|
||||
}
|
||||
}
|
||||
// bottom grad
|
||||
for (y in titleBottomGradStart until titleBottomGradEnd) {
|
||||
val alpha = 1f - ((y - titleBottomGradStart).toFloat() / gradAreaHeight)
|
||||
for (x in 0 until savePixmap.width) {
|
||||
val col = savePixmap.getPixel(x, savePixmap.height - y)
|
||||
val blendAlpha = (col.and(0xFF) * alpha).roundToInt()
|
||||
savePixmap.drawPixel(x, savePixmap.height - y, col.and(0xFFFFFF00.toInt()) or blendAlpha)
|
||||
}
|
||||
}
|
||||
savePixmap.setColor(0f,0f,0f,0f)
|
||||
savePixmap.fillRectangle(0, 0, savePixmap.width, height - titleBottomGradEnd + 1)
|
||||
|
||||
|
||||
|
||||
setCameraPosition(batch, camera, 0f, 0f)
|
||||
val saveTex = Texture(savePixmap)
|
||||
batch.inUse {
|
||||
batch.draw(saveTex, (width - uiWidth - 10) / 2f, 0f)
|
||||
|
||||
// draw texts
|
||||
val loadGameTitleStr = Lang["MENU_IO_LOAD_GAME"]
|
||||
App.fontGame.draw(batch, loadGameTitleStr, (width - App.fontGame.getWidth(loadGameTitleStr)).div(2).toFloat(), titleTextPosY.toFloat())
|
||||
App.fontGame.draw(batch, controlHelp, uiX.toFloat(), controlHelperY.toFloat())
|
||||
}
|
||||
|
||||
saveTex.dispose()
|
||||
savePixmap.dispose()
|
||||
|
||||
batch.begin()
|
||||
}
|
||||
|
||||
|
||||
override fun keyDown(keycode: Int): Boolean {
|
||||
if (this.isVisible) {
|
||||
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("config_keyup")) && scrollTarget > 0) {
|
||||
scrollFrom = listScroll
|
||||
scrollTarget -= 1
|
||||
scrollAnimCounter = 0f
|
||||
}
|
||||
else if ((keycode == Input.Keys.DOWN || keycode == App.getConfigInt("config_keydown")) && scrollTarget < uiItems.size - savesVisible) {
|
||||
scrollFrom = listScroll
|
||||
scrollTarget += 1
|
||||
scrollAnimCounter = 0f
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
override fun doOpening(delta: Float) {
|
||||
}
|
||||
|
||||
@@ -75,9 +224,80 @@ class UILoadDemoSavefiles : UICanvas() {
|
||||
}
|
||||
|
||||
override fun endClosing(delta: Float) {
|
||||
listScroll = 0
|
||||
scrollTarget = 0
|
||||
uiScroll = 0f
|
||||
}
|
||||
|
||||
override fun dispose() {}
|
||||
override fun dispose() {
|
||||
shapeRenderer.dispose()
|
||||
sliderFBO.dispose()
|
||||
sliderFBO2.dispose()
|
||||
shaderAlfamul.dispose()
|
||||
}
|
||||
|
||||
override fun resize(width: Int, height: Int) {
|
||||
super.resize(width, height)
|
||||
scrollAreaHeight = height - 2 * App.scr.tvSafeGraphicsHeight - 64
|
||||
savesVisible = (scrollAreaHeight + cellInterval) / (cellInterval + UIItemDemoSaveCells.HEIGHT)
|
||||
|
||||
listScroll = 0
|
||||
scrollTarget = 0
|
||||
uiScroll = 0f
|
||||
|
||||
sliderFBO.dispose()
|
||||
sliderFBO = FrameBuffer(Pixmap.Format.RGBA8888, uiWidth + 10, height, true)
|
||||
|
||||
sliderFBO2.dispose()
|
||||
sliderFBO2 = FrameBuffer(Pixmap.Format.RGBA8888, width, height, true)
|
||||
}
|
||||
|
||||
private fun setCameraPosition(batch: SpriteBatch, camera: Camera, newX: Float, newY: Float) {
|
||||
camera.position.set((-newX + App.scr.halfw).round(), (-newY + App.scr.halfh).round(), 0f)
|
||||
camera.update()
|
||||
batch.projectionMatrix = camera.combined
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val vert = """
|
||||
attribute vec4 a_position;
|
||||
attribute vec4 a_color;
|
||||
attribute vec2 a_texCoord0;
|
||||
|
||||
uniform mat4 u_projTrans; // camera.combined
|
||||
|
||||
varying vec4 v_color;
|
||||
varying vec2 v_texCoords;
|
||||
|
||||
void main() {
|
||||
v_color = a_color;
|
||||
v_texCoords = a_texCoord0;
|
||||
gl_Position = u_projTrans * a_position;
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
private val frag = """
|
||||
#version 120
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
|
||||
varying vec4 v_color;
|
||||
varying vec2 v_texCoords;
|
||||
uniform sampler2D u_texture;
|
||||
|
||||
uniform sampler2D tex1;
|
||||
|
||||
void main(void) {
|
||||
vec4 colorTex0 = texture2D(u_texture, v_texCoords); // dest
|
||||
vec4 colorTex1 = texture2D(tex1, v_texCoords); // src mask; must be (1,1,1,a)
|
||||
|
||||
// gl_FragColor = colorTex0 * colorTex1;
|
||||
gl_FragColor = colorTex1.aaar;
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
class UIItemDemoSaveCells(
|
||||
@@ -88,7 +308,7 @@ class UIItemDemoSaveCells(
|
||||
|
||||
companion object {
|
||||
const val WIDTH = 480
|
||||
const val HEIGHT = 160
|
||||
const val HEIGHT = 120
|
||||
}
|
||||
|
||||
override val width: Int = WIDTH
|
||||
@@ -100,9 +320,6 @@ class UIItemDemoSaveCells(
|
||||
|
||||
private val meta = ReadMeta(disk)
|
||||
|
||||
private val x = initialX.toFloat()
|
||||
private val y = initialY.toFloat()
|
||||
|
||||
private fun parseDuration(seconds: Long): String {
|
||||
val s = seconds % 60
|
||||
val m = (seconds / 60) % 60
|
||||
@@ -130,7 +347,7 @@ class UIItemDemoSaveCells(
|
||||
val thumbTex = Texture(thumbPixmap)
|
||||
thumbTex.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
thumb = TextureRegion(thumbTex)
|
||||
thumb.setRegion(0, thumbTex.height / 4, thumbTex.width, thumbTex.height / 2)
|
||||
thumb.setRegion(0, (thumbTex.height - 2 * height) / 2, width * 2, height * 2)
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
// use stock texture
|
||||
@@ -145,11 +362,13 @@ class UIItemDemoSaveCells(
|
||||
|
||||
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||
val highlightCol = if (mouseUp) UIItemTextButton.defaultActiveCol else Color.WHITE
|
||||
val x = posX.toFloat()
|
||||
val y = posY.toFloat()
|
||||
|
||||
|
||||
// TODO draw border
|
||||
batch.color = highlightCol
|
||||
Toolkit.drawBoxBorder(batch, x.toInt()-1, y.toInt()-1, width+2, height+2)
|
||||
Toolkit.drawBoxBorder(batch, posX-1, posY-1, width+2, height+2)
|
||||
|
||||
// draw thumbnail
|
||||
batch.color = Color.WHITE
|
||||
@@ -157,14 +376,14 @@ class UIItemDemoSaveCells(
|
||||
batch.draw(thumb, x, y + height, width.toFloat(), -height.toFloat())
|
||||
// draw gradient
|
||||
blendMul(batch)
|
||||
batch.draw(grad, x + width, y, -width.toFloat(), height.toFloat())
|
||||
batch.draw(grad, x + width.toFloat(), y, -width.toFloat(), height.toFloat())
|
||||
|
||||
// draw texts
|
||||
batch.color = highlightCol
|
||||
// draw timestamp
|
||||
blendNormal(batch)
|
||||
val tlen = App.fontSmallNumbers.getWidth(lastPlayedTimestamp)
|
||||
App.fontSmallNumbers.draw(batch, lastPlayedTimestamp, posX + (width - tlen) - 3f, posY + height - 16f)
|
||||
App.fontSmallNumbers.draw(batch, lastPlayedTimestamp, x + (width - tlen) - 3f, y + height - 16f)
|
||||
// draw savegame name
|
||||
// App.fontGame.draw(batch, disk.getDiskNameString(Common.CHARSET), posX + 3f, posY + 1f)
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import com.badlogic.gdx.graphics.Camera
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.EMDASH
|
||||
import net.torvald.getKeycapPC
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.TerrarumScreenSize
|
||||
import net.torvald.terrarum.keyToIcon
|
||||
import net.torvald.terrarum.ui.Movement
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
|
||||
@@ -20,7 +20,7 @@ class UIScreenZoom : UICanvas(
|
||||
App.getConfigInt("config_keyzoom")
|
||||
) {
|
||||
|
||||
val zoomText = "${keyToIcon(handler.toggleKeyLiteral!!)} $EMDASH Zoom Out"
|
||||
val zoomText = "${getKeycapPC(handler.toggleKeyLiteral!!)} $EMDASH Zoom Out"
|
||||
|
||||
override var width = App.fontGame.getWidth(zoomText)
|
||||
override var height = App.fontGame.lineHeight.toInt()
|
||||
|
||||
Reference in New Issue
Block a user