diff --git a/CHANGELOG.md b/CHANGELOG.md index f041ecd..bb9326b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +* **Added** support for skinning in Rhubarb for Spine ([issue #108](https://github.com/DanielSWolf/rhubarb-lip-sync/issues/108)) + ## Version 1.11.0 * **Added** support for more WAVE file features ([issue #101](https://github.com/DanielSWolf/rhubarb-lip-sync/issues/101)) diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/SpineJson.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/SpineJson.kt index 22d4bef..e8f5d41 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/SpineJson.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/SpineJson.kt @@ -10,7 +10,6 @@ class SpineJson(private val filePath: Path) { private val fileDirectoryPath: Path = filePath.parent private val json: JsonObject private val skeleton: JsonObject - private val defaultSkin: JsonObject init { if (!Files.exists(filePath)) { @@ -22,12 +21,6 @@ class SpineJson(private val filePath: Path) { throw EndUserException("Wrong file format. This is not a valid JSON file.") } skeleton = json.obj("skeleton") ?: throw EndUserException("JSON file is corrupted.") - val skins = json["skins"] ?: throw EndUserException("JSON file doesn't contain skins.") - defaultSkin = when (skins) { - is JsonObject -> skins.obj("default") - is JsonArray<*> -> (skins as JsonArray).find { it.string("name") == "default" } - else -> null - } ?: throw EndUserException("JSON file doesn't have a default skin.") validateProperties() } @@ -96,10 +89,21 @@ class SpineJson(private val filePath: Path) { } fun getSlotAttachmentNames(slotName: String): List { - val attachments = defaultSkin.obj(slotName) - ?: defaultSkin.obj("attachments")?.obj(slotName) - ?: JsonObject() - return attachments.map { it.key } + @Suppress("UNCHECKED_CAST") + val skins: Collection = when (val skinsObject = json["skins"]) { + is JsonObject -> skinsObject.values as Collection + is JsonArray<*> -> skinsObject as Collection + else -> emptyList() + } + + // Get attachment names for all skins + return skins + .flatMap { skin -> + skin.obj(slotName)?.keys?.toList() + ?: skin.obj("attachments")?.obj(slotName)?.keys?.toList() + ?: emptyList() + } + .distinct() } val animationNames = observableSet( @@ -156,4 +160,4 @@ class SpineJson(private val filePath: Path) { fun save() { Files.write(filePath, listOf(toString()), StandardCharsets.UTF_8) } -} \ No newline at end of file +}