mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
adproperties now has transforms list; assembler can make transformed skeleton
new fun: LinearSearch(By)
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package net.torvald.spriteassembler
|
package net.torvald.spriteassembler
|
||||||
|
|
||||||
|
import net.torvald.terrarum.linearSearchBy
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -18,19 +19,27 @@ data class Animation(val name: String, val delay: Float, val row: Int, val frame
|
|||||||
override fun toString() = "$name delay: $delay, row: $row, frames: $frames, skeleton: ${skeleton.name}"
|
override fun toString() = "$name delay: $delay, row: $row, frames: $frames, skeleton: ${skeleton.name}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Later the 'translate' can be changed so that it represents affine transformation (Matrix2d) */
|
||||||
|
data class Transform(val joint: Joint, val translate: ADPropertyObject.Vector2i) {
|
||||||
|
override fun toString() = "$joint transform: $translate"
|
||||||
|
fun getTransformVector() = joint.position + translate
|
||||||
|
}
|
||||||
|
|
||||||
class ADProperties {
|
class ADProperties {
|
||||||
private val javaProp = Properties()
|
private val javaProp = Properties()
|
||||||
|
|
||||||
/** Every key is CAPITALISED */
|
/** Every key is CAPITALISED */
|
||||||
private val propTable = HashMap<String, List<ADPropertyObject>>()
|
private val propTable = HashMap<String, List<ADPropertyObject>>()
|
||||||
|
|
||||||
/** list of bodyparts used by all the skeletons */
|
/** 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
|
lateinit var bodypartFiles: List<String>; private set
|
||||||
/** properties that are being used as skeletons */
|
/** properties that are being used as skeletons (SKELETON_STAND) */
|
||||||
lateinit var skeletons: HashMap<String, Skeleton>; private set
|
lateinit var skeletons: HashMap<String, Skeleton>; private set
|
||||||
/** properties that are recognised as animations */
|
/** properties that are recognised as animations (ANIM_RUN, ANIM)IDLE) */
|
||||||
lateinit var animations: HashMap<String, Animation>; private set
|
lateinit var animations: HashMap<String, Animation>; private set
|
||||||
|
/** an "animation frame" property (ANIM_RUN_1, ANIM_RUN_2) */
|
||||||
|
lateinit var transforms: HashMap<String, List<Transform>>; private set
|
||||||
|
|
||||||
private val reservedProps = listOf("SPRITESHEET", "EXTENSION")
|
private val reservedProps = listOf("SPRITESHEET", "EXTENSION")
|
||||||
private val animMustContain = listOf("DELAY", "ROW", "SKELETON")
|
private val animMustContain = listOf("DELAY", "ROW", "SKELETON")
|
||||||
@@ -40,6 +49,8 @@ class ADProperties {
|
|||||||
|
|
||||||
private val animFrameSuffixRegex = Regex("""_[0-9]+""")
|
private val animFrameSuffixRegex = Regex("""_[0-9]+""")
|
||||||
|
|
||||||
|
private val ALL_JOINT = Joint("ALL", ADPropertyObject.Vector2i(0, 0))
|
||||||
|
|
||||||
constructor(reader: Reader) {
|
constructor(reader: Reader) {
|
||||||
javaProp.load(reader)
|
javaProp.load(reader)
|
||||||
continueLoad()
|
continueLoad()
|
||||||
@@ -59,13 +70,14 @@ class ADProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set reserved values for the animation: filename, extension
|
// set reserved values for the animation: filename, extension
|
||||||
baseFilename = get("SPRITESHEET")!![0].variable
|
baseFilename = get("SPRITESHEET")[0].variable
|
||||||
extension = get("EXTENSION")!![0].variable
|
extension = get("EXTENSION")[0].variable
|
||||||
|
|
||||||
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>()
|
||||||
val animFrames = HashMap<String, Int>()
|
val animFrames = HashMap<String, Int>()
|
||||||
|
val transforms = HashMap<String, List<Transform>>()
|
||||||
// scan every props, write down anim frames for later use
|
// scan every props, write down anim frames for later use
|
||||||
propTable.keys.forEach {
|
propTable.keys.forEach {
|
||||||
if (animFrameSuffixRegex.containsMatchIn(it)) {
|
if (animFrameSuffixRegex.containsMatchIn(it)) {
|
||||||
@@ -94,16 +106,16 @@ class ADProperties {
|
|||||||
// if it is indeed anim, populate animations list
|
// if it is indeed anim, populate animations list
|
||||||
if (propsHashMap.containsKey("SKELETON")) {
|
if (propsHashMap.containsKey("SKELETON")) {
|
||||||
val skeletonName = propsHashMap["SKELETON"] as String
|
val skeletonName = propsHashMap["SKELETON"] as String
|
||||||
val skeletonDef = get(skeletonName) ?: throw Error("Skeleton definition for $skeletonName not found")
|
val skeletonDef = get(skeletonName)
|
||||||
|
|
||||||
skeletons.put(skeletonName, Skeleton(skeletonName, skeletonDef.toJoints()))
|
skeletons[skeletonName] = Skeleton(skeletonName, skeletonDef.toJoints())
|
||||||
animations.put(s, Animation(
|
animations[s] = Animation(
|
||||||
s,
|
s,
|
||||||
propsHashMap["DELAY"] as Float,
|
propsHashMap["DELAY"] as Float,
|
||||||
(propsHashMap["ROW"] as Float).toInt(),
|
(propsHashMap["ROW"] as Float).toInt(),
|
||||||
animFrames[s]!!,
|
animFrames[s]!!,
|
||||||
Skeleton(skeletonName, skeletonDef.toJoints())
|
Skeleton(skeletonName, skeletonDef.toJoints())
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,13 +126,44 @@ class ADProperties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// populate transforms
|
||||||
|
animations.forEach { t, u ->
|
||||||
|
for (fc in 1..u.frames) {
|
||||||
|
val frameName = "${t}_$fc"
|
||||||
|
val prop = get(frameName)
|
||||||
|
|
||||||
|
var emptyList = prop.size == 1 && prop[0].variable.isEmpty()
|
||||||
|
|
||||||
|
val transformList = if (!emptyList) {
|
||||||
|
List(prop.size) { index ->
|
||||||
|
val jointNameToSearch = prop[index].variable.toUpperCase()
|
||||||
|
val joint = if (jointNameToSearch == "ALL")
|
||||||
|
ALL_JOINT
|
||||||
|
else
|
||||||
|
u.skeleton.joints.linearSearchBy { it.name == jointNameToSearch }
|
||||||
|
?: throw NullPointerException("No such joint: $jointNameToSearch")
|
||||||
|
val translate = prop[index].input as ADPropertyObject.Vector2i
|
||||||
|
|
||||||
|
Transform(joint, translate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// to make real empty list
|
||||||
|
List(0) { Transform(ALL_JOINT, ADPropertyObject.Vector2i(0, 0)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
transforms[frameName] = transformList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.bodyparts = bodyparts.toList().sorted()
|
this.bodyparts = bodyparts.toList().sorted()
|
||||||
this.skeletons = skeletons
|
this.skeletons = skeletons
|
||||||
this.animations = animations
|
this.animations = animations
|
||||||
this.bodypartFiles = this.bodyparts.map { toFilename(it) }
|
this.bodypartFiles = this.bodyparts.map { toFilename(it) }
|
||||||
|
this.transforms = transforms
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun get(identifier: String) = propTable[identifier.toUpperCase()]
|
operator fun get(identifier: String) = propTable[identifier.toUpperCase()]!!
|
||||||
val keys
|
val keys
|
||||||
get() = propTable.keys
|
get() = propTable.keys
|
||||||
fun containsKey(key: String) = propTable.containsKey(key)
|
fun containsKey(key: String) = propTable.containsKey(key)
|
||||||
@@ -129,14 +172,14 @@ class ADProperties {
|
|||||||
fun toFilename(partName: String) =
|
fun toFilename(partName: String) =
|
||||||
"${this.baseFilename}${partName.toLowerCase()}${this.extension}"
|
"${this.baseFilename}${partName.toLowerCase()}${this.extension}"
|
||||||
|
|
||||||
fun getAnimByFrameName(frameName: String): Animation {
|
fun getAnimByFrameName(frameName: String) = animations[getAnimNameFromFrame(frameName)]!!
|
||||||
return animations[getAnimNameFromFrame(frameName)]!!
|
fun getSkeleton(name: String) = skeletons[name]!!
|
||||||
}
|
fun getTransform(name: String) = transforms[name]!!
|
||||||
|
|
||||||
private fun getAnimNameFromFrame(s: String) = s.substring(0 until s.lastIndexOf('_'))
|
private fun getAnimNameFromFrame(s: String) = s.substring(0 until s.lastIndexOf('_'))
|
||||||
|
|
||||||
private fun List<ADPropertyObject>.toJoints() = List(this.size) {
|
private fun List<ADPropertyObject>.toJoints() = List(this.size) {
|
||||||
Joint(this[it].variable, this[it].input!! as ADPropertyObject.Vector2i)
|
Joint(this[it].variable.toUpperCase(), this[it].input!! as ADPropertyObject.Vector2i)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -167,7 +210,7 @@ class ADPropertyObject(propertyRaw: String) {
|
|||||||
|
|
||||||
if (isADvariable(propertyRaw)) {
|
if (isADvariable(propertyRaw)) {
|
||||||
variable = propPair[0]
|
variable = propPair[0]
|
||||||
val inputStr = propPair[1]!!
|
val inputStr = propPair[1]
|
||||||
|
|
||||||
if (isADivec2(inputStr)) {
|
if (isADivec2(inputStr)) {
|
||||||
type = ADPropertyType.IVEC2
|
type = ADPropertyType.IVEC2
|
||||||
@@ -211,7 +254,9 @@ class ADPropertyObject(propertyRaw: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class Vector2i(var x: Int, var y: Int) {
|
data class Vector2i(var x: Int, var y: Int) {
|
||||||
override fun toString() = "$x, $y"
|
override fun toString() = "($x, $y)"
|
||||||
|
|
||||||
|
operator fun plus(other: Vector2i) = Vector2i(this.x + other.x, this.y + other.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ADPropertyType {
|
enum class ADPropertyType {
|
||||||
|
|||||||
@@ -97,6 +97,14 @@ Remember that 'variables' are contained within 'properties'
|
|||||||
|ROW|variable: float|which row the animation goes in the spritesheet|
|
|ROW|variable: float|which row the animation goes in the spritesheet|
|
||||||
|SKELETON|variable: string_pair|Which skeleton this animation uses
|
|SKELETON|variable: string_pair|Which skeleton this animation uses
|
||||||
|
|
||||||
|
#### Transforms
|
||||||
|
|
||||||
|
Things like ```LEG_RIGHT -1,0``` within ```ANIM_RUN_3``` are called 'Transform'
|
||||||
|
|
||||||
|
|Name|Type|Meaning|
|
||||||
|
|---|---|---|
|
||||||
|
|ALL|variable: ivec2|Shifts (translates) everything by set value|
|
||||||
|
|
||||||
### Notes
|
### Notes
|
||||||
|
|
||||||
* All indices are one-based
|
* All indices are one-based
|
||||||
@@ -104,6 +112,7 @@ Remember that 'variables' are contained within 'properties'
|
|||||||
## Operation
|
## Operation
|
||||||
|
|
||||||
* Each line describes transformation
|
* Each line describes transformation
|
||||||
* Transformation are applied sequentially from left to right. In other words, their order matters. Be wary of the clipping that may occur!
|
* Transformation are applied sequentially from left to right. In other words, their order matters. Be wary of the clipping that may occur! (really?)
|
||||||
* The Field is an identifier the game code -- sprite assembler -- recognises.
|
* The Field is an identifier the game code -- sprite assembler -- recognises.
|
||||||
* The Field of animation's name is the name the game code looks for. Example: ```this.setAnim("ANIM_RUN")```
|
* The Field of animation's name is the name the game code looks for. Example: ```this.setAnim("ANIM_RUN")```
|
||||||
|
* Coord system is Y-Up, meaning Y=0 is the bottommost position.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.torvald.spriteassembler
|
package net.torvald.spriteassembler
|
||||||
|
|
||||||
import net.torvald.terrarum.AppLoader.printdbg
|
import net.torvald.terrarum.linearSearch
|
||||||
import java.awt.Image
|
import java.awt.Image
|
||||||
import java.awt.Toolkit
|
import java.awt.Toolkit
|
||||||
import java.awt.image.BufferedImage
|
import java.awt.image.BufferedImage
|
||||||
@@ -16,6 +16,7 @@ object AssembleFrameAWT {
|
|||||||
operator fun invoke(properties: ADProperties, frameName: String, assembleConfig: AssembleConfig = AssembleConfig()) {
|
operator fun invoke(properties: ADProperties, frameName: String, assembleConfig: 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 bodyparts = Array<Image?>(skeleton.size) {
|
val bodyparts = Array<Image?>(skeleton.size) {
|
||||||
// if file does not exist, null it
|
// if file does not exist, null it
|
||||||
val file = File("assets/" + properties.toFilename(skeleton[it].name))
|
val file = File("assets/" + properties.toFilename(skeleton[it].name))
|
||||||
@@ -33,9 +34,13 @@ object AssembleFrameAWT {
|
|||||||
val canvas = BufferedImage(assembleConfig.fw, assembleConfig.fh, BufferedImage.TYPE_4BYTE_ABGR)
|
val canvas = BufferedImage(assembleConfig.fw, assembleConfig.fh, BufferedImage.TYPE_4BYTE_ABGR)
|
||||||
|
|
||||||
|
|
||||||
//printdbg(this, "==============================")
|
println("Frame name: $frameName")
|
||||||
|
transforms.forEach { println(it) }
|
||||||
properties[frameName].forEach { printdbg(this, it) }
|
println("==========================")
|
||||||
|
println("Transformed skeleton:")
|
||||||
|
AssembleFrameBase.makeTransformList(skeleton, transforms).forEach { (name, transform) ->
|
||||||
|
println("$name transformedOut: $transform")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -46,4 +51,28 @@ object AssembleFrameAWT {
|
|||||||
* @param ox Origin-X, leftmost point being zero
|
* @param ox Origin-X, leftmost point being zero
|
||||||
* @param oy Origin-Y, bottommost point being zero
|
* @param oy Origin-Y, bottommost point being zero
|
||||||
*/
|
*/
|
||||||
data class AssembleConfig(val fw: Int = 48, val fh: Int = 56, val ox: Int = 29, val oy: Int = 0)
|
data class AssembleConfig(val fw: Int = 48, val fh: Int = 56, val ox: Int = 29, val oy: Int = 0)
|
||||||
|
|
||||||
|
object AssembleFrameBase {
|
||||||
|
/**
|
||||||
|
* Returns joints list with tranform applied.
|
||||||
|
* @param skeleton list of joints
|
||||||
|
* @param transform ordered list of transforms should be applied. First come first serve.
|
||||||
|
* @return List of pairs that contains joint name on left, final transform value on right
|
||||||
|
*/
|
||||||
|
fun makeTransformList(joints: List<Joint>, transforms: List<Transform>): List<Pair<String, ADPropertyObject.Vector2i>> {
|
||||||
|
// make our mutable list
|
||||||
|
val transformOutput = ArrayList<Pair<String, ADPropertyObject.Vector2i>>()
|
||||||
|
joints.forEach {
|
||||||
|
transformOutput.add(it.name to it.position)
|
||||||
|
}
|
||||||
|
|
||||||
|
// process transform queue
|
||||||
|
transforms.forEach { transform ->
|
||||||
|
val jointToMoveIndex = transformOutput.linearSearch { it.first == transform.joint.name }!!
|
||||||
|
transformOutput[jointToMoveIndex] = transformOutput[jointToMoveIndex].first to transform.getTransformVector()
|
||||||
|
}
|
||||||
|
|
||||||
|
return transformOutput.toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,10 +26,11 @@ class SpriteAssemblerApp : JFrame() {
|
|||||||
private val panelBodypartsList = JList<String>()
|
private val panelBodypartsList = JList<String>()
|
||||||
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 panelCode = JTextPane()
|
private val panelCode = JTextPane()
|
||||||
private val statBar = JTextArea("Null.")
|
private val statBar = JTextArea("Null.")
|
||||||
|
|
||||||
private var adProperties: ADProperties? = null
|
private lateinit var adProperties: ADProperties
|
||||||
|
|
||||||
private val props = Properties()
|
private val props = Properties()
|
||||||
private val lang = Properties()
|
private val lang = Properties()
|
||||||
@@ -93,12 +94,14 @@ class SpriteAssemblerApp : JFrame() {
|
|||||||
panelBodypartsList.model = DefaultListModel()
|
panelBodypartsList.model = DefaultListModel()
|
||||||
panelImageFilesList.model = DefaultListModel()
|
panelImageFilesList.model = DefaultListModel()
|
||||||
panelSkeletonsList.model = DefaultListModel()
|
panelSkeletonsList.model = DefaultListModel()
|
||||||
|
panelTransformsList.model = DefaultListModel()
|
||||||
|
|
||||||
val panelPartsList = JTabbedPane(JTabbedPane.TOP)
|
val panelPartsList = JTabbedPane(JTabbedPane.TOP)
|
||||||
panelPartsList.add("Animations", JScrollPane(panelAnimationsList))
|
panelPartsList.add("Animations", JScrollPane(panelAnimationsList))
|
||||||
panelPartsList.add("Bodyparts", JScrollPane(panelBodypartsList))
|
panelPartsList.add("Bodyparts", JScrollPane(panelBodypartsList))
|
||||||
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))
|
||||||
|
|
||||||
val panelDataView = JSplitPane(JSplitPane.VERTICAL_SPLIT, JScrollPane(panelProperties), panelPartsList)
|
val panelDataView = JSplitPane(JSplitPane.VERTICAL_SPLIT, JScrollPane(panelProperties), panelPartsList)
|
||||||
|
|
||||||
@@ -116,7 +119,7 @@ class SpriteAssemblerApp : JFrame() {
|
|||||||
|
|
||||||
val propRoot = DefaultMutableTreeNode("Properties")
|
val propRoot = DefaultMutableTreeNode("Properties")
|
||||||
|
|
||||||
adProperties?.forEach { s, list ->
|
adProperties.forEach { s, list ->
|
||||||
// build tree node for the properties display
|
// build tree node for the properties display
|
||||||
val propNode = DefaultMutableTreeNode(s)
|
val propNode = DefaultMutableTreeNode(s)
|
||||||
propRoot.add(propNode)
|
propRoot.add(propNode)
|
||||||
@@ -133,21 +136,25 @@ class SpriteAssemblerApp : JFrame() {
|
|||||||
panelSkeletonsList.model = DefaultListModel()
|
panelSkeletonsList.model = DefaultListModel()
|
||||||
|
|
||||||
// populate animations view
|
// populate animations view
|
||||||
adProperties!!.animations.forEach {
|
adProperties.animations.forEach {
|
||||||
(panelAnimationsList.model as DefaultListModel).addElement("${it.value}")
|
(panelAnimationsList.model as DefaultListModel).addElement("${it.value}")
|
||||||
}
|
}
|
||||||
// populate bodyparts view
|
// populate bodyparts view
|
||||||
adProperties!!.bodyparts.forEach { partName ->
|
adProperties.bodyparts.forEach { partName ->
|
||||||
(panelBodypartsList.model as DefaultListModel).addElement(partName)
|
(panelBodypartsList.model as DefaultListModel).addElement(partName)
|
||||||
}
|
}
|
||||||
// populate image file list view
|
// populate image file list view
|
||||||
adProperties!!.bodypartFiles.forEach { partName ->
|
adProperties.bodypartFiles.forEach { partName ->
|
||||||
(panelImageFilesList.model as DefaultListModel).addElement(partName)
|
(panelImageFilesList.model as DefaultListModel).addElement(partName)
|
||||||
}
|
}
|
||||||
// populate skeletons view
|
// populate skeletons view
|
||||||
adProperties!!.skeletons.forEach {
|
adProperties.skeletons.forEach {
|
||||||
(panelSkeletonsList.model as DefaultListModel).addElement("${it.value}")
|
(panelSkeletonsList.model as DefaultListModel).addElement("${it.value}")
|
||||||
}
|
}
|
||||||
|
// populate transforms view
|
||||||
|
adProperties.transforms.forEach {
|
||||||
|
(panelTransformsList.model as DefaultListModel).addElement("$it")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (fehler: Throwable) {
|
catch (fehler: Throwable) {
|
||||||
displayError("ERROR_PARSE_FAIL", fehler)
|
displayError("ERROR_PARSE_FAIL", fehler)
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ SKELETON_STAND=HEADGEAR 0,32;HAIR_FORE 0,32;\
|
|||||||
|
|
||||||
# skeleton_stand is used for testing purpose
|
# skeleton_stand is used for testing purpose
|
||||||
ANIM_RUN=DELAY 0.15;ROW 2;SKELETON SKELETON_STAND
|
ANIM_RUN=DELAY 0.15;ROW 2;SKELETON SKELETON_STAND
|
||||||
ANIM_RUN_1=LEG_RIGHT 1,-1;LEG_LEFT -1,0
|
ANIM_RUN_1=LEG_RIGHT 1,1;FOOT_RIGHT 1,1;LEG_LEFT -1,0;FOOT_LEFT -1,0
|
||||||
ANIM_RUN_2=ALL 0,-1;LEG_RIGHT 0,1;LEG_LEFT 0,-1
|
ANIM_RUN_2=ALL 0,1;LEG_RIGHT 0,-1;FOOT_RIGHT 0,-1;LEG_LEFT 0,1;FOOT_LEFT 0,1
|
||||||
ANIM_RUN_3=LEG_RIGHT -1,0;LEG_LEFT 1,-1
|
ANIM_RUN_3=LEG_RIGHT -1,0;FOOT_RIGHT -1,0;LEG_LEFT 1,1;FOOT_LEFT 1,1
|
||||||
ANIM_RUN_4=ALL 0,-1;LEG_RIGHT 0,-1;LEG_LEFT 0,1
|
ANIM_RUN_4=ALL 0,1;LEG_RIGHT 0,1;LEG_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=
|
||||||
! ANIM_IDLE_1 will not make any transformation
|
! ANIM_IDLE_1 will not make any transformation
|
||||||
ANIM_IDLE_2=UPPER_TORSO 0,-1
|
ANIM_IDLE_2=UPPER_TORSO 0,-1;HEAD 0,-1;ARM_REST_LEFT 0,-1;HAND_REST_LEFT 0,-1;ARM_REST_RIGHT 0,-1;HAND_REST_RIGHT 0,-1
|
||||||
|
|||||||
@@ -724,3 +724,18 @@ fun interpolateLinear(scale: Double, startValue: Double, endValue: Double): Doub
|
|||||||
}
|
}
|
||||||
return (1.0 - scale) * startValue + scale * endValue
|
return (1.0 - scale) * startValue + scale * endValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> List<T>.linearSearch(selector: (T) -> Boolean): Int? {
|
||||||
|
this.forEachIndexed { index, it ->
|
||||||
|
if (selector.invoke(it)) return index
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
fun <T> List<T>.linearSearchBy(selector: (T) -> Boolean): T? {
|
||||||
|
this.forEach {
|
||||||
|
if (selector.invoke(it)) return it
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,15 +32,15 @@ class ADLParsingTest {
|
|||||||
|
|
||||||
# skeleton_stand is used for testing purpose
|
# skeleton_stand is used for testing purpose
|
||||||
ANIM_RUN=DELAY 0.15;ROW 2;SKELETON SKELETON_STAND
|
ANIM_RUN=DELAY 0.15;ROW 2;SKELETON SKELETON_STAND
|
||||||
ANIM_RUN_1=LEG_RIGHT 1,-1;LEG_LEFT -1,0
|
ANIM_RUN_1=LEG_RIGHT 1,1;FOOT_RIGHT 1,1;LEG_LEFT -1,0;FOOT_LEFT -1,0
|
||||||
ANIM_RUN_2=ALL 0,-1;LEG_RIGHT 0,1;LEG_LEFT 0,-1
|
ANIM_RUN_2=ALL 0,1;LEG_RIGHT 0,-1;FOOT_RIGHT 0,-1;LEG_LEFT 0,1;FOOT_LEFT 0,1
|
||||||
ANIM_RUN_3=LEG_RIGHT -1,0;LEG_LEFT 1,-1
|
ANIM_RUN_3=LEG_RIGHT -1,0;FOOT_RIGHT -1,0;LEG_LEFT 1,1;FOOT_LEFT 1,1
|
||||||
ANIM_RUN_4=ALL 0,-1;LEG_RIGHT 0,-1;LEG_LEFT 0,1
|
ANIM_RUN_4=ALL 0,1;LEG_RIGHT 0,1;LEG_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=
|
||||||
! ANIM_IDLE_1 will not make any transformation
|
! ANIM_IDLE_1 will not make any transformation
|
||||||
ANIM_IDLE_2=UPPER_TORSO 0,-1
|
ANIM_IDLE_2=UPPER_TORSO 0,-1;HEAD 0,-1;ARM_REST_LEFT 0,-1;HAND_REST_LEFT 0,-1;ARM_REST_RIGHT 0,-1;HAND_REST_RIGHT 0,-1
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
operator fun invoke() {
|
operator fun invoke() {
|
||||||
|
|||||||
@@ -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.AssembleFrameGdxPixmap
|
import net.torvald.spriteassembler.AssembleFrameAWT
|
||||||
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))
|
||||||
AssembleFrameGdxPixmap.invoke(properties, "ANIM_RUN_1")
|
AssembleFrameAWT.invoke(properties, "ANIM_RUN_1")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user