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

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

The newest version!
package ru.casperix.spine.animation

import ru.casperix.math.curve.float32.BezierCubic2f
import ru.casperix.math.interpolation.float32.linearInterpolatef
import ru.casperix.math.vector.float32.Vector2f
import ru.casperix.math.BezierCalculation
import ru.casperix.spine.MixBlend
import ru.casperix.spine.json.component.BezierCurve
import ru.casperix.spine.json.component.LinearCurve

object FrameCalculator {
    fun getRelativeValue(
        frames: List,
        time: Float,
        weight: Float,
        blend: MixBlend,
        currentValue: Float,
        poseValue: Float,
        scaleMode: Boolean
    ): Float {
        frames.forEachIndexed { index, nextFrame ->
            if (time >= nextFrame.time) return@forEachIndexed

            val isFirstFrame = index == 0 || time == 0f
            if (isFirstFrame) {
                return when (blend) {
                    MixBlend.setup -> poseValue
                    MixBlend.first -> currentValue + (poseValue - currentValue) * weight
                    else -> currentValue
                }
            } else {
                val lastFrame = frames[index - 1]
                val timeFactor = (time - lastFrame.time) / (nextFrame.time - lastFrame.time)
                val type = lastFrame.curve

                val summaryValue = if (type is BezierCurve) {
                    //bezier
                    val curve = BezierCubic2f(
                        Vector2f(lastFrame.time, lastFrame.value),
                        type.v1,
                        type.v2,
                        Vector2f(nextFrame.time, nextFrame.value),
                    )

                    //TODO: can optimize speed & precision
                    BezierCalculation.getApproximateErrorHeightPrecision(curve, time, 0.01f)
                } else if (type is LinearCurve) {
                    val lastValue = lastFrame.value
                    val nextValue = nextFrame.value
                    linearInterpolatef(lastValue, nextValue, timeFactor)
                } else {
                    //  TODO: correct interpolation for non-linear
                    return currentValue
                }

                if (scaleMode) {
                    return when (blend) {
                        MixBlend.setup -> poseValue + (summaryValue - poseValue) * weight
                        MixBlend.first, MixBlend.replace -> currentValue + (summaryValue - currentValue) * weight
                        MixBlend.add -> currentValue + summaryValue * weight
                    }
                } else {
                    return when (blend) {
                        MixBlend.setup -> poseValue + summaryValue * weight
                        MixBlend.first, MixBlend.replace -> currentValue + (summaryValue + poseValue - currentValue) * weight
                        MixBlend.add -> currentValue + summaryValue * weight
                    }
                }
            }
        }
        return currentValue
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy