Allowing the animation naming to be customized
This commit is contained in:
parent
ce54ba60a7
commit
5db03da56f
|
@ -12,7 +12,7 @@ import tornadofx.observable
|
|||
import tornadofx.setValue
|
||||
import java.util.concurrent.ExecutorService
|
||||
|
||||
class AnimationFileModel(animationFilePath: Path, private val executor: ExecutorService) {
|
||||
class AnimationFileModel(val parentModel: MainModel, animationFilePath: Path, private val executor: ExecutorService) {
|
||||
val spineJson = SpineJson(animationFilePath)
|
||||
|
||||
val slotsProperty = SimpleObjectProperty<ObservableList<String>>()
|
||||
|
@ -55,7 +55,11 @@ class AnimationFileModel(animationFilePath: Path, private val executor: Executor
|
|||
val audioFileModelsProperty = SimpleListProperty<AudioFileModel>(
|
||||
spineJson.audioEvents
|
||||
.map { event ->
|
||||
AudioFileModel(event, this, executor, { result -> saveAnimation(result, event.name) })
|
||||
var audioFileModel: AudioFileModel? = null
|
||||
val reportResult: (List<MouthCue>) -> Unit =
|
||||
{ result -> saveAnimation(audioFileModel!!.animationName, event.name, result) }
|
||||
audioFileModel = AudioFileModel(event, this, executor, reportResult)
|
||||
return@map audioFileModel
|
||||
}
|
||||
.observable()
|
||||
)
|
||||
|
@ -88,14 +92,11 @@ class AnimationFileModel(animationFilePath: Path, private val executor: Executor
|
|||
}
|
||||
val valid by validProperty
|
||||
|
||||
private fun saveAnimation(mouthCues: List<MouthCue>, audioEventName: String) {
|
||||
val animationName = getAnimationName(audioEventName)
|
||||
private fun saveAnimation(animationName: String, audioEventName: String, mouthCues: List<MouthCue>) {
|
||||
spineJson.createOrUpdateAnimation(mouthCues, audioEventName, animationName, mouthSlot, mouthNaming)
|
||||
spineJson.save()
|
||||
}
|
||||
|
||||
private fun getAnimationName(audioEventName: String): String = "say_$audioEventName"
|
||||
|
||||
init {
|
||||
slots = spineJson.slots.observable()
|
||||
mouthSlot = spineJson.guessMouthSlot()
|
||||
|
|
|
@ -29,6 +29,23 @@ class AudioFileModel(
|
|||
val displayFilePathProperty = SimpleStringProperty(audioEvent.relativeAudioFilePath)
|
||||
val displayFilePath by displayFilePathProperty
|
||||
|
||||
val animationNameProperty = SimpleStringProperty().apply {
|
||||
val mainModel = parentModel.parentModel
|
||||
bind(object : ObjectBinding<String>() {
|
||||
init {
|
||||
super.bind(
|
||||
mainModel.animationPrefixProperty,
|
||||
eventNameProperty,
|
||||
mainModel.animationSuffixProperty
|
||||
)
|
||||
}
|
||||
override fun computeValue(): String {
|
||||
return mainModel.animationPrefix + eventName + mainModel.animationSuffix
|
||||
}
|
||||
})
|
||||
}
|
||||
val animationName by animationNameProperty
|
||||
|
||||
val dialogProperty = SimpleStringProperty(audioEvent.dialog)
|
||||
val dialog: String? by dialogProperty
|
||||
|
||||
|
@ -36,8 +53,17 @@ class AudioFileModel(
|
|||
var animationProgress by animationProgressProperty
|
||||
private set
|
||||
|
||||
private val animatedPreviouslyProperty = SimpleBooleanProperty(false) // TODO: Initial value
|
||||
private var animatedPreviously by animatedPreviouslyProperty
|
||||
private val animatedProperty = SimpleBooleanProperty().apply {
|
||||
bind(object : ObjectBinding<Boolean>() {
|
||||
init {
|
||||
super.bind(animationNameProperty, parentModel.spineJson.animationNames)
|
||||
}
|
||||
override fun computeValue(): Boolean {
|
||||
return parentModel.spineJson.animationNames.contains(animationName)
|
||||
}
|
||||
})
|
||||
}
|
||||
private var animated by animatedProperty
|
||||
|
||||
private val futureProperty = SimpleObjectProperty<Future<*>?>()
|
||||
private var future by futureProperty
|
||||
|
@ -45,7 +71,7 @@ class AudioFileModel(
|
|||
private val audioFileStateProperty = SimpleObjectProperty<AudioFileState>().apply {
|
||||
bind(object : ObjectBinding<AudioFileState>() {
|
||||
init {
|
||||
super.bind(animatedPreviouslyProperty, futureProperty, animationProgressProperty)
|
||||
super.bind(animatedProperty, futureProperty, animationProgressProperty)
|
||||
}
|
||||
override fun computeValue(): AudioFileState {
|
||||
return if (future != null) {
|
||||
|
@ -57,7 +83,7 @@ class AudioFileModel(
|
|||
else
|
||||
AudioFileState(AudioFileStatus.Pending)
|
||||
} else {
|
||||
if (animatedPreviously)
|
||||
if (animated)
|
||||
AudioFileState(AudioFileStatus.Done)
|
||||
else
|
||||
AudioFileState(AudioFileStatus.NotAnimated)
|
||||
|
@ -133,7 +159,6 @@ class AudioFileModel(
|
|||
val result = rhubarbTask.call()
|
||||
runAndWait {
|
||||
reportResult(result)
|
||||
animatedPreviously = true
|
||||
}
|
||||
} finally {
|
||||
runAndWait {
|
||||
|
|
|
@ -29,7 +29,7 @@ class MainModel(private val executor: ExecutorService) {
|
|||
throw Exception("File does not exist.")
|
||||
}
|
||||
|
||||
animationFileModel = AnimationFileModel(path, executor)
|
||||
animationFileModel = AnimationFileModel(this, path, executor)
|
||||
}
|
||||
}
|
||||
var filePathString by filePathStringProperty
|
||||
|
@ -42,5 +42,11 @@ class MainModel(private val executor: ExecutorService) {
|
|||
var animationFileModel by animationFileModelProperty
|
||||
private set
|
||||
|
||||
val animationPrefixProperty = SimpleStringProperty("say_")
|
||||
var animationPrefix by animationPrefixProperty
|
||||
|
||||
val animationSuffixProperty = SimpleStringProperty("")
|
||||
var animationSuffix by animationSuffixProperty
|
||||
|
||||
private fun getDefaultPathString() = FX.application.parameters.raw.firstOrNull()
|
||||
}
|
|
@ -71,6 +71,17 @@ class MainView : View() {
|
|||
errorProperty().bind(fileModelProperty.select { it!!.mouthShapesErrorProperty })
|
||||
}
|
||||
}
|
||||
field("Animation naming") {
|
||||
textfield {
|
||||
maxWidth = 100.0
|
||||
textProperty().bindBidirectional(mainModel.animationPrefixProperty)
|
||||
}
|
||||
label("<audio event name>")
|
||||
textfield {
|
||||
maxWidth = 100.0
|
||||
textProperty().bindBidirectional(mainModel.animationSuffixProperty)
|
||||
}
|
||||
}
|
||||
}
|
||||
fieldset("Audio events") {
|
||||
tableview<AudioFileModel> {
|
||||
|
@ -78,6 +89,8 @@ class MainView : View() {
|
|||
columnResizePolicy = SmartResize.POLICY
|
||||
column("Event", AudioFileModel::eventNameProperty)
|
||||
.weigthedWidth(1.0)
|
||||
column("Animation name", AudioFileModel::animationNameProperty)
|
||||
.weigthedWidth(1.0)
|
||||
column("Audio file", AudioFileModel::displayFilePathProperty)
|
||||
.weigthedWidth(1.0)
|
||||
column("Dialog", AudioFileModel::dialogProperty).apply {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.rhubarb_lip_sync.rhubarb_for_spine
|
||||
|
||||
import com.beust.klaxon.*
|
||||
import javafx.collections.FXCollections.observableSet
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
@ -94,10 +95,9 @@ class SpineJson(val filePath: Path) {
|
|||
return attachments.map { it.key }
|
||||
}
|
||||
|
||||
fun hasAnimation(animationName: String): Boolean {
|
||||
val animations = json.obj("animations") ?: return false
|
||||
return animations.any { it.key == animationName }
|
||||
}
|
||||
val animationNames = observableSet<String>(
|
||||
json.obj("animations")?.map{ it.key }?.toSet() ?: setOf()
|
||||
)
|
||||
|
||||
fun createOrUpdateAnimation(mouthCues: List<MouthCue>, eventName: String, animationName: String,
|
||||
mouthSlot: String, mouthNaming: MouthNaming
|
||||
|
@ -138,6 +138,8 @@ class SpineJson(val filePath: Path) {
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
animationNames.add(animationName)
|
||||
}
|
||||
|
||||
fun save() {
|
||||
|
|
Loading…
Reference in New Issue