mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
sprite and spriteassembler update
This commit is contained in:
@@ -1,37 +1,45 @@
|
||||
# complete file name is: SPRITESHEET + bodypart name + EXTENSION
|
||||
SPRITESHEET=mods/basegame/sprites/test_werebeastf/taimu_
|
||||
EXTENSION=.tga
|
||||
# defines frame size and origin point. Origin point is given as: (originx, size.y - 1)
|
||||
# ORIGINY is deduced from the sprite size as shown in above; you only need to set ORIGINX
|
||||
# defines frame size and origin point. Origin point is given as: (originx, 0)
|
||||
CONFIG=SIZE 64,98;ORIGINX 40
|
||||
|
||||
# note to self: don't implement skeleton hierarchy: there's too many exceptions
|
||||
# besides, you have "ALL" key.
|
||||
|
||||
! a skeleton also defines what body parts (images) be used.
|
||||
! you can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! A skeleton also defines what body parts (images) be used.
|
||||
! You can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! skeleton joints are ordered: foremost-drawn object comes first, which means lowermost object IN THIS LIST
|
||||
! are painted first, and any object that comes before it will paint over it. In other words, this list is
|
||||
! first reversed then being iterated.
|
||||
! Joints' original point is defined in the document sprite_joints.psd. It also has visual representations.
|
||||
# TODO right now accessory points are explicitly defined. Should they be injected in run-time?
|
||||
SKELETON_STAND=HEADGEAR 0,32;\
|
||||
ARM_REST_LEFT -9,49;HELD_ITEM -6,11;\
|
||||
HEAD 2,83;\
|
||||
BUST_0 4,60;\
|
||||
TORSO_0 0,55;\
|
||||
TORSO_1 0,55;\
|
||||
LEG_REST_RIGHT -6,22;\
|
||||
LEG_REST_LEFT 7,22;\
|
||||
ARM_REST_RIGHT 12,51;\
|
||||
TAIL_0 -11,27
|
||||
! Some keywords are considered special within the game, they are:
|
||||
! HEADGEAR, HELD_ITEM, BOOT_L, BOOT_R, GAUNTLET_L, GAUNTLET_R and ARMOUR_* (star means any number starting from zero)
|
||||
BODYPARTS=HEADGEAR 13,14;\
|
||||
HEAD 13,14;\
|
||||
ARM_REST_RIGHT 5,3;\
|
||||
ARM_REST_LEFT 6,3;\
|
||||
LEG_REST_RIGHT 12,6;\
|
||||
LEG_REST_LEFT 8,6;\
|
||||
TORSO_0 18,19;\
|
||||
TORSO_1 18,19;\
|
||||
TAIL_0 30,2;\
|
||||
BUST_0 11,2;\
|
||||
HELD_ITEM 0,0
|
||||
SKELETON_STAND=HEADGEAR 0,78;\
|
||||
ARM_REST_RIGHT -15,66;\
|
||||
HELD_ITEM -11,33;\
|
||||
HEAD 0,78;\
|
||||
BUST_0 0,63;\
|
||||
TORSO_0 0,54;\
|
||||
TORSO_1 0,54;\
|
||||
LEG_REST_RIGHT -5,41;\
|
||||
LEG_REST_LEFT 3,41;\
|
||||
ARM_REST_LEFT 8,66;\
|
||||
TAIL_0 2,40
|
||||
|
||||
# skeleton_stand is used for testing purpose
|
||||
ANIM_RUN=DELAY 0.3;ROW 2;SKELETON SKELETON_STAND
|
||||
ANIM_RUN_1=LEG_REST_RIGHT 2,2;LEG_REST_LEFT -2,0;TAIL_0 1,0
|
||||
ANIM_RUN_2=ALL 0,2;LEG_REST_RIGHT 0,-2;LEG_REST_LEFT 0,2;TAIL_0 -1,0
|
||||
ANIM_RUN_3=LEG_REST_RIGHT -2,0;LEG_REST_LEFT 2,2;TAIL_0 -1,0
|
||||
ANIM_RUN_4=ALL 0,2;LEG_REST_RIGHT 0,2;LEG_REST_LEFT 0,-2;TAIL_0 1,0
|
||||
ANIM_RUN_1=LEG_REST_RIGHT 2,2;LEG_REST_LEFT -2,0;TAIL_0 1,0;TORSO_1 0,-999
|
||||
ANIM_RUN_2=ALL 0,2;LEG_REST_RIGHT 0,-2;LEG_REST_LEFT 0,2;TAIL_0 -1,0;TORSO_1 0,-999
|
||||
ANIM_RUN_3=LEG_REST_RIGHT -2,0;LEG_REST_LEFT 2,2;TAIL_0 -1,0;TORSO_1 0,-999
|
||||
ANIM_RUN_4=ALL 0,2;LEG_REST_RIGHT 0,2;LEG_REST_LEFT 0,-2;TAIL_0 1,0;TORSO_1 0,-999
|
||||
|
||||
ANIM_IDLE=DELAY 2;ROW 1;SKELETON SKELETON_STAND
|
||||
ANIM_IDLE_1=TORSO_1 0,-999;HEAD 0,-1
|
||||
|
||||
@@ -1,37 +1,45 @@
|
||||
# complete file name is: SPRITESHEET + bodypart name + EXTENSION
|
||||
SPRITESHEET=mods/basegame/sprites/test_werebeastf/taimuglow_
|
||||
EXTENSION=.tga
|
||||
# defines frame size and origin point. Origin point is given as: (originx, size.y - 1)
|
||||
# ORIGINY is deduced from the sprite size as shown in above; you only need to set ORIGINX
|
||||
# defines frame size and origin point. Origin point is given as: (originx, 0)
|
||||
CONFIG=SIZE 64,98;ORIGINX 40
|
||||
|
||||
# note to self: don't implement skeleton hierarchy: there's too many exceptions
|
||||
# besides, you have "ALL" key.
|
||||
|
||||
! a skeleton also defines what body parts (images) be used.
|
||||
! you can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! A skeleton also defines what body parts (images) be used.
|
||||
! You can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! skeleton joints are ordered: foremost-drawn object comes first, which means lowermost object IN THIS LIST
|
||||
! are painted first, and any object that comes before it will paint over it. In other words, this list is
|
||||
! first reversed then being iterated.
|
||||
! Joints' original point is defined in the document sprite_joints.psd. It also has visual representations.
|
||||
# TODO right now accessory points are explicitly defined. Should they be injected in run-time?
|
||||
SKELETON_STAND=HEADGEAR 0,32;\
|
||||
ARM_REST_LEFT -8,49;HELD_ITEM -6,11;\
|
||||
HEAD 2,83;\
|
||||
BUST_0 4,60;\
|
||||
TORSO_0 0,55;\
|
||||
TORSO_1 0,55;\
|
||||
LEG_REST_RIGHT -5,22;\
|
||||
LEG_REST_LEFT 6,22;\
|
||||
ARM_REST_RIGHT 11,51;\
|
||||
TAIL_0 -11,27
|
||||
! Some keywords are considered special within the game, they are:
|
||||
! HEADGEAR, HELD_ITEM, BOOT_L, BOOT_R, GAUNTLET_L, GAUNTLET_R and ARMOUR_* (star means any number starting from zero)
|
||||
BODYPARTS=HEADGEAR 13,14;\
|
||||
HEAD 13,14;\
|
||||
ARM_REST_RIGHT 5,3;\
|
||||
ARM_REST_LEFT 6,3;\
|
||||
LEG_REST_RIGHT 12,6;\
|
||||
LEG_REST_LEFT 8,6;\
|
||||
TORSO_0 18,19;\
|
||||
TORSO_1 18,19;\
|
||||
TAIL_0 30,2;\
|
||||
BUST_0 11,2;\
|
||||
HELD_ITEM 0,0
|
||||
SKELETON_STAND=HEADGEAR 0,78;\
|
||||
ARM_REST_RIGHT -15,66;\
|
||||
HELD_ITEM -11,33;\
|
||||
HEAD 0,78;\
|
||||
BUST_0 0,63;\
|
||||
TORSO_0 0,54;\
|
||||
TORSO_1 0,54;\
|
||||
LEG_REST_RIGHT -5,41;\
|
||||
LEG_REST_LEFT 3,41;\
|
||||
ARM_REST_LEFT 8,66;\
|
||||
TAIL_0 2,40
|
||||
|
||||
# skeleton_stand is used for testing purpose
|
||||
ANIM_RUN=DELAY 0.3;ROW 2;SKELETON SKELETON_STAND
|
||||
ANIM_RUN_1=LEG_REST_RIGHT 2,2;LEG_REST_LEFT -2,0;TAIL_0 1,0
|
||||
ANIM_RUN_2=ALL 0,2;LEG_REST_RIGHT 0,-2;LEG_REST_LEFT 0,2;TAIL_0 -1,0
|
||||
ANIM_RUN_3=LEG_REST_RIGHT -2,0;LEG_REST_LEFT 2,2;TAIL_0 -1,0
|
||||
ANIM_RUN_4=ALL 0,2;LEG_REST_RIGHT 0,2;LEG_REST_LEFT 0,-2;TAIL_0 1,0
|
||||
ANIM_RUN_1=LEG_REST_RIGHT 2,2;LEG_REST_LEFT -2,0;TAIL_0 1,0;TORSO_1 0,-999
|
||||
ANIM_RUN_2=ALL 0,2;LEG_REST_RIGHT 0,-2;LEG_REST_LEFT 0,2;TAIL_0 -1,0;TORSO_1 0,-999
|
||||
ANIM_RUN_3=LEG_REST_RIGHT -2,0;LEG_REST_LEFT 2,2;TAIL_0 -1,0;TORSO_1 0,-999
|
||||
ANIM_RUN_4=ALL 0,2;LEG_REST_RIGHT 0,2;LEG_REST_LEFT 0,-2;TAIL_0 1,0;TORSO_1 0,-999
|
||||
|
||||
ANIM_IDLE=DELAY 2;ROW 1;SKELETON SKELETON_STAND
|
||||
ANIM_IDLE_1=TORSO_1 0,-999;HEAD 0,-1
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
# complete file name is: SPRITESHEET + bodypart name + EXTENSION
|
||||
SPRITESHEET=mods/basegame/sprites/sprite_assembler_test_assets/test_
|
||||
EXTENSION=.tga
|
||||
# defines frame size and origin point. Origin point is given as: (originx, size.y - 1)
|
||||
# ORIGINY is deduced from the sprite size as shown in above; you only need to set ORIGINX
|
||||
# defines frame size and origin point. Origin point is given as: (originx, 0)
|
||||
CONFIG=SIZE 48,56;ORIGINX 29
|
||||
|
||||
# note to self: don't implement skeleton hierarchy: there's too many exceptions
|
||||
# besides, you have "ALL" key.
|
||||
|
||||
! a skeleton also defines what body parts (images) be used.
|
||||
! you can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! A skeleton also defines what body parts (images) be used.
|
||||
! You can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! skeleton joints are ordered: foremost-drawn object comes first, which means lowermost object IN THIS LIST
|
||||
! are painted first, and any object that comes before it will paint over it. In other words, this list is
|
||||
! first reversed then being iterated.
|
||||
! Joints' original point is defined in the document sprite_joints.psd. It also has visual representations.
|
||||
# TODO right now accessory points are explicitly defined. Should they be injected in run-time? In that case, certain names (e.g. headgear, held_item) will act as an anchor.
|
||||
! Some keywords are considered special within the game, they are:
|
||||
! HEADGEAR, HELD_ITEM, BOOT_L, BOOT_R, GAUNTLET_L, GAUNTLET_R and ARMOUR_* (star means any number starting from zero)
|
||||
BODYPARTS=ARM_REST_RIGHT 3,8;\
|
||||
ARM_REST_LEFT 3,8;\
|
||||
FOOT_LEFT 4,2;\
|
||||
FOOT_RIGHT 4,2;\
|
||||
UPPER_TORSO 9,4;\
|
||||
LOWER_TORSO 7,4;\
|
||||
LEG_REST_RIGHT 3,7;\
|
||||
LEG_REST_LEFT 3,7;\
|
||||
HEAD 8,7;\
|
||||
HAND_REST_RIGHT 3,3;\
|
||||
HAND_REST_LEFT 3,3;\
|
||||
HAIR 20,12;\
|
||||
HAIR_FORE 20,12
|
||||
SKELETON_STAND=HEADGEAR 0,32;HAIR_FORE 0,32;\
|
||||
ARM_REST_RIGHT -7,23;HAND_REST_RIGHT -6,11;HELD_ITEM -6,11;\
|
||||
HAIR 0,32;HEAD 0,32;\
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
# complete file name is: SPRITESHEET + bodypart name + EXTENSION
|
||||
SPRITESHEET=mods/basegame/sprites/sprite_assembler_test_assets/testglow_
|
||||
EXTENSION=.tga
|
||||
# defines frame size and origin point. Origin point is given as: (originx, size.y - 1)
|
||||
# ORIGINY is deduced from the sprite size as shown in above; you only need to set ORIGINX
|
||||
# defines frame size and origin point. Origin point is given as: (originx, 0)
|
||||
CONFIG=SIZE 48,56;ORIGINX 29
|
||||
|
||||
# note to self: don't implement skeleton hierarchy: there's too many exceptions
|
||||
# besides, you have "ALL" key.
|
||||
|
||||
! a skeleton also defines what body parts (images) be used.
|
||||
! you can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! A skeleton also defines what body parts (images) be used.
|
||||
! You can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! skeleton joints are ordered: foremost-drawn object comes first, which means lowermost object IN THIS LIST
|
||||
! are painted first, and any object that comes before it will paint over it. In other words, this list is
|
||||
! first reversed then being iterated.
|
||||
! Joints' original point is defined in the document sprite_joints.psd. It also has visual representations.
|
||||
# TODO right now accessory points are explicitly defined. Should they be injected in run-time? In that case, certain names (e.g. headgear, held_item) will act as an anchor.
|
||||
! Some keywords are considered special within the game, they are:
|
||||
! HEADGEAR, HELD_ITEM, BOOT_L, BOOT_R, GAUNTLET_L, GAUNTLET_R and ARMOUR_* (star means any number starting from zero)
|
||||
BODYPARTS=ARM_REST_RIGHT 3,8;\
|
||||
ARM_REST_LEFT 3,8;\
|
||||
FOOT_LEFT 4,2;\
|
||||
FOOT_RIGHT 4,2;\
|
||||
UPPER_TORSO 9,4;\
|
||||
LOWER_TORSO 7,4;\
|
||||
LEG_REST_RIGHT 3,7;\
|
||||
LEG_REST_LEFT 3,7;\
|
||||
HEAD 8,7;\
|
||||
HAND_REST_RIGHT 3,3;\
|
||||
HAND_REST_LEFT 3,3;\
|
||||
HAIR 20,12;\
|
||||
HAIR_FORE 20,12
|
||||
SKELETON_STAND=HEADGEAR 0,32;HAIR_FORE 0,32;\
|
||||
ARM_REST_RIGHT -7,23;HAND_REST_RIGHT -6,11;HELD_ITEM -6,11;\
|
||||
HAIR 0,32;HEAD 0,32;\
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -29,9 +29,9 @@ interface HasAssembledSprite {
|
||||
* ```
|
||||
*/
|
||||
fun reassembleSprite(sprite: SpriteAnimation, spriteGlow: SpriteAnimation? = null) {
|
||||
_rebuild(ADProperties(Gdx.files.internal(animDescPath).read()), sprite)
|
||||
_rebuild(ADProperties(Gdx.files.internal(animDescPath)), sprite)
|
||||
if (animDescPathGlow != null && spriteGlow != null)
|
||||
_rebuild(ADProperties(Gdx.files.internal(animDescPathGlow).read()), spriteGlow)
|
||||
_rebuild(ADProperties(Gdx.files.internal(animDescPathGlow)), spriteGlow)
|
||||
}
|
||||
|
||||
/*fun rebuild(animDescPath: String, spriteAnimation: SpriteAnimation) {
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package net.torvald.spriteassembler
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import net.torvald.terrarum.linearSearchBy
|
||||
import java.io.InputStream
|
||||
import java.io.Reader
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
internal data class Joint(val name: String, val position: ADPropertyObject.Vector2i) {
|
||||
override fun toString() = "$name $position"
|
||||
@@ -15,6 +14,7 @@ internal data class Skeleton(val name: String, val joints: List<Joint>) {
|
||||
override fun toString() = "$name=$joints"
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name You know it
|
||||
* @param delay Delay between each frame in seconds
|
||||
@@ -32,22 +32,25 @@ internal data class Transform(val joint: Joint, val translate: ADPropertyObject.
|
||||
}
|
||||
|
||||
class ADProperties {
|
||||
private var fileFrom = ""
|
||||
private val javaProp = Properties()
|
||||
|
||||
/** Every key is CAPITALISED */
|
||||
private val propTable = HashMap<String, List<ADPropertyObject>>()
|
||||
|
||||
/** list of bodyparts used by all the skeletons (HEAD, UPPER_TORSO, LOWER_TORSO) */
|
||||
lateinit var bodyparts: List<String>; private set
|
||||
// lateinit var bodyparts: List<String>; private set
|
||||
lateinit var bodypartFiles: List<String>; private set
|
||||
/** properties that are being used as skeletons (SKELETON_STAND) */
|
||||
internal lateinit var skeletons: HashMap<String, Skeleton>; private set
|
||||
/** properties that defines position of joint of the bodypart */
|
||||
internal val bodyparts = HashMap<String, ADPropertyObject.Vector2i>()
|
||||
/** properties that are recognised as animations (ANIM_RUN, ANIM)IDLE) */
|
||||
internal lateinit var animations: HashMap<String, Animation>; private set
|
||||
/** an "animation frame" property (ANIM_RUN_1, ANIM_RUN_2) */
|
||||
internal lateinit var transforms: HashMap<String, List<Transform>>; private set
|
||||
|
||||
private val reservedProps = listOf("SPRITESHEET", "EXTENSION")
|
||||
private val reservedProps = listOf("SPRITESHEET", "EXTENSION", "CONFIG", "BODYPARTS")
|
||||
private val animMustContain = listOf("DELAY", "ROW", "SKELETON")
|
||||
|
||||
lateinit var baseFilename: String; private set
|
||||
@@ -55,9 +58,8 @@ class ADProperties {
|
||||
var frameWidth: Int = -1; private set
|
||||
var frameHeight: Int = -1; private set
|
||||
var originX: Int = -1; private set
|
||||
var originY: Int = -1; private set
|
||||
internal val origin: ADPropertyObject.Vector2i
|
||||
get() = ADPropertyObject.Vector2i(originX, originY)
|
||||
get() = ADPropertyObject.Vector2i(originX, 0)
|
||||
|
||||
private val animFrameSuffixRegex = Regex("""_[0-9]+""")
|
||||
|
||||
@@ -70,6 +72,12 @@ class ADProperties {
|
||||
const val ALL_JOINT_SELECT_KEY = "ALL"
|
||||
}
|
||||
|
||||
constructor(gdxFile: FileHandle) {
|
||||
fileFrom = gdxFile.path()
|
||||
javaProp.load(gdxFile.read())
|
||||
continueLoad()
|
||||
}
|
||||
|
||||
constructor(reader: Reader) {
|
||||
javaProp.load(reader)
|
||||
continueLoad()
|
||||
@@ -85,6 +93,16 @@ class ADProperties {
|
||||
}
|
||||
|
||||
private fun continueLoad() {
|
||||
// sanity check
|
||||
reservedProps.forEach {
|
||||
try {
|
||||
javaProp[it]!!
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
throw IllegalArgumentException("Prop '$it' not found from ${fileFrom.ifBlank { "(path unavailable)" }}", e)
|
||||
}
|
||||
}
|
||||
|
||||
javaProp.keys.forEach { propName ->
|
||||
val propsStr = javaProp.getProperty(propName as String)
|
||||
val propsList = propsStr.split(';').map { ADPropertyObject(it) }
|
||||
@@ -99,11 +117,9 @@ class ADProperties {
|
||||
frameWidth = frameSizeVec.x
|
||||
frameHeight = frameSizeVec.y
|
||||
originX = (get("CONFIG").linearSearchBy { it.name == "ORIGINX" }!!.input as Float).toInt()
|
||||
originY = frameHeight - 1
|
||||
|
||||
var maxColFinder = -1
|
||||
var maxRowFinder = -1
|
||||
val bodyparts = HashSet<String>()
|
||||
val skeletons = HashMap<String, Skeleton>()
|
||||
val animations = HashMap<String, Animation>()
|
||||
val animFrames = HashMap<String, Int>()
|
||||
@@ -153,13 +169,6 @@ class ADProperties {
|
||||
}
|
||||
}
|
||||
|
||||
// populate the bodyparts using skeletons
|
||||
skeletons.forEach { (_, prop: Skeleton) ->
|
||||
prop.joints.forEach {
|
||||
bodyparts.add(it.name)
|
||||
}
|
||||
}
|
||||
|
||||
// populate transforms
|
||||
animations.forEach { t, u ->
|
||||
for (fc in 1..u.frames) {
|
||||
@@ -190,17 +199,28 @@ class ADProperties {
|
||||
}
|
||||
}
|
||||
|
||||
this.bodyparts = bodyparts.toList().sorted()
|
||||
get("BODYPARTS").forEach {
|
||||
try {
|
||||
this.bodyparts[it.name] = (it.input as ADPropertyObject.Vector2i)
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
if (it.name.isBlank())
|
||||
throw IllegalArgumentException("Empty Bodypart name on BODYPARTS; try removing trailing semicolon (';')?")
|
||||
else
|
||||
throw IllegalArgumentException("Bodyparts definition for '${it.name}' not found from ${fileFrom.ifBlank { "(path unavailable)" }}", e)
|
||||
}
|
||||
}
|
||||
|
||||
this.skeletons = skeletons
|
||||
this.animations = animations
|
||||
this.bodypartFiles = this.bodyparts.map { toFilename(it) }
|
||||
this.bodypartFiles = this.bodyparts.keys.map { toFilename(it) }
|
||||
this.transforms = transforms
|
||||
|
||||
cols = maxColFinder
|
||||
rows = maxRowFinder
|
||||
}
|
||||
|
||||
operator fun get(identifier: String) = propTable[identifier.toUpperCase()]!!
|
||||
operator fun get(identifier: String): List<ADPropertyObject> = propTable[identifier.toUpperCase()]!!
|
||||
val keys
|
||||
get() = propTable.keys
|
||||
fun containsKey(key: String) = propTable.containsKey(key)
|
||||
@@ -299,6 +319,8 @@ class ADPropertyObject(propertyRaw: String) {
|
||||
operator fun minus(other: Vector2i) = Vector2i(this.x - other.x, this.y - other.y)
|
||||
|
||||
fun invertY() = Vector2i(this.x, -this.y)
|
||||
fun invertX() = Vector2i(-this.x, this.y)
|
||||
fun invertXY() = Vector2i(-this.x, -this.y)
|
||||
}
|
||||
|
||||
enum class ADPropertyType {
|
||||
|
||||
@@ -3,7 +3,6 @@ package net.torvald.spriteassembler
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import net.torvald.terrarum.linearSearch
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Assembles the single frame of the animation, outputs GDX Pixmap.
|
||||
@@ -34,19 +33,11 @@ object AssembleSheetPixmap {
|
||||
val theAnim = properties.getAnimByFrameName(frameName)
|
||||
val skeleton = theAnim.skeleton.joints.reversed()
|
||||
val transforms = properties.getTransform(frameName)
|
||||
val bodyparts = Array<Pixmap?>(skeleton.size) {
|
||||
// if file does not exist, null it
|
||||
val file = File("assets/" + properties.toFilename(skeleton[it].name))
|
||||
|
||||
//printdbg(this, "Loading file ${file.absolutePath}, exists: ${file.exists()}")
|
||||
|
||||
/*return*/if (file.exists()) {
|
||||
Pixmap(Gdx.files.internal(file.path))
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
}
|
||||
val bodypartOrigins = properties.bodyparts
|
||||
val bodypartImages = properties.bodyparts.keys.map {
|
||||
val file = Gdx.files.internal("assets/${properties.toFilename(it)}")
|
||||
it to (if (file.exists()) Pixmap(file) else null)
|
||||
}.toMap()
|
||||
val transformList = AssembleFrameBase.makeTransformList(skeleton, transforms)
|
||||
|
||||
val animRow = theAnim.row
|
||||
@@ -54,25 +45,26 @@ object AssembleSheetPixmap {
|
||||
|
||||
// AppLoader.printdbg(this, "Frame to draw: $frameName (R$animRow C$animFrame)")
|
||||
|
||||
drawFrame(animRow, animFrame, canvas, properties, bodyparts, transformList)
|
||||
drawFrame(animRow, animFrame, canvas, properties, bodypartOrigins, bodypartImages, transformList)
|
||||
|
||||
bodyparts.forEach { it?.dispose() }
|
||||
bodypartImages.values.forEach { it?.dispose() }
|
||||
}
|
||||
|
||||
private fun drawFrame(row: Int, column: Int,
|
||||
canvas: Pixmap,
|
||||
props: ADProperties,
|
||||
bodyparts: Array<Pixmap?>,
|
||||
bodypartOrigins: HashMap<String, ADPropertyObject.Vector2i>,
|
||||
bodypartImages: Map<String, Pixmap?>,
|
||||
transformList: List<Pair<String, ADPropertyObject.Vector2i>>
|
||||
) {
|
||||
val tmpFrame = Pixmap(props.frameWidth, props.frameHeight, Pixmap.Format.RGBA8888)
|
||||
|
||||
bodyparts.forEachIndexed { index, image ->
|
||||
if (image != null) {
|
||||
val imgCentre = AssembleFrameBase.getCentreOf(image)
|
||||
val drawPos = transformList[index].second.invertY() + props.origin - imgCentre
|
||||
transformList.forEach { (name, pos) ->
|
||||
bodypartImages[name]?.let { image ->
|
||||
val imgCentre = bodypartOrigins[name]!!.invertX()
|
||||
val drawPos = props.origin + pos + imgCentre
|
||||
|
||||
tmpFrame.drawPixmap(image, drawPos.x, drawPos.y)
|
||||
tmpFrame.drawPixmap(image, drawPos.x, props.frameHeight - drawPos.y - 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,9 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
||||
|GNU General Public License for more details.
|
||||
|
|
||||
|You should have received a copy of the GNU General Public License
|
||||
|along with this program. If not, see <https://www.gnu.org/licenses/>.""".trimMargin()
|
||||
|along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
|
||||
|Paste your Animation Description here and press 'Update'!""".trimMargin()
|
||||
panelCode.addMouseListener(object : MouseAdapter() {
|
||||
override fun mousePressed(e: MouseEvent?) {
|
||||
if (panelCodeInit) {
|
||||
@@ -116,14 +118,14 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
||||
|
||||
panelProperties.model = DefaultTreeModel(DefaultMutableTreeNode(lang.getProperty("PROPERTIES_GO_HERE")))
|
||||
val panelDataView = JSplitPane(JSplitPane.VERTICAL_SPLIT, JScrollPane(panelProperties), panelPartsList)
|
||||
panelDataView.resizeWeight = 0.333
|
||||
panelDataView.resizeWeight = 0.4
|
||||
|
||||
// to disable text wrap
|
||||
//val panelCodeNoWrap = JPanel(BorderLayout())
|
||||
//panelCodeNoWrap.add(panelCode)
|
||||
|
||||
val panelMain = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, JScrollPane(panelCode), panelDataView)
|
||||
panelMain.resizeWeight = 0.666
|
||||
panelMain.resizeWeight = 0.6
|
||||
|
||||
val menu = JMenuBar()
|
||||
menu.add(JMenu("Update")).addMouseListener(object : MouseAdapter() {
|
||||
@@ -158,8 +160,8 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
||||
(panelAnimationsList.model as DefaultListModel).addElement("${it.value}")
|
||||
}
|
||||
// populate bodyparts view
|
||||
adProperties.bodyparts.forEach { partName ->
|
||||
(panelBodypartsList.model as DefaultListModel).addElement(partName)
|
||||
adProperties.bodyparts.toSortedMap().forEach { part ->
|
||||
(panelBodypartsList.model as DefaultListModel).addElement("${part.key}: ${part.value}")
|
||||
}
|
||||
// populate image file list view
|
||||
adProperties.bodypartFiles.forEach { partName ->
|
||||
@@ -177,7 +179,7 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
||||
(panelStatList.model as DefaultListModel).addElement("Spritesheet rows: ${adProperties.rows}")
|
||||
(panelStatList.model as DefaultListModel).addElement("Spritesheet columns: ${adProperties.cols}")
|
||||
(panelStatList.model as DefaultListModel).addElement("Frame size: ${adProperties.frameWidth}, ${adProperties.frameHeight}")
|
||||
(panelStatList.model as DefaultListModel).addElement("Origin position: ${adProperties.originX}, ${adProperties.originY}")
|
||||
(panelStatList.model as DefaultListModel).addElement("Origin position: ${adProperties.origin}")
|
||||
|
||||
|
||||
|
||||
@@ -218,7 +220,7 @@ class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
||||
this.add(statBar, BorderLayout.SOUTH)
|
||||
this.title = "Terrarum Sprite Assembler and Viewer"
|
||||
this.isVisible = true
|
||||
this.setSize(1154, 768)
|
||||
this.setSize(1120, 768)
|
||||
this.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
|
||||
}
|
||||
|
||||
@@ -317,7 +319,7 @@ class SpriteAssemblerPreview: Game() {
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val appConfig = Lwjgl3ApplicationConfiguration()
|
||||
appConfig.setWindowedMode(800, 800)
|
||||
appConfig.setWindowedMode(1024, 1024)
|
||||
appConfig.setIdleFPS(5)
|
||||
appConfig.setForegroundFPS(5)
|
||||
appConfig.setResizable(false)
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.EMDASH
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.*
|
||||
import net.torvald.terrarum.Terrarum.PLAYER_REF_ID
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||
import net.torvald.terrarum.blockproperties.BlockPropUtil
|
||||
@@ -293,7 +294,9 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
System.err.println("Could not read the actor ${it} from the disk")
|
||||
// throw e // TODO don't rethrow -- let players play the corrupted world if it loads, they'll be able to cope with their losses even though there will be buncha lone actorblocks lying around...
|
||||
e.printStackTrace()
|
||||
if (it == PLAYER_REF_ID) throw e
|
||||
// throw e // if not player, don't rethrow -- let players play the corrupted world if it loads, they'll be able to cope with their losses even though there will be buncha lone actorblocks lying around...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ object ReadActor {
|
||||
if (actor is ActorWithBody && actor is HasAssembledSprite) {
|
||||
actor.sprite = SpriteAnimation(actor)
|
||||
if (actor.animDescPathGlow != null) actor.spriteGlow = SpriteAnimation(actor)
|
||||
actor.reassembleSprite(actor.sprite!!, actor.spriteGlow)
|
||||
actor.reassembleSprite(actor.sprite ?: throw InternalError("actor.sprite (type: SpriteAnimation) is null"), actor.spriteGlow)
|
||||
}
|
||||
|
||||
return actor
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user