rokojori_action_library/Runtime/Time/TimeLineManager.cs

224 lines
4.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;
2026-05-22 12:25:02 +00:00
using Rokojori.Extensions;
2024-05-19 15:59:41 +00:00
2026-05-22 12:25:02 +00:00
namespace Rokojori;
2024-05-19 15:59:41 +00:00
2026-05-22 12:25:02 +00:00
/** <summary>
<title>
Manages time lines for events, callbacks tweens.
</title>
<description>
Most time-based SequenceActions use a Timeline to define the clock it belongs to.
</description>
2024-05-19 15:59:41 +00:00
2026-05-22 12:25:02 +00:00
</summary>
*/
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
[Tool]
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/TimelineManager.svg") ]
public partial class TimelineManager:NetworkNode
{
[Export]
public Timeline[] timelines = new Timeline[ 0 ];
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
[Export]
public Timeline timeScaleTimeline;
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
[Export]
public Timeline realtimeTimeline;
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
[Export]
public bool computeRealtimeWithEngineDelta;
2024-05-19 15:59:41 +00:00
2026-05-22 12:25:02 +00:00
List<TimelineRunner> _runners = new List<TimelineRunner>();
int _idCounter = 0;
bool _initialized = false;
2024-05-19 15:59:41 +00:00
2026-05-22 12:25:02 +00:00
public override void _Ready()
{
if ( _runners == null )
2025-01-19 20:35:51 +00:00
{
2026-05-22 12:25:02 +00:00
GD.Print( "is null" );
2025-01-19 20:35:51 +00:00
}
2026-05-22 12:25:02 +00:00
_runners = null;
Initialize();
}
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
public static TimelineManager Get()
{
return Unique<TimelineManager>.Get();
}
2026-05-22 12:25:02 +00:00
float _lastUpdate = 0;
//DateTime lastUpdated = DateTime.Now;
float lastUpdated = TimeTool.Now();
float _estimatedDelta = 0;
float _estimatedDeltaFilter = 0.9f;
float _unscaledDelta = 0;
double _lastRealtimePosition = 0;
double _realtimePosition = 0;
2025-10-24 11:38:51 +00:00
2026-05-22 12:25:02 +00:00
float _lastTimeScale = 1;
2025-10-24 11:38:51 +00:00
2026-05-22 12:25:02 +00:00
QueueList<System.Action> _processCallbacks = new QueueList<System.Action>();
2025-10-31 12:09:03 +00:00
2026-05-22 12:25:02 +00:00
bool _inProcess = false;
2025-10-24 11:38:51 +00:00
2026-05-22 12:25:02 +00:00
public bool inProcess => _inProcess;
2025-10-31 12:09:03 +00:00
2026-05-22 12:25:02 +00:00
bool _paused = false;
public bool paused => _paused;
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
public override void _Process( double delta )
{
_inProcess = true;
2026-05-22 12:25:02 +00:00
_paused = GetTree().Paused;
2026-05-22 12:25:02 +00:00
UpdateRealTime( delta );
2025-10-24 11:38:51 +00:00
2026-05-22 12:25:02 +00:00
if ( ! Engine.IsEditorHint() && timeScaleTimeline != null )
{
2026-05-22 12:25:02 +00:00
Engine.TimeScale = GetRunnerByTimeline( timeScaleTimeline ).modulatedSpeed;
2025-01-03 12:09:23 +00:00
}
2026-05-22 12:25:02 +00:00
_runners.ForEach(
r =>
{
if ( r == null )
{
return;
}
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
r.UpdateTimeLine( unscaledTimeDelta );
}
);
2025-01-08 18:46:17 +00:00
2026-05-22 12:25:02 +00:00
_processCallbacks.IterateAndResolve( t => t() );
2025-01-18 20:02:20 +00:00
2026-05-22 12:25:02 +00:00
_inProcess = false;
}
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
public void AddProcessCallback( System.Action a )
{
_processCallbacks.QueueInsert( a );
}
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
public void RemoveProcessCallback( System.Action a )
{
_processCallbacks.QueueRemoval( a );
}
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
public int GetTimeLineIndex( Timeline timeLine )
{
return timelines == null ? -1 : Arrays.IndexOf( timelines, timeLine );
}
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
public void Modulate( Timeline timeline, AnimationCurve c, Action<bool> onReady )
{
var runner = GetRunner( GetTimeLineIndex( timeline ) );
runner.Modulate( c, onReady );
}
2025-01-03 12:09:23 +00:00
2026-05-22 12:25:02 +00:00
void UpdateRealTime( double engineDelta )
{
var now = TimeTool.Now();
var unscaled = ( now - lastUpdated );
lastUpdated = now;
2025-10-24 11:38:51 +00:00
2026-05-22 12:25:02 +00:00
if ( unscaled < 1f/20f )
2024-05-19 15:59:41 +00:00
{
2026-05-22 12:25:02 +00:00
_estimatedDelta += _estimatedDeltaFilter * ( unscaled - _estimatedDelta );
}
2024-05-19 15:59:41 +00:00
2026-05-22 12:25:02 +00:00
if ( computeRealtimeWithEngineDelta )
{
_unscaledDelta = (float)( Engine.TimeScale == 0 ? _estimatedDelta : ( engineDelta / Engine.TimeScale ) );
}
else
{
_unscaledDelta = _estimatedDelta;
}
2025-03-13 16:19:28 +00:00
2026-05-22 12:25:02 +00:00
_lastRealtimePosition = _realtimePosition;
_realtimePosition += _unscaledDelta;
}
2025-01-19 20:35:51 +00:00
2026-05-22 12:25:02 +00:00
public float unscaledTimeDelta => _unscaledDelta;
public double realtime => _realtimePosition;
2025-01-19 20:35:51 +00:00
2026-05-22 12:25:02 +00:00
2025-10-24 11:38:51 +00:00
2026-05-22 12:25:02 +00:00
void Initialize()
{
if ( _initialized )
{
return;
2024-05-19 15:59:41 +00:00
}
2026-05-22 12:25:02 +00:00
_initialized = true;
_runners = ListExtensions.Map<Timeline,TimelineRunner>( timelines, tl => new TimelineRunner( tl, this ) );
// this.LogInfo( "Created runners:", _runners.Count );
}
public static Timeline Ensure( Timeline timeline )
{
if ( timeline != null )
2025-01-08 18:46:17 +00:00
{
2026-05-22 12:25:02 +00:00
return timeline;
2025-01-08 18:46:17 +00:00
}
2025-01-19 20:35:51 +00:00
2026-05-22 12:25:02 +00:00
var tm = Get();
2024-05-19 15:59:41 +00:00
2026-05-22 12:25:02 +00:00
if ( tm == null )
{
return new Timeline();
2024-05-19 15:59:41 +00:00
}
2026-05-22 12:25:02 +00:00
return tm.timeScaleTimeline;
}
public TimelineRunner GetRunnerByTimeline( Timeline timeline )
{
return GetRunner( _runners.FindIndex( r => r.timeLine == timeline ) );
}
2024-05-19 15:59:41 +00:00
2026-05-22 12:25:02 +00:00
public TimelineRunner GetRunner( int index )
{
if ( index < 0 || index >= _runners.Count )
2024-05-19 15:59:41 +00:00
{
2026-05-22 12:25:02 +00:00
return null ;
2024-05-19 15:59:41 +00:00
}
2026-05-22 12:25:02 +00:00
return _runners[ index ];
}
int _CreateID()
{
_idCounter ++;
return _idCounter;
}
public static int CreateID()
{
var tm = Get();
return tm._CreateID();
2024-05-19 15:59:41 +00:00
}
2026-05-22 12:25:02 +00:00
}