using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System; using Godot; namespace Rokojori { [Tool] [GlobalClass] public partial class TimeLineManager:RJTimeLineManager { [Export] public RJTimeLine[] timeLines; [Export] public RJTimeLine engineTimeScale; [Export] public RJTimeLine realTimeTimeLine; [Export] public bool computeRealtimeWithEngineDelta; 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 void Modulate( RJTimeLine 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 ) ); } TimeLineRunner GetRunner( int index ) { if ( index < 0 || index >= _runners.Count ) { return null ; } return _runners[ index ]; } public override int CreateID() { _idCounter ++; return _idCounter; } public static float GetPosition( RJTimeLine 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( RJTimeLine timeLine, float duration, float offset = 0 ) { var time = GetPosition( timeLine ) + offset; return ( time % duration ) / duration; } public static float GetRangePhase( RJTimeLine timeLine, float start, float end ) { var time = GetPosition( timeLine ); var normalized = MathX.Normalize( time, start, end ); return normalized; } public override void ScheduleEvent( int timeLineIndex, double position, int callbackID, bool isPersistent ) { var runner = _runners[ timeLineIndex ]; runner.ScheduleEvent( position, callbackID, isPersistent ); } public override void ScheduleSpan( int timeLineIndex, double start, double end, int callbackID, bool isPersistent ) { var runner = _runners[ timeLineIndex ]; runner.ScheduleSpan( start, end, callbackID, isPersistent ); } public override double GetLastPosition( int timeLineIndex ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return 0; } return runner.lastPosition; } public override double GetPosition( int timeLineIndex ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return 0; } return runner.position; } public override void SetPosition( int timeLineIndex, double position ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return; } runner.position = position; } public override double GetSpeed( int timeLineIndex ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return 1; } return runner.speed; } public float GetModulatedSpeed( RJTimeLine timeline ) { var timeLineIndex = GetTimeLineIndex( timeline ); var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return 1; } return runner.modulatedSpeed; } public float GetSpeed( RJTimeLine timeline ) { return (float) GetSpeed( GetTimeLineIndex( timeline ) ); } public override void SetSpeed( int timeLineIndex, double speed ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return; } runner.speed = speed; } public void SetSpeed( RJTimeLine timeline, double speed ) { SetSpeed( GetTimeLineIndex( timeline ), speed ); } public override bool GetPlayState( int timeLineIndex ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return false; } return runner.playing; } public override void SetPlayState( int timeLineIndex, bool isPlaying ) { var runner = GetRunner( timeLineIndex ); if ( runner == null ){ return; } runner.playing = isPlaying; } } }