mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 19:14:05 +09:00
sprite tool exports "formatted" TGA
meaning if alpha is zero, RGB is also zero
This commit is contained in:
@@ -48,14 +48,20 @@ jar {
|
|||||||
task game(type: JavaExec) {
|
task game(type: JavaExec) {
|
||||||
classpath sourceSets.main.runtimeClasspath
|
classpath sourceSets.main.runtimeClasspath
|
||||||
main = 'net.torvald.terrarum.AppLoader'
|
main = 'net.torvald.terrarum.AppLoader'
|
||||||
|
group = "Application"
|
||||||
|
description = "Launches the game. Should be the same as 'gradlew run'."
|
||||||
}
|
}
|
||||||
|
|
||||||
task spriteassembler(type: JavaExec) {
|
task spriteassembler(type: JavaExec) {
|
||||||
classpath sourceSets.main.runtimeClasspath
|
classpath sourceSets.main.runtimeClasspath
|
||||||
main = 'net.torvald.spriteassembler.SpriteAssemblerAppKt'
|
main = 'net.torvald.spriteassembler.SpriteAssemblerAppKt'
|
||||||
|
group = "Application"
|
||||||
|
description = "Launches the Sprite Assembler."
|
||||||
}
|
}
|
||||||
|
|
||||||
task csveditor(type: JavaExec) {
|
task csveditor(type: JavaExec) {
|
||||||
classpath sourceSets.main.runtimeClasspath
|
classpath sourceSets.main.runtimeClasspath
|
||||||
main = 'net.torvald.terrarum.debuggerapp.CSVEditor'
|
main = 'net.torvald.terrarum.debuggerapp.CSVEditor'
|
||||||
|
group = "Application"
|
||||||
|
description = "Launches the CSV Editor. (for Blocks?)"
|
||||||
}
|
}
|
||||||
|
|||||||
89
src/com/badlogic/gdx/graphics/PixmapIO2.java
Normal file
89
src/com/badlogic/gdx/graphics/PixmapIO2.java
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
package com.badlogic.gdx.graphics;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
|
import com.badlogic.gdx.utils.StreamUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2019-01-07.
|
||||||
|
*/
|
||||||
|
public class PixmapIO2 {
|
||||||
|
|
||||||
|
public static void writeTGA(FileHandle file, Pixmap pixmap) throws IOException {
|
||||||
|
OutputStream output = file.write(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
_writeTGA(output, pixmap);
|
||||||
|
} finally {
|
||||||
|
StreamUtils.closeQuietly(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void _writeTGA(OutputStream out, Pixmap pixmap) throws IOException {
|
||||||
|
byte[] width = toShortLittle(pixmap.getWidth());
|
||||||
|
byte[] height = toShortLittle(pixmap.getHeight());
|
||||||
|
byte[] zero = toShortLittle(0);
|
||||||
|
|
||||||
|
byte[] zeroalpha = new byte[]{0,0,0,0};
|
||||||
|
|
||||||
|
out.write(0); // ID field: empty
|
||||||
|
out.write(0); // no colour map, but should be ignored anyway as it being unmapped RGB
|
||||||
|
out.write(2); // 2 means unmapped RGB
|
||||||
|
out.write(new byte[]{0,0,0,0,0}); // color map spec: empty
|
||||||
|
out.write(zero); // x origin: 0
|
||||||
|
out.write(zero); // y origin: 0
|
||||||
|
out.write(width); // width
|
||||||
|
out.write(height); // height
|
||||||
|
out.write(32); // image pixel size: we're writing 32-bit image (8bpp BGRA)
|
||||||
|
out.write(8); // image descriptor: dunno, Photoshop writes 8 in there
|
||||||
|
|
||||||
|
// write actual image data
|
||||||
|
// since we're following Photoshop's conventional header, we also follows Photoshop's
|
||||||
|
// TGA saving scheme, that is:
|
||||||
|
// 1. BGRA order
|
||||||
|
// 2. Y-Flipped but not X-Flipped
|
||||||
|
|
||||||
|
for (int y = pixmap.getHeight() - 1; y >= 0; y--) {
|
||||||
|
for (int x = 0; x < pixmap.getWidth(); x++) {
|
||||||
|
int color = pixmap.getPixel(x, y);
|
||||||
|
|
||||||
|
// if alpha == 0, write special value instead
|
||||||
|
if ((color & 0xFF) == 0) {
|
||||||
|
out.write(zeroalpha);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out.write(RGBAtoBGRA(color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// write footer
|
||||||
|
// 00 00 00 00 00 00 00 00 TRUEVISION-XFILE 2E 00
|
||||||
|
out.write(new byte[]{0,0,0,0,0,0,0,0});
|
||||||
|
out.write("TerrarumHappyTGA".getBytes());
|
||||||
|
out.write(new byte[]{0x2E,0});
|
||||||
|
|
||||||
|
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] toShortLittle(int i) {
|
||||||
|
return new byte[]{
|
||||||
|
(byte) (i & 0xFF),
|
||||||
|
(byte) ((i >>> 8) & 0xFF)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] RGBAtoBGRA(int rgba) {
|
||||||
|
return new byte[]{
|
||||||
|
(byte) ((rgba >>> 8) & 0xFF),
|
||||||
|
(byte) ((rgba >>> 16) & 0xFF),
|
||||||
|
(byte) ((rgba >>> 24) & 0xFF),
|
||||||
|
(byte) (rgba & 0xFF)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,10 +4,7 @@ import com.badlogic.gdx.Game
|
|||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
|
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
|
||||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
|
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.*
|
||||||
import com.badlogic.gdx.graphics.GL20
|
|
||||||
import com.badlogic.gdx.graphics.Pixmap
|
|
||||||
import com.badlogic.gdx.graphics.Texture
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.inUse
|
import net.torvald.terrarum.inUse
|
||||||
import java.awt.BorderLayout
|
import java.awt.BorderLayout
|
||||||
@@ -76,8 +73,7 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
|||||||
"ADD_ROWS=Enter the number of rows to add:\n" +
|
"ADD_ROWS=Enter the number of rows to add:\n" +
|
||||||
"WRITE_FAIL=Writing to file has failed:\n" +
|
"WRITE_FAIL=Writing to file has failed:\n" +
|
||||||
"STAT_INIT=Creating a new CSV. You can still open existing file.\n" +
|
"STAT_INIT=Creating a new CSV. You can still open existing file.\n" +
|
||||||
"STAT_SAVE_SUCCESSFUL=File saved successfully.\n" +
|
"STAT_SAVE_TGA_SUCCESSFUL=Spritesheet exported successfully.\n" +
|
||||||
"STAT_NEW_FILE=New CSV created.\n" +
|
|
||||||
"STAT_LOAD_SUCCESSFUL=File loaded successfully.\n" +
|
"STAT_LOAD_SUCCESSFUL=File loaded successfully.\n" +
|
||||||
"ERROR_INTERNAL=Something went wrong.\n" +
|
"ERROR_INTERNAL=Something went wrong.\n" +
|
||||||
"ERROR_PARSE_FAIL=Parsing failed\n" +
|
"ERROR_PARSE_FAIL=Parsing failed\n" +
|
||||||
@@ -122,7 +118,6 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
|||||||
panelMain.resizeWeight = 0.666
|
panelMain.resizeWeight = 0.666
|
||||||
|
|
||||||
val menu = JMenuBar()
|
val menu = JMenuBar()
|
||||||
menu.add(JMenu("File"))
|
|
||||||
menu.add(JMenu("Parse")).addMouseListener(object : MouseAdapter() {
|
menu.add(JMenu("Parse")).addMouseListener(object : MouseAdapter() {
|
||||||
override fun mousePressed(e: MouseEvent?) {
|
override fun mousePressed(e: MouseEvent?) {
|
||||||
try {
|
try {
|
||||||
@@ -193,6 +188,17 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
menu.add(JMenu("Export")).addMouseListener(object : MouseAdapter() {
|
||||||
|
override fun mousePressed(e: MouseEvent?) {
|
||||||
|
val fileChooser = JFileChooser()
|
||||||
|
fileChooser.showSaveDialog(null)
|
||||||
|
|
||||||
|
if (fileChooser.selectedFile != null) {
|
||||||
|
gdxWindow.requestExport(fileChooser.selectedFile.absolutePath)
|
||||||
|
statBar.text = lang.getProperty("STAT_SAVE_TGA_SUCCESSFUL")
|
||||||
|
} // else, do nothing
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
this.layout = BorderLayout()
|
this.layout = BorderLayout()
|
||||||
this.add(menu, BorderLayout.NORTH)
|
this.add(menu, BorderLayout.NORTH)
|
||||||
@@ -250,6 +256,9 @@ class SpriteAssemblerPreview: Game() {
|
|||||||
private var doAssemble = false
|
private var doAssemble = false
|
||||||
private lateinit var assembleProp: ADProperties
|
private lateinit var assembleProp: ADProperties
|
||||||
|
|
||||||
|
private var doExport = false
|
||||||
|
private lateinit var exportPath: String
|
||||||
|
|
||||||
override fun render() {
|
override fun render() {
|
||||||
if (doAssemble) {
|
if (doAssemble) {
|
||||||
// assembly requires GL context
|
// assembly requires GL context
|
||||||
@@ -257,6 +266,11 @@ class SpriteAssemblerPreview: Game() {
|
|||||||
assembleImage(assembleProp)
|
assembleImage(assembleProp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (doExport && image != null) {
|
||||||
|
doExport = false
|
||||||
|
PixmapIO2.writeTGA(Gdx.files.absolute(exportPath), image)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Gdx.gl.glClearColor(.62f,.79f,1f,1f)
|
Gdx.gl.glClearColor(.62f,.79f,1f,1f)
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||||
@@ -280,6 +294,14 @@ class SpriteAssemblerPreview: Game() {
|
|||||||
assembleProp = prop
|
assembleProp = prop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun requestExport(path: String) {
|
||||||
|
doExport = true
|
||||||
|
exportPath = path
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resize(width: Int, height: Int) {
|
||||||
|
super.resize(width, height)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
|
|||||||
Reference in New Issue
Block a user