rj-action-library/Runtime/Time/TimeLineRunner.cs

162 lines
3.5 KiB
C#

using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System;
using Godot;
namespace Rokojori
{
public class TimeLineRunner
{
public RJTimeLine timeLine;
public double lastPosition = 0;
public double position = 0;
public bool playing = false;
public double deltaScale = 1;
public double speed = 1;
List<TimeLineEvent> events = new List<TimeLineEvent>();
List<TimeLineSpan> spans = new List<TimeLineSpan>();
public TimeLineRunner( RJTimeLine timeLine )
{
this.timeLine = timeLine;
playing = timeLine.AutoStart;
}
public void UpdateTimeLine( double delta, TimeLineManager manager )
{
if ( ! playing )
{
return;
}
lastPosition = position;
position += delta * deltaScale * speed;
var isForward = speed >= 0;
if ( isForward )
{
ProcessForward( manager );
}
}
void ProcessForward( TimeLineManager manager )
{
List<int> eventRemovals = null;
List<int> spanRemovals = null;
for ( int i = 0; i < events.Count; i++ )
{
var eventPosition = events[ i ].position;
if ( ! RangeDouble.ContainsExclusiveMax( lastPosition, position, eventPosition ) )
{
continue;
}
RJLog.Log( "Emitting:",
"last:", lastPosition,
"now:", position,
"event:", eventPosition
);
manager.EmitSignal( TimeLineManager.SignalName.OnEvent, events[ i ].id );
if ( events[ i ].persistent )
{
continue;
}
if ( eventRemovals == null ){ eventRemovals = new List<int>(); }
eventRemovals.Add( i );
}
if ( eventRemovals != null )
{
Lists.RemoveIncreasingIndices( events, eventRemovals );
}
if ( spans.Count == 0 )
{
return;
}
var timelineSpan = new RangeDouble( lastPosition, position );
var span = new RangeDouble( 0, 1 );
for ( int i = 0; i < spans.Count; i++ )
{
span.min = spans[ i ].start;
span.max = spans[ i ].end;
if ( ! timelineSpan.Overlaps( span ) )
{
continue;
}
var isStart = timelineSpan.Contains( spans[ i ].start );
var isEnd = timelineSpan.Contains( spans[ i ].end );
var spanType = TimeLineSpan.InSpan;
if ( isStart && isEnd )
{
spanType = TimeLineSpan.CompletelyInside;
}
else if ( isStart )
{
spanType = TimeLineSpan.Start;
}
else if ( isEnd )
{
spanType = TimeLineSpan.End;
}
manager.EmitSignal( TimeLineManager.SignalName.OnSpan, spans[ i ].id, spanType );
if ( spans[ i ].persistent )
{
continue;
}
if ( spanRemovals == null ){ spanRemovals = new List<int>(); }
spanRemovals.Add( i );
}
}
public void ScheduleEvent( double position, int callbackID, bool isPersistent )
{
var tle = new TimeLineEvent();
tle.position = position;
tle.id = callbackID;
tle.persistent = isPersistent;
events.Add( tle );
}
public void ScheduleSpan( double start, double end, int callbackID, bool isPersistent )
{
var tse = new TimeLineSpan();
tse.start = start;
tse.end = end;
tse.id = callbackID;
tse.persistent = isPersistent;
tse.wasInside = false;
spans.Add( tse );
}
}
}