All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.spine.animation.FrameCalculator.kt Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
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
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy