commonMain.ru.casperix.spine.animation.FrameCalculator.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spine-jvm Show documentation
Show all versions of spine-jvm Show documentation
Signals for all occasions
package ru.casperix.spine.animation
import ru.casperix.math.interpolation.float32.linearInterpolatef
import ru.casperix.spine.MixBlend
object FrameCalculator {
fun getRelativeValue(
frames: List,
time: Float,
weight: Float,
blend: MixBlend,
currentValue: Float,
poseValue: Float,
isScaleMode: Boolean
): Float {
frames.forEachIndexed { index, nextFrame ->
if (time > nextFrame.time && index < frames.lastIndex) return@forEachIndexed
val lastFrame = frames.getOrNull(index - 1)
if (lastFrame == null || time < 0f) {
return poseValue
}
return interpolateByFrames(time, lastFrame, nextFrame, weight, blend, currentValue, poseValue, isScaleMode)
}
return currentValue
}
private fun interpolateByFrames(
time: Float,
lastFrame: ChannelFrame,
nextFrame: ChannelFrame,
weight: Float,
blend: MixBlend,
currentValue: Float,
poseValue: Float,
isScaleMode: Boolean
): Float {
val normalizedTime = time.coerceIn(lastFrame.time, nextFrame.time)
val timeFactor = (normalizedTime - lastFrame.time) / (nextFrame.time - lastFrame.time)
val summaryValue = when (val type = lastFrame.curve) {
is BezierCurve -> {
type.getValue(lastFrame, nextFrame, normalizedTime)
}
is LinearCurve -> {
val lastValue = lastFrame.value
val nextValue = nextFrame.value
linearInterpolatef(lastValue, nextValue, timeFactor)
}
is SteppedCurve -> {
val isTimeout = time >= nextFrame.time
if (isTimeout) {
nextFrame.value
} else {
lastFrame.value
}
}
else -> {
// TODO("Not supported $type")
return currentValue
}
}
return if (isScaleMode) {
when (blend) {
MixBlend.setup -> poseValue + (summaryValue - poseValue) * weight
MixBlend.first, MixBlend.replace -> currentValue + (summaryValue - currentValue) * weight
MixBlend.add -> currentValue + summaryValue * weight
}
} else {
when (blend) {
MixBlend.setup -> poseValue + summaryValue * weight
MixBlend.first, MixBlend.replace -> currentValue + (summaryValue + poseValue - currentValue) * weight
MixBlend.add -> currentValue + summaryValue * weight
}
}
}
}