From 7a70ab32c98441f3bc8f6b2af830332bb3f5cf79 Mon Sep 17 00:00:00 2001 From: Daniel Wolf Date: Tue, 10 Apr 2018 22:04:19 +0200 Subject: [PATCH 1/3] Show stack trace for internal exceptions --- .../rhubarb_for_spine/AudioFileModel.kt | 12 +++++------ .../rhubarb_for_spine/EndUserException.kt | 4 ++++ .../rhubarb_for_spine/MainModel.kt | 6 +++--- .../rhubarb_for_spine/RhubarbTask.kt | 10 +++++----- .../rhubarb_for_spine/SpineJson.kt | 20 +++++++++---------- .../rhubarb_for_spine/tools.kt | 12 +++++++---- 6 files changed, 36 insertions(+), 28 deletions(-) create mode 100644 extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/EndUserException.kt diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AudioFileModel.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AudioFileModel.kt index fa293ba..bf46277 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AudioFileModel.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AudioFileModel.kt @@ -162,21 +162,21 @@ class AudioFileModel( } } catch (e: InterruptedException) { } catch (e: Exception) { - e.printStackTrace(System.err); + e.printStackTrace(System.err) Platform.runLater { Alert(Alert.AlertType.ERROR).apply { headerText = "Error performing lip sync for event '$eventName'." - contentText = if (e.message.isNullOrEmpty()) - // Some exceptions don't have a message - "An internal error of type ${e.javaClass.name} occurred." - else + contentText = if (e is EndUserException) e.message + else + ("An internal error occurred.\n" + + "Please report an issue, including the following information.\n" + + getStackTrace(e)) show() } } } - } future = executor.submit(wrapperTask) } diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/EndUserException.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/EndUserException.kt new file mode 100644 index 0000000..dc79066 --- /dev/null +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/EndUserException.kt @@ -0,0 +1,4 @@ +package com.rhubarb_lip_sync.rhubarb_for_spine + +// An exception with a human-readable message that can be shown to the end user +class EndUserException(message: String): Exception(message) \ No newline at end of file diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MainModel.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MainModel.kt index ffe55e9..82b1686 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MainModel.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MainModel.kt @@ -15,18 +15,18 @@ class MainModel(private val executor: ExecutorService) { filePathError = getExceptionMessage { animationFileModel = null if (value.isNullOrBlank()) { - throw Exception("No input file specified.") + throw EndUserException("No input file specified.") } val path = try { val trimmed = value.removeSurrounding("\"") Paths.get(trimmed) } catch (e: InvalidPathException) { - throw Exception("Not a valid file path.") + throw EndUserException("Not a valid file path.") } if (!Files.exists(path)) { - throw Exception("File does not exist.") + throw EndUserException("File does not exist.") } animationFileModel = AnimationFileModel(this, path, executor) diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/RhubarbTask.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/RhubarbTask.kt index d0e24a7..29bb34d 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/RhubarbTask.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/RhubarbTask.kt @@ -24,7 +24,7 @@ class RhubarbTask( throw InterruptedException() } if (!Files.exists(audioFilePath)) { - throw IllegalArgumentException("File '$audioFilePath' does not exist."); + throw EndUserException("File '$audioFilePath' does not exist."); } val dialogFile = if (dialog != null) TemporaryTextFile(dialog) else null @@ -50,7 +50,7 @@ class RhubarbTask( return parseRhubarbResult(resultString) } "failure" -> { - throw Exception(message.string("reason")) + throw EndUserException(message.string("reason") ?: "Rhubarb failed without reason.") } } } @@ -58,13 +58,13 @@ class RhubarbTask( process.destroyForcibly() throw e } catch (e: EOFException) { - throw Exception("Rhubarb terminated unexpectedly.") + throw EndUserException("Rhubarb terminated unexpectedly.") } finally { process.waitFor(); } }} - throw Exception("An unexpected error occurred.") + throw EndUserException("Audio file processing terminated in an unexpected way.") } private fun parseRhubarbResult(jsonString: String): List { @@ -118,7 +118,7 @@ class RhubarbTask( } currentDirectory = currentDirectory.parent } - throw Exception("Could not find Rhubarb Lip Sync executable '$rhubarbBinName'." + throw EndUserException("Could not find Rhubarb Lip Sync executable '$rhubarbBinName'." + " Expected to find it in '$guiBinDirectory' or any directory above.") } diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt index d351019..f59df1e 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt @@ -14,16 +14,16 @@ class SpineJson(val filePath: Path) { init { if (!Files.exists(filePath)) { - throw Exception("File '$filePath' does not exist.") + throw EndUserException("File '$filePath' does not exist.") } try { json = Parser().parse(filePath.toString()) as JsonObject } catch (e: Exception) { - throw Exception("Wrong file format. This is not a valid JSON file.") + throw EndUserException("Wrong file format. This is not a valid JSON file.") } - skeleton = json.obj("skeleton") ?: throw Exception("JSON file is corrupted.") - val skins = json.obj("skins") ?: throw Exception("JSON file doesn't contain skins.") - defaultSkin = skins.obj("default") ?: throw Exception("JSON file doesn't have a default skin.") + skeleton = json.obj("skeleton") ?: throw EndUserException("JSON file is corrupted.") + val skins = json.obj("skins") ?: throw EndUserException("JSON file doesn't contain skins.") + defaultSkin = skins.obj("default") ?: throw EndUserException("JSON file doesn't have a default skin.") validateProperties() } @@ -34,12 +34,12 @@ class SpineJson(val filePath: Path) { val imagesDirectoryPath: Path get() { val relativeImagesDirectory = skeleton.string("images") - ?: throw Exception("JSON file is incomplete: Images path is missing." + ?: throw EndUserException("JSON file is incomplete: Images path is missing." + "Make sure to check 'Nonessential data' when exporting.") val imagesDirectoryPath = fileDirectoryPath.resolve(relativeImagesDirectory).normalize() if (!Files.exists(imagesDirectoryPath)) { - throw Exception("Could not find images directory relative to the JSON file." + throw EndUserException("Could not find images directory relative to the JSON file." + " Make sure the JSON file is in the same directory as the original Spine file.") } @@ -48,12 +48,12 @@ class SpineJson(val filePath: Path) { val audioDirectoryPath: Path get() { val relativeAudioDirectory = skeleton.string("audio") - ?: throw Exception("JSON file is incomplete: Audio path is missing." + ?: throw EndUserException("JSON file is incomplete: Audio path is missing." + "Make sure to check 'Nonessential data' when exporting.") val audioDirectoryPath = fileDirectoryPath.resolve(relativeAudioDirectory).normalize() if (!Files.exists(audioDirectoryPath)) { - throw Exception("Could not find audio directory relative to the JSON file." + throw EndUserException("Could not find audio directory relative to the JSON file." + " Make sure the JSON file is in the same directory as the original Spine file.") } @@ -80,7 +80,7 @@ class SpineJson(val filePath: Path) { val events = json.obj("events") ?: JsonObject() val result = mutableListOf() for ((name, value) in events) { - if (value !is JsonObject) throw Exception("Invalid event found.") + if (value !is JsonObject) throw EndUserException("Invalid event found.") val relativeAudioFilePath = value.string("audio") ?: continue diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/tools.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/tools.kt index c5811c0..b8cacbd 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/tools.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/tools.kt @@ -2,11 +2,10 @@ package com.rhubarb_lip_sync.rhubarb_for_spine import javafx.application.Platform import javafx.beans.property.Property -import java.util.concurrent.ExecutionException -import java.util.concurrent.locks.Condition import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock - +import java.io.PrintWriter +import java.io.StringWriter val List.commonPrefix: String get() { return if (isEmpty()) "" else this.reduce { result, string -> result.commonPrefixWith(string) } @@ -36,7 +35,6 @@ fun getExceptionMessage(action: () -> Unit): String? { return null } - /** * Invokes a Runnable on the JFX thread and waits until it's finished. * Similar to SwingUtilities.invokeAndWait. @@ -68,4 +66,10 @@ fun runAndWait(action: () -> Unit) { throwable?.let { throw it } } } +} + +fun getStackTrace(e: Exception): String { + val stringWriter = StringWriter() + e.printStackTrace(PrintWriter(stringWriter)) + return stringWriter.toString() } \ No newline at end of file From 1784458931ba4e92f28c2ff323448611c464e313 Mon Sep 17 00:00:00 2001 From: Daniel Wolf Date: Tue, 10 Apr 2018 22:30:17 +0200 Subject: [PATCH 2/3] Use mutable set for animation names See https://youtrack.jetbrains.com/issue/KT-9959 Fixes #34 (again) --- VERSION.md | 4 ++++ .../com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index 04cc1c9..6644f35 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1,5 +1,9 @@ # Version history +## Unreleased + +* Fixed bug in Rhubarb for Spine where processing failed depending on the number of existing animations. See [issue #34](https://github.com/DanielSWolf/rhubarb-lip-sync/issues/34#issuecomment-378198776). + ## Version 1.7.1 * Fixed [issue #34](https://github.com/DanielSWolf/rhubarb-lip-sync/issues/34): Generic error message in Rhubarb for Spine diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt index f59df1e..f87d028 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt @@ -96,7 +96,7 @@ class SpineJson(val filePath: Path) { } val animationNames = observableSet( - json.obj("animations")?.map{ it.key }?.toSet() ?: setOf() + json.obj("animations")?.map{ it.key }?.toMutableSet() ?: mutableSetOf() ) fun createOrUpdateAnimation(mouthCues: List, eventName: String, animationName: String, From 8f2cc2c5e68a5f69b10973d8ad5ca3fa00073dff Mon Sep 17 00:00:00 2001 From: Daniel Wolf Date: Tue, 10 Apr 2018 22:51:28 +0200 Subject: [PATCH 3/3] Small type fixes and cleanup --- .../rhubarb_for_spine/AnimationFileModel.kt | 33 +++++++++---------- .../rhubarb_for_spine/AudioFileModel.kt | 16 ++++----- .../rhubarb_for_spine/MainModel.kt | 8 ++--- .../rhubarb_for_spine/MouthNaming.kt | 2 +- .../rhubarb_for_spine/MouthShape.kt | 2 +- .../rhubarb_for_spine/RhubarbTask.kt | 4 +-- .../rhubarb_for_spine/SpineJson.kt | 8 ++--- .../rhubarb_for_spine/tools.kt | 2 +- 8 files changed, 35 insertions(+), 40 deletions(-) diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AnimationFileModel.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AnimationFileModel.kt index 630b055..1f5c884 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AnimationFileModel.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AnimationFileModel.kt @@ -16,41 +16,41 @@ class AnimationFileModel(val parentModel: MainModel, animationFilePath: Path, pr val spineJson = SpineJson(animationFilePath) val slotsProperty = SimpleObjectProperty>() - var slots by slotsProperty - private set + private var slots: ObservableList by slotsProperty val mouthSlotProperty: SimpleStringProperty = SimpleStringProperty().alsoListen { - mouthNaming = if (mouthSlot != null) + val mouthSlot = this.mouthSlot + val mouthNaming = if (mouthSlot != null) MouthNaming.guess(spineJson.getSlotAttachmentNames(mouthSlot)) else null + this.mouthNaming = mouthNaming - mouthShapes = if (mouthSlot != null) { + mouthShapes = if (mouthSlot != null && mouthNaming != null) { val mouthNames = spineJson.getSlotAttachmentNames(mouthSlot) MouthShape.values().filter { mouthNames.contains(mouthNaming.getName(it)) } } else listOf() - mouthSlotError = if (mouthSlot != null) null - else "No slot with mouth drawings specified." + mouthSlotError = if (mouthSlot != null) + null + else + "No slot with mouth drawings specified." } - var mouthSlot by mouthSlotProperty + private var mouthSlot: String? by mouthSlotProperty val mouthSlotErrorProperty = SimpleStringProperty() - var mouthSlotError by mouthSlotErrorProperty - private set + private var mouthSlotError: String? by mouthSlotErrorProperty val mouthNamingProperty = SimpleObjectProperty() - var mouthNaming by mouthNamingProperty - private set + private var mouthNaming: MouthNaming? by mouthNamingProperty val mouthShapesProperty = SimpleObjectProperty>().alsoListen { mouthShapesError = getMouthShapesErrorString() } - var mouthShapes by mouthShapesProperty + var mouthShapes: List by mouthShapesProperty private set val mouthShapesErrorProperty = SimpleStringProperty() - var mouthShapesError by mouthShapesErrorProperty - private set + private var mouthShapesError: String? by mouthShapesErrorProperty val audioFileModelsProperty = SimpleListProperty( spineJson.audioEvents @@ -63,7 +63,7 @@ class AnimationFileModel(val parentModel: MainModel, animationFilePath: Path, pr } .observable() ) - val audioFileModels by audioFileModelsProperty + val audioFileModels: ObservableList by audioFileModelsProperty val busyProperty = SimpleBooleanProperty().apply { bind(object : BooleanBinding() { @@ -90,10 +90,9 @@ class AnimationFileModel(val parentModel: MainModel, animationFilePath: Path, pr } }) } - val valid by validProperty private fun saveAnimation(animationName: String, audioEventName: String, mouthCues: List) { - spineJson.createOrUpdateAnimation(mouthCues, audioEventName, animationName, mouthSlot, mouthNaming) + spineJson.createOrUpdateAnimation(mouthCues, audioEventName, animationName, mouthSlot!!, mouthNaming!!) spineJson.save() } diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AudioFileModel.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AudioFileModel.kt index bf46277..e9f41c6 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AudioFileModel.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/AudioFileModel.kt @@ -11,6 +11,7 @@ import javafx.scene.control.Alert import javafx.scene.control.ButtonType import tornadofx.getValue import tornadofx.setValue +import java.nio.file.Path import java.util.concurrent.ExecutorService import java.util.concurrent.Future @@ -20,15 +21,14 @@ class AudioFileModel( private val executor: ExecutorService, private val reportResult: (List) -> Unit ) { - val spineJson = parentModel.spineJson + private val spineJson = parentModel.spineJson - val audioFilePath = spineJson.audioDirectoryPath.resolve(audioEvent.relativeAudioFilePath) + private val audioFilePath: Path = spineJson.audioDirectoryPath.resolve(audioEvent.relativeAudioFilePath) val eventNameProperty = SimpleStringProperty(audioEvent.name) - val eventName by eventNameProperty + val eventName: String by eventNameProperty val displayFilePathProperty = SimpleStringProperty(audioEvent.relativeAudioFilePath) - val displayFilePath by displayFilePathProperty val animationNameProperty = SimpleStringProperty().apply { val mainModel = parentModel.parentModel @@ -45,13 +45,13 @@ class AudioFileModel( } }) } - val animationName by animationNameProperty + val animationName: String by animationNameProperty val dialogProperty = SimpleStringProperty(audioEvent.dialog) - val dialog: String? by dialogProperty + private val dialog: String? by dialogProperty val animationProgressProperty = SimpleObjectProperty(null) - var animationProgress by animationProgressProperty + var animationProgress: Double? by animationProgressProperty private set private val animatedProperty = SimpleBooleanProperty().apply { @@ -92,7 +92,6 @@ class AudioFileModel( } }) } - val audioFileState by audioFileStateProperty val busyProperty = SimpleBooleanProperty().apply { bind(object : BooleanBinding() { @@ -120,7 +119,6 @@ class AudioFileModel( } }) } - val actionLabel by actionLabelProperty fun performAction() { if (future == null) { diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MainModel.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MainModel.kt index 82b1686..9010146 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MainModel.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MainModel.kt @@ -32,21 +32,19 @@ class MainModel(private val executor: ExecutorService) { animationFileModel = AnimationFileModel(this, path, executor) } } - var filePathString by filePathStringProperty val filePathErrorProperty = SimpleStringProperty() - var filePathError by filePathErrorProperty - private set + private var filePathError: String? by filePathErrorProperty val animationFileModelProperty = SimpleObjectProperty() var animationFileModel by animationFileModelProperty private set val animationPrefixProperty = SimpleStringProperty("say_") - var animationPrefix by animationPrefixProperty + var animationPrefix: String by animationPrefixProperty val animationSuffixProperty = SimpleStringProperty("") - var animationSuffix by animationSuffixProperty + var animationSuffix: String by animationSuffixProperty private fun getDefaultPathString() = FX.application.parameters.raw.firstOrNull() } \ No newline at end of file diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MouthNaming.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MouthNaming.kt index 8b6416b..c49b55c 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MouthNaming.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MouthNaming.kt @@ -2,7 +2,7 @@ package com.rhubarb_lip_sync.rhubarb_for_spine import java.util.* -class MouthNaming(val prefix: String, val suffix: String, val mouthShapeCasing: MouthShapeCasing) { +class MouthNaming(private val prefix: String, private val suffix: String, private val mouthShapeCasing: MouthShapeCasing) { companion object { fun guess(mouthNames: List): MouthNaming { diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MouthShape.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MouthShape.kt index de6410d..2e4dcd1 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MouthShape.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/MouthShape.kt @@ -10,7 +10,7 @@ enum class MouthShape { get() = !this.isBasic companion object { - val basicShapeCount = 6 + const val basicShapeCount = 6 val basicShapes = MouthShape.values().take(basicShapeCount) diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/RhubarbTask.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/RhubarbTask.kt index 29bb34d..0268003 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/RhubarbTask.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/RhubarbTask.kt @@ -24,7 +24,7 @@ class RhubarbTask( throw InterruptedException() } if (!Files.exists(audioFilePath)) { - throw EndUserException("File '$audioFilePath' does not exist."); + throw EndUserException("File '$audioFilePath' does not exist.") } val dialogFile = if (dialog != null) TemporaryTextFile(dialog) else null @@ -60,7 +60,7 @@ class RhubarbTask( } catch (e: EOFException) { throw EndUserException("Rhubarb terminated unexpectedly.") } finally { - process.waitFor(); + process.waitFor() } }} diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt index f87d028..2fe77b8 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/SpineJson.kt @@ -6,9 +6,9 @@ import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Path -class SpineJson(val filePath: Path) { - val fileDirectoryPath: Path = filePath.parent - val json: JsonObject +class SpineJson(private val filePath: Path) { + private val fileDirectoryPath: Path = filePath.parent + private val json: JsonObject private val skeleton: JsonObject private val defaultSkin: JsonObject @@ -32,7 +32,7 @@ class SpineJson(val filePath: Path) { audioDirectoryPath } - val imagesDirectoryPath: Path get() { + private val imagesDirectoryPath: Path get() { val relativeImagesDirectory = skeleton.string("images") ?: throw EndUserException("JSON file is incomplete: Images path is missing." + "Make sure to check 'Nonessential data' when exporting.") diff --git a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/tools.kt b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/tools.kt index b8cacbd..fee86f5 100644 --- a/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/tools.kt +++ b/extras/EsotericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/tools.kt @@ -28,7 +28,7 @@ fun > TProperty.alsoListen(listener: (TValu fun getExceptionMessage(action: () -> Unit): String? { try { - action(); + action() } catch (e: Exception) { return e.message }