new debug cmd ExportFBO

This commit is contained in:
minjaesong
2024-11-24 12:53:44 +09:00
parent f5846d9bae
commit 89b12aabb4
6 changed files with 129 additions and 19 deletions

View File

@@ -3,6 +3,7 @@ CheatWarnTest
CodexEdictis
ExportAtlas
ExportCodices
ExportFBO
ExportMap
ExportMap2
ExportWorld
1 CatStdout
3 CodexEdictis
4 ExportAtlas
5 ExportCodices
6 ExportFBO
7 ExportMap
8 ExportMap2
9 ExportWorld

View File

@@ -60,6 +60,7 @@ import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Stream;
import java.util.zip.Deflater;
import static java.lang.Thread.MAX_PRIORITY;
import static net.torvald.terrarum.TerrarumKt.*;
@@ -766,7 +767,7 @@ public class App implements ApplicationListener {
FrameBufferManager.begin(fb);
try {
Pixmap p = Pixmap.createFromFrameBuffer(0, 0, fb.getWidth(), fb.getHeight());
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, 9, true);
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, Deflater.DEFAULT_COMPRESSION, true);
p.dispose();
}
catch (Throwable e) {

View File

@@ -67,7 +67,7 @@ class SavegameCracker(
private val cmds: HashMap<String, KFunction<*>> = HashMap()
init {
SavegameCracker::class.declaredFunctions
.filter { it.findAnnotation<Command>() != null }
.filter { it.findAnnotation<SavegameCrackerCommand>() != null }
// .forEach { it.isAccessible = true; cmds[it.name] = it }
.forEach { cmds[it.name] = it }
}
@@ -100,7 +100,7 @@ class SavegameCracker(
printerrln("${args[0]}: command not found")
else {
try {
val annot = it.findAnnotation<Command>()!!
val annot = it.findAnnotation<SavegameCrackerCommand>()!!
// check arguments
val synopsis = annot.synopsis.split(' ').filter { it.isNotBlank() }
// print out synopsis
@@ -185,14 +185,14 @@ class SavegameCracker(
return this + sb.toString()
}
@Command("Loads a disk archive", "path-to-file")
@SavegameCrackerCommand("Loads a disk archive", "path-to-file")
fun load(args: List<String>) {
file = File(args[1])
disk = VDUtil.readDiskArchive(file!!, Level.INFO) { printerrln("# Warning: $it") }
file!!.copyTo(File(file!!.absolutePath + ".bak"), true)
}
@Command("Lists contents of the disk")
@SavegameCrackerCommand("Lists contents of the disk")
fun ls(args: List<String>) {
letdisk {
it.entries.toSortedMap().forEach { (i, entry) ->
@@ -207,19 +207,19 @@ class SavegameCracker(
}
}
@Command("Prints out available commands and their usage")
@SavegameCrackerCommand("Prints out available commands and their usage")
fun help(args: List<String>) {
cmds.forEach { name, it ->
println("$ccNoun${name.padStart(8)}$cc0 - ${it.findAnnotation<Command>()!!.help}")
println("$ccNoun${name.padStart(8)}$cc0 - ${it.findAnnotation<SavegameCrackerCommand>()!!.help}")
}
}
@Command("Exits the program")
@SavegameCrackerCommand("Exits the program")
fun exit(args: List<String>) { this.exit = true }
@Command("Exits the program")
@SavegameCrackerCommand("Exits the program")
fun quit(args: List<String>) = exit(args)
@Command("Exports contents of the entry into a real file", "entry-id output-file")
@SavegameCrackerCommand("Exports contents of the entry into a real file", "entry-id output-file")
fun export(args: List<String>) {
letdisk {
val entryID = args[1].toLong(10)
@@ -228,7 +228,7 @@ class SavegameCracker(
}
}
@Command("Changes one entry-ID into another", "change-from change-to")
@SavegameCrackerCommand("Changes one entry-ID into another", "change-from change-to")
fun renum(args: List<String>) {
letdisk {
val id0 = args[1].toLong(10)
@@ -244,7 +244,7 @@ class SavegameCracker(
}
}
@Command("Imports a real file onto the savefile", "input-file entry-id")
@SavegameCrackerCommand("Imports a real file onto the savefile", "input-file entry-id")
fun import(args: List<String>) {
letdisk {
val file = File(args[1])
@@ -257,7 +257,7 @@ class SavegameCracker(
}
}
@Command("Removes a file within the savefile", "entry-id")
@SavegameCrackerCommand("Removes a file within the savefile", "entry-id")
fun rm(args: List<String>) {
letdisk {
val id = args[1].toLong(10)
@@ -266,14 +266,14 @@ class SavegameCracker(
}
}
@Command("Saves changes onto the savefile")
@SavegameCrackerCommand("Saves changes onto the savefile")
fun save(args: List<String>) {
letdisk {
VDUtil.dumpToRealMachine(it, file!!)
}
}
@Command("Retrieves all UUIDs found (player UUID, current world UUID, etc.")
@SavegameCrackerCommand("Retrieves all UUIDs found (player UUID, current world UUID, etc.")
fun uuid(args: List<String>) {
letdisk {
val jsonFile = it.getFile(-1) ?: throw FileNotFoundException("savegameinfo.json (entry ID -1) not found")
@@ -294,7 +294,7 @@ class SavegameCracker(
}
}
@Command("Removes the specified chunk(s) completely", "IDs")
@SavegameCrackerCommand("Removes the specified chunk(s) completely", "IDs")
fun discardchunk(args: List<String>) {
letdisk { disk ->
val ids = args[1]
@@ -320,7 +320,7 @@ class SavegameCracker(
}
}
internal annotation class Command(val help: String = "", val synopsis: String = "")
internal annotation class SavegameCrackerCommand(val help: String = "", val synopsis: String = "")
fun main(args: Array<String>) {
SavegameCracker(args).invoke()

View File

@@ -75,6 +75,7 @@ object IngameRenderer : Disposable {
private lateinit var fboA_lightMixed: Float16FrameBuffer
private lateinit var fboEmissive: Float16FrameBuffer
private lateinit var fboMixedOut: Float16FrameBuffer
private lateinit var rgbTex: TextureRegion
private lateinit var aTex: TextureRegion
private lateinit var mixedOutTex: TextureRegion

View File

@@ -0,0 +1,107 @@
package net.torvald.terrarum.modulebasegame.console
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.GL30
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.PixmapIO
import com.badlogic.gdx.graphics.glutils.Float16FrameBuffer
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.utils.BufferUtils
import net.torvald.reflection.extortField
import net.torvald.terrarum.App
import net.torvald.terrarum.ccG
import net.torvald.terrarum.ccO
import net.torvald.terrarum.ccW
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.console.EchoError
import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.unicode.BULLET
import net.torvald.unicode.EMDASH
import java.nio.ByteBuffer
import java.util.zip.Deflater
import kotlin.reflect.KFunction
import kotlin.reflect.full.declaredFunctions
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.hasAnnotation
/**
* Created by minjaesong on 2024-11-24.
*/
internal object ExportFBO : ConsoleCommand {
private val cmds: HashMap<String, KFunction<*>> = HashMap()
private val helpMessages: List<Pair<String, String>>
init {
val helpMsgs: HashMap<String, String> = HashMap()
ExportFBO::class.declaredFunctions.filter { it.hasAnnotation<ExportFBOCmd>() }.forEach {
cmds[it.name.lowercase()] = it
helpMsgs[it.name.lowercase()] = it.findAnnotation<ExportFBOCmd>()!!.description
}
helpMessages = helpMsgs.keys.toList().sorted().map {
it to helpMsgs[it]!!
}
}
override fun execute(args: Array<String>) {
if (args.size != 3) { printUsage(); return }
val fn = cmds[args[1].lowercase()]
if (fn == null) { printUsage(); return }
try {
val filename = "${args[2]}-${args[1]}.png"
val fileHandle = Gdx.files.absolute("${App.defaultDir}/Exports/$filename")
val fbo = fn.call(this) as FrameBuffer
// cannot use createFromFrameBuffer because the specific FBO must be bound in a way we can control
val pixels: ByteBuffer = BufferUtils.newByteBuffer(fbo.width * fbo.height * 4)
Gdx.gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fbo.framebufferHandle)
Gdx.gl.glReadPixels(0, 0, fbo.width, fbo.height, GL30.GL_RGBA, GL30.GL_UNSIGNED_BYTE, pixels)
Gdx.gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0)
val pixmap: Pixmap = Pixmap(fbo.width, fbo.height, Pixmap.Format.RGBA8888)
BufferUtils.copy(pixels, pixmap.pixels, pixels.capacity())
PixmapIO.writePNG(fileHandle, pixmap, Deflater.DEFAULT_COMPRESSION, true)
Echo("Framebuffer exported to$ccG Exports/$filename")
}
catch (e: Throwable) {
EchoError("Could not retrieve the framebuffer: ${e.message}")
System.err.println(e)
return
}
}
override fun printUsage() {
Echo("Usage: exportfbo <identifier> <filename without extension>")
Echo("Available identifiers are:")
helpMessages.forEach { (name, desc) ->
Echo(" $BULLET $ccG$name $ccW$EMDASH $ccO$desc")
}
}
@ExportFBOCmd("Main RGB channel of the IngameRenderer without lighting")
fun fborgb(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGB")!!
}
@ExportFBOCmd("Main A channel of the IngameRenderer without lighting")
fun fboa(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboA")!!
}
@ExportFBOCmd("Main Emissive channel of the IngameRenderer without lighting")
fun fboemissive(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboEmissive")!!
}
}
internal annotation class ExportFBOCmd(val description: String)

View File

@@ -40,12 +40,12 @@ class ConsoleWindow : UICanvas() {
private var commandHistory = CircularArray<String>(COMMAND_HISTORY_MAX, true)
private val LINE_HEIGHT = 20
private val MESSAGES_DISPLAY_COUNT = 11
private val MESSAGES_DISPLAY_COUNT = 12
private val inputToMsgboxGap = 3
override var width: Int = App.scr.width
override var height: Int = LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT + 1) + inputToMsgboxGap
override var height: Int = LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT + 1) + inputToMsgboxGap + 4
override var openCloseTime = 0f