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

157 lines
3.3 KiB
C#

using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class TimeLineManager:NetworkNode
{
[Export]
public TimeLine[] timeLines;
[Export]
public TimeLine gameTimeTimeLine;
[Export]
public TimeLine realTimeTimeLine;
[Export]
public bool computeRealtimeWithEngineDelta;
List<TimeLineRunner> _runners = new List<TimeLineRunner>();
int _idCounter = 0;
bool _initialized = false;
public override void _Ready()
{
Initialize();
}
public static TimeLineManager Get()
{
return Unique<TimeLineManager>.Get();
}
float _lastUpdate = 0;
DateTime lastUpdated = DateTime.Now;
float _estimatedDelta = 0;
float _estimatedDeltaFilter = 0.9f;
float _unscaledDelta = 0;
double _lastRealtimePosition = 0;
double _realtimePosition = 0;
float _lastTimeScale = 1;
public override void _Process( double delta )
{
UpdateRealTime( delta );
if ( ! Engine.IsEditorHint() && gameTimeTimeLine != null )
{
Engine.TimeScale = gameTimeTimeLine.runner.modulatedSpeed;
}
_runners.ForEach( r => r.UpdateTimeLine( unscaledTimeDelta ) );
}
public int GetTimeLineIndex( TimeLine timeLine )
{
return Arrays.IndexOf( timeLines, timeLine );
}
public void Modulate( TimeLine timeline, AnimationCurve c, Action<bool> onReady )
{
var runner = GetRunner( GetTimeLineIndex( timeline ) );
runner.Modulate( c, onReady );
}
void UpdateRealTime( double engineDelta )
{
var now = DateTime.Now;
var unscaled = (float) ( ( now - lastUpdated ).TotalSeconds );
lastUpdated = now;
if ( unscaled < 1f/20f )
{
_estimatedDelta += _estimatedDeltaFilter * ( unscaled - _estimatedDelta );
}
if ( computeRealtimeWithEngineDelta )
{
_unscaledDelta = (float)( Engine.TimeScale == 0 ? _estimatedDelta : ( engineDelta / Engine.TimeScale ) );
}
else
{
_unscaledDelta = _estimatedDelta;
}
_lastRealtimePosition = _realtimePosition;
_realtimePosition += _unscaledDelta;
}
public float unscaledTimeDelta => _unscaledDelta;
public double realtime => _realtimePosition;
void Initialize()
{
if ( _initialized )
{
return;
}
_initialized = true;
_runners = Lists.Map( timeLines, tl => new TimeLineRunner( tl, this ) );
}
public static TimeLine Ensure( TimeLine timeline )
{
if ( timeline != null )
{
return timeline;
}
var tm = TimeLineManager.Get();
return tm.gameTimeTimeLine;
}
public TimeLineRunner GetRunner( TimeLine timeline )
{
return GetRunner( _runners.FindIndex( r => r.timeLine == timeline ) );
}
public TimeLineRunner GetRunner( int index )
{
if ( index < 0 || index >= _runners.Count )
{
return null ;
}
return _runners[ index ];
}
int _CreateID()
{
_idCounter ++;
return _idCounter;
}
public static int CreateID()
{
var tm = TimeLineManager.Get();
return tm._CreateID();
}
}
}