mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 02:24:05 +09:00
sprite assembler can produce intended output
This commit is contained in:
@@ -50,6 +50,9 @@ class ADProperties {
|
|||||||
|
|
||||||
private val ALL_JOINT = Joint(ALL_JOINT_SELECT_KEY, ADPropertyObject.Vector2i(0, 0))
|
private val ALL_JOINT = Joint(ALL_JOINT_SELECT_KEY, ADPropertyObject.Vector2i(0, 0))
|
||||||
|
|
||||||
|
var rows = -1; private set
|
||||||
|
var cols = -1; private set
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val ALL_JOINT_SELECT_KEY = "ALL"
|
const val ALL_JOINT_SELECT_KEY = "ALL"
|
||||||
}
|
}
|
||||||
@@ -76,6 +79,8 @@ class ADProperties {
|
|||||||
baseFilename = get("SPRITESHEET")[0].variable
|
baseFilename = get("SPRITESHEET")[0].variable
|
||||||
extension = get("EXTENSION")[0].variable
|
extension = get("EXTENSION")[0].variable
|
||||||
|
|
||||||
|
var maxColFinder = -1
|
||||||
|
var maxRowFinder = -1
|
||||||
val bodyparts = HashSet<String>()
|
val bodyparts = HashSet<String>()
|
||||||
val skeletons = HashMap<String, Skeleton>()
|
val skeletons = HashMap<String, Skeleton>()
|
||||||
val animations = HashMap<String, Animation>()
|
val animations = HashMap<String, Animation>()
|
||||||
@@ -85,7 +90,7 @@ class ADProperties {
|
|||||||
propTable.keys.forEach {
|
propTable.keys.forEach {
|
||||||
if (animFrameSuffixRegex.containsMatchIn(it)) {
|
if (animFrameSuffixRegex.containsMatchIn(it)) {
|
||||||
val animName = getAnimNameFromFrame(it)
|
val animName = getAnimNameFromFrame(it)
|
||||||
val frameNumber = it.drop(animName.length + 1).toInt()
|
val frameNumber = getFrameNumberFromName(it)
|
||||||
|
|
||||||
// if animFrames does not have our entry, add it.
|
// if animFrames does not have our entry, add it.
|
||||||
// otherwise, max() against the existing value
|
// otherwise, max() against the existing value
|
||||||
@@ -95,6 +100,8 @@ class ADProperties {
|
|||||||
else {
|
else {
|
||||||
animFrames[animName] = frameNumber
|
animFrames[animName] = frameNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxColFinder = maxOf(maxColFinder, frameNumber)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// populate skeletons and animations
|
// populate skeletons and animations
|
||||||
@@ -119,6 +126,8 @@ class ADProperties {
|
|||||||
animFrames[s]!!,
|
animFrames[s]!!,
|
||||||
Skeleton(skeletonName, skeletonDef.toJoints())
|
Skeleton(skeletonName, skeletonDef.toJoints())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
maxRowFinder = maxOf(maxRowFinder, animations[s]!!.row)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +173,9 @@ class ADProperties {
|
|||||||
this.animations = animations
|
this.animations = animations
|
||||||
this.bodypartFiles = this.bodyparts.map { toFilename(it) }
|
this.bodypartFiles = this.bodyparts.map { toFilename(it) }
|
||||||
this.transforms = transforms
|
this.transforms = transforms
|
||||||
|
|
||||||
|
cols = maxColFinder
|
||||||
|
rows = maxRowFinder
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun get(identifier: String) = propTable[identifier.toUpperCase()]!!
|
operator fun get(identifier: String) = propTable[identifier.toUpperCase()]!!
|
||||||
@@ -176,6 +188,8 @@ class ADProperties {
|
|||||||
"${this.baseFilename}${partName.toLowerCase()}${this.extension}"
|
"${this.baseFilename}${partName.toLowerCase()}${this.extension}"
|
||||||
|
|
||||||
fun getAnimByFrameName(frameName: String) = animations[getAnimNameFromFrame(frameName)]!!
|
fun getAnimByFrameName(frameName: String) = animations[getAnimNameFromFrame(frameName)]!!
|
||||||
|
fun getFrameNumberFromName(frameName: String) = frameName.substring(frameName.lastIndexOf('_') + 1 until frameName.length).toInt()
|
||||||
|
|
||||||
fun getSkeleton(name: String) = skeletons[name]!!
|
fun getSkeleton(name: String) = skeletons[name]!!
|
||||||
fun getTransform(name: String) = transforms[name]!!
|
fun getTransform(name: String) = transforms[name]!!
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.torvald.spriteassembler
|
|||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.graphics.Pixmap
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
|
import net.torvald.terrarum.AppLoader
|
||||||
import net.torvald.terrarum.linearSearch
|
import net.torvald.terrarum.linearSearch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -10,11 +11,26 @@ import java.io.File
|
|||||||
*
|
*
|
||||||
* Created by minjaesong on 2019-01-06.
|
* Created by minjaesong on 2019-01-06.
|
||||||
*/
|
*/
|
||||||
object AssembleFramePixmap {
|
object AssembleSheetPixmap {
|
||||||
|
|
||||||
// FIXME fuck this I'll use GDX
|
operator fun invoke(properties: ADProperties, assembleConfig: AssembleConfig = AssembleConfig()): Pixmap {
|
||||||
|
val canvas = Pixmap(properties.cols * assembleConfig.fw, properties.rows * assembleConfig.fh, Pixmap.Format.RGBA8888)
|
||||||
|
canvas.blending = Pixmap.Blending.SourceOver
|
||||||
|
|
||||||
operator fun invoke(properties: ADProperties, frameName: String, assembleConfig: AssembleConfig = AssembleConfig()): Pixmap {
|
|
||||||
|
// actually draw
|
||||||
|
properties.transforms.forEach { t, _ ->
|
||||||
|
drawThisFrame(t, canvas, properties, assembleConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
return canvas
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawThisFrame(frameName: String,
|
||||||
|
canvas: Pixmap,
|
||||||
|
properties: ADProperties,
|
||||||
|
assembleConfig: AssembleConfig
|
||||||
|
) {
|
||||||
val theAnim = properties.getAnimByFrameName(frameName)
|
val theAnim = properties.getAnimByFrameName(frameName)
|
||||||
val skeleton = theAnim.skeleton.joints.reversed()
|
val skeleton = theAnim.skeleton.joints.reversed()
|
||||||
val transforms = properties.getTransform(frameName)
|
val transforms = properties.getTransform(frameName)
|
||||||
@@ -25,40 +41,42 @@ object AssembleFramePixmap {
|
|||||||
//printdbg(this, "Loading file ${file.absolutePath}, exists: ${file.exists()}")
|
//printdbg(this, "Loading file ${file.absolutePath}, exists: ${file.exists()}")
|
||||||
|
|
||||||
/*return*/if (file.exists()) {
|
/*return*/if (file.exists()) {
|
||||||
Pixmap(Gdx.files.internal(file.path))
|
Pixmap(Gdx.files.internal(file.path))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val canvas = Pixmap(assembleConfig.fw, assembleConfig.fh, Pixmap.Format.RGBA8888)
|
|
||||||
|
|
||||||
val transformList = AssembleFrameBase.makeTransformList(skeleton, transforms)
|
val transformList = AssembleFrameBase.makeTransformList(skeleton, transforms)
|
||||||
|
|
||||||
/*println("Frame name: $frameName")
|
val animRow = theAnim.row
|
||||||
transforms.forEach { println(it) }
|
val animFrame = properties.getFrameNumberFromName(frameName)
|
||||||
println("==========================")
|
|
||||||
println("Transformed skeleton:")
|
|
||||||
transformList.forEach { (name, transform) ->
|
|
||||||
println("$name transformedOut: $transform")
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
AppLoader.printdbg(this, "Frame to draw: $frameName (R$animRow C$animFrame)")
|
||||||
|
|
||||||
// actually draw
|
drawFrame(animRow, animFrame, canvas, bodyparts, transformList, assembleConfig)
|
||||||
canvas.blending = Pixmap.Blending.SourceOver
|
}
|
||||||
|
|
||||||
|
private fun drawFrame(row: Int, column: Int,
|
||||||
|
canvas: Pixmap,
|
||||||
|
bodyparts: Array<Pixmap?>,
|
||||||
|
transformList: List<Pair<String, ADPropertyObject.Vector2i>>,
|
||||||
|
assembleConfig: AssembleConfig
|
||||||
|
) {
|
||||||
bodyparts.forEachIndexed { index, image ->
|
bodyparts.forEachIndexed { index, image ->
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
val imgCentre = AssembleFrameBase.getCentreOf(image)
|
val imgCentre = AssembleFrameBase.getCentreOf(image)
|
||||||
val drawPos = transformList[index].second.invertY() + assembleConfig.origin - imgCentre
|
val drawPos = transformList[index].second.invertY() + assembleConfig.origin - imgCentre
|
||||||
|
|
||||||
canvas.drawPixmap(image, drawPos.x, drawPos.y)
|
canvas.drawPixmap(
|
||||||
|
image,
|
||||||
|
(column - 1) * assembleConfig.fw + drawPos.x,
|
||||||
|
(row - 1) * assembleConfig.fh + drawPos.y
|
||||||
|
)
|
||||||
|
|
||||||
image.dispose()
|
image.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return canvas
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
|||||||
private val panelImageFilesList = JList<String>()
|
private val panelImageFilesList = JList<String>()
|
||||||
private val panelSkeletonsList = JList<String>()
|
private val panelSkeletonsList = JList<String>()
|
||||||
private val panelTransformsList = JList<String>()
|
private val panelTransformsList = JList<String>()
|
||||||
|
private val panelStatList = JList<String>()
|
||||||
private val panelCode = JTextPane()
|
private val panelCode = JTextPane()
|
||||||
private val statBar = JTextArea("Null.")
|
private val statBar = JTextArea("Null.")
|
||||||
|
|
||||||
@@ -100,6 +101,7 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
|||||||
panelImageFilesList.model = DefaultListModel()
|
panelImageFilesList.model = DefaultListModel()
|
||||||
panelSkeletonsList.model = DefaultListModel()
|
panelSkeletonsList.model = DefaultListModel()
|
||||||
panelTransformsList.model = DefaultListModel()
|
panelTransformsList.model = DefaultListModel()
|
||||||
|
panelStatList.model = DefaultListModel()
|
||||||
|
|
||||||
val panelPartsList = JTabbedPane(JTabbedPane.TOP)
|
val panelPartsList = JTabbedPane(JTabbedPane.TOP)
|
||||||
panelPartsList.add("Animations", JScrollPane(panelAnimationsList))
|
panelPartsList.add("Animations", JScrollPane(panelAnimationsList))
|
||||||
@@ -107,6 +109,7 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
|||||||
panelPartsList.add("Images", JScrollPane(panelImageFilesList))
|
panelPartsList.add("Images", JScrollPane(panelImageFilesList))
|
||||||
panelPartsList.add("Skeletons", JScrollPane(panelSkeletonsList))
|
panelPartsList.add("Skeletons", JScrollPane(panelSkeletonsList))
|
||||||
panelPartsList.add("Transforms", JScrollPane(panelTransformsList))
|
panelPartsList.add("Transforms", JScrollPane(panelTransformsList))
|
||||||
|
panelPartsList.add("Stats", JScrollPane(panelStatList))
|
||||||
|
|
||||||
val panelDataView = JSplitPane(JSplitPane.VERTICAL_SPLIT, JScrollPane(panelProperties), panelPartsList)
|
val panelDataView = JSplitPane(JSplitPane.VERTICAL_SPLIT, JScrollPane(panelProperties), panelPartsList)
|
||||||
panelDataView.resizeWeight = 0.333
|
panelDataView.resizeWeight = 0.333
|
||||||
@@ -145,6 +148,7 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
|||||||
panelImageFilesList.model = DefaultListModel()
|
panelImageFilesList.model = DefaultListModel()
|
||||||
panelSkeletonsList.model = DefaultListModel()
|
panelSkeletonsList.model = DefaultListModel()
|
||||||
panelTransformsList.model = DefaultListModel()
|
panelTransformsList.model = DefaultListModel()
|
||||||
|
panelStatList.model = DefaultListModel()
|
||||||
|
|
||||||
// populate animations view
|
// populate animations view
|
||||||
adProperties.animations.forEach {
|
adProperties.animations.forEach {
|
||||||
@@ -166,6 +170,9 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
|||||||
adProperties.transforms.forEach {
|
adProperties.transforms.forEach {
|
||||||
(panelTransformsList.model as DefaultListModel).addElement("$it")
|
(panelTransformsList.model as DefaultListModel).addElement("$it")
|
||||||
}
|
}
|
||||||
|
// populate stats
|
||||||
|
(panelStatList.model as DefaultListModel).addElement("Spritesheet rows: ${adProperties.rows}")
|
||||||
|
(panelStatList.model as DefaultListModel).addElement("Spritesheet columns: ${adProperties.cols}")
|
||||||
}
|
}
|
||||||
catch (fehler: Throwable) {
|
catch (fehler: Throwable) {
|
||||||
displayError("ERROR_PARSE_FAIL", fehler)
|
displayError("ERROR_PARSE_FAIL", fehler)
|
||||||
@@ -177,7 +184,7 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
|||||||
menu.add(JMenu("Run")).addMouseListener(object : MouseAdapter() {
|
menu.add(JMenu("Run")).addMouseListener(object : MouseAdapter() {
|
||||||
override fun mousePressed(e: MouseEvent?) {
|
override fun mousePressed(e: MouseEvent?) {
|
||||||
try {
|
try {
|
||||||
gdxWindow.requestAssemblyTest(adProperties, "ANIM_IDLE_2")
|
gdxWindow.requestAssemblyTest(adProperties)
|
||||||
statBar.text = lang.getProperty("SPRITE_ASSEMBLE_SUCCESSFUL")
|
statBar.text = lang.getProperty("SPRITE_ASSEMBLE_SUCCESSFUL")
|
||||||
}
|
}
|
||||||
catch (fehler: Throwable) {
|
catch (fehler: Throwable) {
|
||||||
@@ -242,13 +249,12 @@ class SpriteAssemblerPreview: Game() {
|
|||||||
|
|
||||||
private var doAssemble = false
|
private var doAssemble = false
|
||||||
private lateinit var assembleProp: ADProperties
|
private lateinit var assembleProp: ADProperties
|
||||||
private lateinit var assembleFrameName: String
|
|
||||||
|
|
||||||
override fun render() {
|
override fun render() {
|
||||||
if (doAssemble) {
|
if (doAssemble) {
|
||||||
// assembly requires GL context
|
// assembly requires GL context
|
||||||
doAssemble = false
|
doAssemble = false
|
||||||
assembleImageTest(assembleProp, assembleFrameName)
|
assembleImage(assembleProp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -265,14 +271,13 @@ class SpriteAssemblerPreview: Game() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assembleImageTest(prop: ADProperties, frameName: String) {
|
private fun assembleImage(prop: ADProperties) {
|
||||||
image = AssembleFramePixmap(prop, frameName)
|
image = AssembleSheetPixmap(prop)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestAssemblyTest(prop: ADProperties, frameName: String) {
|
fun requestAssemblyTest(prop: ADProperties) {
|
||||||
doAssemble = true
|
doAssemble = true
|
||||||
assembleProp = prop
|
assembleProp = prop
|
||||||
assembleFrameName = frameName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ ANIM_RUN=DELAY 0.15;ROW 2;SKELETON SKELETON_STAND
|
|||||||
ANIM_RUN_1=LEG_REST_RIGHT 1,1;FOOT_RIGHT 1,1;LEG_REST_LEFT -1,0;FOOT_LEFT -1,0
|
ANIM_RUN_1=LEG_REST_RIGHT 1,1;FOOT_RIGHT 1,1;LEG_REST_LEFT -1,0;FOOT_LEFT -1,0
|
||||||
ANIM_RUN_2=ALL 0,1;LEG_REST_RIGHT 0,-1;FOOT_RIGHT 0,-1;LEG_REST_LEFT 0,1;FOOT_LEFT 0,1
|
ANIM_RUN_2=ALL 0,1;LEG_REST_RIGHT 0,-1;FOOT_RIGHT 0,-1;LEG_REST_LEFT 0,1;FOOT_LEFT 0,1
|
||||||
ANIM_RUN_3=LEG_REST_RIGHT -1,0;FOOT_RIGHT -1,0;LEG_REST_LEFT 1,1;FOOT_LEFT 1,1
|
ANIM_RUN_3=LEG_REST_RIGHT -1,0;FOOT_RIGHT -1,0;LEG_REST_LEFT 1,1;FOOT_LEFT 1,1
|
||||||
ANIM_RUN_4=ALL 0,1;LEG_REST_RIGHT 0,1;LEG_REST_LEFT 0,-1
|
ANIM_RUN_4=ALL 0,1;LEG_REST_RIGHT 0,1;FOOT_RIGHT 0,1;LEG_REST_LEFT 0,-1;FOOT_LEFT 0,-1
|
||||||
|
|
||||||
ANIM_IDLE=DELAY 2;ROW 1;SKELETON SKELETON_STAND
|
ANIM_IDLE=DELAY 2;ROW 1;SKELETON SKELETON_STAND
|
||||||
ANIM_IDLE_1=
|
ANIM_IDLE_1=
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package net.torvald.terrarum.tests
|
package net.torvald.terrarum.tests
|
||||||
|
|
||||||
import net.torvald.spriteassembler.ADProperties
|
import net.torvald.spriteassembler.ADProperties
|
||||||
import net.torvald.spriteassembler.AssembleFramePixmap
|
import net.torvald.spriteassembler.AssembleSheetPixmap
|
||||||
import java.io.StringReader
|
import java.io.StringReader
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,7 +11,7 @@ class SpriteAssemblerTest {
|
|||||||
|
|
||||||
operator fun invoke() {
|
operator fun invoke() {
|
||||||
val properties = ADProperties(StringReader(ADLParsingTest().TEST_STR))
|
val properties = ADProperties(StringReader(ADLParsingTest().TEST_STR))
|
||||||
AssembleFramePixmap.invoke(properties, "ANIM_RUN_1")
|
AssembleSheetPixmap.invoke(properties)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user