using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System; using Godot; namespace Rokojori { [Tool] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/TimeLineManager.svg") ] public partial class TimeLineManager:NetworkNode { [Export] public TimeLine[] timeLines; [Export] public TimeLine gameTimeTimeLine; [Export] public TimeLine realTimeTimeLine; [Export] public bool computeRealtimeWithEngineDelta; List _runners = new List(); int _idCounter = 0; bool _initialized = false; public override void _Ready() { Initialize(); } public static TimeLineManager Get() { return Unique.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 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(); } } }