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

324 lines
7.4 KiB
C#
Raw Normal View History

2024-05-19 15:59:41 +00:00
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System;
using Godot;
namespace Rokojori
{
public class TimeLineRunner
{
2025-01-08 18:46:17 +00:00
public TimeLine timeLine;
2025-01-19 20:35:51 +00:00
public TimeLineManager manager;
2024-05-19 15:59:41 +00:00
2025-01-08 18:46:17 +00:00
public float lastPosition = 0;
public float position = 0;
2024-05-19 15:59:41 +00:00
public bool playing = false;
2025-01-08 18:46:17 +00:00
public float deltaScale = 1;
public float speed = 1;
2024-05-19 15:59:41 +00:00
List<TimeLineEvent> events = new List<TimeLineEvent>();
List<TimeLineSpan> spans = new List<TimeLineSpan>();
2025-01-21 20:58:56 +00:00
List<TimeLineCallback> callbacks = new List<TimeLineCallback>();
2024-05-19 15:59:41 +00:00
2025-01-03 12:09:23 +00:00
AnimationCurve modulatorCurve;
float modulatorTime;
Vector3 modulatorRandomization;
Action<bool> modulatorOnReady = null;
float _lastModulation = 1;
2025-01-08 18:46:17 +00:00
float _currentDelta = 1;
2025-01-03 12:09:23 +00:00
public float modulatedSpeed => (float)( speed * _lastModulation * deltaScale );
2025-01-08 18:46:17 +00:00
public float currentDelta => _currentDelta;
2025-01-03 12:09:23 +00:00
2025-01-19 20:35:51 +00:00
public TimeLineRunner( TimeLine timeLine, TimeLineManager manager )
2024-05-19 15:59:41 +00:00
{
this.timeLine = timeLine;
2025-01-19 20:35:51 +00:00
this.manager = manager;
2024-05-19 15:59:41 +00:00
2025-01-08 18:46:17 +00:00
playing = timeLine.autoStart;
2024-05-19 15:59:41 +00:00
}
2025-01-03 12:09:23 +00:00
public void Modulate( AnimationCurve curve, Action<bool> onReady )
{
if ( modulatorOnReady != null )
{
modulatorOnReady( false );
}
modulatorCurve = curve;
modulatorTime = 0;
modulatorRandomization = curve.Randomize();
modulatorOnReady = onReady;
}
2025-01-19 20:35:51 +00:00
public void UpdateTimeLine( float realtimeDelta )
2024-05-19 15:59:41 +00:00
{
if ( ! playing )
{
return;
}
2025-01-03 12:09:23 +00:00
var modulation = 1f;
if ( modulatorCurve != null )
{
modulation = modulatorCurve.Sample( modulatorTime, modulatorRandomization );
_lastModulation = modulation;
modulatorTime += realtimeDelta;
if ( modulatorTime >= modulatorCurve.GetRandomizedEndTime( modulatorRandomization ) )
{
var mr = modulatorOnReady;
modulatorOnReady = null;
modulatorCurve = null;
modulatorTime = 0;
modulatorRandomization = Vector3.Zero;
if ( mr != null )
{
mr( true );
}
}
}
else
{
_lastModulation = 1;
}
2025-01-08 18:46:17 +00:00
_currentDelta = realtimeDelta * deltaScale * speed * modulation;
2024-05-19 15:59:41 +00:00
lastPosition = position;
2025-01-08 18:46:17 +00:00
position += _currentDelta;
2024-05-19 15:59:41 +00:00
var isForward = speed >= 0;
if ( isForward )
{
2025-01-19 20:35:51 +00:00
ProcessForward();
2024-05-19 15:59:41 +00:00
}
}
2025-01-03 12:09:23 +00:00
2025-01-19 20:35:51 +00:00
void ProcessForward()
{
ProcessEvents();
ProcessSpans();
2025-01-21 20:58:56 +00:00
ProcessCallbacks();
}
List<TimeLineCallback> _callbackAdditions = new List<TimeLineCallback>();
void ProcessCallbacks()
{
if ( _callbackAdditions.Count > 0 )
{
callbacks.AddRange( _callbackAdditions );
_callbackAdditions.Clear();
}
callbacks.ForEach( c => c.callback( c ) );
2025-01-03 12:09:23 +00:00
}
2025-01-19 20:35:51 +00:00
void ProcessEvents()
2024-05-19 15:59:41 +00:00
{
2025-01-16 07:20:32 +00:00
if ( requestedRemovals.Count > 0 )
{
requestedRemovals.Sort();
Lists.RemoveIncreasingSortedIndices( events, requestedRemovals );
requestedRemovals.Clear();
2025-01-19 20:35:51 +00:00
}
2025-01-16 07:20:32 +00:00
2024-05-19 15:59:41 +00:00
List<int> eventRemovals = null;
for ( int i = 0; i < events.Count; i++ )
{
var eventPosition = events[ i ].position;
2025-01-16 07:20:32 +00:00
if ( events[ i ].looping )
{
var next = events[ i ].GetNextLoopPosition( lastPosition );
var previous = events[ i ].GetPreviousLoopPosition( position );
2024-05-19 15:59:41 +00:00
2025-01-16 07:20:32 +00:00
if ( next != previous )
{
continue;
}
eventPosition = next;
}
2024-05-19 15:59:41 +00:00
if ( ! RangeDouble.ContainsExclusiveMax( lastPosition, position, eventPosition ) )
{
2025-01-03 12:09:23 +00:00
if ( events[ i ].wasInside )
{
eventRemovals = AddRemoval( events[ i ].persistent, i, eventRemovals );
}
2024-05-19 15:59:41 +00:00
continue;
}
2025-01-19 20:35:51 +00:00
events[ i ].callback( events[ i ] );
2025-01-03 12:09:23 +00:00
events[ i ].wasInside = true;
2024-05-19 15:59:41 +00:00
}
if ( eventRemovals != null )
{
2025-01-03 12:09:23 +00:00
Lists.RemoveIncreasingSortedIndices( events, eventRemovals );
2024-05-19 15:59:41 +00:00
}
2025-01-19 20:35:51 +00:00
}
void ProcessSpans()
{
2024-05-19 15:59:41 +00:00
if ( spans.Count == 0 )
{
return;
}
2025-01-19 20:35:51 +00:00
List<int> spanRemovals = null;
2024-05-19 15:59:41 +00:00
var timelineSpan = new RangeDouble( lastPosition, position );
var span = new RangeDouble( 0, 1 );
2025-01-03 12:09:23 +00:00
var isForward = lastPosition < position;
2024-05-19 15:59:41 +00:00
for ( int i = 0; i < spans.Count; i++ )
{
span.min = spans[ i ].start;
span.max = spans[ i ].end;
2025-01-03 12:09:23 +00:00
var overlaps = timelineSpan.Overlaps( span );
if ( ! overlaps )
2024-05-19 15:59:41 +00:00
{
2025-01-03 12:09:23 +00:00
if ( spans[ i ].wasInside )
{
2025-01-19 20:35:51 +00:00
spanRemovals = AddRemoval( spans[ i ].persistent, i, spanRemovals );
2025-01-03 12:09:23 +00:00
}
2024-05-19 15:59:41 +00:00
continue;
}
var isStart = timelineSpan.Contains( spans[ i ].start );
var isEnd = timelineSpan.Contains( spans[ i ].end );
2025-01-08 18:46:17 +00:00
var spanType = TimeLineSpanUpdateType.InSpan;
2024-05-19 15:59:41 +00:00
if ( isStart && isEnd )
{
2025-01-08 18:46:17 +00:00
spanType = TimeLineSpanUpdateType.CompletelyInside;
2024-05-19 15:59:41 +00:00
}
else if ( isStart )
{
2025-01-08 18:46:17 +00:00
spanType = TimeLineSpanUpdateType.Start;
2024-05-19 15:59:41 +00:00
}
else if ( isEnd )
{
2025-01-08 18:46:17 +00:00
spanType = TimeLineSpanUpdateType.End;
2024-05-19 15:59:41 +00:00
}
2025-01-03 12:09:23 +00:00
spans[ i ].wasInside = true;
2025-01-08 18:46:17 +00:00
2025-01-19 20:35:51 +00:00
spans[ i ].callback( spans[ i ], spanType );
2024-05-19 15:59:41 +00:00
2025-01-03 12:09:23 +00:00
}
2024-05-19 15:59:41 +00:00
2025-01-19 20:35:51 +00:00
if ( spanRemovals != null )
2025-01-03 12:09:23 +00:00
{
Lists.RemoveIncreasingSortedIndices( spans, spanRemovals );
2024-05-19 15:59:41 +00:00
}
}
2025-01-19 20:35:51 +00:00
List<int> AddRemoval( bool isPersistent, int index, List<int> list )
{
if ( isPersistent )
{
return list;
}
if ( list == null )
{
list = new List<int>();
}
list.Add( index );
return list;
}
2025-01-16 07:20:32 +00:00
List<int> requestedRemovals = new List<int>();
public void RemoveEvent( int eventID )
{
requestedRemovals.Add( eventID );
}
2025-01-21 20:58:56 +00:00
public TimeLineCallback _ScheduleCallback( Action<TimeLineCallback> callback, int eventID )
{
var tle = new TimeLineCallback();
tle.id = eventID;
tle.callback = callback;
tle.timeLine = timeLine;
_callbackAdditions.Add( tle );
return tle;
}
public TimeLineEvent _ScheduleEvent( float position, int eventID, bool isPersistent, Action<TimeLineEvent> callback )
2024-05-19 15:59:41 +00:00
{
var tle = new TimeLineEvent();
tle.position = position;
2025-01-21 20:58:56 +00:00
tle.id = eventID;
2024-05-19 15:59:41 +00:00
tle.persistent = isPersistent;
2025-01-19 20:35:51 +00:00
tle.callback = callback;
tle.timeLine = timeLine;
2024-05-19 15:59:41 +00:00
events.Add( tle );
2025-01-19 20:35:51 +00:00
return tle;
2024-05-19 15:59:41 +00:00
}
2025-01-21 20:58:56 +00:00
public TimeLineEvent _ScheduleLoopEvent( float loopDuration, float loopOffset, int eventID, bool isPersistent, Action<TimeLineEvent> callback )
2025-01-16 07:20:32 +00:00
{
var tle = new TimeLineEvent();
tle.position = loopOffset;
tle.looping = true;
tle.loopDuration = loopDuration;
2025-01-21 20:58:56 +00:00
tle.id = eventID;
2025-01-16 07:20:32 +00:00
tle.persistent = isPersistent;
2025-01-19 20:35:51 +00:00
tle.callback = callback;
tle.timeLine = timeLine;
2025-01-16 07:20:32 +00:00
events.Add( tle );
2025-01-19 20:35:51 +00:00
return tle;
2025-01-16 07:20:32 +00:00
}
2025-01-21 20:58:56 +00:00
public TimeLineSpan _ScheduleSpan( float start, float end, int eventID, bool isPersistent, Action<TimeLineSpan, TimeLineSpanUpdateType> callback )
2024-05-19 15:59:41 +00:00
{
var tse = new TimeLineSpan();
tse.start = start;
tse.end = end;
2025-01-21 20:58:56 +00:00
tse.id = eventID;
2024-05-19 15:59:41 +00:00
tse.persistent = isPersistent;
tse.wasInside = false;
2025-01-19 20:35:51 +00:00
tse.callback = callback;
tse.timeLine = timeLine;
2024-05-19 15:59:41 +00:00
spans.Add( tse );
2025-01-19 20:35:51 +00:00
return tse;
2024-05-19 15:59:41 +00:00
}
}
}