rj-action-library/Runtime/Animation/KeyFrames/KeyFrameAnimation.cs

131 lines
2.3 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
public class KeyFrameAnimation<T>
{
public List<KeyFrame<T>> keyFrames = new List<KeyFrame<T>>();
int _currentIndex = -1;
bool _sorted = false;
public void FlagUnsorted()
{
_sorted = false;
}
public void FlagSorted()
{
_sorted = true;
}
public void Sort()
{
if ( _sorted )
{
return;
}
keyFrames.Sort( ( a, b ) => Mathf.Sign( a.time - b.time ) );
_sorted = true;
}
public KeyFrame<T> GetKeyFrameAt( float time )
{
var index = GetKeyFrameIndexAt( time );
return index == -1 ? null : keyFrames[ index ];
}
public int GetKeyFrameIndexAt( float time )
{
if ( keyFrames.Count == 0 )
{
return -1;
}
Sort();
for ( int i = 0; i < keyFrames.Count; i++ )
{
if ( keyFrames[ i ].time > time )
{
return Mathf.Max( 0, i - 1 );
}
}
if ( _sorted )
{
return keyFrames.Count - 1;
}
if ( IsKeyFrameAt( time, _currentIndex ) )
{
return _currentIndex;
}
_currentIndex = MathX.SafeIndex( _currentIndex, keyFrames );
var kf = keyFrames[ _currentIndex ];
if ( kf.time < time )
{
_currentIndex ++;
while ( _currentIndex < keyFrames.Count )
{
if ( IsKeyFrameAt( time, _currentIndex ) )
{
return _currentIndex;
}
_currentIndex ++;
}
}
else
{
_currentIndex --;
while ( _currentIndex > -1 )
{
if ( IsKeyFrameAt( time, _currentIndex ) )
{
return _currentIndex;
}
_currentIndex --;
}
}
return -1;
}
bool IsKeyFrameAt( float time, int index )
{
if ( index < 0 || index >= keyFrames.Count -1 )
{
return false;
}
var i = keyFrames[ index ];
if ( i.time < time && index == keyFrames.Count - 1 )
{
return true;
}
var n = keyFrames[ index + 1 ];
return i.time < time && time < n.time;
}
}
}