@name anim_lib_test
@outputs Test
@persist Animations:table [TimeLast TimeCurrent TimeDelta TimeTotal] MyAnim:table

if (first()) {

    function void update(UpdateRate) {
        interval(UpdateRate)

        TimeCurrent = curtime()
        TimeDelta   = min(TimeCurrent - TimeLast, UpdateRate/1000)
        TimeLast    = TimeCurrent
        TimeTotal  += TimeDelta
    }

    function table newAnimation(Name:string, Duration) {
        Animations[Name, table] = table(
            "keyPrev"   = 0,
            "keyNext"   = 1,
            "keyLast"   = 0,
            "keyFrames" = table(),
            "animDuration"  = Duration,
            "animProgress"  = 0,
            "frameProgress" = 0,
            "frameFraction" = 0
        )

        return Animations[Name, table]
    }

    function table table:insertKeyFrame(Index, KeyFrame:table) {
        This["keyFrames", table][Index, table] = KeyFrame
        This["frameCount", number] = This["frameCount", number] + 1
        This["frameDuration", number]  = This["animDuration", number]/This["frameCount", number]
    }

    function void table:playAnimation() {
        #if (This["animProgress", number] != This["animDuration", number]) {
            #- Animation
            local Duration = This["animDuration", number] #?: 1
            local SFactor  = 1#This["animSFactor", number] ?: 1
        
            This["animProgress", number] = min(This["animProgress", number] + TimeDelta*SFactor, Duration)
        
            #- Frame
            This["keyLast", number] = This["keyNext", number]
            This["keyNext", number] = floor(This["animProgress", number]/This["frameDuration", number]) % This["frameDuration", number] + 1
            This["keyPrev", number] = This["keyNext", number] - 1
        
            if (This["keyLast", number] != This["keyNext", number]) {
                This["frameProgress", number] = 0
                print( "wtf")
            }
        
            #- Tweening
            This["frameProgress", number] = min(This["frameProgress", number] + This["frameDuration", number]*TimeDelta, This["frameDuration", number])
            This["frameFraction", number] = This["frameProgress", number]/This["frameDuration", number]

            #- Interpolation
            local KeyFrameNext = This["keyFrames", table][This["keyNext", number], table]
            local KeyFramePrev = This["keyFrames", table][This["keyPrev", number], table]
            local Fraction = This["frameFraction", number]
            
            for (I = 1, KeyFrameNext:count()) {
                local NextData = KeyFrameNext[I, table]
                local PrevData = KeyFramePrev[I, table]
    
                holoAng(NextData["index", number], NextData["parent", entity]:toWorld(
                    slerp(quat(PrevData["angle", angle]), quat(NextData["angle", angle]), Fraction):toAngle()
                    #(NextData["angle", angle] - PrevData["angle", angle])*Fraction + PrevData["angle", number]
                ))
            }
        #}
    }


    holoCreate(1)
    holoParent(1, entity())
    
    holoCreate(2)
    holoParent(2, 1)
    holoPos(2, holoEntity(1):toWorld(vec(0, 0, 50)))
    

    MyAnim = newAnimation("Test", 1)

    MyAnim:insertKeyFrame(0, table(
        table( "index" = 1, "parent" = entity(), "angle" = ang(0, 0, 0) ),
        table( "index" = 2, "parent" = holoEntity(1), "angle" = ang(0, 0, 0) )
    ))
    
    MyAnim:insertKeyFrame(1, table(
        table( "index" = 1, "parent" = entity(), "angle" = ang(45, 0, 0) ),
        table( "index" = 2, "parent" = holoEntity(1), "angle" = ang(90, 90, 0) )
    ))

    MyAnim:insertKeyFrame(2, table(
        table( "index" = 1, "parent" = entity(), "angle" = ang(-45, 0, 0) ),
        table( "index" = 2, "parent" = holoEntity(1), "angle" = ang(-90, 90, 0) )
    ))

}

update(60)

MyAnim:playAnimation()
