Advertisement
Guest User

Untitled

a guest
Apr 24th, 2017
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.16 KB | None | 0 0
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using UnityEngine;
  7.  
  8. public class Timed : Singleton<Timed>
  9. {
  10.     private static volatile bool paused;
  11.     private static volatile float timeScale = 1f;
  12.     private static volatile int currentFrame;
  13.     private List<EveryFrameCallback> everyFrameCallbacks = new List<EveryFrameCallback>();
  14.     private PooledQueue<EveryFrameCallback> everyFramePool = new PooledQueue<EveryFrameCallback>(() => new EveryFrameCallback());
  15.     private Queue<NextFrameCallback> nextFrameCallbacks = new Queue<NextFrameCallback>();
  16.     private PooledQueue<NextFrameCallback> nextFramePool = new PooledQueue<NextFrameCallback>(() => new NextFrameCallback());
  17.     private ConcurrentQueue<Action> callbacks = new ConcurrentQueue<Action>();
  18.  
  19.     public static async Task In(float seconds, Action callback, CancellationTokenSource source = null)
  20.     {
  21.         try
  22.         {
  23.             var ins = Ins;
  24.             var delayTask = Task.Delay(TimeSpan.FromSeconds(seconds * timeScale), source?.Token ?? new CancellationToken(false));
  25.             await delayTask.ConfigureAwait(false);
  26.  
  27.             while (paused)
  28.             {
  29.                 Thread.Sleep(1);
  30.             }
  31.  
  32.             ins.callbacks.Enqueue(callback);
  33.         }
  34.         catch (TaskCanceledException)
  35.         {
  36.             // Ignore
  37.         }
  38.         catch (Exception e)
  39.         {
  40.             Debug.LogException(e);
  41.         }
  42.     }
  43.  
  44.     public static async Task Every(float seconds, Action callback, int repeatCount = -1, CancellationTokenSource source = null)
  45.     {
  46.         if (seconds <= 0f)
  47.         {
  48.             Debug.LogError("Unable to start Timed task with <= 0f timer!");
  49.             return;
  50.         }
  51.  
  52.         var ins = Ins;
  53.  
  54.         try
  55.         {
  56.             while (true)
  57.             {
  58.                 var delayTask = Task.Delay(TimeSpan.FromSeconds(seconds * timeScale), source?.Token ?? new CancellationToken(false));
  59.                 await delayTask.ConfigureAwait(false);
  60.  
  61.                 while (paused)
  62.                 {
  63.                     Thread.Sleep(1);
  64.                 }
  65.  
  66.                 ins.callbacks.Enqueue(callback);
  67.  
  68.                 if (repeatCount == -1)
  69.                 {
  70.                     continue;
  71.                 }
  72.  
  73.                 if (--repeatCount == 0)
  74.                 {
  75.                     break;
  76.                 }
  77.             }
  78.         }
  79.         catch (TaskCanceledException)
  80.         {
  81.             // Ignore
  82.         }
  83.         catch (Exception e)
  84.         {
  85.             Debug.LogException(e);
  86.         }
  87.     }
  88.  
  89.     public static EveryFrameStopper EveryFrame(Action callback, int repeatCount = -1)
  90.     {
  91.         var ins = Ins;
  92.         var everyFrameCallback = ins.everyFramePool.Dequeue();
  93.         everyFrameCallback.Setup(callback, repeatCount);
  94.         ins.everyFrameCallbacks.Add(everyFrameCallback);
  95.         return new EveryFrameStopper(everyFrameCallback);
  96.     }
  97.  
  98.     public static void NextFrame(Action callback)
  99.     {
  100.         var ins = Ins;
  101.         var nextFrameCallback = ins.nextFramePool.Dequeue();
  102.         nextFrameCallback.Setup(callback, currentFrame);
  103.         ins.nextFrameCallbacks.Enqueue(nextFrameCallback);
  104.     }
  105.  
  106.     private void Update()
  107.     {
  108.         Action callback;
  109.         while (callbacks.TryDequeue(out callback))
  110.         {
  111.             try
  112.             {
  113.                 callback?.Invoke();
  114.             }
  115.             catch (Exception e)
  116.             {
  117.                 Debug.LogException(e);
  118.             }
  119.         }
  120.  
  121.         var maxCount = nextFrameCallbacks.Count;
  122.  
  123.         while (maxCount > 0)
  124.         {
  125.             try
  126.             {
  127.                 var nextFrameCallback = nextFrameCallbacks.Dequeue();
  128.  
  129.                 if (nextFrameCallback.Execute(currentFrame))
  130.                 {
  131.                     nextFramePool.Enqueue(nextFrameCallback);
  132.                 }
  133.                 else
  134.                 {
  135.                     nextFrameCallbacks.Enqueue(nextFrameCallback);
  136.                 }
  137.  
  138.                 --maxCount;
  139.             }
  140.             catch (Exception e)
  141.             {
  142.                 Debug.LogException(e);
  143.             }
  144.         }
  145.  
  146.         for (var i = everyFrameCallbacks.Count - 1; i >= 0; --i)
  147.         {
  148.             try
  149.             {
  150.                 if (!everyFrameCallbacks[i].Execute())
  151.                 {
  152.                     everyFrameCallbacks.RemoveAt(i);
  153.                 }
  154.             }
  155.             catch (Exception e)
  156.             {
  157.                 Debug.LogError(e);
  158.                 everyFrameCallbacks.RemoveAt(i);
  159.             }
  160.         }
  161.  
  162.         timeScale = Time.timeScale;
  163.         currentFrame = Time.frameCount;
  164.     }
  165.  
  166.     private void OnApplicationPause(bool isPaused)
  167.     {
  168.         paused = isPaused;
  169.     }
  170.  
  171.     private void Awake()
  172.     {
  173.         SetSingletonInstance(this);
  174.  
  175.         timeScale = Time.timeScale;
  176.         currentFrame = Time.frameCount;
  177.  
  178. #if UNITY_EDITOR
  179.         UnityEditor.EditorApplication.playmodeStateChanged += () => { paused = UnityEditor.EditorApplication.isPaused; };
  180. #endif
  181.     }
  182.  
  183.     private void Start()
  184.     {
  185. #if UNITY_EDITOR
  186.         paused = UnityEditor.EditorApplication.isPaused;
  187. #else
  188.         paused = false;
  189. #endif
  190.     }
  191.  
  192.     public class EveryFrameCallback
  193.     {
  194.         public long Revision => revision;
  195.  
  196.         private long revision;
  197.         private Action Callback { get; set; }
  198.         private int RepeatCount { get; set; }
  199.         private bool cancelled;
  200.  
  201.         public void Setup(Action callback, int repeatCount = -1)
  202.         {
  203.             Callback = callback;
  204.             RepeatCount = repeatCount;
  205.             cancelled = false;
  206.             Interlocked.Increment(ref revision);
  207.         }
  208.  
  209.         public bool Execute()
  210.         {
  211.             if (cancelled)
  212.             {
  213.                 return false;
  214.             }
  215.  
  216.             Callback();
  217.             return RepeatCount == -1 || --RepeatCount != 0;
  218.         }
  219.  
  220.         public void Cancel()
  221.         {
  222.             cancelled = true;
  223.         }
  224.     }
  225.  
  226.     public struct EveryFrameStopper
  227.     {
  228.         private long capturedRevision;
  229.         private EveryFrameCallback callback;
  230.  
  231.         public EveryFrameStopper(EveryFrameCallback callback)
  232.         {
  233.             this.callback = callback;
  234.             capturedRevision = callback.Revision;
  235.         }
  236.  
  237.         public void Cancel()
  238.         {
  239.             if (callback == null || capturedRevision != callback.Revision)
  240.             {
  241.                 return;
  242.             }
  243.  
  244.             capturedRevision = 0;
  245.             callback.Cancel();
  246.         }
  247.     }
  248.  
  249.     private class NextFrameCallback
  250.     {
  251.         public void Setup(Action action, int capturedFrame)
  252.         {
  253.             Callback = action;
  254.             CapturedFrame = capturedFrame;
  255.         }
  256.  
  257.         private Action Callback { get; set; }
  258.         private int CapturedFrame { get; set; }
  259.  
  260.         public bool Execute(int currentFrame)
  261.         {
  262.             if (CapturedFrame == currentFrame)
  263.             {
  264.                 return false;
  265.             }
  266.  
  267.             Callback();
  268.             return true;
  269.         }
  270.     }
  271. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement