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 engineTimeScale; [Export] public TimeLine realTimeTimeLine; [Export] public bool computeRealtimeWithEngineDelta; public readonly EventSlot onEvent = new EventSlot(); public readonly EventSlot> onSpan = new EventSlot>(); List _runners = new List(); int _idCounter = 0; bool _initialized = false; public override void _Ready() { Initialize(); } 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 ( engineTimeScale != null ) { Engine.TimeScale = GetModulatedSpeed( engineTimeScale ); } _runners.ForEach( r => r.UpdateTimeLine( unscaledTimeDelta, this ) ); } 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 ) ); } 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 ]; } public int CreateID() { _idCounter ++; return _idCounter; } public static float GetPosition( TimeLine timeLine ) { var manager = Unique.Get(); if ( manager == null ) { return Time.GetTicksMsec() / 1000f; } var index = Arrays.IndexOf( manager.timeLines, timeLine ); index = Mathf.Max( index, 0 ); return (float) manager.GetPosition( index ); } public static float GetPhase( TimeLine timeLine, float duration, float offset = 0 ) { var time = GetPosition( timeLine ) + offset; return ( time % duration ) / duration; } public static float GetRangePhase( TimeLine timeLine, float start, float end ) { var time = GetPosition( timeLine ); var normalized = MathX.Normalize( time, start, end ); return normalized; } public void ScheduleEvent( int timeLineIndex, float position, int callbackID, bool isPersistent ) { var runner = _runners[ timeLineIndex ]; runner.ScheduleEvent( position, callbackID, isPersistent ); } public void ScheduleSpan( int timeLineIndex, float start, float end, int callbackID, bool isPersistent ) { var runner = _runners[ timeLineIndex ]; runner.ScheduleSpan( start, end, callbackID, isPersistent ); } public float GetLastPosition( int timeLineIndex ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return 0; } return runner.lastPosition; } public float GetPosition( int timeLineIndex ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return 0; } return runner.position; } public void SetPosition( int timeLineIndex, float position ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return; } runner.position = position; } public double GetSpeed( int timeLineIndex ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return 1; } return runner.speed; } public float GetModulatedSpeed( TimeLine timeline ) { var timeLineIndex = GetTimeLineIndex( timeline ); var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return 1; } return runner.modulatedSpeed; } public float GetSpeed( TimeLine timeline ) { return (float) GetSpeed( GetTimeLineIndex( timeline ) ); } public void SetSpeed( int timeLineIndex, float speed ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return; } runner.speed = speed; } public void SetSpeed( TimeLine timeline, float speed ) { SetSpeed( GetTimeLineIndex( timeline ), speed ); } public bool GetPlayState( int timeLineIndex ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return false; } return runner.playing; } public void SetPlayState( int timeLineIndex, bool isPlaying ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return; } runner.playing = isPlaying; } } }