diff --git a/assets/mods/basegame/sprites/taimu.properties b/assets/mods/basegame/sprites/taimu.properties index cc09a236b..fadd48226 100644 --- a/assets/mods/basegame/sprites/taimu.properties +++ b/assets/mods/basegame/sprites/taimu.properties @@ -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 diff --git a/assets/mods/basegame/sprites/taimu_glow.properties b/assets/mods/basegame/sprites/taimu_glow.properties index 95b752b4f..45f6db4aa 100644 --- a/assets/mods/basegame/sprites/taimu_glow.properties +++ b/assets/mods/basegame/sprites/taimu_glow.properties @@ -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 diff --git a/assets/mods/basegame/sprites/test_sprite.properties b/assets/mods/basegame/sprites/test_sprite.properties index fb409f728..1cc19ba23 100644 --- a/assets/mods/basegame/sprites/test_sprite.properties +++ b/assets/mods/basegame/sprites/test_sprite.properties @@ -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;\ diff --git a/assets/mods/basegame/sprites/test_sprite_glow.properties b/assets/mods/basegame/sprites/test_sprite_glow.properties index af5005693..a0510df94 100644 --- a/assets/mods/basegame/sprites/test_sprite_glow.properties +++ b/assets/mods/basegame/sprites/test_sprite_glow.properties @@ -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;\ diff --git a/assets/mods/basegame/sprites/test_werebeastf/taimu_arm_rest_left.tga b/assets/mods/basegame/sprites/test_werebeastf/taimu_arm_rest_left.tga index 394c82b56..021e16289 100644 --- a/assets/mods/basegame/sprites/test_werebeastf/taimu_arm_rest_left.tga +++ b/assets/mods/basegame/sprites/test_werebeastf/taimu_arm_rest_left.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0854bb8f961a5059d9486d0029010c92fbfccab73534775219ff538b84495ba9 -size 2258 +oid sha256:df0a5c68ff738373ff88a863e6bd7fcabbe5503566d3b14e41a337feee2973d6 +size 1942 diff --git a/assets/mods/basegame/sprites/test_werebeastf/taimu_arm_rest_right.tga b/assets/mods/basegame/sprites/test_werebeastf/taimu_arm_rest_right.tga index 021e16289..394c82b56 100644 --- a/assets/mods/basegame/sprites/test_werebeastf/taimu_arm_rest_right.tga +++ b/assets/mods/basegame/sprites/test_werebeastf/taimu_arm_rest_right.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df0a5c68ff738373ff88a863e6bd7fcabbe5503566d3b14e41a337feee2973d6 -size 1942 +oid sha256:0854bb8f961a5059d9486d0029010c92fbfccab73534775219ff538b84495ba9 +size 2258 diff --git a/assets/mods/basegame/sprites/test_werebeastf/taimu_leg_rest_left.tga b/assets/mods/basegame/sprites/test_werebeastf/taimu_leg_rest_left.tga index 91f6a2ba3..2884c4b3d 100644 --- a/assets/mods/basegame/sprites/test_werebeastf/taimu_leg_rest_left.tga +++ b/assets/mods/basegame/sprites/test_werebeastf/taimu_leg_rest_left.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1195aed638eece6fa9e7e89b4da4c4fbb4352aeee527717627c6a09dbb1e6257 -size 3146 +oid sha256:f26a02e64c0c8dfdd78918ffec9bdda58488f142b1f9c6623020b93262ded976 +size 3282 diff --git a/assets/mods/basegame/sprites/test_werebeastf/taimu_leg_rest_right.tga b/assets/mods/basegame/sprites/test_werebeastf/taimu_leg_rest_right.tga index b3ec06be0..bd4bd5b55 100644 --- a/assets/mods/basegame/sprites/test_werebeastf/taimu_leg_rest_right.tga +++ b/assets/mods/basegame/sprites/test_werebeastf/taimu_leg_rest_right.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c7d7e430e97d7d37a08b1bec2a90eb5b686b7304f2019945084a60539cfcb37 -size 2778 +oid sha256:29108c63086204c4f689be7fbee3d524e6b8b58dea596e07563c86d2761c1efa +size 3282 diff --git a/assets/mods/basegame/sprites/test_werebeastf/taimu_torso_0.tga b/assets/mods/basegame/sprites/test_werebeastf/taimu_torso_0.tga index 5819493ef..e4265ec2d 100644 --- a/assets/mods/basegame/sprites/test_werebeastf/taimu_torso_0.tga +++ b/assets/mods/basegame/sprites/test_werebeastf/taimu_torso_0.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ca1a9fb8dbe50f10752a95d369f9cbc65b886df7bf6751cacc509b4bf06c61c +oid sha256:be5d3f315173e164f8ae5867a402f52ff436edbd3328a441ad213507fbfb8eb2 size 4310 diff --git a/assets/mods/basegame/sprites/test_werebeastf/taimu_torso_1.tga b/assets/mods/basegame/sprites/test_werebeastf/taimu_torso_1.tga index 9aec029a5..99d94bdad 100644 --- a/assets/mods/basegame/sprites/test_werebeastf/taimu_torso_1.tga +++ b/assets/mods/basegame/sprites/test_werebeastf/taimu_torso_1.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4be477b8ec20bcce725d5bb9f8353a97922b976711810290875e2df4511005a +oid sha256:a831b521fa19d1439c2740c001513aa9fa9fa9bd0e893a96659342d657eab03a size 4310 diff --git a/src/net/torvald/spriteanimation/HasAssembledSprite.kt b/src/net/torvald/spriteanimation/HasAssembledSprite.kt index cb37894d1..33742672e 100644 --- a/src/net/torvald/spriteanimation/HasAssembledSprite.kt +++ b/src/net/torvald/spriteanimation/HasAssembledSprite.kt @@ -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) { diff --git a/src/net/torvald/spriteassembler/ADProperties.kt b/src/net/torvald/spriteassembler/ADProperties.kt index 3a6ae9bfe..6972dfb79 100644 --- a/src/net/torvald/spriteassembler/ADProperties.kt +++ b/src/net/torvald/spriteassembler/ADProperties.kt @@ -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) { 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>() /** list of bodyparts used by all the skeletons (HEAD, UPPER_TORSO, LOWER_TORSO) */ - lateinit var bodyparts: List; private set +// lateinit var bodyparts: List; private set lateinit var bodypartFiles: List; private set /** properties that are being used as skeletons (SKELETON_STAND) */ internal lateinit var skeletons: HashMap; private set + /** properties that defines position of joint of the bodypart */ + internal val bodyparts = HashMap() /** properties that are recognised as animations (ANIM_RUN, ANIM)IDLE) */ internal lateinit var animations: HashMap; private set /** an "animation frame" property (ANIM_RUN_1, ANIM_RUN_2) */ internal lateinit var transforms: HashMap>; 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() val skeletons = HashMap() val animations = HashMap() val animFrames = HashMap() @@ -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 = 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 { diff --git a/src/net/torvald/spriteassembler/AssembleSheetPixmap.kt b/src/net/torvald/spriteassembler/AssembleSheetPixmap.kt index 4b59b2a62..7249f3a3e 100644 --- a/src/net/torvald/spriteassembler/AssembleSheetPixmap.kt +++ b/src/net/torvald/spriteassembler/AssembleSheetPixmap.kt @@ -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(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, + bodypartOrigins: HashMap, + bodypartImages: Map, transformList: List> ) { 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) } } diff --git a/src/net/torvald/spriteassembler/SpriteAssemblerApp.kt b/src/net/torvald/spriteassembler/SpriteAssemblerApp.kt index a4ae58f70..9962e6ec5 100644 --- a/src/net/torvald/spriteassembler/SpriteAssemblerApp.kt +++ b/src/net/torvald/spriteassembler/SpriteAssemblerApp.kt @@ -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 .""".trimMargin() + |along with this program. If not, see . + | + |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) { val appConfig = Lwjgl3ApplicationConfiguration() - appConfig.setWindowedMode(800, 800) + appConfig.setWindowedMode(1024, 1024) appConfig.setIdleFPS(5) appConfig.setForegroundFPS(5) appConfig.setResizable(false) diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index 32a1e8a14..3b1161abb 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -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... } } diff --git a/src/net/torvald/terrarum/serialise/WriteActor.kt b/src/net/torvald/terrarum/serialise/WriteActor.kt index fe3bc4803..b2d4a8a7e 100644 --- a/src/net/torvald/terrarum/serialise/WriteActor.kt +++ b/src/net/torvald/terrarum/serialise/WriteActor.kt @@ -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 diff --git a/work_files/graphics/sprites/npc_template_humanoid_savagef.kra b/work_files/graphics/sprites/npc_template_humanoid_savagef.kra index 803753100..e5978e63d 100644 --- a/work_files/graphics/sprites/npc_template_humanoid_savagef.kra +++ b/work_files/graphics/sprites/npc_template_humanoid_savagef.kra @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6b46b6dbe9496e3e6f0bd24194bac6346c9bed05736450ca8f0b9b2a7edd74d -size 145138 +oid sha256:28ae70a3874483bd1f6433a306dab840a5285ef55fc366f30d8785f0cdcaa850 +size 157317