mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-15 16:16:10 +09:00
reading savefiles won't freeze the ui (too much)
This commit is contained in:
@@ -16,7 +16,6 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
|||||||
import com.badlogic.gdx.utils.Disposable;
|
import com.badlogic.gdx.utils.Disposable;
|
||||||
import com.badlogic.gdx.utils.JsonValue;
|
import com.badlogic.gdx.utils.JsonValue;
|
||||||
import com.github.strikerx3.jxinput.XInputDevice;
|
import com.github.strikerx3.jxinput.XInputDevice;
|
||||||
import kotlin.Pair;
|
|
||||||
import net.torvald.gdx.graphics.PixmapIO2;
|
import net.torvald.gdx.graphics.PixmapIO2;
|
||||||
import net.torvald.getcpuname.GetCpuName;
|
import net.torvald.getcpuname.GetCpuName;
|
||||||
import net.torvald.terrarum.concurrent.ThreadExecutor;
|
import net.torvald.terrarum.concurrent.ThreadExecutor;
|
||||||
@@ -32,9 +31,7 @@ import net.torvald.terrarum.modulebasegame.IngameRenderer;
|
|||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame;
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame;
|
||||||
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory;
|
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory;
|
||||||
import net.torvald.terrarum.serialise.WriteConfig;
|
import net.torvald.terrarum.serialise.WriteConfig;
|
||||||
import net.torvald.terrarum.serialise.WriteMeta;
|
|
||||||
import net.torvald.terrarum.tvda.DiskSkimmer;
|
import net.torvald.terrarum.tvda.DiskSkimmer;
|
||||||
import net.torvald.terrarum.tvda.VirtualDisk;
|
|
||||||
import net.torvald.terrarum.utils.JsonFetcher;
|
import net.torvald.terrarum.utils.JsonFetcher;
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas;
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas;
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase;
|
import net.torvald.terrarumsansbitmap.gdx.GameFontBase;
|
||||||
@@ -235,7 +232,7 @@ public class App implements ApplicationListener {
|
|||||||
private static com.badlogic.gdx.graphics.Color gradWhiteTop = new com.badlogic.gdx.graphics.Color(0xf8f8f8ff);
|
private static com.badlogic.gdx.graphics.Color gradWhiteTop = new com.badlogic.gdx.graphics.Color(0xf8f8f8ff);
|
||||||
private static com.badlogic.gdx.graphics.Color gradWhiteBottom = new com.badlogic.gdx.graphics.Color(0xd8d8d8ff);
|
private static com.badlogic.gdx.graphics.Color gradWhiteBottom = new com.badlogic.gdx.graphics.Color(0xd8d8d8ff);
|
||||||
|
|
||||||
private static Screen currenScreen;
|
private static Screen currentScreen;
|
||||||
private static LoadScreenBase currentSetLoadScreen;
|
private static LoadScreenBase currentSetLoadScreen;
|
||||||
|
|
||||||
public static Texture textureWhiteSquare;
|
public static Texture textureWhiteSquare;
|
||||||
@@ -288,6 +285,10 @@ public class App implements ApplicationListener {
|
|||||||
"xinput", "xbox", "game", "joy", "pad"
|
"xinput", "xbox", "game", "joy", "pad"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static Screen getCurrentScreen() {
|
||||||
|
return currentScreen;
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// print copyright message
|
// print copyright message
|
||||||
System.out.println(csiB+GAME_NAME+" "+csiG+getVERSION_STRING()+" "+csiK+"\u2014"+" "+csi0+TerrarumAppConfiguration.COPYRIGHT_DATE_NAME);
|
System.out.println(csiB+GAME_NAME+" "+csiG+getVERSION_STRING()+" "+csiK+"\u2014"+" "+csi0+TerrarumAppConfiguration.COPYRIGHT_DATE_NAME);
|
||||||
@@ -521,7 +522,7 @@ public class App implements ApplicationListener {
|
|||||||
// draw splash screen when predefined screen is null
|
// draw splash screen when predefined screen is null
|
||||||
// because in normal operation, the only time screen == null is when the app is cold-launched
|
// because in normal operation, the only time screen == null is when the app is cold-launched
|
||||||
// you can't have a text drawn here :v
|
// you can't have a text drawn here :v
|
||||||
if (currenScreen == null) {
|
if (currentScreen == null) {
|
||||||
drawSplash();
|
drawSplash();
|
||||||
|
|
||||||
loadTimer += Gdx.graphics.getDeltaTime();
|
loadTimer += Gdx.graphics.getDeltaTime();
|
||||||
@@ -539,10 +540,10 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
// draw the screen
|
// draw the screen
|
||||||
else {
|
else {
|
||||||
currenScreen.render(UPDATE_RATE);
|
currentScreen.render(UPDATE_RATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyToggler.INSTANCE.update(currenScreen instanceof TerrarumIngame);
|
KeyToggler.INSTANCE.update(currentScreen instanceof TerrarumIngame);
|
||||||
|
|
||||||
// nested FBOs are just not a thing in GL!
|
// nested FBOs are just not a thing in GL!
|
||||||
net.torvald.terrarum.FrameBufferManager.end();
|
net.torvald.terrarum.FrameBufferManager.end();
|
||||||
@@ -663,7 +664,7 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
scr.setDimension(width, height);
|
scr.setDimension(width, height);
|
||||||
|
|
||||||
if (currenScreen != null) currenScreen.resize(scr.getWidth(), scr.getHeight());
|
if (currentScreen != null) currentScreen.resize(scr.getWidth(), scr.getHeight());
|
||||||
updateFullscreenQuad(scr.getWidth(), scr.getHeight());
|
updateFullscreenQuad(scr.getWidth(), scr.getHeight());
|
||||||
|
|
||||||
|
|
||||||
@@ -692,9 +693,9 @@ public class App implements ApplicationListener {
|
|||||||
System.out.println("Goodbye !");
|
System.out.println("Goodbye !");
|
||||||
|
|
||||||
|
|
||||||
if (currenScreen != null) {
|
if (currentScreen != null) {
|
||||||
currenScreen.hide();
|
currentScreen.hide();
|
||||||
currenScreen.dispose();
|
currentScreen.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
//IngameRenderer.INSTANCE.dispose();
|
//IngameRenderer.INSTANCE.dispose();
|
||||||
@@ -741,12 +742,12 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pause() {
|
public void pause() {
|
||||||
if (currenScreen != null) currenScreen.pause();
|
if (currentScreen != null) currentScreen.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resume() {
|
public void resume() {
|
||||||
if (currenScreen != null) currenScreen.resume();
|
if (currentScreen != null) currentScreen.resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoadScreenBase getLoadScreen() {
|
public static LoadScreenBase getLoadScreen() {
|
||||||
@@ -773,26 +774,26 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
// this whole thing is directtly copied from com.badlogic.gdx.Game
|
// this whole thing is directtly copied from com.badlogic.gdx.Game
|
||||||
|
|
||||||
if (currenScreen != null) {
|
if (currentScreen != null) {
|
||||||
printdbg("AppLoader-Static", "Screen before change: " + currenScreen.getClass().getCanonicalName());
|
printdbg("AppLoader-Static", "Screen before change: " + currentScreen.getClass().getCanonicalName());
|
||||||
|
|
||||||
currenScreen.hide();
|
currentScreen.hide();
|
||||||
currenScreen.dispose();
|
currentScreen.dispose();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printdbg("AppLoader-Static", "Screen before change: null");
|
printdbg("AppLoader-Static", "Screen before change: null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
currenScreen = screen;
|
currentScreen = screen;
|
||||||
|
|
||||||
currenScreen.show();
|
currentScreen.show();
|
||||||
currenScreen.resize(scr.getWidth(), scr.getHeight());
|
currentScreen.resize(scr.getWidth(), scr.getHeight());
|
||||||
|
|
||||||
|
|
||||||
System.gc();
|
System.gc();
|
||||||
|
|
||||||
printdbg("AppLoader-Static", "Screen transition complete: " + currenScreen.getClass().getCanonicalName());
|
printdbg("AppLoader-Static", "Screen transition complete: " + currentScreen.getClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
val uiContainer = UIContainer()
|
val uiContainer = UIContainer()
|
||||||
private lateinit var uiMenu: UICanvas
|
internal lateinit var uiRemoCon: UICanvas
|
||||||
internal lateinit var uiFakeBlurOverlay: UICanvas
|
internal lateinit var uiFakeBlurOverlay: UICanvas
|
||||||
|
|
||||||
private lateinit var worldFBO: FrameBuffer
|
private lateinit var worldFBO: FrameBuffer
|
||||||
@@ -189,12 +189,12 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
uiContainer.add(uiFakeBlurOverlay)
|
uiContainer.add(uiFakeBlurOverlay)
|
||||||
|
|
||||||
|
|
||||||
uiMenu = UIRemoCon(this, UITitleRemoConYaml(App.savegames.isNotEmpty()))
|
uiRemoCon = UIRemoCon(this, UITitleRemoConYaml(App.savegames.isNotEmpty()))
|
||||||
uiMenu.setPosition(0, 0)
|
uiRemoCon.setPosition(0, 0)
|
||||||
uiMenu.setAsOpen()
|
uiRemoCon.setAsOpen()
|
||||||
|
|
||||||
|
|
||||||
uiContainer.add(uiMenu)
|
uiContainer.add(uiRemoCon)
|
||||||
|
|
||||||
CommandDict // invoke
|
CommandDict // invoke
|
||||||
// TODO add console here
|
// TODO add console here
|
||||||
@@ -340,10 +340,10 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
// resize UI by re-creating it (!!)
|
// resize UI by re-creating it (!!)
|
||||||
uiMenu.resize(App.scr.width, App.scr.height)
|
uiRemoCon.resize(App.scr.width, App.scr.height)
|
||||||
// TODO I forgot what the fuck kind of hack I was talking about
|
// TODO I forgot what the fuck kind of hack I was talking about
|
||||||
//uiMenu.setPosition(0, UITitleRemoConRoot.menubarOffY)
|
//uiMenu.setPosition(0, UITitleRemoConRoot.menubarOffY)
|
||||||
uiMenu.setPosition(0, 0) // shitty hack. Could be:
|
uiRemoCon.setPosition(0, 0) // shitty hack. Could be:
|
||||||
// 1: Init code and resize code are different
|
// 1: Init code and resize code are different
|
||||||
// 2: The UI is coded shit
|
// 2: The UI is coded shit
|
||||||
|
|
||||||
@@ -354,7 +354,7 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
uiMenu.dispose()
|
uiRemoCon.dispose()
|
||||||
demoWorld.dispose()
|
demoWorld.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,8 @@ import net.torvald.terrarum.langpack.Lang
|
|||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
import net.torvald.terrarum.serialise.LoadSavegame
|
import net.torvald.terrarum.serialise.LoadSavegame
|
||||||
import net.torvald.terrarum.serialise.ReadMeta
|
import net.torvald.terrarum.serialise.ReadMeta
|
||||||
import net.torvald.terrarum.tvda.ByteArray64InputStream
|
import net.torvald.terrarum.serialise.WriteMeta
|
||||||
import net.torvald.terrarum.tvda.DiskSkimmer
|
import net.torvald.terrarum.tvda.*
|
||||||
import net.torvald.terrarum.tvda.EntryFile
|
|
||||||
import net.torvald.terrarum.tvda.VDUtil
|
|
||||||
import net.torvald.terrarum.ui.*
|
import net.torvald.terrarum.ui.*
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@@ -29,6 +27,8 @@ import java.util.zip.GZIPInputStream
|
|||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Only works if current screen set by the App is [TitleScreen]
|
||||||
|
*
|
||||||
* Created by minjaesong on 2021-09-09.
|
* Created by minjaesong on 2021-09-09.
|
||||||
*/
|
*/
|
||||||
class UILoadDemoSavefiles : UICanvas() {
|
class UILoadDemoSavefiles : UICanvas() {
|
||||||
@@ -37,6 +37,9 @@ class UILoadDemoSavefiles : UICanvas() {
|
|||||||
CommonResourcePool.addToLoadingList("terrarum-defaultsavegamethumb") {
|
CommonResourcePool.addToLoadingList("terrarum-defaultsavegamethumb") {
|
||||||
TextureRegion(Texture(Gdx.files.internal("assets/graphics/gui/savegame_thumb_placeholder.png")))
|
TextureRegion(Texture(Gdx.files.internal("assets/graphics/gui/savegame_thumb_placeholder.png")))
|
||||||
}
|
}
|
||||||
|
CommonResourcePool.addToLoadingList("savegame_status_icon") {
|
||||||
|
TextureRegionPack("assets/graphics/gui/savegame_status_icon.tga", 24, 24)
|
||||||
|
}
|
||||||
CommonResourcePool.loadAll()
|
CommonResourcePool.loadAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,21 +55,21 @@ class UILoadDemoSavefiles : UICanvas() {
|
|||||||
private val shapeRenderer = ShapeRenderer()
|
private val shapeRenderer = ShapeRenderer()
|
||||||
|
|
||||||
|
|
||||||
private val uiWidth = UIItemDemoSaveCells.WIDTH // 480
|
internal val uiWidth = UIItemDemoSaveCells.WIDTH // 480
|
||||||
private val uiX = (width - uiWidth) / 2
|
internal val uiX = (width - uiWidth) / 2
|
||||||
|
|
||||||
private val textH = App.fontGame.lineHeight.toInt()
|
internal val textH = App.fontGame.lineHeight.toInt()
|
||||||
|
|
||||||
private val cellGap = 20
|
internal val cellGap = 20
|
||||||
private val cellInterval = cellGap + UIItemDemoSaveCells.HEIGHT
|
internal val cellInterval = cellGap + UIItemDemoSaveCells.HEIGHT
|
||||||
private val gradAreaHeight = 32
|
internal val gradAreaHeight = 32
|
||||||
|
|
||||||
private val titleTextPosY: Int = App.scr.tvSafeGraphicsHeight + 10
|
internal val titleTextPosY: Int = App.scr.tvSafeGraphicsHeight + 10
|
||||||
private val titleTopGradStart: Int = titleTextPosY + textH
|
internal val titleTopGradStart: Int = titleTextPosY + textH
|
||||||
private val titleTopGradEnd: Int = titleTopGradStart + gradAreaHeight
|
internal val titleTopGradEnd: Int = titleTopGradStart + gradAreaHeight
|
||||||
private val titleBottomGradStart: Int = height - App.scr.tvSafeGraphicsHeight - gradAreaHeight
|
internal val titleBottomGradStart: Int = height - App.scr.tvSafeGraphicsHeight - gradAreaHeight
|
||||||
private val titleBottomGradEnd: Int = titleBottomGradStart + gradAreaHeight
|
internal val titleBottomGradEnd: Int = titleBottomGradStart + gradAreaHeight
|
||||||
private val controlHelperY: Int = titleBottomGradStart + gradAreaHeight - textH
|
internal val controlHelperY: Int = titleBottomGradStart + gradAreaHeight - textH
|
||||||
|
|
||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
@@ -89,24 +92,42 @@ class UILoadDemoSavefiles : UICanvas() {
|
|||||||
|
|
||||||
private var sliderFBO = FrameBuffer(Pixmap.Format.RGBA8888, uiWidth + 10, height, true)
|
private var sliderFBO = FrameBuffer(Pixmap.Format.RGBA8888, uiWidth + 10, height, true)
|
||||||
|
|
||||||
|
private var showSpinner = false
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
printdbg(this, "savefiles show()")
|
printdbg(this, "savefiles show()")
|
||||||
|
|
||||||
// read savegames
|
try {
|
||||||
var savegamesCount = 0
|
val remoCon = (App.getCurrentScreen() as TitleScreen).uiRemoCon
|
||||||
App.savegames.forEach { skimmer ->
|
|
||||||
val x = uiX
|
remoCon.handler.lockToggle()
|
||||||
val y = titleTopGradEnd + cellInterval * savegamesCount
|
showSpinner = true
|
||||||
try {
|
|
||||||
addUIitem(UIItemDemoSaveCells(this, x, y, skimmer))
|
Thread {
|
||||||
savegamesCount += 1
|
// read savegames
|
||||||
}
|
var savegamesCount = 0
|
||||||
catch (e: Throwable) {
|
App.savegames.forEach { skimmer ->
|
||||||
System.err.println("[UILoadDemoSavefiles] Savefile '${skimmer.diskFile.absolutePath}' cannot be loaded")
|
val x = uiX
|
||||||
e.printStackTrace()
|
val y = titleTopGradEnd + cellInterval * savegamesCount
|
||||||
}
|
try {
|
||||||
|
addUIitem(UIItemDemoSaveCells(this, x, y, skimmer))
|
||||||
|
savegamesCount += 1
|
||||||
|
}
|
||||||
|
catch (e: Throwable) {
|
||||||
|
System.err.println("[UILoadDemoSavefiles] Savefile '${skimmer.diskFile.absolutePath}' cannot be loaded")
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
remoCon.handler.unlockToggle()
|
||||||
|
showSpinner = false
|
||||||
|
}.start()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
catch (e: UninitializedPropertyAccessException) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hide() {
|
override fun hide() {
|
||||||
@@ -132,8 +153,8 @@ class UILoadDemoSavefiles : UICanvas() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (index in 0 until uiItems.size) {
|
||||||
uiItems.forEachIndexed { index, it ->
|
val it = uiItems[index]
|
||||||
if (index in listScroll - 2 until listScroll + savesVisible + 2) {
|
if (index in listScroll - 2 until listScroll + savesVisible + 2) {
|
||||||
// re-position
|
// re-position
|
||||||
it.posY = (it.initialY - uiScroll).roundToInt()
|
it.posY = (it.initialY - uiScroll).roundToInt()
|
||||||
@@ -155,7 +176,8 @@ class UILoadDemoSavefiles : UICanvas() {
|
|||||||
setCameraPosition(batch, camera, 0f, 0f)
|
setCameraPosition(batch, camera, 0f, 0f)
|
||||||
batch.color = Color.WHITE
|
batch.color = Color.WHITE
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
uiItems.forEachIndexed { index, it ->
|
for (index in 0 until uiItems.size) {
|
||||||
|
val it = uiItems[index]
|
||||||
if (index in listScroll - 2 until listScroll + savesVisible + 2) {
|
if (index in listScroll - 2 until listScroll + savesVisible + 2) {
|
||||||
it.render(batch, camera)
|
it.render(batch, camera)
|
||||||
}
|
}
|
||||||
@@ -303,27 +325,37 @@ class UIItemDemoSaveCells(
|
|||||||
const val HEIGHT = 120
|
const val HEIGHT = 120
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
CommonResourcePool.addToLoadingList("savegame_status_icon") {
|
|
||||||
TextureRegionPack("assets/graphics/gui/savegame_status_icon.tga", 24, 24)
|
|
||||||
}
|
|
||||||
CommonResourcePool.loadAll()
|
|
||||||
|
|
||||||
|
private val metaFile: DiskEntry?
|
||||||
|
private val saveName: String
|
||||||
|
private val saveMode: Int
|
||||||
|
private val isQuick: Boolean
|
||||||
|
private val isAuto: Boolean
|
||||||
|
private val meta: WriteMeta.WorldMeta?
|
||||||
|
private val saveDamaged: Boolean
|
||||||
|
private val lastPlayedTimestamp: String
|
||||||
|
|
||||||
|
init {
|
||||||
printdbg(this, "Rebuilding skimmer for savefile ${skimmer.diskFile.absolutePath}")
|
printdbg(this, "Rebuilding skimmer for savefile ${skimmer.diskFile.absolutePath}")
|
||||||
skimmer.rebuild()
|
skimmer.rebuild()
|
||||||
|
|
||||||
|
metaFile = skimmer.requestFile(-1)
|
||||||
|
saveName = skimmer.getDiskName(Common.CHARSET)
|
||||||
|
saveMode = skimmer.getSaveMode()
|
||||||
|
isQuick = (saveMode % 2 == 1)
|
||||||
|
isAuto = (saveMode.ushr(1) != 0)
|
||||||
|
meta = if (metaFile != null) ReadMeta.fromDiskEntry(metaFile) else null
|
||||||
|
|
||||||
|
saveDamaged = checkForSavegameDamage(skimmer)
|
||||||
|
|
||||||
|
lastPlayedTimestamp = if (meta != null)
|
||||||
|
Instant.ofEpochSecond(meta.lastplay_t)
|
||||||
|
.atZone(TimeZone.getDefault().toZoneId())
|
||||||
|
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) +
|
||||||
|
"/${parseDuration(meta.playtime_t)}"
|
||||||
|
else "--:--:--/--h--m--s"
|
||||||
}
|
}
|
||||||
|
|
||||||
private var saveDamaged = checkForSavegameDamage(skimmer)
|
|
||||||
|
|
||||||
override val width: Int = WIDTH
|
|
||||||
override val height: Int = HEIGHT
|
|
||||||
|
|
||||||
private var thumbPixmap: Pixmap? = null
|
|
||||||
private var thumb: TextureRegion? = null
|
|
||||||
private val grad = CommonResourcePool.getAsTexture("title_halfgrad")
|
|
||||||
|
|
||||||
private val icons = CommonResourcePool.getAsTextureRegionPack("savegame_status_icon")
|
|
||||||
|
|
||||||
private fun parseDuration(seconds: Long): String {
|
private fun parseDuration(seconds: Long): String {
|
||||||
val s = seconds % 60
|
val s = seconds % 60
|
||||||
val m = (seconds / 60) % 60
|
val m = (seconds / 60) % 60
|
||||||
@@ -335,36 +367,20 @@ class UIItemDemoSaveCells(
|
|||||||
"${d}d${h.toString().padStart(2,'0')}h${m.toString().padStart(2,'0')}m${s.toString().padStart(2,'0')}s"
|
"${d}d${h.toString().padStart(2,'0')}h${m.toString().padStart(2,'0')}m${s.toString().padStart(2,'0')}s"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val metaFile = skimmer.requestFile(-1)
|
override val width: Int = WIDTH
|
||||||
|
override val height: Int = HEIGHT
|
||||||
|
|
||||||
private val saveName = skimmer.getDiskName(Common.CHARSET)
|
private var thumbPixmap: Pixmap? = null
|
||||||
private val saveMode = skimmer.getSaveMode()
|
private var thumb: TextureRegion? = null
|
||||||
private val isQuick = (saveMode % 2 == 1)
|
private val grad = CommonResourcePool.getAsTexture("title_halfgrad")
|
||||||
private val isAuto = (saveMode.ushr(1) != 0)
|
|
||||||
private val meta = if (metaFile != null) ReadMeta.fromDiskEntry(metaFile) else null
|
|
||||||
|
|
||||||
private val colourBad = Color(0xFF8888FF.toInt())
|
private val icons = CommonResourcePool.getAsTextureRegionPack("savegame_status_icon")
|
||||||
|
|
||||||
|
|
||||||
|
private val colourBad = Color(0xFF0011FF.toInt())
|
||||||
|
|
||||||
private val lastPlayedTimestamp = if (meta != null)
|
|
||||||
Instant.ofEpochSecond(meta.lastplay_t)
|
|
||||||
.atZone(TimeZone.getDefault().toZoneId())
|
|
||||||
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) +
|
|
||||||
"/${parseDuration(meta.playtime_t)}"
|
|
||||||
else "--:--:--/--h--m--s"
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// load thumbnail or use stock if the file is not there
|
|
||||||
skimmer.requestFile(-2)?.let {
|
|
||||||
val zippedTga = (it.contents as EntryFile).bytes
|
|
||||||
val gzin = GZIPInputStream(ByteArray64InputStream(zippedTga))
|
|
||||||
val tgaFileContents = gzin.readAllBytes(); gzin.close()
|
|
||||||
|
|
||||||
thumbPixmap = Pixmap(tgaFileContents, 0, tgaFileContents.size)
|
|
||||||
val thumbTex = Texture(thumbPixmap)
|
|
||||||
thumbTex.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
|
||||||
thumb = TextureRegion(thumbTex)
|
|
||||||
thumb!!.setRegion(0, (thumbTex.height - 2 * height) / 2, width * 2, height * 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +388,29 @@ class UIItemDemoSaveCells(
|
|||||||
LoadSavegame(VDUtil.readDiskArchive(skimmer.diskFile, Level.INFO))
|
LoadSavegame(VDUtil.readDiskArchive(skimmer.diskFile, Level.INFO))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal var hasTexture = false
|
||||||
|
private set
|
||||||
|
|
||||||
override fun render(batch: SpriteBatch, camera: Camera) {
|
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
|
// try to generate a texture
|
||||||
|
if (skimmer.initialised && !hasTexture) {
|
||||||
|
// load thumbnail or use stock if the file is not there
|
||||||
|
skimmer.requestFile(-2)?.let {
|
||||||
|
val zippedTga = (it.contents as EntryFile).bytes
|
||||||
|
val gzin = GZIPInputStream(ByteArray64InputStream(zippedTga))
|
||||||
|
val tgaFileContents = gzin.readAllBytes(); gzin.close()
|
||||||
|
|
||||||
|
thumbPixmap = Pixmap(tgaFileContents, 0, tgaFileContents.size)
|
||||||
|
val thumbTex = Texture(thumbPixmap)
|
||||||
|
thumbTex.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||||
|
thumb = TextureRegion(thumbTex)
|
||||||
|
thumb!!.setRegion(0, (thumbTex.height - 2 * height) / 2, width * 2, height * 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hasTexture = true
|
||||||
|
}
|
||||||
|
|
||||||
val highlightCol = if (mouseUp) UIItemTextButton.defaultActiveCol else Color.WHITE
|
val highlightCol = if (mouseUp) UIItemTextButton.defaultActiveCol else Color.WHITE
|
||||||
val x = posX.toFloat()
|
val x = posX.toFloat()
|
||||||
val y = posY.toFloat()
|
val y = posY.toFloat()
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ import com.badlogic.gdx.Input
|
|||||||
import com.badlogic.gdx.graphics.Camera
|
import com.badlogic.gdx.graphics.Camera
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.App.printdbgerr
|
import net.torvald.terrarum.App.printdbgerr
|
||||||
|
import net.torvald.terrarum.QNDTreeNode
|
||||||
|
import net.torvald.terrarum.TitleScreen
|
||||||
|
import net.torvald.terrarum.Yaml
|
||||||
import net.torvald.terrarum.serialise.WriteConfig
|
import net.torvald.terrarum.serialise.WriteConfig
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import net.torvald.terrarum.ui.UIItemTextButton
|
import net.torvald.terrarum.ui.UIItemTextButton
|
||||||
@@ -85,69 +88,71 @@ open class UIRemoCon(val parent: TitleScreen, treeRepresentation: QNDTreeNode<St
|
|||||||
val selectedItem = remoConTray.selectedItem
|
val selectedItem = remoConTray.selectedItem
|
||||||
val selectedIndex = remoConTray.selectedIndex
|
val selectedIndex = remoConTray.selectedIndex
|
||||||
|
|
||||||
selectedItem?.let {
|
if (!handler.uiToggleLocked) {
|
||||||
// selection change
|
selectedItem?.let {
|
||||||
if (it.labelText == "MENU_LABEL_QUIT") {
|
// selection change
|
||||||
//System.exit(0)
|
if (it.labelText == "MENU_LABEL_QUIT") {
|
||||||
Gdx.app.exit()
|
//System.exit(0)
|
||||||
}
|
Gdx.app.exit()
|
||||||
else if (it.labelText.startsWith("MENU_LABEL_RETURN")) {
|
|
||||||
val tag = it.tags
|
|
||||||
if (tag.contains("WRITETOCONFIG")) WriteConfig()
|
|
||||||
|
|
||||||
|
|
||||||
if (currentRemoConContents.parent != null) {
|
|
||||||
remoConTray.consume()
|
|
||||||
|
|
||||||
currentRemoConContents = currentRemoConContents.parent!!
|
|
||||||
currentlySelectedRemoConItem = currentRemoConContents.data
|
|
||||||
remoConTray = generateNewRemoCon(currentRemoConContents)
|
|
||||||
|
|
||||||
parent.uiFakeBlurOverlay.setAsClose()
|
|
||||||
}
|
}
|
||||||
else {
|
else if (it.labelText.startsWith("MENU_LABEL_RETURN")) {
|
||||||
throw NullPointerException("No parent node to return")
|
val tag = it.tags
|
||||||
}
|
if (tag.contains("WRITETOCONFIG")) WriteConfig()
|
||||||
}
|
|
||||||
else {
|
|
||||||
// check if target exists
|
|
||||||
//println("current node: ${currentRemoConContents.data}")
|
|
||||||
//currentRemoConContents.children.forEach { println("- ${it.data}") }
|
|
||||||
|
|
||||||
if (currentRemoConContents.children.size > selectedIndex ?: 0x7FFFFFFF) {
|
|
||||||
|
|
||||||
|
|
||||||
val newCurrentRemoConContents = currentRemoConContents.children[selectedIndex!!]
|
if (currentRemoConContents.parent != null) {
|
||||||
|
|
||||||
// only go deeper if that node has child to navigate
|
|
||||||
if (currentRemoConContents.children[selectedIndex].children.size != 0) {
|
|
||||||
remoConTray.consume()
|
remoConTray.consume()
|
||||||
remoConTray = generateNewRemoCon(newCurrentRemoConContents)
|
|
||||||
currentRemoConContents = newCurrentRemoConContents
|
currentRemoConContents = currentRemoConContents.parent!!
|
||||||
|
currentlySelectedRemoConItem = currentRemoConContents.data
|
||||||
|
remoConTray = generateNewRemoCon(currentRemoConContents)
|
||||||
|
|
||||||
|
parent.uiFakeBlurOverlay.setAsClose()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw NullPointerException("No parent node to return")
|
||||||
}
|
}
|
||||||
|
|
||||||
currentlySelectedRemoConItem = newCurrentRemoConContents.data
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw RuntimeException("Index: $selectedIndex, Size: ${currentRemoConContents.children.size}")
|
// check if target exists
|
||||||
|
//println("current node: ${currentRemoConContents.data}")
|
||||||
|
//currentRemoConContents.children.forEach { println("- ${it.data}") }
|
||||||
|
|
||||||
|
if (currentRemoConContents.children.size > selectedIndex ?: 0x7FFFFFFF) {
|
||||||
|
|
||||||
|
|
||||||
|
val newCurrentRemoConContents = currentRemoConContents.children[selectedIndex!!]
|
||||||
|
|
||||||
|
// only go deeper if that node has child to navigate
|
||||||
|
if (currentRemoConContents.children[selectedIndex].children.size != 0) {
|
||||||
|
remoConTray.consume()
|
||||||
|
remoConTray = generateNewRemoCon(newCurrentRemoConContents)
|
||||||
|
currentRemoConContents = newCurrentRemoConContents
|
||||||
|
}
|
||||||
|
|
||||||
|
currentlySelectedRemoConItem = newCurrentRemoConContents.data
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw RuntimeException("Index: $selectedIndex, Size: ${currentRemoConContents.children.size}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// do something with the actual selection
|
// do something with the actual selection
|
||||||
//printdbg(this, "$currentlySelectedRemoConItem")
|
//printdbg(this, "$currentlySelectedRemoConItem")
|
||||||
|
|
||||||
screens.forEach {
|
screens.forEach {
|
||||||
//printdbg(this, "> ${it.first}")
|
//printdbg(this, "> ${it.first}")
|
||||||
|
|
||||||
if (currentlySelectedRemoConItem == it.first) {
|
if (currentlySelectedRemoConItem == it.first) {
|
||||||
parent.uiFakeBlurOverlay.setAsOpen()
|
parent.uiFakeBlurOverlay.setAsOpen()
|
||||||
it.second.setAsOpen()
|
it.second.setAsOpen()
|
||||||
|
|
||||||
//printdbg(this, ">> ding - ${it.second.javaClass.canonicalName}")
|
//printdbg(this, ">> ding - ${it.second.javaClass.canonicalName}")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
it.second.setAsClose()
|
it.second.setAsClose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,30 +282,11 @@ open class UIRemoCon(val parent: TitleScreen, treeRepresentation: QNDTreeNode<St
|
|||||||
tagsCollection = tags
|
tagsCollection = tags
|
||||||
)
|
)
|
||||||
|
|
||||||
private val spinner = CommonResourcePool.getAsTextureRegionPack("inline_loading_spinner")
|
|
||||||
private var spinnerTimer = 0f
|
|
||||||
private var spinnerFrame = 0
|
|
||||||
private val spinnerInterval = 1f / 60f
|
|
||||||
|
|
||||||
fun update(delta: Float) {
|
fun update(delta: Float) {
|
||||||
spinnerTimer += delta
|
|
||||||
if (spinnerTimer > spinnerInterval) {
|
|
||||||
spinnerFrame = (spinnerFrame + 1) % 32
|
|
||||||
spinnerTimer -= spinnerInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
menubar.update(delta)
|
menubar.update(delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(batch: SpriteBatch, camera: Camera) {
|
fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
val spin = spinner.get(spinnerFrame % 8, spinnerFrame / 8)
|
|
||||||
|
|
||||||
val inlineOffsetY = if (App.GAME_LOCALE.startsWith("th")) 0f
|
|
||||||
else if (App.GAME_LOCALE.startsWith("ko")) 0f
|
|
||||||
else 1f
|
|
||||||
|
|
||||||
batch.draw(spin, menubar.posX + paddingLeft - 5f, menubar.posY + (lineHeight - 20) / 2 - inlineOffsetY)
|
|
||||||
|
|
||||||
menubar.render(batch, camera)
|
menubar.render(batch, camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
58
src/net/torvald/terrarum/ui/UIAutosaveNotifier.kt
Normal file
58
src/net/torvald/terrarum/ui/UIAutosaveNotifier.kt
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package net.torvald.terrarum.ui
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Camera
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.CommonResourcePool
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2021-10-01.
|
||||||
|
*/
|
||||||
|
class UIAutosaveNotifier : UICanvas() {
|
||||||
|
|
||||||
|
override var width: Int
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
set(value) {}
|
||||||
|
override var height: Int
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
set(value) {}
|
||||||
|
override var openCloseTime = 0.2f
|
||||||
|
|
||||||
|
private val spinner = CommonResourcePool.getAsTextureRegionPack("inline_loading_spinner")
|
||||||
|
private var spinnerTimer = 0f
|
||||||
|
private var spinnerFrame = 0
|
||||||
|
private val spinnerInterval = 1f / 60f
|
||||||
|
|
||||||
|
override fun updateUI(delta: Float) {
|
||||||
|
spinnerTimer += delta
|
||||||
|
if (spinnerTimer > spinnerInterval) {
|
||||||
|
spinnerFrame = (spinnerFrame + 1) % 32
|
||||||
|
spinnerTimer -= spinnerInterval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||||
|
val spin = spinner.get(spinnerFrame % 8, spinnerFrame / 8)
|
||||||
|
|
||||||
|
val inlineOffsetY = if (App.GAME_LOCALE.startsWith("th")) 0f
|
||||||
|
else if (App.GAME_LOCALE.startsWith("ko")) 0f
|
||||||
|
else 1f
|
||||||
|
|
||||||
|
batch.draw(spin, posX.toFloat(), posY.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doOpening(delta: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doClosing(delta: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endOpening(delta: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endClosing(delta: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,7 +118,7 @@ void main() {
|
|||||||
|
|
||||||
private val shader = App.loadShaderInline(SHADER_PROG_VERT, SHADER_PROG_FRAG)
|
private val shader = App.loadShaderInline(SHADER_PROG_VERT, SHADER_PROG_FRAG)
|
||||||
|
|
||||||
private var uiToggleLocked = false
|
var uiToggleLocked = false; private set
|
||||||
|
|
||||||
init {
|
init {
|
||||||
//UI.handler = this
|
//UI.handler = this
|
||||||
|
|||||||
Reference in New Issue
Block a user