summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documents/实现/20minutes.txt7
-rw-r--r--Documents/实现/消息通知.xlsxbin0 -> 10203 bytes
-rw-r--r--WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs2738
-rw-r--r--WorldlineKeepers/Assets/Scenes/0_Test.unity20
-rw-r--r--WorldlineKeepers/Assets/Scripts/Application/ApplicationMain.cs28
-rw-r--r--WorldlineKeepers/Assets/Scripts/Battle/SceneManager.cs2
-rw-r--r--WorldlineKeepers/Assets/Scripts/Common/SingletonMB.cs3
-rw-r--r--WorldlineKeepers/Assets/Scripts/Physics/Quadtree.cs3
-rw-r--r--WorldlineKeepers/Assets/Scripts/Rendering/SpriteAnimationController.cs3
-rw-r--r--WorldlineKeepers/Assets/Scripts/Stages/GameStageBase.cs1
-rw-r--r--WorldlineKeepers/Assets/Scripts/Stages/GameStageManager.cs5
-rw-r--r--WorldlineKeepers/Assets/Scripts/Stages/GameStage_Dojo.cs15
-rw-r--r--WorldlineKeepers/Assets/Scripts/Stages/GameStage_Main.cs2
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tests/TestCSV.cs4
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs2
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tests/TestJson.cs3
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Commands.meta8
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Commands/Command.cs47
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Commands/Command.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Commands/CommandGroup.cs96
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Commands/CommandGroup.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/GameObjectPool.cs51
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/GameObjectPool.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Notification/NotificationCenter.cs2
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Notification/ScopedNotification.cs3
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/ObjectPool.cs51
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/ObjectPool.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Recycle.cs70
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Recycle.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/ScopedEvent.cs54
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/ScopedEvent.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs18
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs8
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs87
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Trinary Software.meta (renamed from WorldlineKeepers/Assets/Plugins/Trinary Software.meta)0
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Editor.meta (renamed from WorldlineKeepers/Assets/Plugins/Trinary Software/Editor.meta)0
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png (renamed from WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png)bin36388 -> 36388 bytes
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png.meta (renamed from WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png.meta)0
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf (renamed from WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf)bin690071 -> 690071 bytes
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf.meta (renamed from WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf.meta)0
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Timing.cs4655
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Timing.cs.meta (renamed from WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs.meta)0
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs128
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/UI/PanelBase.cs16
-rw-r--r--WorldlineKeepers/Assets/Scripts/UI/PanelBase.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Utils/LogHelper.cs10
-rw-r--r--WorldlineKeepers/Assets/Scripts/Utils/TransformUtils.cs18
-rw-r--r--WorldlineKeepers/Assets/Scripts/Utils/TransformUtils.cs.meta11
-rw-r--r--WorldlineKeepers/ProjectSettings/EditorBuildSettings.asset14
51 files changed, 5515 insertions, 2767 deletions
diff --git a/Documents/实现/20minutes.txt b/Documents/实现/20minutes.txt
new file mode 100644
index 0000000..189a923
--- /dev/null
+++ b/Documents/实现/20minutes.txt
@@ -0,0 +1,7 @@
+Character Passive InputAction
+Perk Trigger Action NotificationCenter
+Pickup OnTriggerEnter
+Buff IDamageModifier.GetMod() ValueModifier Buff NotificationCenter
+Powerup NotificationCenter UnityEvent
+Rune NotificationCenter
+
diff --git a/Documents/实现/消息通知.xlsx b/Documents/实现/消息通知.xlsx
new file mode 100644
index 0000000..bcac959
--- /dev/null
+++ b/Documents/实现/消息通知.xlsx
Binary files differ
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs b/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs
deleted file mode 100644
index c61b93e..0000000
--- a/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs
+++ /dev/null
@@ -1,2738 +0,0 @@
-using UnityEngine;
-using System.Collections.Generic;
-using UnityEngine.Assertions;
-#if UNITY_5_5_OR_NEWER
-using UnityEngine.Profiling;
-#endif
-
-// /////////////////////////////////////////////////////////////////////////////////////////
-// More Effective Coroutines
-// v3.10.2
-//
-// This is an improved implementation of coroutines that boasts zero per-frame memory allocations,
-// runs about twice as fast as Unity's built in coroutines and has a range of extra features.
-//
-// This is the free version. MEC also has a pro version, which can be found here:
-// https://www.assetstore.unity3d.com/en/#!/content/68480
-// The pro version contains exactly the same core that the free version uses, but also
-// contains many additional features. Every function that exists in MEC Free also exists in MEC Pro,
-// so you can upgrade at any time without breaking existing code.
-//
-// For manual, support, or upgrade guide visit http://trinary.tech/
-//
-// Created by Teal Rogers
-// Trinary Software
-// All rights preserved
-// /////////////////////////////////////////////////////////////////////////////////////////
-
-namespace MEC
-{
- public class Timing : MonoBehaviour
- {
- /// <summary>
- /// The time between calls to SlowUpdate.
- /// </summary>
- [Tooltip("How quickly the SlowUpdate segment ticks.")]
- public float TimeBetweenSlowUpdateCalls = 1f / 7f;
- /// <summary>
- /// The amount that each coroutine should be seperated inside the Unity profiler. NOTE: When the profiler window
- /// is not open this value is ignored and all coroutines behave as if "None" is selected.
- /// </summary>
- [Tooltip("How much data should be sent to the profiler window when it's open.")]
- public DebugInfoType ProfilerDebugAmount;
- /// <summary>
- /// The number of coroutines that are being run in the Update segment.
- /// </summary>
- [Tooltip("A count of the number of Update coroutines that are currently running."), Space(12)]
- public int UpdateCoroutines;
- /// <summary>
- /// The number of coroutines that are being run in the FixedUpdate segment.
- /// </summary>
- [Tooltip("A count of the number of FixedUpdate coroutines that are currently running.")]
- public int FixedUpdateCoroutines;
- /// <summary>
- /// The number of coroutines that are being run in the LateUpdate segment.
- /// </summary>
- [Tooltip("A count of the number of LateUpdate coroutines that are currently running.")]
- public int LateUpdateCoroutines;
- /// <summary>
- /// The number of coroutines that are being run in the SlowUpdate segment.
- /// </summary>
- [Tooltip("A count of the number of SlowUpdate coroutines that are currently running.")]
- public int SlowUpdateCoroutines;
- /// <summary>
- /// The time in seconds that the current segment has been running.
- /// </summary>
- [System.NonSerialized]
- public float localTime;
- /// <summary>
- /// The time in seconds that the current segment has been running.
- /// </summary>
- public static float LocalTime { get { return Instance.localTime; } }
- /// <summary>
- /// The amount of time in fractional seconds that elapsed between this frame and the last frame.
- /// </summary>
- [System.NonSerialized]
- public float deltaTime;
- /// <summary>
- /// The amount of time in fractional seconds that elapsed between this frame and the last frame.
- /// </summary>
- public static float DeltaTime { get { return Instance.deltaTime; } }
- /// <summary>
- /// Used for advanced coroutine control.
- /// </summary>
- public static System.Func<IEnumerator<float>, CoroutineHandle, IEnumerator<float>> ReplacementFunction;
- /// <summary>
- /// This event fires just before each segment is run.
- /// </summary>
- public static event System.Action OnPreExecute;
- /// <summary>
- /// You can use "yield return Timing.WaitForOneFrame;" inside a coroutine function to go to the next frame.
- /// </summary>
- public const float WaitForOneFrame = float.NegativeInfinity;
- /// <summary>
- /// The main thread that (almost) everything in unity runs in.
- /// </summary>
- public static System.Threading.Thread MainThread { get; private set; }
- /// <summary>
- /// The handle of the current coroutine that is running.
- /// </summary>
- public static CoroutineHandle CurrentCoroutine
- {
- get
- {
- for (int i = 0; i < ActiveInstances.Length; i++)
- if (ActiveInstances[i] != null && ActiveInstances[i].currentCoroutine.IsValid)
- return ActiveInstances[i].currentCoroutine;
- return default(CoroutineHandle);
- }
- }
- /// <summary>
- /// The handle of the current coroutine that is running.
- /// </summary>
- public CoroutineHandle currentCoroutine { get; private set; }
-
- private static object _tmpRef;
- private static bool _tmpBool;
- private static CoroutineHandle _tmpHandle;
-
- private int _currentUpdateFrame;
- private int _currentLateUpdateFrame;
- private int _currentSlowUpdateFrame;
- private int _nextUpdateProcessSlot;
- private int _nextLateUpdateProcessSlot;
- private int _nextFixedUpdateProcessSlot;
- private int _nextSlowUpdateProcessSlot;
- private int _lastUpdateProcessSlot;
- private int _lastLateUpdateProcessSlot;
- private int _lastFixedUpdateProcessSlot;
- private int _lastSlowUpdateProcessSlot;
- private float _lastUpdateTime;
- private float _lastLateUpdateTime;
- private float _lastFixedUpdateTime;
- private float _lastSlowUpdateTime;
- private float _lastSlowUpdateDeltaTime;
- private ushort _framesSinceUpdate;
- private ushort _expansions = 1;
- [SerializeField, HideInInspector]
- private byte _instanceID;
-
- private readonly Dictionary<CoroutineHandle, HashSet<CoroutineHandle>> _waitingTriggers = new Dictionary<CoroutineHandle, HashSet<CoroutineHandle>>();
- private readonly HashSet<CoroutineHandle> _allWaiting = new HashSet<CoroutineHandle>();
- private readonly Dictionary<CoroutineHandle, ProcessIndex> _handleToIndex = new Dictionary<CoroutineHandle, ProcessIndex>();
- private readonly Dictionary<ProcessIndex, CoroutineHandle> _indexToHandle = new Dictionary<ProcessIndex, CoroutineHandle>();
- private readonly Dictionary<CoroutineHandle, string> _processTags = new Dictionary<CoroutineHandle, string>();
- private readonly Dictionary<string, HashSet<CoroutineHandle>> _taggedProcesses = new Dictionary<string, HashSet<CoroutineHandle>>();
-
- private IEnumerator<float>[] UpdateProcesses = new IEnumerator<float>[InitialBufferSizeLarge];
- private IEnumerator<float>[] LateUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
- private IEnumerator<float>[] FixedUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
- private IEnumerator<float>[] SlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
-
- private bool[] UpdatePaused = new bool[InitialBufferSizeLarge];
- private bool[] LateUpdatePaused = new bool[InitialBufferSizeSmall];
- private bool[] FixedUpdatePaused = new bool[InitialBufferSizeMedium];
- private bool[] SlowUpdatePaused = new bool[InitialBufferSizeMedium];
- private bool[] UpdateHeld = new bool[InitialBufferSizeLarge];
- private bool[] LateUpdateHeld = new bool[InitialBufferSizeSmall];
- private bool[] FixedUpdateHeld = new bool[InitialBufferSizeMedium];
- private bool[] SlowUpdateHeld = new bool[InitialBufferSizeMedium];
-
- private const ushort FramesUntilMaintenance = 64;
- private const int ProcessArrayChunkSize = 64;
- private const int InitialBufferSizeLarge = 256;
- private const int InitialBufferSizeMedium = 64;
- private const int InitialBufferSizeSmall = 8;
-
- private static Timing[] ActiveInstances = new Timing[16];
- private static Timing _instance;
-
- public static Timing Instance
- {
- get
- {
- if (_instance == null || !_instance.gameObject)
- {
- GameObject instanceHome = GameObject.Find("Timing Controller");
-
- if (instanceHome == null)
- {
- instanceHome = new GameObject { name = "Timing Controller" };
-
- DontDestroyOnLoad(instanceHome);
- }
-
- _instance = instanceHome.GetComponent<Timing>() ?? instanceHome.AddComponent<Timing>();
-
- _instance.InitializeInstanceID();
- }
-
- return _instance;
- }
- set { _instance = value; }
- }
-
- void OnDestroy()
- {
- if (_instance == this)
- _instance = null;
- }
-
- void OnEnable()
- {
- if (MainThread == null)
- MainThread = System.Threading.Thread.CurrentThread;
-
- InitializeInstanceID();
- }
-
- void OnDisable()
- {
- if (_instanceID < ActiveInstances.Length)
- ActiveInstances[_instanceID] = null;
- }
-
- private void InitializeInstanceID()
- {
- if (ActiveInstances[_instanceID] == null)
- {
- if (_instanceID == 0x00)
- _instanceID++;
-
- for (; _instanceID <= 0x10; _instanceID++)
- {
- if (_instanceID == 0x10)
- {
- GameObject.Destroy(gameObject);
- throw new System.OverflowException("You are only allowed 15 different contexts for MEC to run inside at one time.");
- }
-
- if (ActiveInstances[_instanceID] == null)
- {
- ActiveInstances[_instanceID] = this;
- break;
- }
- }
- }
- }
-
- void Update()
- {
- if (OnPreExecute != null)
- OnPreExecute();
-
- if (_lastSlowUpdateTime + TimeBetweenSlowUpdateCalls < Time.realtimeSinceStartup && _nextSlowUpdateProcessSlot > 0)
- {
- ProcessIndex coindex = new ProcessIndex { seg = Segment.SlowUpdate };
- if (UpdateTimeValues(coindex.seg))
- _lastSlowUpdateProcessSlot = _nextSlowUpdateProcessSlot;
-
- for (coindex.i = 0; coindex.i < _lastSlowUpdateProcessSlot; coindex.i++)
- {
- try
- {
- if (!SlowUpdatePaused[coindex.i] && !SlowUpdateHeld[coindex.i] && SlowUpdateProcesses[coindex.i] != null && !(localTime < SlowUpdateProcesses[coindex.i].Current))
- {
- currentCoroutine = _indexToHandle[coindex];
-
- if (ProfilerDebugAmount != DebugInfoType.None && _indexToHandle.ContainsKey(coindex))
- {
- Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine (Slow Update)" +
- (_processTags.ContainsKey(_indexToHandle[coindex]) ? ", tag " + _processTags[_indexToHandle[coindex]] : ", no tag"))
- : "Processing Coroutine (Slow Update)");
- }
-
- if (!SlowUpdateProcesses[coindex.i].MoveNext())
- {
- if (_indexToHandle.ContainsKey(coindex))
- KillCoroutinesOnInstance(_indexToHandle[coindex]);
- }
- else if (SlowUpdateProcesses[coindex.i] != null && float.IsNaN(SlowUpdateProcesses[coindex.i].Current))
- {
- if (ReplacementFunction != null)
- {
- SlowUpdateProcesses[coindex.i] = ReplacementFunction(SlowUpdateProcesses[coindex.i], _indexToHandle[coindex]);
- ReplacementFunction = null;
- }
- coindex.i--;
- }
-
- if (ProfilerDebugAmount != DebugInfoType.None)
- Profiler.EndSample();
- }
- }
- catch (System.Exception ex)
- {
- Debug.LogException(ex);
-
- if (ex is MissingReferenceException)
- Debug.LogError("This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\n"
- + "Example: Timing.RunCoroutine(_foo().CancelWith(gameObject), Segment.SlowUpdate);");
- }
- }
- }
-
- if (_nextUpdateProcessSlot > 0)
- {
- ProcessIndex coindex = new ProcessIndex { seg = Segment.Update };
- if (UpdateTimeValues(coindex.seg))
- _lastUpdateProcessSlot = _nextUpdateProcessSlot;
-
- for (coindex.i = 0; coindex.i < _lastUpdateProcessSlot; coindex.i++)
- {
- try
- {
- if (!UpdatePaused[coindex.i] && !UpdateHeld[coindex.i] && UpdateProcesses[coindex.i] != null && !(localTime < UpdateProcesses[coindex.i].Current))
- {
- currentCoroutine = _indexToHandle[coindex];
-
- if (ProfilerDebugAmount != DebugInfoType.None && _indexToHandle.ContainsKey(coindex))
- {
- Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine" +
- (_processTags.ContainsKey(_indexToHandle[coindex]) ? ", tag " + _processTags[_indexToHandle[coindex]] : ", no tag"))
- : "Processing Coroutine");
- }
-
- if (!UpdateProcesses[coindex.i].MoveNext())
- {
- if (_indexToHandle.ContainsKey(coindex))
- KillCoroutinesOnInstance(_indexToHandle[coindex]);
- }
- else if (UpdateProcesses[coindex.i] != null && float.IsNaN(UpdateProcesses[coindex.i].Current))
- {
- if (ReplacementFunction != null)
- {
- UpdateProcesses[coindex.i] = ReplacementFunction(UpdateProcesses[coindex.i], _indexToHandle[coindex]);
- ReplacementFunction = null;
- }
- coindex.i--;
- }
-
- if (ProfilerDebugAmount != DebugInfoType.None)
- Profiler.EndSample();
- }
- }
- catch (System.Exception ex)
- {
- Debug.LogException(ex);
-
- if (ex is MissingReferenceException)
- Debug.LogError("This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\n"
- + "Example: Timing.RunCoroutine(_foo().CancelWith(gameObject));");
- }
- }
- }
-
- currentCoroutine = default(CoroutineHandle);
-
- if(++_framesSinceUpdate > FramesUntilMaintenance)
- {
- _framesSinceUpdate = 0;
-
- if (ProfilerDebugAmount != DebugInfoType.None)
- Profiler.BeginSample("Maintenance Task");
-
- RemoveUnused();
-
- if (ProfilerDebugAmount != DebugInfoType.None)
- Profiler.EndSample();
- }
- }
-
- void FixedUpdate()
- {
- if (OnPreExecute != null)
- OnPreExecute();
-
- if (_nextFixedUpdateProcessSlot > 0)
- {
- ProcessIndex coindex = new ProcessIndex { seg = Segment.FixedUpdate };
- if (UpdateTimeValues(coindex.seg))
- _lastFixedUpdateProcessSlot = _nextFixedUpdateProcessSlot;
-
- for (coindex.i = 0; coindex.i < _lastFixedUpdateProcessSlot; coindex.i++)
- {
- try
- {
- if (!FixedUpdatePaused[coindex.i] && !FixedUpdateHeld[coindex.i] && FixedUpdateProcesses[coindex.i] != null && !(localTime < FixedUpdateProcesses[coindex.i].Current))
- {
- currentCoroutine = _indexToHandle[coindex];
-
-
- if (ProfilerDebugAmount != DebugInfoType.None && _indexToHandle.ContainsKey(coindex))
- {
- Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine" +
- (_processTags.ContainsKey(_indexToHandle[coindex]) ? ", tag " + _processTags[_indexToHandle[coindex]] : ", no tag"))
- : "Processing Coroutine");
- }
-
- if (!FixedUpdateProcesses[coindex.i].MoveNext())
- {
- if (_indexToHandle.ContainsKey(coindex))
- KillCoroutinesOnInstance(_indexToHandle[coindex]);
- }
- else if (FixedUpdateProcesses[coindex.i] != null && float.IsNaN(FixedUpdateProcesses[coindex.i].Current))
- {
- if (ReplacementFunction != null)
- {
- FixedUpdateProcesses[coindex.i] = ReplacementFunction(FixedUpdateProcesses[coindex.i], _indexToHandle[coindex]);
- ReplacementFunction = null;
- }
- coindex.i--;
- }
-
- if (ProfilerDebugAmount != DebugInfoType.None)
- Profiler.EndSample();
- }
- }
- catch (System.Exception ex)
- {
- Debug.LogException(ex);
-
- if (ex is MissingReferenceException)
- Debug.LogError("This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\n"
- + "Example: Timing.RunCoroutine(_foo().CancelWith(gameObject), Segment.FixedUpdate);");
- }
- }
-
- currentCoroutine = default(CoroutineHandle);
- }
- }
-
- void LateUpdate()
- {
- if (OnPreExecute != null)
- OnPreExecute();
-
- if (_nextLateUpdateProcessSlot > 0)
- {
- ProcessIndex coindex = new ProcessIndex { seg = Segment.LateUpdate };
- if (UpdateTimeValues(coindex.seg))
- _lastLateUpdateProcessSlot = _nextLateUpdateProcessSlot;
-
- for (coindex.i = 0; coindex.i < _lastLateUpdateProcessSlot; coindex.i++)
- {
- try
- {
- if (!LateUpdatePaused[coindex.i] && !LateUpdateHeld[coindex.i] && LateUpdateProcesses[coindex.i] != null && !(localTime < LateUpdateProcesses[coindex.i].Current))
- {
- currentCoroutine = _indexToHandle[coindex];
-
-
- if (ProfilerDebugAmount != DebugInfoType.None && _indexToHandle.ContainsKey(coindex))
- {
- Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine" +
- (_processTags.ContainsKey(_indexToHandle[coindex]) ? ", tag " + _processTags[_indexToHandle[coindex]] : ", no tag"))
- : "Processing Coroutine");
- }
-
- if (!LateUpdateProcesses[coindex.i].MoveNext())
- {
- if (_indexToHandle.ContainsKey(coindex))
- KillCoroutinesOnInstance(_indexToHandle[coindex]);
- }
- else if (LateUpdateProcesses[coindex.i] != null && float.IsNaN(LateUpdateProcesses[coindex.i].Current))
- {
- if (ReplacementFunction != null)
- {
- LateUpdateProcesses[coindex.i] = ReplacementFunction(LateUpdateProcesses[coindex.i], _indexToHandle[coindex]);
- ReplacementFunction = null;
- }
- coindex.i--;
- }
-
- if (ProfilerDebugAmount != DebugInfoType.None)
- Profiler.EndSample();
- }
- }
- catch (System.Exception ex)
- {
- Debug.LogException(ex);
-
- if (ex is MissingReferenceException)
- Debug.LogError("This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\n"
- + "Example: Timing.RunCoroutine(_foo().CancelWith(gameObject), Segment.LateUpdate);");
- }
- }
- currentCoroutine = default(CoroutineHandle);
- }
- }
-
- private void RemoveUnused()
- {
- var waitTrigsEnum = _waitingTriggers.GetEnumerator();
- while (waitTrigsEnum.MoveNext())
- {
- if (waitTrigsEnum.Current.Value.Count == 0)
- {
- _waitingTriggers.Remove(waitTrigsEnum.Current.Key);
- waitTrigsEnum = _waitingTriggers.GetEnumerator();
- continue;
- }
-
- if (_handleToIndex.ContainsKey(waitTrigsEnum.Current.Key) && CoindexIsNull(_handleToIndex[waitTrigsEnum.Current.Key]))
- {
- CloseWaitingProcess(waitTrigsEnum.Current.Key);
- waitTrigsEnum = _waitingTriggers.GetEnumerator();
- }
- }
-
- ProcessIndex outer, inner;
- outer.seg = inner.seg = Segment.Update;
-
- for (outer.i = inner.i = 0; outer.i < _nextUpdateProcessSlot; outer.i++)
- {
- if (UpdateProcesses[outer.i] != null)
- {
- if (outer.i != inner.i)
- {
- UpdateProcesses[inner.i] = UpdateProcesses[outer.i];
- UpdatePaused[inner.i] = UpdatePaused[outer.i];
- UpdateHeld[inner.i] = UpdateHeld[outer.i];
-
- if (_indexToHandle.ContainsKey(inner))
- {
- RemoveTag(_indexToHandle[inner]);
- _handleToIndex.Remove(_indexToHandle[inner]);
- _indexToHandle.Remove(inner);
- }
-
- _handleToIndex[_indexToHandle[outer]] = inner;
- _indexToHandle.Add(inner, _indexToHandle[outer]);
- _indexToHandle.Remove(outer);
- }
- inner.i++;
- }
- }
- for (outer.i = inner.i; outer.i < _nextUpdateProcessSlot; outer.i++)
- {
- UpdateProcesses[outer.i] = null;
- UpdatePaused[outer.i] = false;
- UpdateHeld[outer.i] = false;
-
- if (_indexToHandle.ContainsKey(outer))
- {
- RemoveTag(_indexToHandle[outer]);
-
- _handleToIndex.Remove(_indexToHandle[outer]);
- _indexToHandle.Remove(outer);
- }
- }
-
- _lastUpdateProcessSlot -= _nextUpdateProcessSlot - inner.i;
- UpdateCoroutines = _nextUpdateProcessSlot = inner.i;
-
- outer.seg = inner.seg = Segment.FixedUpdate;
- for (outer.i = inner.i = 0; outer.i < _nextFixedUpdateProcessSlot; outer.i++)
- {
- if (FixedUpdateProcesses[outer.i] != null)
- {
- if (outer.i != inner.i)
- {
- FixedUpdateProcesses[inner.i] = FixedUpdateProcesses[outer.i];
- FixedUpdatePaused[inner.i] = FixedUpdatePaused[outer.i];
- FixedUpdateHeld[inner.i] = FixedUpdateHeld[outer.i];
-
- if (_indexToHandle.ContainsKey(inner))
- {
- RemoveTag(_indexToHandle[inner]);
- _handleToIndex.Remove(_indexToHandle[inner]);
- _indexToHandle.Remove(inner);
- }
-
- _handleToIndex[_indexToHandle[outer]] = inner;
- _indexToHandle.Add(inner, _indexToHandle[outer]);
- _indexToHandle.Remove(outer);
- }
- inner.i++;
- }
- }
- for (outer.i = inner.i; outer.i < _nextFixedUpdateProcessSlot; outer.i++)
- {
- FixedUpdateProcesses[outer.i] = null;
- FixedUpdatePaused[outer.i] = false;
- FixedUpdateHeld[outer.i] = false;
-
- if (_indexToHandle.ContainsKey(outer))
- {
- RemoveTag(_indexToHandle[outer]);
-
- _handleToIndex.Remove(_indexToHandle[outer]);
- _indexToHandle.Remove(outer);
- }
- }
-
- _lastFixedUpdateProcessSlot -= _nextFixedUpdateProcessSlot - inner.i;
- FixedUpdateCoroutines = _nextFixedUpdateProcessSlot = inner.i;
-
- outer.seg = inner.seg = Segment.LateUpdate;
- for (outer.i = inner.i = 0; outer.i < _nextLateUpdateProcessSlot; outer.i++)
- {
- if (LateUpdateProcesses[outer.i] != null)
- {
- if (outer.i != inner.i)
- {
- LateUpdateProcesses[inner.i] = LateUpdateProcesses[outer.i];
- LateUpdatePaused[inner.i] = LateUpdatePaused[outer.i];
- LateUpdateHeld[inner.i] = LateUpdateHeld[outer.i];
-
- if (_indexToHandle.ContainsKey(inner))
- {
- RemoveTag(_indexToHandle[inner]);
- _handleToIndex.Remove(_indexToHandle[inner]);
- _indexToHandle.Remove(inner);
- }
-
- _handleToIndex[_indexToHandle[outer]] = inner;
- _indexToHandle.Add(inner, _indexToHandle[outer]);
- _indexToHandle.Remove(outer);
- }
- inner.i++;
- }
- }
- for (outer.i = inner.i; outer.i < _nextLateUpdateProcessSlot; outer.i++)
- {
- LateUpdateProcesses[outer.i] = null;
- LateUpdatePaused[outer.i] = false;
- LateUpdateHeld[outer.i] = false;
-
- if (_indexToHandle.ContainsKey(outer))
- {
- RemoveTag(_indexToHandle[outer]);
-
- _handleToIndex.Remove(_indexToHandle[outer]);
- _indexToHandle.Remove(outer);
- }
- }
-
- _lastLateUpdateProcessSlot -= _nextLateUpdateProcessSlot - inner.i;
- LateUpdateCoroutines = _nextLateUpdateProcessSlot = inner.i;
-
- outer.seg = inner.seg = Segment.SlowUpdate;
- for (outer.i = inner.i = 0; outer.i < _nextSlowUpdateProcessSlot; outer.i++)
- {
- if (SlowUpdateProcesses[outer.i] != null)
- {
- if (outer.i != inner.i)
- {
- SlowUpdateProcesses[inner.i] = SlowUpdateProcesses[outer.i];
- SlowUpdatePaused[inner.i] = SlowUpdatePaused[outer.i];
- SlowUpdateHeld[inner.i] = SlowUpdateHeld[outer.i];
-
- if (_indexToHandle.ContainsKey(inner))
- {
- RemoveTag(_indexToHandle[inner]);
- _handleToIndex.Remove(_indexToHandle[inner]);
- _indexToHandle.Remove(inner);
- }
-
- _handleToIndex[_indexToHandle[outer]] = inner;
- _indexToHandle.Add(inner, _indexToHandle[outer]);
- _indexToHandle.Remove(outer);
- }
- inner.i++;
- }
- }
- for (outer.i = inner.i; outer.i < _nextSlowUpdateProcessSlot; outer.i++)
- {
- SlowUpdateProcesses[outer.i] = null;
- SlowUpdatePaused[outer.i] = false;
- SlowUpdateHeld[outer.i] = false;
-
- if (_indexToHandle.ContainsKey(outer))
- {
- RemoveTag(_indexToHandle[outer]);
-
- _handleToIndex.Remove(_indexToHandle[outer]);
- _indexToHandle.Remove(outer);
- }
- }
-
- _lastSlowUpdateProcessSlot -= _nextSlowUpdateProcessSlot - inner.i;
- SlowUpdateCoroutines = _nextSlowUpdateProcessSlot = inner.i;
- }
-
- /// <summary>
- /// Run a new coroutine in the Update segment.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine)
- {
- return coroutine == null ? new CoroutineHandle()
- : Instance.RunCoroutineInternal(coroutine, Segment.Update, null, new CoroutineHandle(Instance._instanceID), true);
- }
-
- /// <summary>
- /// Run a new coroutine in the Update segment.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <param name="tag">An optional tag to attach to the coroutine which can later be used for Kill operations.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, string tag)
- {
- return coroutine == null ? new CoroutineHandle()
- : Instance.RunCoroutineInternal(coroutine, Segment.Update, tag, new CoroutineHandle(Instance._instanceID), true);
- }
-
- /// <summary>
- /// Run a new coroutine.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <param name="segment">The segment that the coroutine should run in.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment segment)
- {
- return coroutine == null ? new CoroutineHandle()
- : Instance.RunCoroutineInternal(coroutine, segment, null, new CoroutineHandle(Instance._instanceID), true);
- }
-
- /// <summary>
- /// Run a new coroutine.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <param name="segment">The segment that the coroutine should run in.</param>
- /// <param name="tag">An optional tag to attach to the coroutine which can later be used for Kill operations.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment segment, string tag)
- {
- return coroutine == null ? new CoroutineHandle()
- : Instance.RunCoroutineInternal(coroutine, segment, tag, new CoroutineHandle(Instance._instanceID), true);
- }
-
- /// <summary>
- /// Run a new coroutine on this Timing instance in the Update segment.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine)
- {
- return coroutine == null ? new CoroutineHandle()
- : RunCoroutineInternal(coroutine, Segment.Update, null, new CoroutineHandle(_instanceID), true);
- }
-
- /// <summary>
- /// Run a new coroutine on this Timing instance in the Update segment.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <param name="tag">An optional tag to attach to the coroutine which can later be used for Kill operations.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, string tag)
- {
- return coroutine == null ? new CoroutineHandle()
- : RunCoroutineInternal(coroutine, Segment.Update, tag, new CoroutineHandle(_instanceID), true);
- }
-
- /// <summary>
- /// Run a new coroutine on this Timing instance.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <param name="segment">The segment that the coroutine should run in.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment segment)
- {
- return coroutine == null ? new CoroutineHandle()
- : RunCoroutineInternal(coroutine, segment, null, new CoroutineHandle(_instanceID), true);
- }
-
- /// <summary>
- /// Run a new coroutine on this Timing instance.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <param name="segment">The segment that the coroutine should run in.</param>
- /// <param name="tag">An optional tag to attach to the coroutine which can later be used for Kill operations.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment segment, string tag)
- {
- return coroutine == null ? new CoroutineHandle()
- : RunCoroutineInternal(coroutine, segment, tag, new CoroutineHandle(_instanceID), true);
- }
-
-
- private CoroutineHandle RunCoroutineInternal(IEnumerator<float> coroutine, Segment segment, string tag, CoroutineHandle handle, bool prewarm)
- {
- ProcessIndex slot = new ProcessIndex { seg = segment };
-
- if (_handleToIndex.ContainsKey(handle))
- {
- _indexToHandle.Remove(_handleToIndex[handle]);
- _handleToIndex.Remove(handle);
- }
-
- float currentLocalTime = localTime;
- float currentDeltaTime = deltaTime;
- CoroutineHandle cachedHandle = currentCoroutine;
- currentCoroutine = handle;
-
- switch (segment)
- {
- case Segment.Update:
-
- if (_nextUpdateProcessSlot >= UpdateProcesses.Length)
- {
- IEnumerator<float>[] oldProcArray = UpdateProcesses;
- bool[] oldPausedArray = UpdatePaused;
- bool[] oldHeldArray = UpdateHeld;
-
- UpdateProcesses = new IEnumerator<float>[UpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
- UpdatePaused = new bool[UpdateProcesses.Length];
- UpdateHeld = new bool[UpdateProcesses.Length];
-
- for (int i = 0; i < oldProcArray.Length; i++)
- {
- UpdateProcesses[i] = oldProcArray[i];
- UpdatePaused[i] = oldPausedArray[i];
- UpdateHeld[i] = oldHeldArray[i];
- }
- }
-
- if (UpdateTimeValues(slot.seg))
- _lastUpdateProcessSlot = _nextUpdateProcessSlot;
-
- slot.i = _nextUpdateProcessSlot++;
- UpdateProcesses[slot.i] = coroutine;
-
- if (null != tag)
- AddTag(tag, handle);
-
- _indexToHandle.Add(slot, handle);
- _handleToIndex.Add(handle, slot);
-
- while (prewarm)
- {
- if (!UpdateProcesses[slot.i].MoveNext())
- {
- if (_indexToHandle.ContainsKey(slot))
- KillCoroutinesOnInstance(_indexToHandle[slot]);
-
- prewarm = false;
- }
- else if (UpdateProcesses[slot.i] != null && float.IsNaN(UpdateProcesses[slot.i].Current))
- {
- if (ReplacementFunction != null)
- {
- UpdateProcesses[slot.i] = ReplacementFunction(UpdateProcesses[slot.i], _indexToHandle[slot]);
- ReplacementFunction = null;
- }
- prewarm = !UpdatePaused[slot.i] && !UpdateHeld[slot.i];
- }
- else
- {
- prewarm = false;
- }
- }
-
- break;
-
- case Segment.FixedUpdate:
-
- if (_nextFixedUpdateProcessSlot >= FixedUpdateProcesses.Length)
- {
- IEnumerator<float>[] oldProcArray = FixedUpdateProcesses;
- bool[] oldPausedArray = FixedUpdatePaused;
- bool[] oldHeldArray = FixedUpdateHeld;
-
- FixedUpdateProcesses = new IEnumerator<float>[FixedUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
- FixedUpdatePaused = new bool[FixedUpdateProcesses.Length];
- FixedUpdateHeld = new bool[FixedUpdateProcesses.Length];
-
- for (int i = 0; i < oldProcArray.Length; i++)
- {
- FixedUpdateProcesses[i] = oldProcArray[i];
- FixedUpdatePaused[i] = oldPausedArray[i];
- FixedUpdateHeld[i] = oldHeldArray[i];
- }
- }
-
- if (UpdateTimeValues(slot.seg))
- _lastFixedUpdateProcessSlot = _nextFixedUpdateProcessSlot;
-
- slot.i = _nextFixedUpdateProcessSlot++;
- FixedUpdateProcesses[slot.i] = coroutine;
-
- if (null != tag)
- AddTag(tag, handle);
-
- _indexToHandle.Add(slot, handle);
- _handleToIndex.Add(handle, slot);
-
- while (prewarm)
- {
- if (!FixedUpdateProcesses[slot.i].MoveNext())
- {
- if (_indexToHandle.ContainsKey(slot))
- KillCoroutinesOnInstance(_indexToHandle[slot]);
-
- prewarm = false;
- }
- else if (FixedUpdateProcesses[slot.i] != null && float.IsNaN(FixedUpdateProcesses[slot.i].Current))
- {
- if (ReplacementFunction != null)
- {
- FixedUpdateProcesses[slot.i] = ReplacementFunction(FixedUpdateProcesses[slot.i], _indexToHandle[slot]);
- ReplacementFunction = null;
- }
- prewarm = !FixedUpdatePaused[slot.i] && !FixedUpdateHeld[slot.i];
- }
- else
- {
- prewarm = false;
- }
- }
-
- break;
-
- case Segment.LateUpdate:
-
- if (_nextLateUpdateProcessSlot >= LateUpdateProcesses.Length)
- {
- IEnumerator<float>[] oldProcArray = LateUpdateProcesses;
- bool[] oldPausedArray = LateUpdatePaused;
- bool[] oldHeldArray = LateUpdateHeld;
-
- LateUpdateProcesses = new IEnumerator<float>[LateUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
- LateUpdatePaused = new bool[LateUpdateProcesses.Length];
- LateUpdateHeld = new bool[LateUpdateProcesses.Length];
-
- for (int i = 0; i < oldProcArray.Length; i++)
- {
- LateUpdateProcesses[i] = oldProcArray[i];
- LateUpdatePaused[i] = oldPausedArray[i];
- LateUpdateHeld[i] = oldHeldArray[i];
- }
- }
-
- if (UpdateTimeValues(slot.seg))
- _lastLateUpdateProcessSlot = _nextLateUpdateProcessSlot;
-
- slot.i = _nextLateUpdateProcessSlot++;
- LateUpdateProcesses[slot.i] = coroutine;
-
- if (tag != null)
- AddTag(tag, handle);
-
- _indexToHandle.Add(slot, handle);
- _handleToIndex.Add(handle, slot);
-
- while (prewarm)
- {
- if (!LateUpdateProcesses[slot.i].MoveNext())
- {
- if (_indexToHandle.ContainsKey(slot))
- KillCoroutinesOnInstance(_indexToHandle[slot]);
-
- prewarm = false;
- }
- else if (LateUpdateProcesses[slot.i] != null && float.IsNaN(LateUpdateProcesses[slot.i].Current))
- {
- if (ReplacementFunction != null)
- {
- LateUpdateProcesses[slot.i] = ReplacementFunction(LateUpdateProcesses[slot.i], _indexToHandle[slot]);
- ReplacementFunction = null;
- }
- prewarm = !LateUpdatePaused[slot.i] && !LateUpdateHeld[slot.i];
- }
- else
- {
- prewarm = false;
- }
- }
-
- break;
-
- case Segment.SlowUpdate:
-
- if (_nextSlowUpdateProcessSlot >= SlowUpdateProcesses.Length)
- {
- IEnumerator<float>[] oldProcArray = SlowUpdateProcesses;
- bool[] oldPausedArray = SlowUpdatePaused;
- bool[] oldHeldArray = SlowUpdateHeld;
-
- SlowUpdateProcesses = new IEnumerator<float>[SlowUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
- SlowUpdatePaused = new bool[SlowUpdateProcesses.Length];
- SlowUpdateHeld = new bool[SlowUpdateProcesses.Length];
-
- for (int i = 0; i < oldProcArray.Length; i++)
- {
- SlowUpdateProcesses[i] = oldProcArray[i];
- SlowUpdatePaused[i] = oldPausedArray[i];
- SlowUpdateHeld[i] = oldHeldArray[i];
- }
- }
-
- if (UpdateTimeValues(slot.seg))
- _lastSlowUpdateProcessSlot = _nextSlowUpdateProcessSlot;
-
- slot.i = _nextSlowUpdateProcessSlot++;
- SlowUpdateProcesses[slot.i] = coroutine;
-
- if (tag != null)
- AddTag(tag, handle);
-
- _indexToHandle.Add(slot, handle);
- _handleToIndex.Add(handle, slot);
-
- while (prewarm)
- {
- if (!SlowUpdateProcesses[slot.i].MoveNext())
- {
- if (_indexToHandle.ContainsKey(slot))
- KillCoroutinesOnInstance(_indexToHandle[slot]);
-
- prewarm = false;
- }
- else if (SlowUpdateProcesses[slot.i] != null && float.IsNaN(SlowUpdateProcesses[slot.i].Current))
- {
- if (ReplacementFunction != null)
- {
- SlowUpdateProcesses[slot.i] = ReplacementFunction(SlowUpdateProcesses[slot.i], _indexToHandle[slot]);
- ReplacementFunction = null;
- }
- prewarm = !SlowUpdatePaused[slot.i] && !SlowUpdateHeld[slot.i];
- }
- else
- {
- prewarm = false;
- }
- }
-
- break;
-
- default:
- handle = new CoroutineHandle();
- break;
- }
-
- localTime = currentLocalTime;
- deltaTime = currentDeltaTime;
- currentCoroutine = cachedHandle;
-
- return handle;
- }
-
- /// <summary>
- /// This will kill all coroutines running on the main MEC instance and reset the context.
- /// NOTE: If you call this function from within a running coroutine then you MUST end the current
- /// coroutine. If the running coroutine has more work to do you may run a new "part 2" coroutine
- /// function to complete the task before ending the current one.
- /// </summary>
- /// <returns>The number of coroutines that were killed.</returns>
- public static int KillCoroutines()
- {
- return _instance == null ? 0 : _instance.KillCoroutinesOnInstance();
- }
-
- /// <summary>
- /// This will kill all coroutines running on the current MEC instance and reset the context.
- /// NOTE: If you call this function from within a running coroutine then you MUST end the current
- /// coroutine. If the running coroutine has more work to do you may run a new "part 2" coroutine
- /// function to complete the task before ending the current one.
- /// </summary>
- /// <returns>The number of coroutines that were killed.</returns>
- public int KillCoroutinesOnInstance()
- {
- int retVal = _nextUpdateProcessSlot + _nextLateUpdateProcessSlot + _nextFixedUpdateProcessSlot + _nextSlowUpdateProcessSlot;
-
- UpdateProcesses = new IEnumerator<float>[InitialBufferSizeLarge];
- UpdatePaused = new bool[InitialBufferSizeLarge];
- UpdateHeld = new bool[InitialBufferSizeLarge];
- UpdateCoroutines = 0;
- _nextUpdateProcessSlot = 0;
-
- LateUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
- LateUpdatePaused = new bool[InitialBufferSizeSmall];
- LateUpdateHeld = new bool[InitialBufferSizeSmall];
- LateUpdateCoroutines = 0;
- _nextLateUpdateProcessSlot = 0;
-
- FixedUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
- FixedUpdatePaused = new bool[InitialBufferSizeMedium];
- FixedUpdateHeld = new bool[InitialBufferSizeMedium];
- FixedUpdateCoroutines = 0;
- _nextFixedUpdateProcessSlot = 0;
-
- SlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
- SlowUpdatePaused = new bool[InitialBufferSizeMedium];
- SlowUpdateHeld = new bool[InitialBufferSizeMedium];
- SlowUpdateCoroutines = 0;
- _nextSlowUpdateProcessSlot = 0;
-
- _processTags.Clear();
- _taggedProcesses.Clear();
- _handleToIndex.Clear();
- _indexToHandle.Clear();
- _waitingTriggers.Clear();
- _expansions = (ushort)((_expansions / 2) + 1);
-
- return retVal;
- }
-
- /// <summary>
- /// Kills the instances of the coroutine handle if it exists.
- /// </summary>
- /// <param name="handle">The handle of the coroutine to kill.</param>
- /// <returns>The number of coroutines that were found and killed (0 or 1).</returns>
- public static int KillCoroutines(CoroutineHandle handle)
- {
- return ActiveInstances[handle.Key] != null ? GetInstance(handle.Key).KillCoroutinesOnInstance(handle) : 0;
- }
-
- /// <summary>
- /// Kills the instance of the coroutine handle on this Timing instance if it exists.
- /// </summary>
- /// <param name="handle">The handle of the coroutine to kill.</param>
- /// <returns>The number of coroutines that were found and killed (0 or 1).</returns>
- public int KillCoroutinesOnInstance(CoroutineHandle handle)
- {
- bool foundOne = false;
-
- if (_handleToIndex.ContainsKey(handle))
- {
- if (_waitingTriggers.ContainsKey(handle))
- CloseWaitingProcess(handle);
-
- foundOne = CoindexExtract(_handleToIndex[handle]) != null;
- RemoveTag(handle);
- }
-
- return foundOne ? 1 : 0;
- }
-
- /// <summary>
- /// Kills all coroutines that have the given tag.
- /// </summary>
- /// <param name="tag">All coroutines with this tag will be killed.</param>
- /// <returns>The number of coroutines that were found and killed.</returns>
- public static int KillCoroutines(string tag)
- {
- return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(tag);
- }
-
- /// <summary>
- /// Kills all coroutines that have the given tag.
- /// </summary>
- /// <param name="tag">All coroutines with this tag will be killed.</param>
- /// <returns>The number of coroutines that were found and killed.</returns>
- public int KillCoroutinesOnInstance(string tag)
- {
- if (tag == null) return 0;
- int numberFound = 0;
-
- while (_taggedProcesses.ContainsKey(tag))
- {
- var matchEnum = _taggedProcesses[tag].GetEnumerator();
- matchEnum.MoveNext();
-
- if (Nullify(_handleToIndex[matchEnum.Current]))
- {
- if (_waitingTriggers.ContainsKey(matchEnum.Current))
- CloseWaitingProcess(matchEnum.Current);
-
- numberFound++;
- }
-
- RemoveTag(matchEnum.Current);
-
- if (_handleToIndex.ContainsKey(matchEnum.Current))
- {
- _indexToHandle.Remove(_handleToIndex[matchEnum.Current]);
- _handleToIndex.Remove(matchEnum.Current);
- }
- }
-
- return numberFound;
- }
-
- /// <summary>
- /// This will pause all coroutines running on the current MEC instance until ResumeCoroutines is called.
- /// </summary>
- /// <returns>The number of coroutines that were paused.</returns>
- public static int PauseCoroutines()
- {
- return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance();
- }
-
- /// <summary>
- /// This will pause all coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
- /// </summary>
- /// <returns>The number of coroutines that were paused.</returns>
- public int PauseCoroutinesOnInstance()
- {
- int count = 0;
- int i;
- for (i = 0; i < _nextUpdateProcessSlot; i++)
- {
- if (!UpdatePaused[i] && UpdateProcesses[i] != null)
- {
- count++;
- UpdatePaused[i] = true;
-
- if (UpdateProcesses[i].Current > GetSegmentTime(Segment.Update))
- UpdateProcesses[i] = _InjectDelay(UpdateProcesses[i],
- UpdateProcesses[i].Current - GetSegmentTime(Segment.Update));
- }
- }
-
- for (i = 0; i < _nextLateUpdateProcessSlot; i++)
- {
- if (!LateUpdatePaused[i] && LateUpdateProcesses[i] != null)
- {
- count++;
- LateUpdatePaused[i] = true;
-
- if (LateUpdateProcesses[i].Current > GetSegmentTime(Segment.LateUpdate))
- LateUpdateProcesses[i] = _InjectDelay(LateUpdateProcesses[i],
- LateUpdateProcesses[i].Current - GetSegmentTime(Segment.LateUpdate));
- }
- }
-
- for (i = 0; i < _nextFixedUpdateProcessSlot; i++)
- {
- if (!FixedUpdatePaused[i] && FixedUpdateProcesses[i] != null)
- {
- count++;
- FixedUpdatePaused[i] = true;
-
- if (FixedUpdateProcesses[i].Current > GetSegmentTime(Segment.FixedUpdate))
- FixedUpdateProcesses[i] = _InjectDelay(FixedUpdateProcesses[i],
- FixedUpdateProcesses[i].Current - GetSegmentTime(Segment.FixedUpdate));
- }
- }
-
- for (i = 0; i < _nextSlowUpdateProcessSlot; i++)
- {
- if (!SlowUpdatePaused[i] && SlowUpdateProcesses[i] != null)
- {
- count++;
- SlowUpdatePaused[i] = true;
-
- if (SlowUpdateProcesses[i].Current > GetSegmentTime(Segment.SlowUpdate))
- SlowUpdateProcesses[i] = _InjectDelay(SlowUpdateProcesses[i],
- SlowUpdateProcesses[i].Current - GetSegmentTime(Segment.SlowUpdate));
- }
- }
-
- return count;
- }
-
- /// <summary>
- /// This will pause any matching coroutines until ResumeCoroutines is called.
- /// </summary>
- /// <param name="handle">The handle of the coroutine to pause.</param>
- /// <returns>The number of coroutines that were paused (0 or 1).</returns>
- public static int PauseCoroutines(CoroutineHandle handle)
- {
- return ActiveInstances[handle.Key] != null ? GetInstance(handle.Key).PauseCoroutinesOnInstance(handle) : 0;
- }
-
- /// <summary>
- /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
- /// </summary>
- /// <param name="handle">The handle of the coroutine to pause.</param>
- /// <returns>The number of coroutines that were paused (0 or 1).</returns>
- public int PauseCoroutinesOnInstance(CoroutineHandle handle)
- {
- return _handleToIndex.ContainsKey(handle) && !CoindexIsNull(_handleToIndex[handle]) && !SetPause(_handleToIndex[handle], true) ? 1 : 0;
- }
-
- /// <summary>
- /// This will pause any matching coroutines running on the current MEC instance until ResumeCoroutines is called.
- /// </summary>
- /// <param name="tag">Any coroutines with a matching tag will be paused.</param>
- /// <returns>The number of coroutines that were paused.</returns>
- public static int PauseCoroutines(string tag)
- {
- return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(tag);
- }
-
- /// <summary>
- /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
- /// </summary>
- /// <param name="tag">Any coroutines with a matching tag will be paused.</param>
- /// <returns>The number of coroutines that were paused.</returns>
- public int PauseCoroutinesOnInstance(string tag)
- {
- if (tag == null || !_taggedProcesses.ContainsKey(tag))
- return 0;
-
- int count = 0;
- var matchesEnum = _taggedProcesses[tag].GetEnumerator();
-
- while (matchesEnum.MoveNext())
- if (!CoindexIsNull(_handleToIndex[matchesEnum.Current]) && !SetPause(_handleToIndex[matchesEnum.Current], true))
- count++;
-
- return count;
- }
-
- /// <summary>
- /// This resumes all coroutines on the current MEC instance if they are currently paused, otherwise it has
- /// no effect.
- /// </summary>
- /// <returns>The number of coroutines that were resumed.</returns>
- public static int ResumeCoroutines()
- {
- return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance();
- }
-
- /// <summary>
- /// This resumes all coroutines on this MEC instance if they are currently paused, otherwise it has no effect.
- /// </summary>
- /// <returns>The number of coroutines that were resumed.</returns>
- public int ResumeCoroutinesOnInstance()
- {
- int count = 0;
- ProcessIndex coindex;
- for (coindex.i = 0, coindex.seg = Segment.Update; coindex.i < _nextUpdateProcessSlot; coindex.i++)
- {
- if (UpdatePaused[coindex.i] && UpdateProcesses[coindex.i] != null)
- {
- UpdatePaused[coindex.i] = false;
- count++;
- }
- }
-
- for (coindex.i = 0, coindex.seg = Segment.LateUpdate; coindex.i < _nextLateUpdateProcessSlot; coindex.i++)
- {
- if (LateUpdatePaused[coindex.i] && LateUpdateProcesses[coindex.i] != null)
- {
- LateUpdatePaused[coindex.i] = false;
- count++;
- }
- }
-
- for (coindex.i = 0, coindex.seg = Segment.FixedUpdate; coindex.i < _nextFixedUpdateProcessSlot; coindex.i++)
- {
- if (FixedUpdatePaused[coindex.i] && FixedUpdateProcesses[coindex.i] != null)
- {
- FixedUpdatePaused[coindex.i] = false;
- count++;
- }
- }
-
- for (coindex.i = 0, coindex.seg = Segment.SlowUpdate; coindex.i < _nextSlowUpdateProcessSlot; coindex.i++)
- {
- if (SlowUpdatePaused[coindex.i] && SlowUpdateProcesses[coindex.i] != null)
- {
- SlowUpdatePaused[coindex.i] = false;
- count++;
- }
- }
-
- return count;
- }
-
- /// <summary>
- /// This will resume any matching coroutines.
- /// </summary>
- /// <param name="handle">The handle of the coroutine to resume.</param>
- /// <returns>The number of coroutines that were resumed (0 or 1).</returns>
- public static int ResumeCoroutines(CoroutineHandle handle)
- {
- return ActiveInstances[handle.Key] != null ? GetInstance(handle.Key).ResumeCoroutinesOnInstance(handle) : 0;
- }
-
- /// <summary>
- /// This will resume any matching coroutines running on this MEC instance.
- /// </summary>
- /// <param name="handle">The handle of the coroutine to resume.</param>
- /// <returns>The number of coroutines that were resumed (0 or 1).</returns>
- public int ResumeCoroutinesOnInstance(CoroutineHandle handle)
- {
- return _handleToIndex.ContainsKey(handle) &&
- !CoindexIsNull(_handleToIndex[handle]) && SetPause(_handleToIndex[handle], false) ? 1 : 0;
- }
-
- /// <summary>
- /// This resumes any matching coroutines on the current MEC instance if they are currently paused, otherwise it has
- /// no effect.
- /// </summary>
- /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param>
- /// <returns>The number of coroutines that were resumed.</returns>
- public static int ResumeCoroutines(string tag)
- {
- return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(tag);
- }
-
- /// <summary>
- /// This resumes any matching coroutines on this MEC instance if they are currently paused, otherwise it has no effect.
- /// </summary>
- /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param>
- /// <returns>The number of coroutines that were resumed.</returns>
- public int ResumeCoroutinesOnInstance(string tag)
- {
- if (tag == null || !_taggedProcesses.ContainsKey(tag))
- return 0;
- int count = 0;
-
- var indexesEnum = _taggedProcesses[tag].GetEnumerator();
- while (indexesEnum.MoveNext())
- {
- if (!CoindexIsNull(_handleToIndex[indexesEnum.Current]) && SetPause(_handleToIndex[indexesEnum.Current], false))
- {
- count++;
- }
- }
-
- return count;
- }
-
- private bool UpdateTimeValues(Segment segment)
- {
- switch(segment)
- {
- case Segment.Update:
- if (_currentUpdateFrame != Time.frameCount)
- {
- deltaTime = Time.deltaTime;
- _lastUpdateTime += deltaTime;
- localTime = _lastUpdateTime;
- _currentUpdateFrame = Time.frameCount;
- return true;
- }
- else
- {
- deltaTime = Time.deltaTime;
- localTime = _lastUpdateTime;
- return false;
- }
- case Segment.LateUpdate:
- if (_currentLateUpdateFrame != Time.frameCount)
- {
- deltaTime = Time.deltaTime;
- _lastLateUpdateTime += deltaTime;
- localTime = _lastLateUpdateTime;
- _currentLateUpdateFrame = Time.frameCount;
- return true;
- }
- else
- {
- deltaTime = Time.deltaTime;
- localTime = _lastLateUpdateTime;
- return false;
- }
- case Segment.FixedUpdate:
- deltaTime = Time.fixedDeltaTime;
- localTime = Time.fixedTime;
-
- if (_lastFixedUpdateTime + 0.0001f < Time.fixedTime)
- {
- _lastFixedUpdateTime = Time.fixedTime;
- return true;
- }
-
- return false;
- case Segment.SlowUpdate:
- if (_currentSlowUpdateFrame != Time.frameCount)
- {
- deltaTime = _lastSlowUpdateDeltaTime = Time.realtimeSinceStartup - _lastSlowUpdateTime;
- localTime = _lastSlowUpdateTime = Time.realtimeSinceStartup;
- _currentSlowUpdateFrame = Time.frameCount;
- return true;
- }
- else
- {
- deltaTime = _lastSlowUpdateDeltaTime;
- localTime = _lastSlowUpdateTime;
- return false;
- }
- }
- return true;
- }
-
- private float GetSegmentTime(Segment segment)
- {
- switch (segment)
- {
- case Segment.Update:
- if (_currentUpdateFrame == Time.frameCount)
- return _lastUpdateTime;
- else
- return _lastUpdateTime + Time.deltaTime;
- case Segment.LateUpdate:
- if (_currentUpdateFrame == Time.frameCount)
- return _lastLateUpdateTime;
- else
- return _lastLateUpdateTime + Time.deltaTime;
- case Segment.FixedUpdate:
- return Time.fixedTime;
- case Segment.SlowUpdate:
- return Time.realtimeSinceStartup;
- default:
- return 0f;
- }
- }
-
- /// <summary>
- /// Retrieves the MEC manager that corresponds to the supplied instance id.
- /// </summary>
- /// <param name="ID">The instance ID.</param>
- /// <returns>The manager, or null if not found.</returns>
- public static Timing GetInstance(byte ID)
- {
- if (ID >= 0x10)
- return null;
- return ActiveInstances[ID];
- }
-
- private void AddTag(string tag, CoroutineHandle coindex)
- {
- _processTags.Add(coindex, tag);
-
- if (_taggedProcesses.ContainsKey(tag))
- _taggedProcesses[tag].Add(coindex);
- else
- _taggedProcesses.Add(tag, new HashSet<CoroutineHandle> { coindex });
- }
-
- private void RemoveTag(CoroutineHandle coindex)
- {
- if (_processTags.ContainsKey(coindex))
- {
- if (_taggedProcesses[_processTags[coindex]].Count > 1)
- _taggedProcesses[_processTags[coindex]].Remove(coindex);
- else
- _taggedProcesses.Remove(_processTags[coindex]);
-
- _processTags.Remove(coindex);
- }
- }
-
- /// <returns>Whether it was already null.</returns>
- private bool Nullify(ProcessIndex coindex)
- {
- bool retVal;
-
- switch (coindex.seg)
- {
- case Segment.Update:
- retVal = UpdateProcesses[coindex.i] != null;
- UpdateProcesses[coindex.i] = null;
- return retVal;
- case Segment.FixedUpdate:
- retVal = FixedUpdateProcesses[coindex.i] != null;
- FixedUpdateProcesses[coindex.i] = null;
- return retVal;
- case Segment.LateUpdate:
- retVal = LateUpdateProcesses[coindex.i] != null;
- LateUpdateProcesses[coindex.i] = null;
- return retVal;
- case Segment.SlowUpdate:
- retVal = SlowUpdateProcesses[coindex.i] != null;
- SlowUpdateProcesses[coindex.i] = null;
- return retVal;
- default:
- return false;
- }
- }
-
- private IEnumerator<float> CoindexExtract(ProcessIndex coindex)
- {
- IEnumerator<float> retVal;
-
- switch (coindex.seg)
- {
- case Segment.Update:
- retVal = UpdateProcesses[coindex.i];
- UpdateProcesses[coindex.i] = null;
- return retVal;
- case Segment.FixedUpdate:
- retVal = FixedUpdateProcesses[coindex.i];
- FixedUpdateProcesses[coindex.i] = null;
- return retVal;
- case Segment.LateUpdate:
- retVal = LateUpdateProcesses[coindex.i];
- LateUpdateProcesses[coindex.i] = null;
- return retVal;
- case Segment.SlowUpdate:
- retVal = SlowUpdateProcesses[coindex.i];
- SlowUpdateProcesses[coindex.i] = null;
- return retVal;
- default:
- return null;
- }
- }
-
- private IEnumerator<float> CoindexPeek(ProcessIndex coindex)
- {
- switch (coindex.seg)
- {
- case Segment.Update:
- return UpdateProcesses[coindex.i];
- case Segment.FixedUpdate:
- return FixedUpdateProcesses[coindex.i];
- case Segment.LateUpdate:
- return LateUpdateProcesses[coindex.i];
- case Segment.SlowUpdate:
- return SlowUpdateProcesses[coindex.i];
- default:
- return null;
- }
- }
-
- private bool CoindexIsNull(ProcessIndex coindex)
- {
- switch (coindex.seg)
- {
- case Segment.Update:
- return UpdateProcesses[coindex.i] == null;
- case Segment.FixedUpdate:
- return FixedUpdateProcesses[coindex.i] == null;
- case Segment.LateUpdate:
- return LateUpdateProcesses[coindex.i] == null;
- case Segment.SlowUpdate:
- return SlowUpdateProcesses[coindex.i] == null;
- default:
- return true;
- }
- }
-
- private bool SetPause(ProcessIndex coindex, bool newPausedState)
- {
- if (CoindexPeek(coindex) == null)
- return false;
-
- bool isPaused;
-
- switch (coindex.seg)
- {
- case Segment.Update:
- isPaused = UpdatePaused[coindex.i];
- UpdatePaused[coindex.i] = newPausedState;
-
- if (newPausedState && UpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
- UpdateProcesses[coindex.i] = _InjectDelay(UpdateProcesses[coindex.i],
- UpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
-
- return isPaused;
- case Segment.FixedUpdate:
- isPaused = FixedUpdatePaused[coindex.i];
- FixedUpdatePaused[coindex.i] = newPausedState;
-
- if (newPausedState && FixedUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
- FixedUpdateProcesses[coindex.i] = _InjectDelay(FixedUpdateProcesses[coindex.i],
- FixedUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
-
- return isPaused;
- case Segment.LateUpdate:
- isPaused = LateUpdatePaused[coindex.i];
- LateUpdatePaused[coindex.i] = newPausedState;
-
- if (newPausedState && LateUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
- LateUpdateProcesses[coindex.i] = _InjectDelay(LateUpdateProcesses[coindex.i],
- LateUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
-
- return isPaused;
- case Segment.SlowUpdate:
- isPaused = SlowUpdatePaused[coindex.i];
- SlowUpdatePaused[coindex.i] = newPausedState;
-
- if (newPausedState && SlowUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
- SlowUpdateProcesses[coindex.i] = _InjectDelay(SlowUpdateProcesses[coindex.i],
- SlowUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
-
- return isPaused;
- default:
- return false;
- }
- }
-
- private bool SetHeld(ProcessIndex coindex, bool newHeldState)
- {
- if (CoindexPeek(coindex) == null)
- return false;
-
- bool isHeld;
-
- switch (coindex.seg)
- {
- case Segment.Update:
- isHeld = UpdateHeld[coindex.i];
- UpdateHeld[coindex.i] = newHeldState;
-
- if (newHeldState && UpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
- UpdateProcesses[coindex.i] = _InjectDelay(UpdateProcesses[coindex.i],
- UpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
-
- return isHeld;
- case Segment.FixedUpdate:
- isHeld = FixedUpdateHeld[coindex.i];
- FixedUpdateHeld[coindex.i] = newHeldState;
-
- if (newHeldState && FixedUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
- FixedUpdateProcesses[coindex.i] = _InjectDelay(FixedUpdateProcesses[coindex.i],
- FixedUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
-
- return isHeld;
- case Segment.LateUpdate:
- isHeld = LateUpdateHeld[coindex.i];
- LateUpdateHeld[coindex.i] = newHeldState;
-
- if (newHeldState && LateUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
- LateUpdateProcesses[coindex.i] = _InjectDelay(LateUpdateProcesses[coindex.i],
- LateUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
-
- return isHeld;
- case Segment.SlowUpdate:
- isHeld = SlowUpdateHeld[coindex.i];
- SlowUpdateHeld[coindex.i] = newHeldState;
-
- if (newHeldState && SlowUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
- SlowUpdateProcesses[coindex.i] = _InjectDelay(SlowUpdateProcesses[coindex.i],
- SlowUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
-
- return isHeld;
- default:
- return false;
- }
- }
-
- private IEnumerator<float> _InjectDelay(IEnumerator<float> proc, float delayTime)
- {
- yield return WaitForSecondsOnInstance(delayTime);
-
- _tmpRef = proc;
- ReplacementFunction = ReturnTmpRefForRepFunc;
- yield return float.NaN;
- }
-
- private bool CoindexIsPaused(ProcessIndex coindex)
- {
- switch (coindex.seg)
- {
- case Segment.Update:
- return UpdatePaused[coindex.i];
- case Segment.FixedUpdate:
- return FixedUpdatePaused[coindex.i];
- case Segment.LateUpdate:
- return LateUpdatePaused[coindex.i];
- case Segment.SlowUpdate:
- return SlowUpdatePaused[coindex.i];
- default:
- return false;
- }
- }
-
- private bool CoindexIsHeld(ProcessIndex coindex)
- {
- switch (coindex.seg)
- {
- case Segment.Update:
- return UpdateHeld[coindex.i];
- case Segment.FixedUpdate:
- return FixedUpdateHeld[coindex.i];
- case Segment.LateUpdate:
- return LateUpdateHeld[coindex.i];
- case Segment.SlowUpdate:
- return SlowUpdateHeld[coindex.i];
- default:
- return false;
- }
- }
-
- private void CoindexReplace(ProcessIndex coindex, IEnumerator<float> replacement)
- {
- switch (coindex.seg)
- {
- case Segment.Update:
- UpdateProcesses[coindex.i] = replacement;
- return;
- case Segment.FixedUpdate:
- FixedUpdateProcesses[coindex.i] = replacement;
- return;
- case Segment.LateUpdate:
- LateUpdateProcesses[coindex.i] = replacement;
- return;
- case Segment.SlowUpdate:
- SlowUpdateProcesses[coindex.i] = replacement;
- return;
- }
- }
-
- /// <summary>
- /// Use "yield return Timing.WaitForSeconds(time);" to wait for the specified number of seconds.
- /// </summary>
- /// <param name="waitTime">Number of seconds to wait.</param>
- public static float WaitForSeconds(float waitTime)
- {
- if (float.IsNaN(waitTime)) waitTime = 0f;
- return LocalTime + waitTime;
- }
-
- /// <summary>
- /// Use "yield return timingInstance.WaitForSecondsOnInstance(time);" to wait for the specified number of seconds.
- /// </summary>
- /// <param name="waitTime">Number of seconds to wait.</param>
- public float WaitForSecondsOnInstance(float waitTime)
- {
- if (float.IsNaN(waitTime)) waitTime = 0f;
- return localTime + waitTime;
- }
-
- /// <summary>
- /// Use the command "yield return Timing.WaitUntilDone(otherCoroutine);" to pause the current
- /// coroutine until otherCoroutine is done.
- /// </summary>
- /// <param name="otherCoroutine">The coroutine to pause for.</param>
- public static float WaitUntilDone(CoroutineHandle otherCoroutine)
- {
- return WaitUntilDone(otherCoroutine, true);
- }
-
- /// <summary>
- /// Use the command "yield return Timing.WaitUntilDone(otherCoroutine, false);" to pause the current
- /// coroutine until otherCoroutine is done, supressing warnings.
- /// </summary>
- /// <param name="otherCoroutine">The coroutine to pause for.</param>
- /// <param name="warnOnIssue">Post a warning to the console if no hold action was actually performed.</param>
- public static float WaitUntilDone(CoroutineHandle otherCoroutine, bool warnOnIssue)
- {
- Timing inst = GetInstance(otherCoroutine.Key);
-
- if (inst != null && inst._handleToIndex.ContainsKey(otherCoroutine))
- {
- if (inst.CoindexIsNull(inst._handleToIndex[otherCoroutine]))
- return 0f;
-
- if (!inst._waitingTriggers.ContainsKey(otherCoroutine))
- {
- inst.CoindexReplace(inst._handleToIndex[otherCoroutine],
- inst._StartWhenDone(otherCoroutine, inst.CoindexPeek(inst._handleToIndex[otherCoroutine])));
- inst._waitingTriggers.Add(otherCoroutine, new HashSet<CoroutineHandle>());
- }
-
- if (inst.currentCoroutine == otherCoroutine)
- {
- Assert.IsFalse(warnOnIssue, "A coroutine cannot wait for itself.");
- return WaitForOneFrame;
- }
- if (!inst.currentCoroutine.IsValid)
- {
- Assert.IsFalse(warnOnIssue, "The two coroutines are not running on the same MEC instance.");
- return WaitForOneFrame;
- }
-
- inst._waitingTriggers[otherCoroutine].Add(inst.currentCoroutine);
- if (!inst._allWaiting.Contains(inst.currentCoroutine))
- inst._allWaiting.Add(inst.currentCoroutine);
- inst.SetHeld(inst._handleToIndex[inst.currentCoroutine], true);
- inst.SwapToLast(otherCoroutine, inst.currentCoroutine);
-
- return float.NaN;
- }
-
- Assert.IsFalse(warnOnIssue, "WaitUntilDone cannot hold: The coroutine handle that was passed in is invalid.\n" + otherCoroutine);
- return WaitForOneFrame;
- }
-
- private IEnumerator<float> _StartWhenDone(CoroutineHandle handle, IEnumerator<float> proc)
- {
- if (!_waitingTriggers.ContainsKey(handle)) yield break;
-
- try
- {
- if (proc.Current > localTime)
- yield return proc.Current;
-
- while (proc.MoveNext())
- yield return proc.Current;
- }
- finally
- {
- CloseWaitingProcess(handle);
- }
- }
-
- private void SwapToLast(CoroutineHandle firstHandle, CoroutineHandle lastHandle)
- {
- if (firstHandle.Key != lastHandle.Key)
- return;
-
- ProcessIndex firstIndex = _handleToIndex[firstHandle];
- ProcessIndex lastIndex = _handleToIndex[lastHandle];
-
- if (firstIndex.seg != lastIndex.seg || firstIndex.i < lastIndex.i)
- return;
-
- IEnumerator<float> tempCoptr = CoindexPeek(firstIndex);
- CoindexReplace(firstIndex, CoindexPeek(lastIndex));
- CoindexReplace(lastIndex, tempCoptr);
-
- _indexToHandle[firstIndex] = lastHandle;
- _indexToHandle[lastIndex] = firstHandle;
- _handleToIndex[firstHandle] = lastIndex;
- _handleToIndex[lastHandle] = firstIndex;
- bool tmpB = SetPause(firstIndex, CoindexIsPaused(lastIndex));
- SetPause(lastIndex, tmpB);
- tmpB = SetHeld(firstIndex, CoindexIsHeld(lastIndex));
- SetHeld(lastIndex, tmpB);
-
- if (_waitingTriggers.ContainsKey(lastHandle))
- {
- var trigsEnum = _waitingTriggers[lastHandle].GetEnumerator();
- while (trigsEnum.MoveNext())
- SwapToLast(lastHandle, trigsEnum.Current);
- }
-
- if (_allWaiting.Contains(firstHandle))
- {
- var keyEnum = _waitingTriggers.GetEnumerator();
- while (keyEnum.MoveNext())
- {
- var valueEnum = keyEnum.Current.Value.GetEnumerator();
- while (valueEnum.MoveNext())
- if (valueEnum.Current == firstHandle)
- SwapToLast(keyEnum.Current.Key, firstHandle);
- }
- }
- }
-
- private void CloseWaitingProcess(CoroutineHandle handle)
- {
- if (!_waitingTriggers.ContainsKey(handle)) return;
-
- var tasksEnum = _waitingTriggers[handle].GetEnumerator();
- _waitingTriggers.Remove(handle);
-
- while (tasksEnum.MoveNext())
- {
- if (_handleToIndex.ContainsKey(tasksEnum.Current) && !HandleIsInWaitingList(tasksEnum.Current))
- {
- SetHeld(_handleToIndex[tasksEnum.Current], false);
- _allWaiting.Remove(tasksEnum.Current);
- }
- }
- }
-
- private bool HandleIsInWaitingList(CoroutineHandle handle)
- {
- var triggersEnum = _waitingTriggers.GetEnumerator();
- while (triggersEnum.MoveNext())
- if (triggersEnum.Current.Value.Contains(handle))
- return true;
-
- return false;
- }
-
- private static IEnumerator<float> ReturnTmpRefForRepFunc(IEnumerator<float> coptr, CoroutineHandle handle)
- {
- return _tmpRef as IEnumerator<float>;
- }
-
-#if !UNITY_2018_3_OR_NEWER
- /// <summary>
- /// Use the command "yield return Timing.WaitUntilDone(wwwObject);" to pause the current
- /// coroutine until the wwwObject is done.
- /// </summary>
- /// <param name="wwwObject">The www object to pause for.</param>
- public static float WaitUntilDone(WWW wwwObject)
- {
- if (wwwObject == null || wwwObject.isDone) return 0f;
-
- _tmpRef = wwwObject;
- ReplacementFunction = WaitUntilDoneWwwHelper;
- return float.NaN;
- }
-
-
- private static IEnumerator<float> WaitUntilDoneWwwHelper(IEnumerator<float> coptr, CoroutineHandle handle)
- {
- return _StartWhenDone(_tmpRef as WWW, coptr);
- }
-
- private static IEnumerator<float> _StartWhenDone(WWW www, IEnumerator<float> pausedProc)
- {
- while (!www.isDone)
- yield return WaitForOneFrame;
-
- _tmpRef = pausedProc;
- ReplacementFunction = ReturnTmpRefForRepFunc;
- yield return float.NaN;
- }
-#endif
-
- /// <summary>
- /// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current
- /// coroutine until the operation is done.
- /// </summary>
- /// <param name="operation">The operation variable returned.</param>
- public static float WaitUntilDone(AsyncOperation operation)
- {
- if (operation == null || operation.isDone) return float.NaN;
-
- CoroutineHandle handle = CurrentCoroutine;
- Timing inst = GetInstance(CurrentCoroutine.Key);
- if (inst == null) return float.NaN;
-
- _tmpRef = _StartWhenDone(operation, inst.CoindexPeek(inst._handleToIndex[handle]));
- ReplacementFunction = ReturnTmpRefForRepFunc;
- return float.NaN;
- }
-
- private static IEnumerator<float> _StartWhenDone(AsyncOperation operation, IEnumerator<float> pausedProc)
- {
- while (!operation.isDone)
- yield return WaitForOneFrame;
-
- _tmpRef = pausedProc;
- ReplacementFunction = ReturnTmpRefForRepFunc;
- yield return float.NaN;
- }
-
- /// <summary>
- /// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current
- /// coroutine until the operation is done.
- /// </summary>
- /// <param name="operation">The operation variable returned.</param>
- public static float WaitUntilDone(CustomYieldInstruction operation)
- {
- if (operation == null || !operation.keepWaiting) return float.NaN;
-
- CoroutineHandle handle = CurrentCoroutine;
- Timing inst = GetInstance(CurrentCoroutine.Key);
- if (inst == null) return float.NaN;
-
- _tmpRef = _StartWhenDone(operation, inst.CoindexPeek(inst._handleToIndex[handle]));
- ReplacementFunction = ReturnTmpRefForRepFunc;
- return float.NaN;
- }
-
- private static IEnumerator<float> _StartWhenDone(CustomYieldInstruction operation, IEnumerator<float> pausedProc)
- {
- while (operation.keepWaiting)
- yield return WaitForOneFrame;
-
- _tmpRef = pausedProc;
- ReplacementFunction = ReturnTmpRefForRepFunc;
- yield return float.NaN;
- }
-
- /// <summary>
- /// Keeps this coroutine from executing until UnlockCoroutine is called with a matching key.
- /// </summary>
- /// <param name="coroutine">The handle to the coroutine to be locked.</param>
- /// <param name="key">The key to use. A new key can be generated by calling "new CoroutineHandle(0)".</param>
- /// <returns>Whether the lock was successful.</returns>
- public bool LockCoroutine(CoroutineHandle coroutine, CoroutineHandle key)
- {
- if (coroutine.Key != _instanceID || key == new CoroutineHandle() || key.Key != 0)
- return false;
-
- if (!_waitingTriggers.ContainsKey(key))
- _waitingTriggers.Add(key, new HashSet<CoroutineHandle> { coroutine });
- else
- _waitingTriggers[key].Add(coroutine);
-
- _allWaiting.Add(coroutine);
-
- SetHeld(_handleToIndex[coroutine], true);
-
- return true;
- }
-
- /// <summary>
- /// Unlocks a coroutine that has been locked, so long as the key matches.
- /// </summary>
- /// <param name="coroutine">The handle to the coroutine to be unlocked.</param>
- /// <param name="key">The key that the coroutine was previously locked with.</param>
- /// <returns>Whether the coroutine was successfully unlocked.</returns>
- public bool UnlockCoroutine(CoroutineHandle coroutine, CoroutineHandle key)
- {
- if (coroutine.Key != _instanceID || key == new CoroutineHandle() ||
- !_handleToIndex.ContainsKey(coroutine) || !_waitingTriggers.ContainsKey(key))
- return false;
-
- if (_waitingTriggers[key].Count == 1)
- _waitingTriggers.Remove(key);
- else
- _waitingTriggers[key].Remove(coroutine);
-
- if (!HandleIsInWaitingList(coroutine))
- {
- SetHeld(_handleToIndex[coroutine], false);
- _allWaiting.Remove(coroutine);
- }
-
- return true;
- }
-
- /// <summary>
- /// Calls the specified action after a specified number of seconds.
- /// </summary>
- /// <param name="delay">The number of seconds to wait before calling the action.</param>
- /// <param name="action">The action to call.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallDelayed(float delay, System.Action action)
- {
- return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, null));
- }
-
- /// <summary>
- /// Calls the specified action after a specified number of seconds.
- /// </summary>
- /// <param name="delay">The number of seconds to wait before calling the action.</param>
- /// <param name="action">The action to call.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallDelayedOnInstance(float delay, System.Action action)
- {
- return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, null));
- }
-
- /// <summary>
- /// Calls the specified action after a specified number of seconds.
- /// </summary>
- /// <param name="delay">The number of seconds to wait before calling the action.</param>
- /// <param name="action">The action to call.</param>
- /// <param name="cancelWith">A GameObject that will be checked to make sure it hasn't been destroyed before calling the action.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallDelayed(float delay, System.Action action, GameObject cancelWith)
- {
- return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, cancelWith));
- }
-
- /// <summary>
- /// Calls the specified action after a specified number of seconds.
- /// </summary>
- /// <param name="delay">The number of seconds to wait before calling the action.</param>
- /// <param name="action">The action to call.</param>
- /// <param name="cancelWith">A GameObject that will be checked to make sure it hasn't been destroyed before calling the action.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallDelayedOnInstance(float delay, System.Action action, GameObject cancelWith)
- {
- return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, cancelWith));
- }
-
- /// <summary>
- /// Calls the specified action after a specified number of seconds.
- /// </summary>
- /// <param name="delay">The number of seconds to wait before calling the action.</param>
- /// <param name="action">The action to call.</param>
- /// <param name="segment">The timing segment that the call should be made in.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallDelayed(float delay, Segment segment, System.Action action)
- {
- return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, null), segment);
- }
-
- /// <summary>
- /// Calls the specified action after a specified number of seconds.
- /// </summary>
- /// <param name="delay">The number of seconds to wait before calling the action.</param>
- /// <param name="action">The action to call.</param>
- /// <param name="segment">The timing segment that the call should be made in.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallDelayedOnInstance(float delay, Segment segment, System.Action action)
- {
- return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, null), segment);
- }
-
- /// <summary>
- /// Calls the specified action after a specified number of seconds.
- /// </summary>
- /// <param name="delay">The number of seconds to wait before calling the action.</param>
- /// <param name="action">The action to call.</param>
- /// <param name="gameObject">A GameObject that will be checked to make sure it hasn't been destroyed
- /// before calling the action.</param>
- /// <param name="segment">The timing segment that the call should be made in.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallDelayed(float delay, Segment segment, System.Action action, GameObject gameObject)
- {
- return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, gameObject), segment);
- }
-
- /// <summary>
- /// Calls the specified action after a specified number of seconds.
- /// </summary>
- /// <param name="delay">The number of seconds to wait before calling the action.</param>
- /// <param name="action">The action to call.</param>
- /// <param name="gameObject">A GameObject that will be tagged onto the coroutine and checked to make sure it hasn't been destroyed
- /// before calling the action.</param>
- /// <param name="segment">The timing segment that the call should be made in.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallDelayedOnInstance(float delay, Segment segment, System.Action action, GameObject gameObject)
- {
- return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, gameObject), segment);
- }
-
- private IEnumerator<float> _DelayedCall(float delay, System.Action action, GameObject cancelWith)
- {
- yield return WaitForSecondsOnInstance(delay);
-
- if(ReferenceEquals(cancelWith, null) || cancelWith != null)
- action();
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="period">The amount of time between calls.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallPeriodically(float timeframe, float period, System.Action action, System.Action onDone = null)
- {
- return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, period, action, onDone), Segment.Update);
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="period">The amount of time between calls.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallPeriodicallyOnInstance(float timeframe, float period, System.Action action, System.Action onDone = null)
- {
- return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, period, action, onDone), Segment.Update);
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="period">The amount of time between calls.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="segment">The timing segment to run in.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallPeriodically(float timeframe, float period, System.Action action, Segment segment, System.Action onDone = null)
- {
- return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, period, action, onDone), segment);
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="period">The amount of time between calls.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="segment">The timing segment to run in.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallPeriodicallyOnInstance(float timeframe, float period, System.Action action, Segment segment, System.Action onDone = null)
- {
- return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, period, action, onDone), segment);
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallContinuously(float timeframe, System.Action action, System.Action onDone = null)
- {
- return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, 0f, action, onDone), Segment.Update);
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallContinuouslyOnInstance(float timeframe, System.Action action, System.Action onDone = null)
- {
- return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, 0f, action, onDone), Segment.Update);
- }
-
- /// <summary>
- /// Calls the supplied action every frame for a given number of seconds.
- /// </summary>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="timing">The timing segment to run in.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallContinuously(float timeframe, System.Action action, Segment timing, System.Action onDone = null)
- {
- return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, 0f, action, onDone), timing);
- }
-
- /// <summary>
- /// Calls the supplied action every frame for a given number of seconds.
- /// </summary>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="timing">The timing segment to run in.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallContinuouslyOnInstance(float timeframe, System.Action action, Segment timing, System.Action onDone = null)
- {
- return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, 0f, action, onDone), timing);
- }
-
- private IEnumerator<float> _CallContinuously(float timeframe, float period, System.Action action, System.Action onDone)
- {
- double startTime = localTime;
- while (localTime <= startTime + timeframe)
- {
- yield return WaitForSecondsOnInstance(period);
-
- action();
- }
-
- if (onDone != null)
- onDone();
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="period">The amount of time between calls.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallPeriodically<T>
- (T reference, float timeframe, float period, System.Action<T> action, System.Action<T> onDone = null)
- {
- return action == null ? new CoroutineHandle() :
- RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), Segment.Update);
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="period">The amount of time between calls.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallPeriodicallyOnInstance<T>
- (T reference, float timeframe, float period, System.Action<T> action, System.Action<T> onDone = null)
- {
- return action == null ? new CoroutineHandle() :
- RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), Segment.Update);
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="period">The amount of time between calls.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="timing">The timing segment to run in.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallPeriodically<T>(T reference, float timeframe, float period, System.Action<T> action,
- Segment timing, System.Action<T> onDone = null)
- {
- return action == null ? new CoroutineHandle() :
- RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), timing);
- }
-
- /// <summary>
- /// Calls the supplied action at the given rate for a given number of seconds.
- /// </summary>
- /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="period">The amount of time between calls.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="timing">The timing segment to run in.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallPeriodicallyOnInstance<T>(T reference, float timeframe, float period, System.Action<T> action,
- Segment timing, System.Action<T> onDone = null)
- {
- return action == null ? new CoroutineHandle() :
- RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), timing);
- }
-
- /// <summary>
- /// Calls the supplied action every frame for a given number of seconds.
- /// </summary>
- /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallContinuously<T>(T reference, float timeframe, System.Action<T> action, System.Action<T> onDone = null)
- {
- return action == null ? new CoroutineHandle() :
- RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update);
- }
-
- /// <summary>
- /// Calls the supplied action every frame for a given number of seconds.
- /// </summary>
- /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallContinuouslyOnInstance<T>(T reference, float timeframe, System.Action<T> action, System.Action<T> onDone = null)
- {
- return action == null ? new CoroutineHandle() :
- RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update);
- }
-
- /// <summary>
- /// Calls the supplied action every frame for a given number of seconds.
- /// </summary>
- /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="timing">The timing segment to run in.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public static CoroutineHandle CallContinuously<T>(T reference, float timeframe, System.Action<T> action,
- Segment timing, System.Action<T> onDone = null)
- {
- return action == null ? new CoroutineHandle() :
- RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), timing);
- }
-
- /// <summary>
- /// Calls the supplied action every frame for a given number of seconds.
- /// </summary>
- /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
- /// <param name="timeframe">The number of seconds that this function should run.</param>
- /// <param name="action">The action to call every frame.</param>
- /// <param name="timing">The timing segment to run in.</param>
- /// <param name="onDone">An optional action to call when this function finishes.</param>
- /// <returns>The handle to the coroutine that is started by this function.</returns>
- public CoroutineHandle CallContinuouslyOnInstance<T>(T reference, float timeframe, System.Action<T> action,
- Segment timing, System.Action<T> onDone = null)
- {
- return action == null ? new CoroutineHandle() :
- RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), timing);
- }
-
- private IEnumerator<float> _CallContinuously<T>(T reference, float timeframe, float period,
- System.Action<T> action, System.Action<T> onDone = null)
- {
- double startTime = localTime;
- while (localTime <= startTime + timeframe)
- {
- yield return WaitForSecondsOnInstance(period);
-
- action(reference);
- }
-
- if (onDone != null)
- onDone(reference);
- }
-
- private struct ProcessIndex : System.IEquatable<ProcessIndex>
- {
- public Segment seg;
- public int i;
-
- public bool Equals(ProcessIndex other)
- {
- return seg == other.seg && i == other.i;
- }
-
- public override bool Equals(object other)
- {
- if (other is ProcessIndex)
- return Equals((ProcessIndex)other);
- return false;
- }
-
- public static bool operator ==(ProcessIndex a, ProcessIndex b)
- {
- return a.seg == b.seg && a.i == b.i;
- }
-
- public static bool operator !=(ProcessIndex a, ProcessIndex b)
- {
- return a.seg != b.seg || a.i != b.i;
- }
-
- public override int GetHashCode()
- {
- return (((int)seg - 2) * (int.MaxValue / 3)) + i;
- }
- }
-
- [System.Obsolete("Unity coroutine function, use RunCoroutine instead.", true)]
- public new Coroutine StartCoroutine(System.Collections.IEnumerator routine) { return null; }
-
- [System.Obsolete("Unity coroutine function, use RunCoroutine instead.", true)]
- public new Coroutine StartCoroutine(string methodName, object value) { return null; }
-
- [System.Obsolete("Unity coroutine function, use RunCoroutine instead.", true)]
- public new Coroutine StartCoroutine(string methodName) { return null; }
-
- [System.Obsolete("Unity coroutine function, use RunCoroutine instead.", true)]
- public new Coroutine StartCoroutine_Auto(System.Collections.IEnumerator routine) { return null; }
-
- [System.Obsolete("Unity coroutine function, use KillCoroutines instead.", true)]
- public new void StopCoroutine(string methodName) { }
-
- [System.Obsolete("Unity coroutine function, use KillCoroutines instead.", true)]
- public new void StopCoroutine(System.Collections.IEnumerator routine) { }
-
- [System.Obsolete("Unity coroutine function, use KillCoroutines instead.", true)]
- public new void StopCoroutine(Coroutine routine) { }
-
- [System.Obsolete("Unity coroutine function, use KillCoroutines instead.", true)]
- public new void StopAllCoroutines() { }
-
- [System.Obsolete("Use your own GameObject for this.", true)]
- public new static void Destroy(Object obj) { }
-
- [System.Obsolete("Use your own GameObject for this.", true)]
- public new static void Destroy(Object obj, float f) { }
-
- [System.Obsolete("Use your own GameObject for this.", true)]
- public new static void DestroyObject(Object obj) { }
-
- [System.Obsolete("Use your own GameObject for this.", true)]
- public new static void DestroyObject(Object obj, float f) { }
-
- [System.Obsolete("Use your own GameObject for this.", true)]
- public new static void DestroyImmediate(Object obj) { }
-
- [System.Obsolete("Use your own GameObject for this.", true)]
- public new static void DestroyImmediate(Object obj, bool b) { }
-
- [System.Obsolete("Use your own GameObject for this.", true)]
- public new static void Instantiate(Object obj) { }
-
- [System.Obsolete("Use your own GameObject for this.", true)]
- public new static void Instantiate(Object original, Vector3 position, Quaternion rotation) { }
-
- [System.Obsolete("Use your own GameObject for this.", true)]
- public new static void Instantiate<T>(T original) where T : Object { }
-
- [System.Obsolete("Just.. no.", true)]
- public new static T FindObjectOfType<T>() where T : Object { return null; }
-
- [System.Obsolete("Just.. no.", true)]
- public new static Object FindObjectOfType(System.Type t) { return null; }
-
- [System.Obsolete("Just.. no.", true)]
- public new static T[] FindObjectsOfType<T>() where T : Object { return null; }
-
- [System.Obsolete("Just.. no.", true)]
- public new static Object[] FindObjectsOfType(System.Type t) { return null; }
-
- [System.Obsolete("Just.. no.", true)]
- public new static void print(object message) { }
- }
-
- /// <summary>
- /// The timing segment that a coroutine is running in or should be run in.
- /// </summary>
- public enum Segment
- {
- /// <summary>
- /// Sometimes returned as an error state
- /// </summary>
- Invalid = -1,
- /// <summary>
- /// This is the default timing segment
- /// </summary>
- Update,
- /// <summary>
- /// This is primarily used for physics calculations
- /// </summary>
- FixedUpdate,
- /// <summary>
- /// This is run immediately after update
- /// </summary>
- LateUpdate,
- /// <summary>
- /// This executes, by default, about as quickly as the eye can detect changes in a text field
- /// </summary>
- SlowUpdate
- }
-
- /// <summary>
- /// How much debug info should be sent to the Unity profiler. NOTE: Setting this to anything above none shows up in the profiler as a
- /// decrease in performance and a memory alloc. Those effects do not translate onto device.
- /// </summary>
- public enum DebugInfoType
- {
- /// <summary>
- /// None coroutines will be separated in the Unity profiler
- /// </summary>
- None,
- /// <summary>
- /// The Unity profiler will identify each coroutine individually
- /// </summary>
- SeperateCoroutines,
- /// <summary>
- /// Coroutines will be separated and any tags or layers will be identified
- /// </summary>
- SeperateTags
- }
-
- /// <summary>
- /// A handle for a MEC coroutine.
- /// </summary>
- public struct CoroutineHandle : System.IEquatable<CoroutineHandle>
- {
- private const byte ReservedSpace = 0x0F;
- private readonly static int[] NextIndex = { ReservedSpace + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- private readonly int _id;
-
- public byte Key { get { return (byte)(_id & ReservedSpace); } }
-
- public CoroutineHandle(byte ind)
- {
- if (ind > ReservedSpace)
- ind -= ReservedSpace;
-
- _id = NextIndex[ind] + ind;
- NextIndex[ind] += ReservedSpace + 1;
- }
-
- public bool Equals(CoroutineHandle other)
- {
- return _id == other._id;
- }
-
- public override bool Equals(object other)
- {
- if (other is CoroutineHandle)
- return Equals((CoroutineHandle)other);
- return false;
- }
-
- public static bool operator==(CoroutineHandle a, CoroutineHandle b)
- {
- return a._id == b._id;
- }
-
- public static bool operator!=(CoroutineHandle a, CoroutineHandle b)
- {
- return a._id != b._id;
- }
-
- public override int GetHashCode()
- {
- return _id;
- }
-
- /// <summary>
- /// Is true if this handle may have been a valid handle at some point. (i.e. is not an uninitialized handle, error handle, or a key to a coroutine lock)
- /// </summary>
- public bool IsValid
- {
- get { return Key != 0; }
- }
- }
-
- public static class MECExtensionMethods1
- {
- /// <summary>
- /// Run a new coroutine in the Update segment.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public static CoroutineHandle RunCoroutine(this IEnumerator<float> coroutine)
- {
- return Timing.RunCoroutine(coroutine);
- }
-
- /// <summary>
- /// Run a new coroutine in the Update segment.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public static CoroutineHandle RunCoroutine(this IEnumerator<float> coroutine, string tag)
- {
- return Timing.RunCoroutine(coroutine, tag);
- }
-
- /// <summary>
- /// Run a new coroutine.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <param name="segment">The segment that the coroutine should run in.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public static CoroutineHandle RunCoroutine(this IEnumerator<float> coroutine, Segment segment)
- {
- return Timing.RunCoroutine(coroutine, segment);
- }
-
- /// <summary>
- /// Run a new coroutine.
- /// </summary>
- /// <param name="coroutine">The new coroutine's handle.</param>
- /// <param name="segment">The segment that the coroutine should run in.</param>
- /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
- /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
- public static CoroutineHandle RunCoroutine(this IEnumerator<float> coroutine, Segment segment, string tag)
- {
- return Timing.RunCoroutine(coroutine, segment, tag);
- }
- }
-}
-
-public static class MECExtensionMethods2
-{
- /// <summary>
- /// Cancels this coroutine when the supplied game object is destroyed or made inactive.
- /// </summary>
- /// <param name="coroutine">The coroutine handle to act upon.</param>
- /// <param name="gameObject">The GameObject to test.</param>
- /// <returns>The modified coroutine handle.</returns>
- public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, GameObject gameObject)
- {
- while (MEC.Timing.MainThread != System.Threading.Thread.CurrentThread || (gameObject && gameObject.activeInHierarchy && coroutine.MoveNext()))
- yield return coroutine.Current;
- }
-
- /// <summary>
- /// Cancels this coroutine when the supplied game objects are destroyed or made inactive.
- /// </summary>
- /// <param name="coroutine">The coroutine handle to act upon.</param>
- /// <param name="gameObject1">The first GameObject to test.</param>
- /// <param name="gameObject2">The second GameObject to test</param>
- /// <returns>The modified coroutine handle.</returns>
- public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, GameObject gameObject1, GameObject gameObject2)
- {
- while (MEC.Timing.MainThread != System.Threading.Thread.CurrentThread || (gameObject1 && gameObject1.activeInHierarchy &&
- gameObject2 && gameObject2.activeInHierarchy && coroutine.MoveNext()))
- yield return coroutine.Current;
- }
-
- /// <summary>
- /// Cancels this coroutine when the supplied game objects are destroyed or made inactive.
- /// </summary>
- /// <param name="coroutine">The coroutine handle to act upon.</param>
- /// <param name="gameObject1">The first GameObject to test.</param>
- /// <param name="gameObject2">The second GameObject to test</param>
- /// <param name="gameObject3">The third GameObject to test.</param>
- /// <returns>The modified coroutine handle.</returns>
- public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine,
- GameObject gameObject1, GameObject gameObject2, GameObject gameObject3)
- {
- while (MEC.Timing.MainThread != System.Threading.Thread.CurrentThread || (gameObject1 && gameObject1.activeInHierarchy &&
- gameObject2 && gameObject2.activeInHierarchy && gameObject3 && gameObject3.activeInHierarchy && coroutine.MoveNext()))
- yield return coroutine.Current;
- }
-}
diff --git a/WorldlineKeepers/Assets/Scenes/0_Test.unity b/WorldlineKeepers/Assets/Scenes/0_Test.unity
index 0c1e493..5b24157 100644
--- a/WorldlineKeepers/Assets/Scenes/0_Test.unity
+++ b/WorldlineKeepers/Assets/Scenes/0_Test.unity
@@ -9988,6 +9988,7 @@ GameObject:
- component: {fileID: 1552119909}
- component: {fileID: 1552119911}
- component: {fileID: 1552119913}
+ - component: {fileID: 1552119914}
m_Layer: 0
m_Name: Main
m_TagString: Untagged
@@ -10058,6 +10059,25 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 0825a89e4815bc94eb58cd23aa6f4814, type: 3}
m_Name:
m_EditorClassIdentifier:
+--- !u!114 &1552119914
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1552119908}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 2d2433f4570c1404da40af9ea0b12741, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ TimeBetweenSlowUpdateCalls: 0.14285715
+ ProfilerDebugAmount: 0
+ UpdateCoroutines: 0
+ FixedUpdateCoroutines: 0
+ LateUpdateCoroutines: 0
+ SlowUpdateCoroutines: 0
+ _instanceID: 0
--- !u!1 &1566097397
GameObject:
m_ObjectHideFlags: 0
diff --git a/WorldlineKeepers/Assets/Scripts/Application/ApplicationMain.cs b/WorldlineKeepers/Assets/Scripts/Application/ApplicationMain.cs
index a4698f4..214a785 100644
--- a/WorldlineKeepers/Assets/Scripts/Application/ApplicationMain.cs
+++ b/WorldlineKeepers/Assets/Scripts/Application/ApplicationMain.cs
@@ -25,36 +25,54 @@ namespace WK
public void OnAwake()
{
onAwakeHandler?.Invoke();
+
+ GameStageManager.Instance.OnAwake();
+
}
public void OnStart()
{
- onStartHandler?.Invoke();
+ onStartHandler?.Invoke();
+
+
+ GameStageManager.Instance.OnStart();
+
}
public void OnUpdate()
{
- onUpdateHandler?.Invoke();
+ onUpdateHandler?.Invoke();
+
+ GameStageManager.Instance.OnUpdate();
}
public void OnFixedUpdate()
{
- onFixedUpdateHandler?.Invoke();
+ onFixedUpdateHandler?.Invoke();
+
+ GameStageManager.Instance.OnFixedUpdate();
+
}
public void OnDestroy()
{
- onDestroyHandler?.Invoke();
+ onDestroyHandler?.Invoke();
+
+ GameStageManager.Instance.OnDestroy();
}
public void OnApplicationQuit()
{
- onApplicationQuitHandler?.Invoke();
+ onApplicationQuitHandler?.Invoke();
+
+ GameStageManager.Instance.OnApplicationQuit();
}
public void OnApplicationPause()
{
onApplicationPauseHandler?.Invoke();
+
+ GameStageManager.Instance.OnApplicationPause();
}
}
diff --git a/WorldlineKeepers/Assets/Scripts/Battle/SceneManager.cs b/WorldlineKeepers/Assets/Scripts/Battle/SceneManager.cs
index ff7ac65..ac800ee 100644
--- a/WorldlineKeepers/Assets/Scripts/Battle/SceneManager.cs
+++ b/WorldlineKeepers/Assets/Scripts/Battle/SceneManager.cs
@@ -19,7 +19,7 @@ namespace WK
}
}
- public void LoadScene(string sceneName, UnityEngine.SceneManagement.LoadSceneMode loadMode)
+ public void LoadScene(string sceneName, UnityEngine.SceneManagement.LoadSceneMode loadMode = UnityEngine.SceneManagement.LoadSceneMode.Single)
{
m_AsyncOpt = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(sceneName, loadMode);
}
diff --git a/WorldlineKeepers/Assets/Scripts/Common/SingletonMB.cs b/WorldlineKeepers/Assets/Scripts/Common/SingletonMB.cs
index 5debe57..458f642 100644
--- a/WorldlineKeepers/Assets/Scripts/Common/SingletonMB.cs
+++ b/WorldlineKeepers/Assets/Scripts/Common/SingletonMB.cs
@@ -1,5 +1,6 @@
using Newtonsoft.Json.Utilities;
using UnityEngine;
+using WK;
public abstract class SingletonMB<T> : MonoBehaviour where T : class
{
@@ -52,7 +53,7 @@ public abstract class SingletonMB<T> : MonoBehaviour where T : class
}
else
{
- Debug.LogError("m_Instance is already null!! type is " + typeof(T).ToString());
+ LogHelper.LogError("m_Instance is already null!! type is " + typeof(T).ToString());
}
}
} \ No newline at end of file
diff --git a/WorldlineKeepers/Assets/Scripts/Physics/Quadtree.cs b/WorldlineKeepers/Assets/Scripts/Physics/Quadtree.cs
index a012d26..bb20c76 100644
--- a/WorldlineKeepers/Assets/Scripts/Physics/Quadtree.cs
+++ b/WorldlineKeepers/Assets/Scripts/Physics/Quadtree.cs
@@ -7,6 +7,7 @@ using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Unity.VisualScripting;
using UnityEngine;
+using WK;
// https://gamedev.stackexchange.com/questions/6345/quad-tree-vs-grid-based-collision-detection
@@ -104,7 +105,7 @@ namespace mh
{
if(!m_IsRoot)
{
- Debug.LogError("Quadtree.Rebound()ֻ");
+ LogHelper.LogError("Quadtree.Rebound()ֻ");
return;
}
m_Bounds = bounds;
diff --git a/WorldlineKeepers/Assets/Scripts/Rendering/SpriteAnimationController.cs b/WorldlineKeepers/Assets/Scripts/Rendering/SpriteAnimationController.cs
index 63ba394..3c4bf2b 100644
--- a/WorldlineKeepers/Assets/Scripts/Rendering/SpriteAnimationController.cs
+++ b/WorldlineKeepers/Assets/Scripts/Rendering/SpriteAnimationController.cs
@@ -38,6 +38,9 @@ namespace WK.Rendering
StartCoroutine(CoPlayAnimation(m_SpriteAnimation.duration));
m_IsPlaying = true;
+
+
+ m_SpriteRenderer.sprite = m_SpriteAnimation.sprites[0];
}
IEnumerator CoPlayAnimation(float duration = 1f)
diff --git a/WorldlineKeepers/Assets/Scripts/Stages/GameStageBase.cs b/WorldlineKeepers/Assets/Scripts/Stages/GameStageBase.cs
index 73ded6e..9b53354 100644
--- a/WorldlineKeepers/Assets/Scripts/Stages/GameStageBase.cs
+++ b/WorldlineKeepers/Assets/Scripts/Stages/GameStageBase.cs
@@ -9,6 +9,7 @@ namespace WK
public class GameStageBase : AsyncStatemachine.State
{
+ GameStageManager owner = GameStageManager.Instance;
public override IEnumerator<float> OnStart()
{
diff --git a/WorldlineKeepers/Assets/Scripts/Stages/GameStageManager.cs b/WorldlineKeepers/Assets/Scripts/Stages/GameStageManager.cs
index a92a3d8..2e1ea6b 100644
--- a/WorldlineKeepers/Assets/Scripts/Stages/GameStageManager.cs
+++ b/WorldlineKeepers/Assets/Scripts/Stages/GameStageManager.cs
@@ -27,7 +27,12 @@ namespace WK
{
m_Statemachine = new AsyncStatemachine();
+ stages[(int)EGameStage.Launch] = m_Statemachine.RegisterState(new GameStage_Launch());
+ stages[(int)EGameStage.Main] = m_Statemachine.RegisterState(new GameStage_Main());
+ stages[(int)EGameStage.Battle] = m_Statemachine.RegisterState(new GameStage_Battle());
+ stages[(int)EGameStage.Dojo] = m_Statemachine.RegisterState(new GameStage_Dojo());
+ m_Statemachine.Start(stages[(int)EGameStage.Dojo]);
}
public void OnStart()
diff --git a/WorldlineKeepers/Assets/Scripts/Stages/GameStage_Dojo.cs b/WorldlineKeepers/Assets/Scripts/Stages/GameStage_Dojo.cs
index fbb92a4..fa4e8ed 100644
--- a/WorldlineKeepers/Assets/Scripts/Stages/GameStage_Dojo.cs
+++ b/WorldlineKeepers/Assets/Scripts/Stages/GameStage_Dojo.cs
@@ -8,7 +8,22 @@ namespace WK
public class GameStage_Dojo : GameStageBase
{
+ public override IEnumerator<float> OnStart()
+ {
+ GameSceneManager.Instance.LoadScene("Scenes/3_Dojo");
+ yield break;
+ }
+ public override IEnumerator<float> OnEnd()
+ {
+ yield break;
+ }
+
+ public override void OnUpdate(float deltaTime)
+ {
+
+
+ }
}
diff --git a/WorldlineKeepers/Assets/Scripts/Stages/GameStage_Main.cs b/WorldlineKeepers/Assets/Scripts/Stages/GameStage_Main.cs
index 01488d9..8a1d5eb 100644
--- a/WorldlineKeepers/Assets/Scripts/Stages/GameStage_Main.cs
+++ b/WorldlineKeepers/Assets/Scripts/Stages/GameStage_Main.cs
@@ -5,7 +5,7 @@ using UnityEngine;
namespace WK
{
- public class GameStage_Lobby
+ public class GameStage_Main : GameStageBase
{
diff --git a/WorldlineKeepers/Assets/Scripts/Tests/TestCSV.cs b/WorldlineKeepers/Assets/Scripts/Tests/TestCSV.cs
index b24a8c7..09f810c 100644
--- a/WorldlineKeepers/Assets/Scripts/Tests/TestCSV.cs
+++ b/WorldlineKeepers/Assets/Scripts/Tests/TestCSV.cs
@@ -54,11 +54,11 @@ namespace WK
styled.AppendLine();
}
- Debug.Log(styled.ToString()); // Unity
+ LogHelper.Log(styled.ToString()); // Unity
Console.WriteLine(styled.ToString()); // C#
List<CharacterStatsMetadata> stats = CSVReader.Read<CharacterStatsMetadata>(text.text);
- Debug.Log(stats.Count);
+ LogHelper.Log(stats.Count);
}
diff --git a/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs b/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs
index 54df05b..482595e 100644
--- a/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs
+++ b/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs
@@ -36,7 +36,7 @@ public class TestEvent : MonoBehaviour, INotification
private void OnEventCheck(params object[] p)
{
- Debug.Log("msg" + p[0]);
+ LogHelper.Log("msg" + p[0]);
}
}
diff --git a/WorldlineKeepers/Assets/Scripts/Tests/TestJson.cs b/WorldlineKeepers/Assets/Scripts/Tests/TestJson.cs
index dbfa8dc..762b8e4 100644
--- a/WorldlineKeepers/Assets/Scripts/Tests/TestJson.cs
+++ b/WorldlineKeepers/Assets/Scripts/Tests/TestJson.cs
@@ -2,6 +2,7 @@ using LitJson;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
+using WK;
public class SaveData
{
@@ -61,7 +62,7 @@ public class TestJson : MonoBehaviour
//解析Json
SaveDatas sd = JsonMapper.ToObject<SaveDatas>(Datas);
- Debug.Log(Datas);
+ LogHelper.Log(Datas);
}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Commands.meta b/WorldlineKeepers/Assets/Scripts/Tools/Commands.meta
new file mode 100644
index 0000000..e9f33f2
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Commands.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 43e010091f201b6468a42e7ea26b6885
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Commands/Command.cs b/WorldlineKeepers/Assets/Scripts/Tools/Commands/Command.cs
new file mode 100644
index 0000000..120eb08
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Commands/Command.cs
@@ -0,0 +1,47 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK
+{
+
+ public abstract class Command
+ {
+
+ public abstract void Execute();
+
+ }
+
+ public class CommandList
+ {
+ private List<Command> m_Commands = new List<Command>();
+
+ public void AddCommand(Command cmd)
+ {
+ if (cmd == null)
+ {
+ return;
+ }
+ m_Commands.Add(cmd);
+ }
+
+ public void RemoveCommand(Command cmd)
+ {
+ if (cmd == null)
+ {
+ return;
+ }
+ m_Commands.Remove(cmd);
+ }
+
+ public void Execute()
+ {
+ for (int i = 0; i < m_Commands.Count; ++i)
+ {
+ m_Commands[i].Execute();
+ }
+ }
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Commands/Command.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/Commands/Command.cs.meta
new file mode 100644
index 0000000..651a018
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Commands/Command.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f81999dab5f39be408c8e5c5f809eddf
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Commands/CommandGroup.cs b/WorldlineKeepers/Assets/Scripts/Tools/Commands/CommandGroup.cs
new file mode 100644
index 0000000..8e53888
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Commands/CommandGroup.cs
@@ -0,0 +1,96 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel.Design;
+using System.Diagnostics.Tracing;
+using System.Linq;
+using UnityEngine;
+using UnityEngine.AI;
+using UnityEngine.UIElements;
+
+namespace WK
+{
+ //http://warmcat.org/chai/blog/?p=2343
+
+ public abstract class CommandsGroup
+ {
+
+ public abstract class Command
+ {
+ public CommandID ID;
+ public Command(CommandID id)
+ {
+ this.ID = id;
+ }
+ /// <summary>
+ /// ִ
+ /// </summary>
+ public abstract void Execute();
+ /// <summary>
+ /// עIJ
+ /// </summary>
+ /// <param name="_param"></param>
+ public abstract void Register(params object[] _param);
+ }
+
+ protected List<Command> commandQueue = new List<Command>();
+ protected void AddCommand(Command cmd)
+ {
+ commandQueue.Add(cmd);
+ }
+
+ public CommandsGroup()
+ {
+ SetupCommands();
+ }
+
+ /// <summary>
+ /// commandQueue
+ /// </summary>
+ protected abstract void SetupCommands();
+
+ public void Execute()
+ {
+ foreach (Command e in commandQueue)
+ {
+ e.Execute();
+ }
+ }
+
+ public void RegisterParams(params object[] data)
+ {
+ if (data.Length < 1)
+ return;
+ CommandID id = (CommandID)data[0];
+ int len = data.Length;
+ foreach (Command e in commandQueue)
+ {
+ if (e.ID == id)
+ {
+ e.Register(data.Skip(1).Take(len - 1));
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ /// <summary>
+ /// ʱִе
+ /// </summary>
+ class MainSceneLoadCommandsGroup : CommandsGroup
+ {
+ public MainSceneLoadCommandsGroup() : base()
+ {
+ // Ҫִе
+
+ AddCommand(new OpenPanelCommand());
+ //
+ //AddCommand(new MessageBox());
+ //AddCommand(new OpenChest());
+ //...
+ }
+ }
+
+ */
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Commands/CommandGroup.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/Commands/CommandGroup.cs.meta
new file mode 100644
index 0000000..3df093c
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Commands/CommandGroup.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 61d8f0e869532c64395b21a493d17a45
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/GameObjectPool.cs b/WorldlineKeepers/Assets/Scripts/Tools/GameObjectPool.cs
new file mode 100644
index 0000000..1d948e6
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/GameObjectPool.cs
@@ -0,0 +1,51 @@
+using UnityEngine;
+using WK;
+
+namespace WK
+{
+ public class GameObjectPool : System.IDisposable, UnityObjectPool<GameObject>.IPooledInstanceInitializer
+ {
+ UnityObjectPool<GameObject> _pool;
+ Transform _poolParent;
+
+ public GameObjectPool(GameObject sourceObject, Transform poolParent, int initialSize = 0)
+ {
+ _pool = new UnityObjectPool<GameObject>(sourceObject, poolParent, this, initialSize);
+ _poolParent = poolParent;
+ }
+
+ public GameObject Acquire(Transform parent)
+ {
+ GameObject instance = _pool.Acquire();
+ instance.transform.SetParent(parent);
+ instance.transform.ResetLocal();
+ instance.SetActive(true);
+
+ return instance;
+ }
+
+ public void Release(GameObject instance)
+ {
+ instance.SetActive(false);
+ instance.transform.SetParent(_poolParent);
+ _pool.Release(instance);
+ }
+
+ public void InitPooledInstance(GameObject instance)
+ {
+ instance.SetActive(false);
+ }
+
+ public void DestroyPooledInstance(GameObject instance)
+ {
+ UnityEngine.Object.Destroy(instance);
+ }
+
+ public void Dispose()
+ {
+ _pool.Dispose();
+ _pool = null;
+ _poolParent = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/GameObjectPool.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/GameObjectPool.cs.meta
new file mode 100644
index 0000000..d3234ce
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/GameObjectPool.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6df40d153f41aa446b2746e80abc19d9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Notification/NotificationCenter.cs b/WorldlineKeepers/Assets/Scripts/Tools/Notification/NotificationCenter.cs
index bb4e08e..4e52656 100644
--- a/WorldlineKeepers/Assets/Scripts/Tools/Notification/NotificationCenter.cs
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Notification/NotificationCenter.cs
@@ -5,7 +5,7 @@ using UnityEngine;
namespace WK
{
- public class NotificationCenter : Singleton<NotificationCenter>
+ public sealed class NotificationCenter : Singleton<NotificationCenter>
{
public delegate void NotificatonHandler(params object[] args);
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Notification/ScopedNotification.cs b/WorldlineKeepers/Assets/Scripts/Tools/Notification/ScopedNotification.cs
index 0002f14..5a1171e 100644
--- a/WorldlineKeepers/Assets/Scripts/Tools/Notification/ScopedNotification.cs
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Notification/ScopedNotification.cs
@@ -5,6 +5,9 @@ using UnityEngine;
namespace WK
{
+ /// <summary>
+ /// ΧϢ֪ͨ
+ /// </summary>
public class ScopedNotification
{
public delegate void NotificatonHandler(params object[] args);
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/ObjectPool.cs b/WorldlineKeepers/Assets/Scripts/Tools/ObjectPool.cs
new file mode 100644
index 0000000..ac18a9a
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/ObjectPool.cs
@@ -0,0 +1,51 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Events;
+
+namespace WK
+{
+ class ObjectPool<T> where T : new()
+ {
+ private readonly Stack<T> m_Stack = new Stack<T>();
+ private readonly UnityAction<T> m_ActionOnGet;
+ private readonly UnityAction<T> m_ActionOnRelease;
+
+ public int countAll { get; private set; }
+ public int countActive { get { return countAll - countInactive; } }
+ public int countInactive { get { return m_Stack.Count; } }
+
+ public ObjectPool(UnityAction<T> actionOnGet, UnityAction<T> actionOnRelease)
+ {
+ m_ActionOnGet = actionOnGet;
+ m_ActionOnRelease = actionOnRelease;
+ }
+
+ public T Get()
+ {
+ T element;
+ if (m_Stack.Count == 0)
+ {
+ element = new T();
+ countAll++;
+ }
+ else
+ {
+ element = m_Stack.Pop();
+ }
+ if (m_ActionOnGet != null)
+ m_ActionOnGet(element);
+ return element;
+ }
+
+ public void Release(T element)
+ {
+ if (m_Stack.Count > 0 && ReferenceEquals(m_Stack.Peek(), element))
+ Debug.LogError("Internal error. Trying to destroy object that is already released to pool.");
+ if (m_ActionOnRelease != null)
+ m_ActionOnRelease(element);
+ m_Stack.Push(element);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/ObjectPool.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/ObjectPool.cs.meta
new file mode 100644
index 0000000..b9cdb21
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/ObjectPool.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bc1e2a929537ad04bb2ae5f26ce4ad77
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Recycle.cs b/WorldlineKeepers/Assets/Scripts/Tools/Recycle.cs
new file mode 100644
index 0000000..a53289f
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Recycle.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+
+namespace WK
+{
+
+ /// <summary>
+ /// ʵִ˽ӿûնijԱֵ
+ /// </summary>
+ public interface IRcycle
+ {
+ void Release();
+ }
+
+ public class Recycle<T> where T : IRcycle, new()
+ {
+ private List<T> cachedNodeList;
+ private int maxCapacity;
+
+ public Recycle(int initCapacity, int maxCapacity)
+ {
+ this.maxCapacity = maxCapacity;
+ if (cachedNodeList == null)
+ {
+ cachedNodeList = new List<T>(initCapacity);
+ for (int i = 0; i < initCapacity; ++i)
+ {
+ cachedNodeList.Add(new T());
+ }
+ }
+ }
+
+ public T GetUnusedNode()
+ {
+ if (cachedNodeList.Count > 0)
+ {
+ // remove and return last node
+ int i = cachedNodeList.Count - 1;
+ T t = cachedNodeList[i];
+ cachedNodeList.RemoveAt(i);
+ return t;
+ }
+ return new T();
+ }
+
+ //ն󲢽ԭΪʼֵ(0null)
+ public bool ReleaseNode(ref T t)
+ {
+ if (t == null)
+ return false;
+
+ T refT = t;
+ t = default(T);
+
+ if (cachedNodeList.Count > maxCapacity)
+ return false;
+
+ if (cachedNodeList.Contains(refT))
+ {
+ LogHelper.LogError("ظ");
+ return false;
+ }
+
+ refT.Release();
+ cachedNodeList.Add(refT);
+ return true;
+ }
+
+ }
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Recycle.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/Recycle.cs.meta
new file mode 100644
index 0000000..e0a21a6
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Recycle.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 413419b3354bc304691bcf8c075052fd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/ScopedEvent.cs b/WorldlineKeepers/Assets/Scripts/Tools/ScopedEvent.cs
new file mode 100644
index 0000000..23bfaa8
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/ScopedEvent.cs
@@ -0,0 +1,54 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.AI;
+
+namespace WK
+{
+
+ /// <summary>
+ /// UnityEventǸ
+ /// </summary>
+ public class ScopedEvent
+ {
+ public delegate void EventHandler(params object[] args);
+
+ private List<EventHandler> m_Handlers = new List<EventHandler>();
+
+ public void AddListener(EventHandler handler)
+ {
+ if(handler == null)
+ {
+ return;
+ }
+ if (m_Handlers.Contains(handler))
+ return;
+ m_Handlers.Add(handler);
+ }
+
+ public void RemoveListener(EventHandler handler)
+ {
+
+ if (handler == null)
+ {
+ return;
+ }
+ m_Handlers.Remove(handler);
+ }
+
+ public bool HasHandler(EventHandler handler)
+ {
+ return m_Handlers.Contains(handler);
+ }
+
+ public void Invoke(params object[] args)
+ {
+ for(int i = 0; i < m_Handlers.Count; ++i)
+ {
+ m_Handlers[i](args);
+ }
+ }
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/ScopedEvent.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/ScopedEvent.cs.meta
new file mode 100644
index 0000000..bcbce6e
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/ScopedEvent.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 332ddd24c01402a498f667a06c63b3cd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs
index 605f737..67c791d 100644
--- a/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs
@@ -1,7 +1,7 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
-using MEC;
+using MovementEffects;
namespace WK
{
@@ -43,7 +43,7 @@ namespace WK
return NULL_STATE_ID;
if (stateIDDistributor + 1 >= int.MaxValue)
{
- Debug.LogError("״̬״̬ʧܣ״̬ӵ״̬");
+ LogHelper.LogError("״̬״̬ʧܣ״̬ӵ״̬");
return NULL_STATE_ID;
}
++stateIDDistributor;
@@ -54,7 +54,7 @@ namespace WK
allState.Add(stateIDDistributor, newState);
return stateIDDistributor;
}
- Debug.LogError("״̬״̬ʧܣ״̬Ѿ");
+ LogHelper.LogError("״̬״̬ʧܣ״̬Ѿ");
return NULL_STATE_ID;
}
@@ -64,7 +64,7 @@ namespace WK
{
return RemoveState(state.stateID);
}
- Debug.LogError("״̬ɾ״̬ʧܣ״̬Ϊ");
+ LogHelper.LogError("״̬ɾ״̬ʧܣ״̬Ϊ");
return false;
}
@@ -75,7 +75,7 @@ namespace WK
allState.Remove(stateID);
return true;
}
- Debug.LogError("״̬ɾ״̬ʧܣ״̬ڣstateID = " + stateID);
+ LogHelper.LogError("״̬ɾ״̬ʧܣ״̬ڣstateID = " + stateID);
return false;
}
@@ -147,7 +147,7 @@ namespace WK
{
isUpdateActive = false;
CoroutineHandle handle = Timing.RunCoroutine(EndState(curStateID));
- while (handle.IsValid)
+ while (handle.IsRunning)
{
yield return Timing.WaitForSeconds(COROUINT_DELTIME);
}
@@ -155,7 +155,7 @@ namespace WK
if (!skipStartFunc)
{
CoroutineHandle handle2 = Timing.RunCoroutine(StartState(curStateID));
- while (handle2.IsValid)
+ while (handle2.IsRunning)
{
yield return Timing.WaitForSeconds(COROUINT_DELTIME);
}
@@ -215,7 +215,7 @@ namespace WK
if (state != null)
{
CoroutineHandle handle = Timing.RunCoroutine(state.OnStart());
- while (handle.IsValid)
+ while (handle.IsRunning)
{
yield return Timing.WaitForSeconds(COROUINT_DELTIME);
}
@@ -231,7 +231,7 @@ namespace WK
if (state != null)
{
CoroutineHandle handle = Timing.RunCoroutine(state.OnEnd());
- while (handle.IsValid)
+ while (handle.IsRunning)
{
yield return Timing.WaitForSeconds(COROUINT_DELTIME);
}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs
index 56dd28b..b54b5e1 100644
--- a/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs
@@ -42,7 +42,7 @@ namespace WK
{
if (stateIdDistributor + 1 > int.MaxValue)
{
- Debug.LogError("״̬״̬ʧܣһ״̬˹״̬");
+ LogHelper.LogError("״̬״̬ʧܣһ״̬˹״̬");
return -1;
}
@@ -55,7 +55,7 @@ namespace WK
return stateIdDistributor;
}
}
- Debug.LogError("״̬״̬ʧܣЧ״̬״̬Ѵڣ");
+ LogHelper.LogError("״̬״̬ʧܣЧ״̬״̬Ѵڣ");
return -1;
}
@@ -63,7 +63,7 @@ namespace WK
{
if (toBeRemoveState != null)
return RemoveState(toBeRemoveState.stateId);
- Debug.LogError("״̬ɾ״̬ʧܣЧ״̬");
+ LogHelper.LogError("״̬ɾ״̬ʧܣЧ״̬");
return false;
}
@@ -74,7 +74,7 @@ namespace WK
stateDic.Remove(stateId);
return true;
}
- Debug.LogError("״̬ɾ״̬ʧܣ״̬ڣ");
+ LogHelper.LogError("״̬ɾ״̬ʧܣ״̬ڣ");
return false;
}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs b/WorldlineKeepers/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs
new file mode 100644
index 0000000..50da91b
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Diagnostics;
+
+/// <summary>
+/// 线程安全的时间流逝类
+/// 从游戏运行开始计时
+/// </summary>
+public static class ThreadSafeElapsedTime
+{
+ private static bool _isStart = false;
+ private static Stopwatch _stopwatch;
+ private static long _curRawElapsedTicks;
+ private static float _curRawElapsedSeconds;
+
+ static private double ticks2seconds = 1 / (double) TimeSpan.TicksPerSecond;
+
+
+ //必须在启动后调用
+ public static void Start()
+ {
+ if (!_isStart)
+ {
+ _isStart = true;
+ _stopwatch = new Stopwatch();
+ _stopwatch.Start();
+ _curRawElapsedTicks = 0;
+ _curRawElapsedSeconds = 0;
+ }
+ }
+
+ public static void Stop()
+ {
+ if (_isStart)
+ {
+ _isStart = false;
+ _stopwatch.Stop();
+ }
+ }
+
+ public static void Update()
+ {
+ if (_isStart)
+ {
+ _curRawElapsedTicks = _stopwatch.ElapsedTicks;
+ //_curRawElapsedSeconds = (int)(_curRawElapsedTicks / System.TimeSpan.TicksPerSecond);
+ _curRawElapsedSeconds = (float)(((double) _curRawElapsedTicks ) * ticks2seconds);
+ }
+ }
+
+ /// <summary>
+ /// 自游戏启动以来的ticks
+ /// </summary>
+ /// <returns></returns>
+ public static long GetElapsedTicksSinceStartUp()
+ {
+ #if UNITY_EDITOR
+ Start();
+ Update();
+ #endif
+ return _curRawElapsedTicks;
+ }
+ /// <summary>
+ /// 自游戏启动以来的seconds
+ /// </summary>
+ /// <returns></returns>
+ public static float GetElapsedSecondsSinceStartUp()
+ {
+#if UNITY_EDITOR
+ Start();
+ Update();
+#endif
+ return _curRawElapsedSeconds;
+ }
+
+ /// <summary>
+ /// 自游戏启动以来的miniseconds
+ /// </summary>
+ /// <returns></returns>
+ public static int GetElapsedMiniSecondsSinceStartUp()
+ {
+#if UNITY_EDITOR
+ Start();
+ Update();
+#endif
+ return (int)(_curRawElapsedSeconds * 1000);
+ }
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs.meta
new file mode 100644
index 0000000..072611a
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6767239866ef68a4b841b36c5bd140b9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software.meta b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software.meta
index 616b6fb..616b6fb 100644
--- a/WorldlineKeepers/Assets/Plugins/Trinary Software.meta
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software.meta
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor.meta b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Editor.meta
index 2e833c9..2e833c9 100644
--- a/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor.meta
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Editor.meta
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png
index caf3365..caf3365 100644
--- a/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png
Binary files differ
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png.meta b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png.meta
index 733447a..733447a 100644
--- a/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png.meta
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png.meta
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf
index e2f028f..e2f028f 100644
--- a/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf
Binary files differ
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf.meta b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf.meta
index 4a34c89..4a34c89 100644
--- a/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf.meta
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf.meta
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Timing.cs b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Timing.cs
new file mode 100644
index 0000000..6e38b0c
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Timing.cs
@@ -0,0 +1,4655 @@
+using UnityEngine;
+using System.Collections.Generic;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+#if UNITY_5_5_OR_NEWER
+using UnityEngine.Profiling;
+#endif
+
+// /////////////////////////////////////////////////////////////////////////////////////////
+// More Effective Coroutines Pro
+// v2.03.0
+//
+// This is an improved implementation of coroutines that boasts zero per-frame memory allocations,
+// runs about twice as fast as Unity's built in coroutines and has a range of extra features.
+//
+// For manual, support, or upgrade guide visit http://trinary.tech/
+//
+// Created by Teal Rogers
+// Trinary Software
+// All rights preserved
+// trinaryllc@gmail.com
+// /////////////////////////////////////////////////////////////////////////////////////////
+
+namespace MovementEffects
+{
+ public class Timing : MonoBehaviour
+ {
+ public enum DebugInfoType
+ {
+ None,
+ SeperateCoroutines,
+ SeperateTags
+ }
+
+ /// <summary>
+ /// The time between calls to SlowUpdate.
+ /// </summary>
+ [Tooltip("How quickly the SlowUpdate segment ticks.")]
+ public float TimeBetweenSlowUpdateCalls = 1f / 7f;
+ /// <summary>
+ /// The amount that each coroutine should be seperated inside the Unity profiler. NOTE: When the profiler window
+ /// is not open this value is ignored and all coroutines behave as if "None" is selected.
+ /// </summary>
+ [Tooltip("How much data should be sent to the profiler window when it's open.")]
+ public DebugInfoType ProfilerDebugAmount = DebugInfoType.None;
+ /// <summary>
+ /// Whether the manual timeframe should automatically trigger during the update segment.
+ /// </summary>
+ [Tooltip("When using manual timeframe, should it run automatically after the update loop or only when TriggerManualTimframeUpdate is called.")]
+ public bool AutoTriggerManualTimeframe = true;
+ /// <summary>
+ /// The number of coroutines that are being run in the Update segment.
+ /// </summary>
+ [Tooltip("A count of the number of Update coroutines that are currently running."), Space(12)]
+ public int UpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the FixedUpdate segment.
+ /// </summary>
+ [Tooltip("A count of the number of FixedUpdate coroutines that are currently running.")]
+ public int FixedUpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the LateUpdate segment.
+ /// </summary>
+ [Tooltip("A count of the number of LateUpdate coroutines that are currently running.")]
+ public int LateUpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the SlowUpdate segment.
+ /// </summary>
+ [Tooltip("A count of the number of SlowUpdate coroutines that are currently running.")]
+ public int SlowUpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the RealtimeUpdate segment.
+ /// </summary>
+ [Tooltip("A count of the number of RealtimeUpdate coroutines that are currently running.")]
+ public int RealtimeUpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the EditorUpdate segment.
+ /// </summary>
+ [Tooltip("A count of the number of EditorUpdate coroutines that are currently running.")]
+ public int EditorUpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the EditorSlowUpdate segment.
+ /// </summary>
+ [Tooltip("A count of the number of EditorSlowUpdate coroutines that are currently running.")]
+ public int EditorSlowUpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the EndOfFrame segment.
+ /// </summary>
+ [Tooltip("A count of the number of EndOfFrame coroutines that are currently running.")]
+ public int EndOfFrameCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the ManualTimeframe segment.
+ /// </summary>
+ [Tooltip("A count of the number of ManualTimeframe coroutines that are currently running.")]
+ public int ManualTimeframeCoroutines;
+
+ /// <summary>
+ /// The time in seconds that the current segment has been running.
+ /// </summary>
+ [HideInInspector]
+ public double localTime;
+ /// <summary>
+ /// The time in seconds that the current segment has been running.
+ /// </summary>
+ public static float LocalTime { get { return (float)Instance.localTime; } }
+ /// <summary>
+ /// The amount of time in fractional seconds that elapsed between this frame and the last frame.
+ /// </summary>
+ [HideInInspector]
+ public float deltaTime;
+ /// <summary>
+ /// The amount of time in fractional seconds that elapsed between this frame and the last frame.
+ /// </summary>
+ public static float DeltaTime { get { return Instance.deltaTime; } }
+ /// <summary>
+ /// When defined, all errors from inside coroutines will be passed into this function instead of falling through to the Unity console.
+ /// </summary>
+ public System.Action<System.Exception> OnError;
+ /// <summary>
+ /// When defined, this function will be called every time manual timeframe needs to be set. The last manual timeframe time is passed in, and
+ /// the new manual timeframe time needs to be returned. If this function is left as null, manual timeframe will be set to the current Time.time.
+ /// </summary>
+ public System.Func<double, double> SetManualTimeframeTime;
+ /// <summary>
+ /// Used for advanced coroutine control.
+ /// </summary>
+ public static System.Func<IEnumerator<float>, Timing, CoroutineHandle, IEnumerator<float>> ReplacementFunction;
+
+ private bool _runningUpdate;
+ private bool _runningFixedUpdate;
+ private bool _runningLateUpdate;
+ private bool _runningRealtimeUpdate;
+ private bool _runningEditorUpdate;
+ private int _nextUpdateProcessSlot;
+ private int _nextLateUpdateProcessSlot;
+ private int _nextFixedUpdateProcessSlot;
+ private int _nextSlowUpdateProcessSlot;
+ private int _nextRealtimeUpdateProcessSlot;
+ private int _nextEditorUpdateProcessSlot;
+ private int _nextEditorSlowUpdateProcessSlot;
+ private int _nextEndOfFrameProcessSlot;
+ private int _nextManualTimeframeProcessSlot;
+ private double _lastUpdateTime;
+ private double _lastLateUpdateTime;
+ private double _lastFixedUpdateTime;
+ private double _lastSlowUpdateTime;
+ private double _lastRealtimeUpdateTime;
+ private double _lastEditorUpdateTime;
+ private double _lastEditorSlowUpdateTime;
+ private double _lastManualTimeframeTime;
+ private ushort _framesSinceUpdate;
+ private ushort _expansions = 1;
+ private byte _instanceID;
+ private bool _EOFPumpRan;
+
+ private readonly WaitForEndOfFrame _EOFWaitObject = new WaitForEndOfFrame();
+ private readonly Dictionary<CoroutineHandle, HashSet<ProcessData>> _waitingTriggers = new Dictionary<CoroutineHandle, HashSet<ProcessData>>();
+ private readonly Queue<System.Exception> _exceptions = new Queue<System.Exception>();
+ private readonly Dictionary<CoroutineHandle, ProcessIndex> _handleToIndex = new Dictionary<CoroutineHandle, ProcessIndex>();
+ private readonly Dictionary<ProcessIndex, CoroutineHandle> _indexToHandle = new Dictionary<ProcessIndex, CoroutineHandle>();
+ private readonly Dictionary<ProcessIndex, string> _processTags = new Dictionary<ProcessIndex, string>();
+ private readonly Dictionary<string, HashSet<ProcessIndex>> _taggedProcesses = new Dictionary<string, HashSet<ProcessIndex>>();
+ private readonly Dictionary<ProcessIndex, int> _processLayers = new Dictionary<ProcessIndex, int>();
+ private readonly Dictionary<int, HashSet<ProcessIndex>> _layeredProcesses = new Dictionary<int, HashSet<ProcessIndex>>();
+
+ private IEnumerator<float>[] UpdateProcesses = new IEnumerator<float>[InitialBufferSizeLarge];
+ private IEnumerator<float>[] LateUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ private IEnumerator<float>[] FixedUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
+ private IEnumerator<float>[] SlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
+ private IEnumerator<float>[] RealtimeUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ private IEnumerator<float>[] EditorUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ private IEnumerator<float>[] EditorSlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ private IEnumerator<float>[] EndOfFrameProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ private IEnumerator<float>[] ManualTimeframeProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+
+ private volatile bool[] UpdatePaused = new bool[InitialBufferSizeLarge];
+ private volatile bool[] LateUpdatePaused = new bool[InitialBufferSizeSmall];
+ private volatile bool[] FixedUpdatePaused = new bool[InitialBufferSizeMedium];
+ private volatile bool[] SlowUpdatePaused = new bool[InitialBufferSizeMedium];
+ private volatile bool[] RealtimeUpdatePaused = new bool[InitialBufferSizeSmall];
+ private volatile bool[] EditorUpdatePaused = new bool[InitialBufferSizeSmall];
+ private volatile bool[] EditorSlowUpdatePaused = new bool[InitialBufferSizeSmall];
+ private volatile bool[] EndOfFramePaused = new bool[InitialBufferSizeSmall];
+ private volatile bool[] ManualTimeframePaused = new bool[InitialBufferSizeSmall];
+
+ private const ushort FramesUntilMaintenance = 64;
+ private const int ProcessArrayChunkSize = 64;
+ private const int InitialBufferSizeLarge = 256;
+ private const int InitialBufferSizeMedium = 64;
+ private const int InitialBufferSizeSmall = 8;
+
+ private static readonly Dictionary<byte, Timing> ActiveInstances = new Dictionary<byte, Timing>();
+ private static Timing _instance;
+
+ public static Timing Instance
+ {
+ get
+ {
+ if (_instance == null || !_instance.gameObject)
+ {
+ GameObject instanceHome = GameObject.Find("Movement Effects");
+ System.Type movementType =
+ System.Type.GetType("MovementEffects.Movement, MovementOverTime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
+
+ if (instanceHome == null)
+ {
+ instanceHome = new GameObject { name = "Movement Effects" };
+ DontDestroyOnLoad(instanceHome);
+
+ if (movementType != null)
+ instanceHome.AddComponent(movementType);
+
+ _instance = instanceHome.AddComponent<Timing>();
+ }
+ else
+ {
+ if (movementType != null && instanceHome.GetComponent(movementType) == null)
+ instanceHome.AddComponent(movementType);
+
+ _instance = instanceHome.GetComponent<Timing>() ?? instanceHome.AddComponent<Timing>();
+ }
+ }
+
+ return _instance;
+ }
+
+ set { _instance = value; }
+ }
+
+ void Awake()
+ {
+ if (_instance == null)
+ _instance = this;
+ else
+ deltaTime = Instance.deltaTime;
+
+ _instanceID = 0x01;
+ while (ActiveInstances.ContainsKey(_instanceID))
+ _instanceID++;
+
+ if (_instanceID == 0x20)
+ {
+ GameObject.Destroy(gameObject);
+ throw new System.OverflowException("You are only allowed 31 instances of MEC at one time.");
+ }
+
+ ActiveInstances.Add(_instanceID, this);
+ }
+
+ void OnDestroy()
+ {
+ if (_instance == this)
+ _instance = null;
+
+ ActiveInstances.Remove(_instanceID);
+ }
+
+ void OnEnable()
+ {
+ if (_nextEditorUpdateProcessSlot > 0 || _nextEditorSlowUpdateProcessSlot > 0)
+ OnEditorStart();
+
+ if (_nextEndOfFrameProcessSlot > 0)
+ RunCoroutineSingletonOnInstance(_EOFPumpWatcher(), "MEC_EOFPumpWatcher");
+ }
+
+ void Update()
+ {
+ if (_lastSlowUpdateTime + TimeBetweenSlowUpdateCalls < ThreadSafeElapsedTime.GetElapsedSecondsSinceStartUp() && _nextSlowUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.SlowUpdate };
+ UpdateTimeValues(coindex.seg);
+
+ for (coindex.i = 0; coindex.i < _nextSlowUpdateProcessSlot; coindex.i++)
+ {
+ if (!SlowUpdatePaused[coindex.i] && SlowUpdateProcesses[coindex.i] != null && !(localTime < SlowUpdateProcesses[coindex.i].Current))
+ {
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine (Slow Update), " +
+ (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") +
+ (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag"))
+ : "Processing Coroutine (Slow Update)");
+ }
+
+ try
+ {
+ if (!SlowUpdateProcesses[coindex.i].MoveNext())
+ {
+ SlowUpdateProcesses[coindex.i] = null;
+ }
+ else if (SlowUpdateProcesses[coindex.i] != null && float.IsNaN(SlowUpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ SlowUpdateProcesses[coindex.i] = null;
+ }
+ else
+ {
+ SlowUpdateProcesses[coindex.i] = ReplacementFunction(SlowUpdateProcesses[coindex.i], this, _indexToHandle[coindex]);
+
+ ReplacementFunction = null;
+ coindex.i--;
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ SlowUpdateProcesses[coindex.i] = null;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+ }
+
+ if (_nextRealtimeUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.RealtimeUpdate };
+ _runningRealtimeUpdate = true;
+ UpdateTimeValues(coindex.seg);
+
+ for (coindex.i = 0; coindex.i < _nextRealtimeUpdateProcessSlot; coindex.i++)
+ {
+ if (!RealtimeUpdatePaused[coindex.i] && RealtimeUpdateProcesses[coindex.i] != null && !(localTime < RealtimeUpdateProcesses[coindex.i].Current))
+ {
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine (Realtime Update), " +
+ (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") +
+ (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag"))
+ : "Processing Coroutine (Realtime Update)");
+ }
+
+ try
+ {
+ if (!RealtimeUpdateProcesses[coindex.i].MoveNext())
+ {
+ RealtimeUpdateProcesses[coindex.i] = null;
+ }
+ else if (RealtimeUpdateProcesses[coindex.i] != null && float.IsNaN(RealtimeUpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ RealtimeUpdateProcesses[coindex.i] = null;
+ }
+ else
+ {
+ RealtimeUpdateProcesses[coindex.i] = ReplacementFunction(RealtimeUpdateProcesses[coindex.i], this, _indexToHandle[coindex]);
+
+ ReplacementFunction = null;
+ coindex.i--;
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ RealtimeUpdateProcesses[coindex.i] = null;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+
+ _runningRealtimeUpdate = false;
+ }
+
+ if (_nextUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.Update };
+ _runningUpdate = true;
+ UpdateTimeValues(coindex.seg);
+
+ for (coindex.i = 0; coindex.i < _nextUpdateProcessSlot; coindex.i++)
+ {
+ if (!UpdatePaused[coindex.i] && UpdateProcesses[coindex.i] != null && !(localTime < UpdateProcesses[coindex.i].Current))
+ {
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine, " +
+ (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") +
+ (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) : "Processing Coroutine");
+ }
+
+ try
+ {
+ if (!UpdateProcesses[coindex.i].MoveNext())
+ {
+ UpdateProcesses[coindex.i] = null;
+ }
+ else if (UpdateProcesses[coindex.i] != null && float.IsNaN(UpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ UpdateProcesses[coindex.i] = null;
+ }
+ else
+ {
+ UpdateProcesses[coindex.i] = ReplacementFunction(UpdateProcesses[coindex.i], this, _indexToHandle[coindex]);
+
+ ReplacementFunction = null;
+ coindex.i--;
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ UpdateProcesses[coindex.i] = null;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+
+ _runningUpdate = false;
+ }
+
+ if (AutoTriggerManualTimeframe)
+ {
+ TriggerManualTimeframeUpdate();
+ }
+ else
+ {
+ if (++_framesSinceUpdate > FramesUntilMaintenance)
+ {
+ _framesSinceUpdate = 0;
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.BeginSample("Maintenance Task");
+
+ RemoveUnused();
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+
+ if (_exceptions.Count > 0)
+ throw _exceptions.Dequeue();
+ }
+ }
+
+ void FixedUpdate()
+ {
+ if (_nextFixedUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.FixedUpdate };
+ _runningFixedUpdate = true;
+ UpdateTimeValues(coindex.seg);
+
+ for (coindex.i = 0; coindex.i < _nextFixedUpdateProcessSlot; coindex.i++)
+ {
+ if (!FixedUpdatePaused[coindex.i] && FixedUpdateProcesses[coindex.i] != null && !(localTime < FixedUpdateProcesses[coindex.i].Current))
+ {
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine, " +
+ (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") +
+ (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) : "Processing Coroutine");
+ }
+
+ try
+ {
+ if (!FixedUpdateProcesses[coindex.i].MoveNext())
+ {
+ FixedUpdateProcesses[coindex.i] = null;
+ }
+ else if (FixedUpdateProcesses[coindex.i] != null && float.IsNaN(FixedUpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ FixedUpdateProcesses[coindex.i] = null;
+ }
+ else
+ {
+ FixedUpdateProcesses[coindex.i] = ReplacementFunction(FixedUpdateProcesses[coindex.i], this, _indexToHandle[coindex]);
+
+ ReplacementFunction = null;
+ coindex.i--;
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ FixedUpdateProcesses[coindex.i] = null;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+
+ _runningFixedUpdate = false;
+ }
+
+ if (_exceptions.Count > 0)
+ throw _exceptions.Dequeue();
+ }
+
+ void LateUpdate()
+ {
+ if (_nextLateUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.LateUpdate };
+ _runningLateUpdate = true;
+ UpdateTimeValues(coindex.seg);
+
+ for (coindex.i = 0; coindex.i < _nextLateUpdateProcessSlot; coindex.i++)
+ {
+ if (!LateUpdatePaused[coindex.i] && LateUpdateProcesses[coindex.i] != null && !(localTime < LateUpdateProcesses[coindex.i].Current))
+ {
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine, " +
+ (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") +
+ (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) : "Processing Coroutine");
+ }
+
+ try
+ {
+ if (!LateUpdateProcesses[coindex.i].MoveNext())
+ {
+ LateUpdateProcesses[coindex.i] = null;
+ }
+ else if (LateUpdateProcesses[coindex.i] != null && float.IsNaN(LateUpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ LateUpdateProcesses[coindex.i] = null;
+ }
+ else
+ {
+ LateUpdateProcesses[coindex.i] = ReplacementFunction(LateUpdateProcesses[coindex.i], this, _indexToHandle[coindex]);
+
+ ReplacementFunction = null;
+ coindex.i--;
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ LateUpdateProcesses[coindex.i] = null;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+
+ _runningLateUpdate = false;
+ }
+
+ if (_exceptions.Count > 0)
+ throw _exceptions.Dequeue();
+ }
+
+ /// <summary>
+ /// This will trigger an update in the manual timeframe segment. If the AutoTriggerManualTimeframeDuringUpdate variable is set to true
+ /// then this function will be automitically called every Update, so you would normally want to set that variable to false before
+ /// calling this function yourself.
+ /// </summary>
+ public void TriggerManualTimeframeUpdate()
+ {
+ if (_nextManualTimeframeProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.ManualTimeframe };
+ UpdateTimeValues(coindex.seg);
+
+ for (coindex.i = 0; coindex.i < _nextManualTimeframeProcessSlot; coindex.i++)
+ {
+ if (!ManualTimeframePaused[coindex.i] && ManualTimeframeProcesses[coindex.i] != null &&
+ !(localTime < ManualTimeframeProcesses[coindex.i].Current))
+ {
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine (Manual Timeframe), " +
+ (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") +
+ (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag"))
+ : "Processing Coroutine (Manual Timeframe)");
+ }
+
+ try
+ {
+ if (!ManualTimeframeProcesses[coindex.i].MoveNext())
+ {
+ ManualTimeframeProcesses[coindex.i] = null;
+ }
+ else if (ManualTimeframeProcesses[coindex.i] != null && float.IsNaN(ManualTimeframeProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ ManualTimeframeProcesses[coindex.i] = null;
+ }
+ else
+ {
+ ManualTimeframeProcesses[coindex.i] = ReplacementFunction(ManualTimeframeProcesses[coindex.i],
+ this, _indexToHandle[coindex]);
+
+ ReplacementFunction = null;
+ coindex.i--;
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ ManualTimeframeProcesses[coindex.i] = null;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+ }
+
+ if (++_framesSinceUpdate > FramesUntilMaintenance)
+ {
+ _framesSinceUpdate = 0;
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.BeginSample("Maintenance Task");
+
+ RemoveUnused();
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+
+ if (_exceptions.Count > 0)
+ throw _exceptions.Dequeue();
+ }
+
+ private bool OnEditorStart()
+ {
+#if UNITY_EDITOR
+ if (EditorApplication.isPlayingOrWillChangePlaymode)
+ return false;
+
+ if (_lastEditorUpdateTime == 0d)
+ _lastEditorUpdateTime = EditorApplication.timeSinceStartup;
+
+ EditorApplication.update -= OnEditorUpdate;
+
+ EditorApplication.update += OnEditorUpdate;
+
+ return true;
+#else
+ return false;
+#endif
+ }
+
+#if UNITY_EDITOR
+ private void OnEditorUpdate()
+ {
+ if (EditorApplication.isPlayingOrWillChangePlaymode)
+ {
+ for (int i = 0; i < _nextEditorUpdateProcessSlot; i++)
+ EditorUpdateProcesses[i] = null;
+ _nextEditorUpdateProcessSlot = 0;
+ for (int i = 0; i < _nextEditorSlowUpdateProcessSlot; i++)
+ EditorSlowUpdateProcesses[i] = null;
+ _nextEditorSlowUpdateProcessSlot = 0;
+
+ EditorApplication.update -= OnEditorUpdate;
+ _instance = null;
+ }
+
+ if (_lastEditorSlowUpdateTime + TimeBetweenSlowUpdateCalls < EditorApplication.timeSinceStartup && _nextEditorSlowUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.EditorSlowUpdate };
+ UpdateTimeValues(coindex.seg);
+
+ for (coindex.i = 0; coindex.i < _nextEditorSlowUpdateProcessSlot; coindex.i++)
+ {
+ if (!EditorSlowUpdatePaused[coindex.i] && EditorSlowUpdateProcesses[coindex.i] != null &&
+ !(EditorApplication.timeSinceStartup < EditorSlowUpdateProcesses[coindex.i].Current))
+ {
+ try
+ {
+ if (!EditorSlowUpdateProcesses[coindex.i].MoveNext())
+ {
+ EditorSlowUpdateProcesses[coindex.i] = null;
+ }
+ else if (EditorSlowUpdateProcesses[coindex.i] != null && float.IsNaN(EditorSlowUpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ EditorSlowUpdateProcesses[coindex.i] = null;
+ }
+ else
+ {
+ EditorSlowUpdateProcesses[coindex.i] = ReplacementFunction(EditorSlowUpdateProcesses[coindex.i],
+ this, _indexToHandle[coindex]);
+
+ ReplacementFunction = null;
+ coindex.i--;
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ EditorSlowUpdateProcesses[coindex.i] = null;
+ }
+ }
+ }
+ }
+
+ if (_nextEditorUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.EditorUpdate };
+ _runningEditorUpdate = true;
+ UpdateTimeValues(coindex.seg);
+
+ for (coindex.i = 0; coindex.i < _nextEditorUpdateProcessSlot; coindex.i++)
+ {
+ if (!EditorUpdatePaused[coindex.i] && EditorUpdateProcesses[coindex.i] != null &&
+ !(EditorApplication.timeSinceStartup < EditorUpdateProcesses[coindex.i].Current))
+ {
+ try
+ {
+ if (!EditorUpdateProcesses[coindex.i].MoveNext())
+ {
+ EditorUpdateProcesses[coindex.i] = null;
+ }
+ else if (EditorUpdateProcesses[coindex.i] != null && float.IsNaN(EditorUpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ EditorUpdateProcesses[coindex.i] = null;
+ }
+ else
+ {
+ EditorUpdateProcesses[coindex.i] = ReplacementFunction(EditorUpdateProcesses[coindex.i], this, _indexToHandle[coindex]);
+
+ ReplacementFunction = null;
+ coindex.i--;
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ EditorUpdateProcesses[coindex.i] = null;
+ }
+ }
+ }
+
+ _runningEditorUpdate = false;
+ }
+
+ if (++_framesSinceUpdate > FramesUntilMaintenance)
+ {
+ _framesSinceUpdate = 0;
+
+ EditorRemoveUnused();
+ }
+
+ if (_exceptions.Count > 0)
+ throw _exceptions.Dequeue();
+ }
+#endif
+
+ private IEnumerator<float> _EOFPumpWatcher()
+ {
+ while (_nextEndOfFrameProcessSlot > 0)
+ {
+ if (!_EOFPumpRan)
+ base.StartCoroutine(_EOFPump());
+
+ _EOFPumpRan = false;
+
+ yield return 0f;
+ }
+
+ _EOFPumpRan = false;
+ }
+
+ private System.Collections.IEnumerator _EOFPump()
+ {
+ while (_nextEndOfFrameProcessSlot > 0)
+ {
+ yield return _EOFWaitObject;
+
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.EndOfFrame };
+ _EOFPumpRan = true;
+ UpdateTimeValues(coindex.seg);
+
+ for (coindex.i = 0; coindex.i < _nextEndOfFrameProcessSlot; coindex.i++)
+ {
+ if (!EndOfFramePaused[coindex.i] && EndOfFrameProcesses[coindex.i] != null && !(localTime < EndOfFrameProcesses[coindex.i].Current))
+ {
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine, " +
+ (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") +
+ (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) : "Processing Coroutine");
+ }
+
+ try
+ {
+ if (!EndOfFrameProcesses[coindex.i].MoveNext())
+ {
+ EndOfFrameProcesses[coindex.i] = null;
+ }
+ else if (EndOfFrameProcesses[coindex.i] != null && float.IsNaN(EndOfFrameProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ EndOfFrameProcesses[coindex.i] = null;
+ }
+ else
+ {
+ EndOfFrameProcesses[coindex.i] = ReplacementFunction(EndOfFrameProcesses[coindex.i], this, _indexToHandle[coindex]);
+
+ ReplacementFunction = null;
+ coindex.i--;
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ EndOfFrameProcesses[coindex.i] = null;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+ }
+ }
+
+ private void RemoveUnused()
+ {
+ var waitTrigsEnum = _waitingTriggers.GetEnumerator();
+ while (waitTrigsEnum.MoveNext())
+ {
+ if (waitTrigsEnum.Current.Value.Count == 0)
+ {
+ _waitingTriggers.Remove(waitTrigsEnum.Current.Key);
+ waitTrigsEnum = _waitingTriggers.GetEnumerator();
+ continue;
+ }
+
+ if (_handleToIndex.ContainsKey(waitTrigsEnum.Current.Key) && CoindexIsNull(_handleToIndex[waitTrigsEnum.Current.Key]))
+ {
+ CloseWaitingProcess(waitTrigsEnum.Current.Key);
+ waitTrigsEnum = _waitingTriggers.GetEnumerator();
+ }
+ }
+
+ ProcessIndex outer, inner;
+ outer.seg = inner.seg = Segment.Update;
+ for (outer.i = inner.i = 0; outer.i < _nextUpdateProcessSlot; outer.i++)
+ {
+ if (UpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ UpdateProcesses[inner.i] = UpdateProcesses[outer.i];
+ UpdatePaused[inner.i] = UpdatePaused[outer.i];
+ MoveGraffiti(outer, inner);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextUpdateProcessSlot; outer.i++)
+ {
+ UpdateProcesses[outer.i] = null;
+ UpdatePaused[outer.i] = false;
+ RemoveGraffiti(outer);
+ }
+
+ UpdateCoroutines = _nextUpdateProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.FixedUpdate;
+ for (outer.i = inner.i = 0; outer.i < _nextFixedUpdateProcessSlot; outer.i++)
+ {
+ if (FixedUpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ FixedUpdateProcesses[inner.i] = FixedUpdateProcesses[outer.i];
+ FixedUpdatePaused[inner.i] = FixedUpdatePaused[outer.i];
+ MoveGraffiti(outer, inner);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextFixedUpdateProcessSlot; outer.i++)
+ {
+ FixedUpdateProcesses[outer.i] = null;
+ FixedUpdatePaused[outer.i] = false;
+ RemoveGraffiti(outer);
+ }
+
+ FixedUpdateCoroutines = _nextFixedUpdateProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.LateUpdate;
+ for (outer.i = inner.i = 0; outer.i < _nextLateUpdateProcessSlot; outer.i++)
+ {
+ if (LateUpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ LateUpdateProcesses[inner.i] = LateUpdateProcesses[outer.i];
+ LateUpdatePaused[inner.i] = LateUpdatePaused[outer.i];
+ MoveGraffiti(outer, inner);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextLateUpdateProcessSlot; outer.i++)
+ {
+ LateUpdateProcesses[outer.i] = null;
+ LateUpdatePaused[outer.i] = false;
+ RemoveGraffiti(outer);
+ }
+
+ LateUpdateCoroutines = _nextLateUpdateProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.SlowUpdate;
+ for (outer.i = inner.i = 0; outer.i < _nextSlowUpdateProcessSlot; outer.i++)
+ {
+ if (SlowUpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ SlowUpdateProcesses[inner.i] = SlowUpdateProcesses[outer.i];
+ SlowUpdatePaused[inner.i] = SlowUpdatePaused[outer.i];
+ MoveGraffiti(outer, inner);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextSlowUpdateProcessSlot; outer.i++)
+ {
+ SlowUpdateProcesses[outer.i] = null;
+ SlowUpdatePaused[outer.i] = false;
+ RemoveGraffiti(outer);
+ }
+
+ SlowUpdateCoroutines = _nextSlowUpdateProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.RealtimeUpdate;
+ for (outer.i = inner.i = 0; outer.i < _nextRealtimeUpdateProcessSlot; outer.i++)
+ {
+ if (RealtimeUpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ RealtimeUpdateProcesses[inner.i] = RealtimeUpdateProcesses[outer.i];
+ RealtimeUpdatePaused[inner.i] = RealtimeUpdatePaused[outer.i];
+ MoveGraffiti(outer, inner);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextRealtimeUpdateProcessSlot; outer.i++)
+ {
+ RealtimeUpdateProcesses[outer.i] = null;
+ RealtimeUpdatePaused[outer.i] = false;
+ RemoveGraffiti(outer);
+ }
+
+ RealtimeUpdateCoroutines = _nextRealtimeUpdateProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.EndOfFrame;
+ for (outer.i = inner.i = 0; outer.i < _nextEndOfFrameProcessSlot; outer.i++)
+ {
+ if (EndOfFrameProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ EndOfFrameProcesses[inner.i] = EndOfFrameProcesses[outer.i];
+ EndOfFramePaused[inner.i] = EndOfFramePaused[outer.i];
+ MoveGraffiti(outer, inner);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextEndOfFrameProcessSlot; outer.i++)
+ {
+ EndOfFrameProcesses[outer.i] = null;
+ EndOfFramePaused[outer.i] = false;
+ RemoveGraffiti(outer);
+ }
+
+ EndOfFrameCoroutines = _nextEndOfFrameProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.ManualTimeframe;
+ for (outer.i = inner.i = 0; outer.i < _nextManualTimeframeProcessSlot; outer.i++)
+ {
+ if (ManualTimeframeProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ ManualTimeframeProcesses[inner.i] = ManualTimeframeProcesses[outer.i];
+ ManualTimeframePaused[inner.i] = ManualTimeframePaused[outer.i];
+ MoveGraffiti(outer, inner);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextManualTimeframeProcessSlot; outer.i++)
+ {
+ ManualTimeframeProcesses[outer.i] = null;
+ ManualTimeframePaused[outer.i] = false;
+ RemoveGraffiti(outer);
+ }
+
+ ManualTimeframeCoroutines = _nextManualTimeframeProcessSlot = inner.i;
+ }
+
+ private void EditorRemoveUnused()
+ {
+ var waitTrigsEnum = _waitingTriggers.GetEnumerator();
+ while (waitTrigsEnum.MoveNext())
+ {
+ if (_handleToIndex.ContainsKey(waitTrigsEnum.Current.Key) && CoindexIsNull(_handleToIndex[waitTrigsEnum.Current.Key]))
+ {
+ CloseWaitingProcess(waitTrigsEnum.Current.Key);
+ waitTrigsEnum = _waitingTriggers.GetEnumerator();
+ }
+ }
+
+ ProcessIndex outer, inner;
+ outer.seg = inner.seg = Segment.EditorUpdate;
+ for (outer.i = inner.i = 0; outer.i < _nextEditorUpdateProcessSlot; outer.i++)
+ {
+ if (EditorUpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ EditorUpdateProcesses[inner.i] = EditorUpdateProcesses[outer.i];
+ EditorUpdatePaused[inner.i] = EditorUpdatePaused[outer.i];
+ MoveGraffiti(outer, inner);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextEditorUpdateProcessSlot; outer.i++)
+ {
+ EditorUpdateProcesses[outer.i] = null;
+ EditorUpdatePaused[outer.i] = false;
+ RemoveGraffiti(outer);
+ }
+
+ EditorUpdateCoroutines = _nextEditorUpdateProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.EditorSlowUpdate;
+ for (outer.i = inner.i = 0; outer.i < _nextEditorSlowUpdateProcessSlot; outer.i++)
+ {
+ if (EditorSlowUpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ EditorSlowUpdateProcesses[inner.i] = EditorSlowUpdateProcesses[outer.i];
+ EditorUpdatePaused[inner.i] = EditorUpdatePaused[outer.i];
+ MoveGraffiti(outer, inner);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextEditorSlowUpdateProcessSlot; outer.i++)
+ {
+ EditorSlowUpdateProcesses[outer.i] = null;
+ EditorSlowUpdatePaused[outer.i] = false;
+ RemoveGraffiti(outer);
+ }
+
+ EditorSlowUpdateCoroutines = _nextEditorSlowUpdateProcessSlot = inner.i;
+ }
+
+ /// <summary>
+ /// Retrieves the MEC manager that corresponds to the supplied instance id.
+ /// </summary>
+ /// <param name="ID">The instance ID.</param>
+ /// <returns>The manager, or null if not found.</returns>
+ public static Timing GetInstance(byte ID)
+ {
+ return ActiveInstances.ContainsKey(ID) ? ActiveInstances[ID] : null;
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, Segment.Update, null, null, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, Segment.Update, null, tag, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, int layer)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, Segment.Update, layer, null, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, int layer, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment timing)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, timing, null, null, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment timing, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, timing, null, tag, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment timing, int layer)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, timing, layer, null, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment timing, int layer, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, Segment.Update, null, null, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, Segment.Update, null, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, int layer)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, Segment.Update, layer, null, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, int layer, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment timing)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, timing, null, null, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment timing, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, timing, null, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment timing, int layer)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, timing, layer, null, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment timing, int layer, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, string tag, bool overwrite = false)
+ {
+ if (_instance == null || coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(tag);
+ }
+ else if (_instance._taggedProcesses.ContainsKey(tag))
+ {
+ var indexEnum = _instance._taggedProcesses[tag].GetEnumerator();
+ if (indexEnum.MoveNext())
+ return _instance._indexToHandle[indexEnum.Current];
+ }
+
+ return _instance.RunCoroutineInternal(coroutine, Segment.Update, null, tag, new CoroutineHandle(_instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, int layer, bool overwrite = false)
+ {
+ if (_instance == null || coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(layer);
+ }
+ else if (_instance._layeredProcesses.ContainsKey(layer))
+ {
+ var indexEnum = _instance._layeredProcesses[layer].GetEnumerator();
+ if (indexEnum.MoveNext())
+ return _instance._indexToHandle[indexEnum.Current];
+ }
+
+ return _instance.RunCoroutineInternal(coroutine, Segment.Update, layer, null, new CoroutineHandle(_instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, int layer, string tag, bool overwrite = false)
+ {
+ if (_instance == null || coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(layer, tag);
+ return _instance.RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instance._instanceID), true);
+ }
+
+ if (!_instance._taggedProcesses.ContainsKey(tag) || !_instance._layeredProcesses.ContainsKey(layer))
+ return _instance.RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instance._instanceID), true);
+
+ var matchesEnum = _instance._taggedProcesses[tag].GetEnumerator();
+ while (matchesEnum.MoveNext())
+ if (_instance._processLayers.ContainsKey(matchesEnum.Current) && _instance._processLayers[matchesEnum.Current] == layer)
+ return _instance._indexToHandle[matchesEnum.Current];
+
+ return _instance.RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, Segment timing, int layer, bool overwrite = false)
+ {
+ if (_instance == null || coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(layer);
+ }
+ else if (_instance._layeredProcesses.ContainsKey(layer))
+ {
+ var indexEnum = _instance._layeredProcesses[layer].GetEnumerator();
+ if (indexEnum.MoveNext())
+ return _instance._indexToHandle[indexEnum.Current];
+ }
+
+ return _instance.RunCoroutineInternal(coroutine, timing, layer, null, new CoroutineHandle(_instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, Segment timing, string tag, bool overwrite = false)
+ {
+ if (_instance == null || coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(tag);
+ }
+ else if (_instance._taggedProcesses.ContainsKey(tag))
+ {
+ var indexEnum = _instance._taggedProcesses[tag].GetEnumerator();
+ if (indexEnum.MoveNext())
+ return _instance._indexToHandle[indexEnum.Current];
+ }
+
+ return _instance.RunCoroutineInternal(coroutine, timing, null, tag, new CoroutineHandle(_instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, Segment timing, int layer, string tag, bool overwrite = false)
+ {
+ if (_instance == null || coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(layer, tag);
+ return _instance.RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instance._instanceID), true);
+ }
+
+ if (!_instance._taggedProcesses.ContainsKey(tag) || !_instance._layeredProcesses.ContainsKey(layer))
+ return _instance.RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instance._instanceID), true);
+
+ var matchesEnum = _instance._taggedProcesses[tag].GetEnumerator();
+ while (matchesEnum.MoveNext())
+ if (_instance._processLayers.ContainsKey(matchesEnum.Current) && _instance._processLayers[matchesEnum.Current] == layer)
+ return _instance._indexToHandle[matchesEnum.Current];
+
+ return _instance.RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, int layer, bool overwrite = false)
+ {
+ if (coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(layer);
+ }
+ else if (_layeredProcesses.ContainsKey(layer))
+ {
+ var indexEnum = _layeredProcesses[layer].GetEnumerator();
+ if (indexEnum.MoveNext())
+ return _indexToHandle[indexEnum.Current];
+ }
+
+ return RunCoroutineInternal(coroutine, Segment.Update, layer, null, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, string tag, bool overwrite = false)
+ {
+ if (coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(tag);
+ }
+ else if (_taggedProcesses.ContainsKey(tag))
+ {
+ var indexEnum = _taggedProcesses[tag].GetEnumerator();
+ if (indexEnum.MoveNext())
+ return _indexToHandle[indexEnum.Current];
+ }
+
+ return RunCoroutineInternal(coroutine, Segment.Update, null, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, int layer, string tag, bool overwrite = false)
+ {
+ if (coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(layer, tag);
+ return RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ if (!_taggedProcesses.ContainsKey(tag) || !_layeredProcesses.ContainsKey(layer))
+ return RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instanceID), true);
+
+ var matchesEnum = _taggedProcesses[tag].GetEnumerator();
+ while (matchesEnum.MoveNext())
+ if (_processLayers.ContainsKey(matchesEnum.Current) && _processLayers[matchesEnum.Current] == layer)
+ return _indexToHandle[matchesEnum.Current];
+
+ return RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, Segment timing, int layer, bool overwrite = false)
+ {
+ if (coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(layer);
+ }
+ else if (_layeredProcesses.ContainsKey(layer))
+ {
+ var indexEnum = _layeredProcesses[layer].GetEnumerator();
+ if (indexEnum.MoveNext())
+ return _indexToHandle[indexEnum.Current];
+ }
+
+ return RunCoroutineInternal(coroutine, timing, layer, null, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, Segment timing, string tag, bool overwrite = false)
+ {
+ if (coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(tag);
+ }
+ else if (_taggedProcesses.ContainsKey(tag))
+ {
+ var indexEnum = _taggedProcesses[tag].GetEnumerator();
+ if (indexEnum.MoveNext())
+ return _indexToHandle[indexEnum.Current];
+ }
+
+ return RunCoroutineInternal(coroutine, timing, null, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="timing">The segment that the coroutine should run in.</param>
+ /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param>
+ /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param>
+ /// <returns>The newly created or existing handle.</returns>
+ public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, Segment timing, int layer, string tag, bool overwrite = false)
+ {
+ if (coroutine == null)
+ return new CoroutineHandle();
+
+ if (overwrite)
+ {
+ KillCoroutines(layer, tag);
+ return RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ if (!_taggedProcesses.ContainsKey(tag) || !_layeredProcesses.ContainsKey(layer))
+ return RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instanceID), true);
+
+ var matchesEnum = _taggedProcesses[tag].GetEnumerator();
+ while (matchesEnum.MoveNext())
+ if (_processLayers.ContainsKey(matchesEnum.Current) && _processLayers[matchesEnum.Current] == layer)
+ return _indexToHandle[matchesEnum.Current];
+
+ return RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ private CoroutineHandle RunCoroutineInternal(IEnumerator<float> coroutine, Segment timing, int? layer, string tag, CoroutineHandle handle, bool prewarm)
+ {
+ ProcessIndex slot = new ProcessIndex { seg = timing };
+
+ if (_handleToIndex.ContainsKey(handle))
+ {
+ _indexToHandle.Remove(_handleToIndex[handle]);
+ _handleToIndex.Remove(handle);
+ }
+
+ switch (timing)
+ {
+ case Segment.Update:
+
+ if (_nextUpdateProcessSlot >= UpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = UpdateProcesses;
+ bool[] oldPausedArray = UpdatePaused;
+
+ UpdateProcesses = new IEnumerator<float>[UpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ UpdatePaused = new bool[UpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ UpdateProcesses[i] = oldProcArray[i];
+ UpdatePaused[i] = oldPausedArray[i];
+ }
+ }
+
+ slot.i = _nextUpdateProcessSlot++;
+ UpdateProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, slot);
+
+ if (layer.HasValue)
+ AddLayer((int)layer, slot);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ if (!_runningUpdate && prewarm)
+ {
+ try
+ {
+ _runningUpdate = true;
+ SetTimeValues(slot.seg);
+
+ if (UpdateProcesses[slot.i] != null && !UpdateProcesses[slot.i].MoveNext())
+ {
+ UpdateProcesses[slot.i] = null;
+ }
+ else if (UpdateProcesses[slot.i] != null && float.IsNaN(UpdateProcesses[slot.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ UpdateProcesses[slot.i] = null;
+ }
+ else
+ {
+ UpdateProcesses[slot.i] = ReplacementFunction(UpdateProcesses[slot.i], this, _indexToHandle[slot]);
+
+ ReplacementFunction = null;
+
+ if (UpdateProcesses[slot.i] != null)
+ UpdateProcesses[slot.i].MoveNext();
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ UpdateProcesses[slot.i] = null;
+ }
+ finally
+ {
+ _runningUpdate = false;
+ }
+ }
+
+ return handle;
+
+ case Segment.FixedUpdate:
+
+ if (_nextFixedUpdateProcessSlot >= FixedUpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = FixedUpdateProcesses;
+ bool[] oldPausedArray = FixedUpdatePaused;
+
+ FixedUpdateProcesses = new IEnumerator<float>[FixedUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ FixedUpdatePaused = new bool[FixedUpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ FixedUpdateProcesses[i] = oldProcArray[i];
+ FixedUpdatePaused[i] = oldPausedArray[i];
+ }
+ }
+
+ slot.i = _nextFixedUpdateProcessSlot++;
+ FixedUpdateProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, slot);
+
+ if (layer.HasValue)
+ AddLayer((int)layer, slot);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ if (!_runningFixedUpdate && prewarm)
+ {
+ try
+ {
+ _runningFixedUpdate = true;
+ SetTimeValues(slot.seg);
+
+ if (FixedUpdateProcesses[slot.i] != null && !FixedUpdateProcesses[slot.i].MoveNext())
+ {
+ FixedUpdateProcesses[slot.i] = null;
+ }
+ else if (FixedUpdateProcesses[slot.i] != null && float.IsNaN(FixedUpdateProcesses[slot.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ FixedUpdateProcesses[slot.i] = null;
+ }
+ else
+ {
+ FixedUpdateProcesses[slot.i] = ReplacementFunction(FixedUpdateProcesses[slot.i], this, _indexToHandle[slot]);
+
+ ReplacementFunction = null;
+
+ if (FixedUpdateProcesses[slot.i] != null)
+ FixedUpdateProcesses[slot.i].MoveNext();
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ FixedUpdateProcesses[slot.i] = null;
+ }
+ finally
+ {
+ _runningFixedUpdate = false;
+ }
+ }
+
+ return handle;
+
+ case Segment.LateUpdate:
+
+ if (_nextLateUpdateProcessSlot >= LateUpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = LateUpdateProcesses;
+ bool[] oldPausedArray = LateUpdatePaused;
+
+ LateUpdateProcesses = new IEnumerator<float>[LateUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ LateUpdatePaused = new bool[LateUpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ LateUpdateProcesses[i] = oldProcArray[i];
+ LateUpdatePaused[i] = oldPausedArray[i];
+ }
+ }
+
+ slot.i = _nextLateUpdateProcessSlot++;
+ LateUpdateProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, slot);
+
+ if (layer.HasValue)
+ AddLayer((int)layer, slot);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ if (!_runningLateUpdate && prewarm)
+ {
+ try
+ {
+ _runningLateUpdate = true;
+ SetTimeValues(slot.seg);
+
+ if (LateUpdateProcesses[slot.i] != null && !LateUpdateProcesses[slot.i].MoveNext())
+ {
+ LateUpdateProcesses[slot.i] = null;
+ }
+ else if (LateUpdateProcesses[slot.i] != null && float.IsNaN(LateUpdateProcesses[slot.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ LateUpdateProcesses[slot.i] = null;
+ }
+ else
+ {
+ LateUpdateProcesses[slot.i] = ReplacementFunction(LateUpdateProcesses[slot.i],
+ this, _indexToHandle[slot]);
+
+ ReplacementFunction = null;
+
+ if (LateUpdateProcesses[slot.i] != null)
+ LateUpdateProcesses[slot.i].MoveNext();
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ LateUpdateProcesses[slot.i] = null;
+ }
+ finally
+ {
+ _runningLateUpdate = false;
+ }
+ }
+
+ return handle;
+
+ case Segment.SlowUpdate:
+
+ if (_nextSlowUpdateProcessSlot >= SlowUpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = SlowUpdateProcesses;
+ bool[] oldPausedArray = SlowUpdatePaused;
+
+ SlowUpdateProcesses = new IEnumerator<float>[SlowUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ SlowUpdatePaused = new bool[SlowUpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ SlowUpdateProcesses[i] = oldProcArray[i];
+ SlowUpdatePaused[i] = oldPausedArray[i];
+ }
+ }
+
+ slot.i = _nextSlowUpdateProcessSlot++;
+ SlowUpdateProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, slot);
+
+ if (layer.HasValue)
+ AddLayer((int)layer, slot);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ return handle;
+
+ case Segment.RealtimeUpdate:
+
+ if (_nextRealtimeUpdateProcessSlot >= RealtimeUpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = RealtimeUpdateProcesses;
+ bool[] oldPausedArray = RealtimeUpdatePaused;
+
+ RealtimeUpdateProcesses = new IEnumerator<float>[RealtimeUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ RealtimeUpdatePaused = new bool[RealtimeUpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ RealtimeUpdateProcesses[i] = oldProcArray[i];
+ RealtimeUpdatePaused[i] = oldPausedArray[i];
+ }
+ }
+
+ slot.i = _nextRealtimeUpdateProcessSlot++;
+ RealtimeUpdateProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, slot);
+
+ if (layer.HasValue)
+ AddLayer((int)layer, slot);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ if (!_runningRealtimeUpdate && prewarm)
+ {
+ try
+ {
+ _runningRealtimeUpdate = true;
+ SetTimeValues(slot.seg);
+
+ if (RealtimeUpdateProcesses[slot.i] != null && !RealtimeUpdateProcesses[slot.i].MoveNext())
+ {
+ RealtimeUpdateProcesses[slot.i] = null;
+ }
+ else if (RealtimeUpdateProcesses[slot.i] != null && float.IsNaN(RealtimeUpdateProcesses[slot.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ RealtimeUpdateProcesses[slot.i] = null;
+ }
+ else
+ {
+ RealtimeUpdateProcesses[slot.i] = ReplacementFunction(RealtimeUpdateProcesses[slot.i],
+ this, _indexToHandle[slot]);
+
+ ReplacementFunction = null;
+
+ if (RealtimeUpdateProcesses[slot.i] != null)
+ RealtimeUpdateProcesses[slot.i].MoveNext();
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ RealtimeUpdateProcesses[slot.i] = null;
+ }
+ finally
+ {
+ _runningRealtimeUpdate = false;
+ }
+ }
+
+ return handle;
+
+ case Segment.EditorUpdate:
+
+ if (!OnEditorStart())
+ return new CoroutineHandle();
+
+ if (_nextEditorUpdateProcessSlot >= EditorUpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = EditorUpdateProcesses;
+ bool[] oldPausedArray = EditorUpdatePaused;
+
+ EditorUpdateProcesses = new IEnumerator<float>[EditorUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ EditorUpdatePaused = new bool[EditorUpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ EditorUpdateProcesses[i] = oldProcArray[i];
+ EditorUpdatePaused[i] = oldPausedArray[i];
+ }
+ }
+
+ slot.i = _nextEditorUpdateProcessSlot++;
+ EditorUpdateProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, slot);
+
+ if (layer.HasValue)
+ AddLayer((int)layer, slot);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ if (!_runningEditorUpdate && prewarm)
+ {
+ try
+ {
+ _runningEditorUpdate = true;
+ SetTimeValues(slot.seg);
+
+ if (EditorUpdateProcesses[slot.i] != null && !EditorUpdateProcesses[slot.i].MoveNext())
+ {
+ EditorUpdateProcesses[slot.i] = null;
+ }
+ else if (EditorUpdateProcesses[slot.i] != null && float.IsNaN(EditorUpdateProcesses[slot.i].Current))
+ {
+ if (ReplacementFunction == null)
+ {
+ EditorUpdateProcesses[slot.i] = null;
+ }
+ else
+ {
+ EditorUpdateProcesses[slot.i] = ReplacementFunction(EditorUpdateProcesses[slot.i],
+ this, _indexToHandle[slot]);
+
+ ReplacementFunction = null;
+
+ if (EditorUpdateProcesses[slot.i] != null)
+ EditorUpdateProcesses[slot.i].MoveNext();
+ }
+ }
+ }
+ catch (System.Exception ex)
+ {
+ if (OnError == null)
+ _exceptions.Enqueue(ex);
+ else
+ OnError(ex);
+
+ EditorUpdateProcesses[slot.i] = null;
+ }
+ finally
+ {
+ _runningEditorUpdate = false;
+ }
+ }
+
+ return handle;
+
+ case Segment.EditorSlowUpdate:
+
+ if (!OnEditorStart())
+ return new CoroutineHandle();
+
+ if (_nextEditorSlowUpdateProcessSlot >= EditorSlowUpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = EditorSlowUpdateProcesses;
+ bool[] oldPausedArray = EditorSlowUpdatePaused;
+
+ EditorSlowUpdateProcesses = new IEnumerator<float>[EditorSlowUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ EditorSlowUpdatePaused = new bool[EditorSlowUpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ EditorSlowUpdateProcesses[i] = oldProcArray[i];
+ EditorSlowUpdatePaused[i] = oldPausedArray[i];
+ }
+ }
+
+ slot.i = _nextEditorSlowUpdateProcessSlot++;
+ EditorSlowUpdateProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, slot);
+
+ if (layer.HasValue)
+ AddLayer((int)layer, slot);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ return handle;
+
+ case Segment.EndOfFrame:
+
+ if (_nextEndOfFrameProcessSlot >= EndOfFrameProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = EndOfFrameProcesses;
+ bool[] oldPausedArray = EndOfFramePaused;
+
+ EndOfFrameProcesses = new IEnumerator<float>[EndOfFrameProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ EndOfFramePaused = new bool[EndOfFrameProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ EndOfFrameProcesses[i] = oldProcArray[i];
+ EndOfFramePaused[i] = oldPausedArray[i];
+ }
+ }
+
+ slot.i = _nextEndOfFrameProcessSlot++;
+ EndOfFrameProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, slot);
+
+ if (layer.HasValue)
+ AddLayer((int)layer, slot);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ RunCoroutineSingletonOnInstance(_EOFPumpWatcher(), "MEC_EOFPumpWatcher");
+
+ return handle;
+
+ case Segment.ManualTimeframe:
+
+ if (_nextManualTimeframeProcessSlot >= ManualTimeframeProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = ManualTimeframeProcesses;
+ bool[] oldPausedArray = ManualTimeframePaused;
+
+ ManualTimeframeProcesses = new IEnumerator<float>[ManualTimeframeProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ ManualTimeframePaused = new bool[ManualTimeframeProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ ManualTimeframeProcesses[i] = oldProcArray[i];
+ ManualTimeframePaused[i] = oldPausedArray[i];
+ }
+ }
+
+ slot.i = _nextManualTimeframeProcessSlot++;
+ ManualTimeframeProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, slot);
+
+ if (layer.HasValue)
+ AddLayer((int)layer, slot);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ return handle;
+
+ default:
+ return new CoroutineHandle();
+ }
+ }
+
+ /// <summary>
+ /// This will kill all coroutines running on the main MEC instance and reset the context.
+ /// </summary>
+ /// <returns>The number of coroutines that were killed.</returns>
+ public static int KillCoroutines()
+ {
+ return _instance == null ? 0 : _instance.KillCoroutinesOnInstance();
+ }
+
+ /// <summary>
+ /// This will kill all coroutines running on the current MEC instance and reset the context.
+ /// </summary>
+ /// <returns>The number of coroutines that were killed.</returns>
+ public int KillCoroutinesOnInstance()
+ {
+ int retVal = _nextUpdateProcessSlot + _nextLateUpdateProcessSlot + _nextFixedUpdateProcessSlot + _nextSlowUpdateProcessSlot +
+ _nextRealtimeUpdateProcessSlot + _nextEditorUpdateProcessSlot + _nextEditorSlowUpdateProcessSlot +
+ _nextEndOfFrameProcessSlot + _nextManualTimeframeProcessSlot;
+
+ UpdateProcesses = new IEnumerator<float>[InitialBufferSizeLarge];
+ UpdatePaused = new bool[InitialBufferSizeLarge];
+ UpdateCoroutines = 0;
+ _nextUpdateProcessSlot = 0;
+
+ LateUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ LateUpdatePaused = new bool[InitialBufferSizeSmall];
+ LateUpdateCoroutines = 0;
+ _nextLateUpdateProcessSlot = 0;
+
+ FixedUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
+ FixedUpdatePaused = new bool[InitialBufferSizeMedium];
+ FixedUpdateCoroutines = 0;
+ _nextFixedUpdateProcessSlot = 0;
+
+ SlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
+ SlowUpdatePaused = new bool[InitialBufferSizeMedium];
+ SlowUpdateCoroutines = 0;
+ _nextSlowUpdateProcessSlot = 0;
+
+ RealtimeUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ RealtimeUpdatePaused = new bool[InitialBufferSizeSmall];
+ RealtimeUpdateCoroutines = 0;
+ _nextRealtimeUpdateProcessSlot = 0;
+
+ EditorUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ EditorUpdatePaused = new bool[InitialBufferSizeSmall];
+ EditorUpdateCoroutines = 0;
+ _nextEditorUpdateProcessSlot = 0;
+
+ EditorSlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ EditorSlowUpdatePaused = new bool[InitialBufferSizeSmall];
+ EditorSlowUpdateCoroutines = 0;
+ _nextEditorSlowUpdateProcessSlot = 0;
+
+ EndOfFrameProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ EndOfFramePaused = new bool[InitialBufferSizeSmall];
+ EndOfFrameCoroutines = 0;
+ _nextEndOfFrameProcessSlot = 0;
+
+ ManualTimeframeProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ ManualTimeframePaused = new bool[InitialBufferSizeSmall];
+ ManualTimeframeCoroutines = 0;
+ _nextManualTimeframeProcessSlot = 0;
+
+ _processTags.Clear();
+ _taggedProcesses.Clear();
+ _processLayers.Clear();
+ _layeredProcesses.Clear();
+ _handleToIndex.Clear();
+ _indexToHandle.Clear();
+ _waitingTriggers.Clear();
+ _expansions = (ushort)((_expansions / 2) + 1);
+
+ ResetTimeCountOnInstance();
+
+#if UNITY_EDITOR
+ EditorApplication.update -= OnEditorUpdate;
+#endif
+ return retVal;
+ }
+
+ /// <summary>
+ /// Kills all coroutines that have the given tag.
+ /// </summary>
+ /// <param name="tag">All coroutines with this tag will be killed.</param>
+ /// <returns>The number of coroutines that were found and killed.</returns>
+ public static int KillCoroutines(string tag)
+ {
+ return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(tag);
+ }
+
+ /// <summary>
+ /// Kills all coroutines that have the given tag.
+ /// </summary>
+ /// <param name="tag">All coroutines with this tag will be killed.</param>
+ /// <returns>The number of coroutines that were found and killed.</returns>
+ public int KillCoroutinesOnInstance(string tag)
+ {
+ if (tag == null) return 0;
+ int numberFound = 0;
+
+ while (_taggedProcesses.ContainsKey(tag))
+ {
+ var matchEnum = _taggedProcesses[tag].GetEnumerator();
+ matchEnum.MoveNext();
+
+ if (CoindexKill(matchEnum.Current))
+ {
+ if (_waitingTriggers.ContainsKey(_indexToHandle[matchEnum.Current]))
+ CloseWaitingProcess(_indexToHandle[matchEnum.Current]);
+
+ numberFound++;
+ }
+
+ RemoveGraffiti(matchEnum.Current);
+ }
+
+ return numberFound;
+ }
+
+ /// <summary>
+ /// Kills all coroutines on the given layer.
+ /// </summary>
+ /// <param name="layer">All coroutines on this layer will be killed.</param>
+ /// <returns>The number of coroutines that were found and killed.</returns>
+ public static int KillCoroutines(int layer)
+ {
+ return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(layer);
+ }
+
+ /// <summary>
+ /// Kills all coroutines on the given layer.
+ /// </summary>
+ /// <param name="layer">All coroutines on this layer will be killed.</param>
+ /// <returns>The number of coroutines that were found and killed.</returns>
+ public int KillCoroutinesOnInstance(int layer)
+ {
+ int numberFound = 0;
+
+ while (_layeredProcesses.ContainsKey(layer))
+ {
+ var matchEnum = _layeredProcesses[layer].GetEnumerator();
+ matchEnum.MoveNext();
+
+ if (CoindexKill(matchEnum.Current))
+ {
+ if (_waitingTriggers.ContainsKey(_indexToHandle[matchEnum.Current]))
+ CloseWaitingProcess(_indexToHandle[matchEnum.Current]);
+
+ numberFound++;
+ }
+
+ RemoveGraffiti(matchEnum.Current);
+ }
+
+ return numberFound;
+ }
+
+ /// <summary>
+ /// Kills all coroutines with the given tag on the given layer.
+ /// </summary>
+ /// <param name="layer">All coroutines on this layer with the given tag will be killed.</param>
+ /// <param name="tag">All coroutines with this tag on the given layer will be killed.</param>
+ /// <returns>The number of coroutines that were found and killed.</returns>
+ public static int KillCoroutines(int layer, string tag)
+ {
+ return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(layer, tag);
+ }
+
+ /// <summary>
+ /// Kills all coroutines with the given tag on the given layer.
+ /// </summary>
+ /// <param name="layer">All coroutines on this layer with the given tag will be killed.</param>
+ /// <param name="tag">All coroutines with this tag on the given layer will be killed.</param>
+ /// <returns>The number of coroutines that were found and killed.</returns>
+ public int KillCoroutinesOnInstance(int layer, string tag)
+ {
+ if (tag == null)
+ return KillCoroutinesOnInstance(layer);
+ if (!_layeredProcesses.ContainsKey(layer) || !_taggedProcesses.ContainsKey(tag))
+ return 0;
+ int count = 0;
+
+ var indexesEnum = _taggedProcesses[tag].GetEnumerator();
+ while (indexesEnum.MoveNext())
+ {
+ if (CoindexIsNull(indexesEnum.Current) || !_layeredProcesses[layer].Contains(indexesEnum.Current) || !CoindexKill(indexesEnum.Current))
+ continue;
+
+ if (_waitingTriggers.ContainsKey(_indexToHandle[indexesEnum.Current]))
+ CloseWaitingProcess(_indexToHandle[indexesEnum.Current]);
+
+ count++;
+ RemoveGraffiti(indexesEnum.Current);
+
+ if (!_taggedProcesses.ContainsKey(tag) || !_layeredProcesses.ContainsKey(layer))
+ break;
+
+ indexesEnum = _taggedProcesses[tag].GetEnumerator();
+ }
+
+ return count;
+ }
+
+ /// <summary>
+ /// Kills the instance of the coroutine handle if it exists.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to kill.</param>
+ /// <returns>The number of coroutines that were found and killed (0 or 1).</returns>
+ public static int KillCoroutines(CoroutineHandle handle)
+ {
+ return ActiveInstances.ContainsKey(handle.Key) ? GetInstance(handle.Key).KillCoroutinesOnInstance(handle) : 0;
+ }
+
+ /// <summary>
+ /// Kills the instance of the coroutine handle on this Timing instance if it exists.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to kill.</param>
+ /// <returns>The number of coroutines that were found and killed (0 or 1).</returns>
+ public int KillCoroutinesOnInstance(CoroutineHandle handle)
+ {
+ bool foundOne = false;
+
+ if (_handleToIndex.ContainsKey(handle))
+ {
+ if (_waitingTriggers.ContainsKey(handle))
+ CloseWaitingProcess(handle);
+
+ foundOne = CoindexExtract(_handleToIndex[handle]) != null;
+ RemoveGraffiti(_handleToIndex[handle]);
+ }
+
+ return foundOne ? 1 : 0;
+ }
+
+ /// <summary>
+ /// Use "yield return Timing.WaitForSeconds(time);" to wait for the specified number of seconds.
+ /// </summary>
+ /// <param name="waitTime">Number of seconds to wait.</param>
+ public static float WaitForSeconds(float waitTime)
+ {
+ if (float.IsNaN(waitTime)) waitTime = 0f;
+ return LocalTime + waitTime;
+ }
+
+ /// <summary>
+ /// Use "yield return timingInstance.WaitForSecondsOnInstance(time);" to wait for the specified number of seconds.
+ /// </summary>
+ /// <param name="waitTime">Number of seconds to wait.</param>
+ public float WaitForSecondsOnInstance(float waitTime)
+ {
+ if (float.IsNaN(waitTime)) waitTime = 0f;
+ return (float)localTime + waitTime;
+ }
+
+ private void UpdateTimeValues(Segment segment)
+ {
+ switch (segment)
+ {
+ case Segment.Update:
+ deltaTime = Time.deltaTime;
+ _lastUpdateTime += deltaTime;
+ localTime = _lastUpdateTime;
+ return;
+ case Segment.LateUpdate:
+ deltaTime = Time.deltaTime;
+ _lastLateUpdateTime += deltaTime;
+ localTime = _lastLateUpdateTime;
+ return;
+ case Segment.FixedUpdate:
+ deltaTime = Time.deltaTime;
+ _lastFixedUpdateTime += deltaTime;
+ localTime = _lastFixedUpdateTime;
+ return;
+ case Segment.SlowUpdate:
+ if (_lastSlowUpdateTime == 0d)
+ deltaTime = TimeBetweenSlowUpdateCalls;
+ else
+ deltaTime = ThreadSafeElapsedTime.GetElapsedSecondsSinceStartUp() - (float)_lastSlowUpdateTime;
+
+ localTime = _lastSlowUpdateTime = ThreadSafeElapsedTime.GetElapsedSecondsSinceStartUp();
+ return;
+ case Segment.RealtimeUpdate:
+ deltaTime = Time.unscaledDeltaTime;
+ _lastRealtimeUpdateTime += deltaTime;
+ localTime = _lastRealtimeUpdateTime;
+ return;
+#if UNITY_EDITOR
+ case Segment.EditorUpdate:
+ deltaTime = (float)(EditorApplication.timeSinceStartup - _lastEditorUpdateTime);
+
+ if (deltaTime > Time.maximumDeltaTime)
+ deltaTime = Time.maximumDeltaTime;
+
+ localTime = _lastEditorUpdateTime = EditorApplication.timeSinceStartup;
+ return;
+ case Segment.EditorSlowUpdate:
+ deltaTime = (float)(EditorApplication.timeSinceStartup - _lastEditorSlowUpdateTime);
+ localTime = _lastEditorSlowUpdateTime = EditorApplication.timeSinceStartup;
+ return;
+#endif
+ case Segment.EndOfFrame:
+ deltaTime = Time.deltaTime;
+ localTime = _lastUpdateTime;
+ return;
+ case Segment.ManualTimeframe:
+ localTime = SetManualTimeframeTime == null ? Time.time : SetManualTimeframeTime(_lastManualTimeframeTime);
+ deltaTime = (float)(localTime - _lastManualTimeframeTime);
+
+ if (deltaTime > Time.maximumDeltaTime)
+ deltaTime = Time.maximumDeltaTime;
+
+ _lastManualTimeframeTime = localTime;
+ return;
+ }
+ }
+
+ private void SetTimeValues(Segment segment)
+ {
+ switch (segment)
+ {
+ case Segment.Update:
+ deltaTime = Time.deltaTime;
+ localTime = _lastUpdateTime;
+ return;
+ case Segment.LateUpdate:
+ deltaTime = Time.deltaTime;
+ localTime = _lastLateUpdateTime;
+ return;
+ case Segment.FixedUpdate:
+ deltaTime = Time.deltaTime;
+ localTime = _lastFixedUpdateTime;
+ return;
+ case Segment.SlowUpdate:
+ deltaTime = ThreadSafeElapsedTime.GetElapsedSecondsSinceStartUp() - (float)_lastSlowUpdateTime;
+ localTime = _lastSlowUpdateTime;
+ return;
+ case Segment.RealtimeUpdate:
+ deltaTime = Time.unscaledDeltaTime;
+ localTime = _lastRealtimeUpdateTime;
+ return;
+#if UNITY_EDITOR
+ case Segment.EditorUpdate:
+ deltaTime = (float)(EditorApplication.timeSinceStartup - _lastEditorUpdateTime);
+
+ if (deltaTime > Time.maximumDeltaTime)
+ deltaTime = Time.maximumDeltaTime;
+
+ localTime = _lastEditorUpdateTime;
+ return;
+ case Segment.EditorSlowUpdate:
+ deltaTime = (float)(EditorApplication.timeSinceStartup - _lastEditorSlowUpdateTime);
+ localTime = _lastEditorSlowUpdateTime;
+ return;
+#endif
+ case Segment.EndOfFrame:
+ deltaTime = Time.deltaTime;
+ localTime = _lastUpdateTime;
+ return;
+ case Segment.ManualTimeframe:
+ deltaTime = Time.deltaTime;
+ localTime = _lastManualTimeframeTime;
+ return;
+ }
+ }
+
+ private double GetSegmentTime(Segment segment)
+ {
+ switch (segment)
+ {
+ case Segment.Update:
+ return _lastUpdateTime;
+ case Segment.LateUpdate:
+ return _lastLateUpdateTime;
+ case Segment.FixedUpdate:
+ return _lastFixedUpdateTime;
+ case Segment.SlowUpdate:
+ return _lastSlowUpdateTime;
+ case Segment.RealtimeUpdate:
+ return _lastRealtimeUpdateTime;
+ case Segment.EditorUpdate:
+ return _lastEditorUpdateTime;
+ case Segment.EditorSlowUpdate:
+ return _lastEditorSlowUpdateTime;
+ case Segment.EndOfFrame:
+ return _lastUpdateTime;
+ case Segment.ManualTimeframe:
+ return _lastManualTimeframeTime;
+ default:
+ return 0d;
+ }
+ }
+
+ /// <summary>
+ /// Resets the value of LocalTime to zero (only for the Update, LateUpdate, FixedUpdate, and RealtimeUpdate loops).
+ /// </summary>
+ public void ResetTimeCountOnInstance()
+ {
+ localTime = 0d;
+
+ _lastUpdateTime = 0d;
+ _lastLateUpdateTime = 0d;
+ _lastFixedUpdateTime = 0d;
+ _lastRealtimeUpdateTime = 0d;
+
+ _EOFPumpRan = false;
+ }
+
+ /// <summary>
+ /// This will pause all coroutines running on the current MEC instance until ResumeCoroutines is called.
+ /// </summary>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public static int PauseCoroutines()
+ {
+ return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance();
+ }
+
+ /// <summary>
+ /// This will pause all coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
+ /// </summary>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public int PauseCoroutinesOnInstance()
+ {
+ int count = 0;
+ int i;
+ for (i = 0; i < _nextUpdateProcessSlot; i++)
+ {
+ if (!UpdatePaused[i] && UpdateProcesses[i] != null)
+ {
+ UpdatePaused[i] = true;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextLateUpdateProcessSlot; i++)
+ {
+ if (!LateUpdatePaused[i] && LateUpdateProcesses[i] != null)
+ {
+ LateUpdatePaused[i] = true;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextFixedUpdateProcessSlot; i++)
+ {
+ if (!FixedUpdatePaused[i] && FixedUpdateProcesses[i] != null)
+ {
+ FixedUpdatePaused[i] = true;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextSlowUpdateProcessSlot; i++)
+ {
+ if (!SlowUpdatePaused[i] && SlowUpdateProcesses[i] != null)
+ {
+ SlowUpdatePaused[i] = true;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextRealtimeUpdateProcessSlot; i++)
+ {
+ if (!RealtimeUpdatePaused[i] && RealtimeUpdateProcesses[i] != null)
+ {
+ RealtimeUpdatePaused[i] = true;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextEditorUpdateProcessSlot; i++)
+ {
+ if (!EditorUpdatePaused[i] && EditorUpdateProcesses[i] != null)
+ {
+ EditorUpdatePaused[i] = true;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextEditorSlowUpdateProcessSlot; i++)
+ {
+ if (!EditorSlowUpdatePaused[i] && EditorSlowUpdateProcesses[i] != null)
+ {
+ EditorSlowUpdatePaused[i] = true;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextEndOfFrameProcessSlot; i++)
+ {
+ if (!EndOfFramePaused[i] && EndOfFrameProcesses[i] != null)
+ {
+ EndOfFramePaused[i] = true;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextManualTimeframeProcessSlot; i++)
+ {
+ if (!ManualTimeframePaused[i] && ManualTimeframeProcesses[i] != null)
+ {
+ ManualTimeframePaused[i] = true;
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on the current MEC instance until ResumeCoroutines is called.
+ /// </summary>
+ /// <param name="tag">Any coroutines with a matching tag will be paused.</param>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public static int PauseCoroutines(string tag)
+ {
+ return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(tag);
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
+ /// </summary>
+ /// <param name="tag">Any coroutines with a matching tag will be paused.</param>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public int PauseCoroutinesOnInstance(string tag)
+ {
+ if (tag == null || !_taggedProcesses.ContainsKey(tag))
+ return 0;
+
+ int count = 0;
+ var matchesEnum = _taggedProcesses[tag].GetEnumerator();
+
+ while (matchesEnum.MoveNext())
+ if (!CoindexIsNull(matchesEnum.Current) && !CoindexSetPause(matchesEnum.Current))
+ count++;
+
+ return count;
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on the current MEC instance until ResumeCoroutines is called.
+ /// </summary>
+ /// <param name="layer">Any coroutines on the matching layer will be paused.</param>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public static int PauseCoroutines(int layer)
+ {
+ return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(layer);
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
+ /// </summary>
+ /// <param name="layer">Any coroutines on the matching layer will be paused.</param>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public int PauseCoroutinesOnInstance(int layer)
+ {
+ if (!_layeredProcesses.ContainsKey(layer))
+ return 0;
+
+ int count = 0;
+ var matchesEnum = _layeredProcesses[layer].GetEnumerator();
+
+ while (matchesEnum.MoveNext())
+ if (!CoindexIsNull(matchesEnum.Current) && !CoindexSetPause(matchesEnum.Current))
+ count++;
+
+ return count;
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on the current MEC instance until ResumeCoroutines is called.
+ /// </summary>
+ /// <param name="layer">Any coroutines on the matching layer will be paused.</param>
+ /// <param name="tag">Any coroutines with a matching tag will be paused.</param>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public static int PauseCoroutines(int layer, string tag)
+ {
+ return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(layer, tag);
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
+ /// </summary>
+ /// <param name="layer">Any coroutines on the matching layer will be paused.</param>
+ /// <param name="tag">Any coroutines with a matching tag will be paused.</param>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public int PauseCoroutinesOnInstance(int layer, string tag)
+ {
+ if (tag == null)
+ return PauseCoroutinesOnInstance(layer);
+
+ if (!_taggedProcesses.ContainsKey(tag) || !_layeredProcesses.ContainsKey(layer))
+ return 0;
+
+ int count = 0;
+ var matchesEnum = _taggedProcesses[tag].GetEnumerator();
+
+ while (matchesEnum.MoveNext())
+ if (_processLayers.ContainsKey(matchesEnum.Current) && _processLayers[matchesEnum.Current] == layer
+ && !CoindexIsNull(matchesEnum.Current) && !CoindexSetPause(matchesEnum.Current))
+ count++;
+
+ return count;
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines until ResumeCoroutines is called.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to pause.</param>
+ /// <returns>The number of coroutines that were paused (0 or 1).</returns>
+ public static int PauseCoroutines(CoroutineHandle handle)
+ {
+ return ActiveInstances.ContainsKey(handle.Key) ? GetInstance(handle.Key).PauseCoroutinesOnInstance(handle) : 0;
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to pause.</param>
+ /// <returns>The number of coroutines that were paused (0 or 1).</returns>
+ public int PauseCoroutinesOnInstance(CoroutineHandle handle)
+ {
+ return _handleToIndex.ContainsKey(handle) && !CoindexIsNull(_handleToIndex[handle]) && !CoindexSetPause(_handleToIndex[handle]) ? 1 : 0;
+ }
+
+ /// <summary>
+ /// This resumes all coroutines on the current MEC instance if they are currently paused, otherwise it has
+ /// no effect.
+ /// </summary>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public static int ResumeCoroutines()
+ {
+ return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance();
+ }
+
+ /// <summary>
+ /// This resumes all coroutines on this MEC instance if they are currently paused, otherwise it has no effect.
+ /// </summary>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public int ResumeCoroutinesOnInstance()
+ {
+ int count = 0;
+ int i;
+ for (i = 0; i < _nextUpdateProcessSlot; i++)
+ {
+ if (UpdatePaused[i] && UpdateProcesses[i] != null)
+ {
+ UpdatePaused[i] = false;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextLateUpdateProcessSlot; i++)
+ {
+ if (LateUpdatePaused[i] && LateUpdateProcesses[i] != null)
+ {
+ LateUpdatePaused[i] = false;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextFixedUpdateProcessSlot; i++)
+ {
+ if (FixedUpdatePaused[i] && FixedUpdateProcesses[i] != null)
+ {
+ FixedUpdatePaused[i] = false;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextSlowUpdateProcessSlot; i++)
+ {
+ if (SlowUpdatePaused[i] && SlowUpdateProcesses[i] != null)
+ {
+ SlowUpdatePaused[i] = false;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextRealtimeUpdateProcessSlot; i++)
+ {
+ if (RealtimeUpdatePaused[i] && RealtimeUpdateProcesses[i] != null)
+ {
+ RealtimeUpdatePaused[i] = false;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextEditorUpdateProcessSlot; i++)
+ {
+ if (EditorUpdatePaused[i] && EditorUpdateProcesses[i] != null)
+ {
+ EditorUpdatePaused[i] = false;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextEditorSlowUpdateProcessSlot; i++)
+ {
+ if (EditorSlowUpdatePaused[i] && EditorSlowUpdateProcesses[i] != null)
+ {
+ EditorSlowUpdatePaused[i] = false;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextEndOfFrameProcessSlot; i++)
+ {
+ if (EndOfFramePaused[i] && EndOfFrameProcesses[i] != null)
+ {
+ EndOfFramePaused[i] = false;
+ count++;
+ }
+ }
+
+ for (i = 0; i < _nextManualTimeframeProcessSlot; i++)
+ {
+ if (ManualTimeframePaused[i] && ManualTimeframeProcesses[i] != null)
+ {
+ ManualTimeframePaused[i] = false;
+ count++;
+ }
+ }
+
+ var waitingEnum = _waitingTriggers.GetEnumerator();
+ while (waitingEnum.MoveNext())
+ {
+ int listCount = 0;
+ var pausedList = waitingEnum.Current.Value.GetEnumerator();
+
+ while (pausedList.MoveNext())
+ {
+ if (_handleToIndex.ContainsKey(pausedList.Current.Handle) && !CoindexIsNull(_handleToIndex[pausedList.Current.Handle]))
+ {
+ CoindexSetPause(_handleToIndex[pausedList.Current.Handle]);
+ listCount++;
+ }
+ else
+ {
+ waitingEnum.Current.Value.Remove(pausedList.Current);
+ listCount = 0;
+ pausedList = waitingEnum.Current.Value.GetEnumerator();
+ }
+ }
+
+ count -= listCount;
+ }
+
+ return count;
+ }
+
+ /// <summary>
+ /// This resumes any matching coroutines on the current MEC instance if they are currently paused, otherwise it has no effect.
+ /// </summary>
+ /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public static int ResumeCoroutines(string tag)
+ {
+ return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(tag);
+ }
+
+ /// <summary>
+ /// This resumes any matching coroutines on this MEC instance if they are currently paused, otherwise it has no effect.
+ /// </summary>
+ /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public int ResumeCoroutinesOnInstance(string tag)
+ {
+ if (tag == null || !_taggedProcesses.ContainsKey(tag))
+ return 0;
+ int count = 0;
+
+ var indexesEnum = _taggedProcesses[tag].GetEnumerator();
+ while (indexesEnum.MoveNext())
+ if (!CoindexIsNull(indexesEnum.Current) && CoindexSetPause(indexesEnum.Current, false))
+ count++;
+
+ var waitingEnum = _waitingTriggers.GetEnumerator();
+ while (waitingEnum.MoveNext())
+ {
+ var pausedList = waitingEnum.Current.Value.GetEnumerator();
+ while (pausedList.MoveNext())
+ {
+ if (_handleToIndex.ContainsKey(pausedList.Current.Handle) && !CoindexIsNull(_handleToIndex[pausedList.Current.Handle])
+ && !CoindexSetPause(_handleToIndex[pausedList.Current.Handle]))
+ count--;
+ }
+ }
+
+ return count;
+ }
+
+ /// <summary>
+ /// This resumes any matching coroutines on the current MEC instance if they are currently paused, otherwise it has
+ /// no effect.
+ /// </summary>
+ /// <param name="layer">Any coroutines previously paused on the matching layer will be resumend.</param>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public static int ResumeCoroutines(int layer)
+ {
+ return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(layer);
+ }
+
+ /// <summary>
+ /// This resumes any matching coroutines on this MEC instance if they are currently paused, otherwise it has no effect.
+ /// </summary>
+ /// <param name="layer">Any coroutines previously paused on the matching layer will be resumend.</param>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public int ResumeCoroutinesOnInstance(int layer)
+ {
+ if (!_layeredProcesses.ContainsKey(layer))
+ return 0;
+ int count = 0;
+
+ var indexesEnum = _layeredProcesses[layer].GetEnumerator();
+ while (indexesEnum.MoveNext())
+ if (!CoindexIsNull(indexesEnum.Current) && CoindexSetPause(indexesEnum.Current, false))
+ count++;
+
+ var waitingEnum = _waitingTriggers.GetEnumerator();
+ while (waitingEnum.MoveNext())
+ {
+ var pausedList = waitingEnum.Current.Value.GetEnumerator();
+ while (pausedList.MoveNext())
+ {
+ if (_handleToIndex.ContainsKey(pausedList.Current.Handle) && !CoindexIsNull(_handleToIndex[pausedList.Current.Handle])
+ && !CoindexSetPause(_handleToIndex[pausedList.Current.Handle]))
+ count--;
+ }
+ }
+
+ return count;
+ }
+
+ /// <summary>
+ /// This resumes any matching coroutines on the current MEC instance if they are currently paused, otherwise it has
+ /// no effect.
+ /// </summary>
+ /// <param name="layer">Any coroutines previously paused on the matching layer will be resumend.</param>
+ /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public static int ResumeCoroutines(int layer, string tag)
+ {
+ return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(layer, tag);
+ }
+
+ /// <summary>
+ /// This resumes any matching coroutines on this MEC instance if they are currently paused, otherwise it has no effect.
+ /// </summary>
+ /// <param name="layer">Any coroutines previously paused on the matching layer will be resumend.</param>
+ /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public int ResumeCoroutinesOnInstance(int layer, string tag)
+ {
+ if (tag == null)
+ return ResumeCoroutinesOnInstance(layer);
+ if (!_layeredProcesses.ContainsKey(layer) || !_taggedProcesses.ContainsKey(tag))
+ return 0;
+ int count = 0;
+
+ var indexesEnum = _taggedProcesses[tag].GetEnumerator();
+ while (indexesEnum.MoveNext())
+ if (!CoindexIsNull(indexesEnum.Current) && _layeredProcesses[layer].Contains(indexesEnum.Current) &&
+ CoindexSetPause(indexesEnum.Current, false))
+ count++;
+
+ var waitingEnum = _waitingTriggers.GetEnumerator();
+ while (waitingEnum.MoveNext())
+ {
+ var pausedList = waitingEnum.Current.Value.GetEnumerator();
+ while (pausedList.MoveNext())
+ {
+ if (_handleToIndex.ContainsKey(pausedList.Current.Handle) && !CoindexIsNull(_handleToIndex[pausedList.Current.Handle])
+ && !CoindexSetPause(_handleToIndex[pausedList.Current.Handle]))
+ count--;
+ }
+ }
+
+ return count;
+ }
+
+ /// <summary>
+ /// This will resume any matching coroutines.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to resume.</param>
+ /// <returns>The number of coroutines that were resumed (0 or 1).</returns>
+ public static int ResumeCoroutines(CoroutineHandle handle)
+ {
+ return ActiveInstances.ContainsKey(handle.Key) ? GetInstance(handle.Key).ResumeCoroutinesOnInstance(handle) : 0;
+ }
+
+ /// <summary>
+ /// This will resume any matching coroutines running on this MEC instance.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to resume.</param>
+ /// <returns>The number of coroutines that were resumed (0 or 1).</returns>
+ public int ResumeCoroutinesOnInstance(CoroutineHandle handle)
+ {
+ var waitingEnum = _waitingTriggers.GetEnumerator();
+ while (waitingEnum.MoveNext())
+ {
+ var pausedList = waitingEnum.Current.Value.GetEnumerator();
+ while (pausedList.MoveNext())
+ if (pausedList.Current.Handle == handle)
+ return 0;
+ }
+
+ return _handleToIndex.ContainsKey(handle) &&
+ !CoindexIsNull(_handleToIndex[handle]) && CoindexSetPause(_handleToIndex[handle], false) ? 1 : 0;
+ }
+
+ /// <summary>
+ /// Returns the tag associated with the coroutine that the given handle points to, if it is running.
+ /// </summary>
+ /// <param name="handle">The handle to the coroutine.</param>
+ /// <returns>The coroutine's tag, or null if there is no matching tag.</returns>
+ public static string GetTag(CoroutineHandle handle)
+ {
+ Timing inst = GetInstance(handle.Key);
+ return inst != null && inst._handleToIndex.ContainsKey(handle) && inst._processTags.ContainsKey(inst._handleToIndex[handle])
+ ? inst._processTags[inst._handleToIndex[handle]] : null;
+ }
+
+ /// <summary>
+ /// Returns the layer associated with the coroutine that the given handle points to, if it is running.
+ /// </summary>
+ /// <param name="handle">The handle to the coroutine.</param>
+ /// <returns>The coroutine's layer as a nullable integer, or null if there is no matching layer.</returns>
+ public static int? GetLayer(CoroutineHandle handle)
+ {
+ Timing inst = GetInstance(handle.Key);
+ return inst != null && inst._handleToIndex.ContainsKey(handle) && inst._processLayers.ContainsKey(inst._handleToIndex[handle])
+ ? inst._processLayers[inst._handleToIndex[handle]] : (int?)null;
+ }
+
+ /// <summary>
+ /// Returns the segment that the coroutine with the given handle is running on.
+ /// </summary>
+ /// <param name="handle">The handle to the coroutine.</param>
+ /// <returns>The coroutine's segment, or Segment.Invalid if it's not found.</returns>
+ public static Segment GetSegment(CoroutineHandle handle)
+ {
+ Timing inst = GetInstance(handle.Key);
+ return inst != null && inst._handleToIndex.ContainsKey(handle) ? inst._handleToIndex[handle].seg : Segment.Invalid;
+ }
+
+ /// <summary>
+ /// Sets the coroutine that the handle points to to have the given tag.
+ /// </summary>
+ /// <param name="handle">The handle to the coroutine.</param>
+ /// <param name="newTag">The new tag to assign, or null to clear the tag.</param>
+ /// <param name="overwriteExisting">If set to false then the tag will not be changed if the coroutine has an existing tag.</param>
+ /// <returns>Whether the tag was set successfully.</returns>
+ public static bool SetTag(CoroutineHandle handle, string newTag, bool overwriteExisting = true)
+ {
+ Timing inst = GetInstance(handle.Key);
+ if (inst == null || !inst._handleToIndex.ContainsKey(handle) || inst.CoindexIsNull(inst._handleToIndex[handle])
+ || (!overwriteExisting && inst._processTags.ContainsKey(inst._handleToIndex[handle])))
+ return false;
+
+ if (newTag == null)
+ {
+ inst.RemoveTag(inst._handleToIndex[handle]);
+ return true;
+ }
+
+ if (inst._processTags.ContainsKey(inst._handleToIndex[handle]))
+ {
+ if (inst._taggedProcesses[inst._processTags[inst._handleToIndex[handle]]].Count <= 1)
+ inst._taggedProcesses.Remove(inst._processTags[inst._handleToIndex[handle]]);
+ else
+ inst._taggedProcesses[inst._processTags[inst._handleToIndex[handle]]].Remove(inst._handleToIndex[handle]);
+
+ inst._processTags[inst._handleToIndex[handle]] = newTag;
+ }
+ else
+ {
+ inst._processTags.Add(inst._handleToIndex[handle], newTag);
+ }
+
+ if (inst._taggedProcesses.ContainsKey(newTag))
+ inst._taggedProcesses[newTag].Add(inst._handleToIndex[handle]);
+ else
+ inst._taggedProcesses.Add(newTag, new HashSet<ProcessIndex> { inst._handleToIndex[handle] });
+
+ return true;
+ }
+
+ /// <summary>
+ /// Sets the coroutine that the handle points to to have the given layer.
+ /// </summary>
+ /// <param name="handle">The handle to the coroutine.</param>
+ /// <param name="newLayer">The new tag to assign.</param>
+ /// <param name="overwriteExisting">If set to false then the tag will not be changed if the coroutine has an existing tag.</param>
+ /// <returns>Whether the layer was set successfully.</returns>
+ public static bool SetLayer(CoroutineHandle handle, int newLayer, bool overwriteExisting = true)
+ {
+ Timing inst = GetInstance(handle.Key);
+ if (inst == null || !inst._handleToIndex.ContainsKey(handle) || inst.CoindexIsNull(inst._handleToIndex[handle])
+ || (!overwriteExisting && inst._processLayers.ContainsKey(inst._handleToIndex[handle])))
+ return false;
+
+ if (inst._processLayers.ContainsKey(inst._handleToIndex[handle]))
+ {
+ if (inst._layeredProcesses[inst._processLayers[inst._handleToIndex[handle]]].Count <= 1)
+ inst._layeredProcesses.Remove(inst._processLayers[inst._handleToIndex[handle]]);
+ else
+ inst._layeredProcesses[inst._processLayers[inst._handleToIndex[handle]]].Remove(inst._handleToIndex[handle]);
+
+ inst._processLayers[inst._handleToIndex[handle]] = newLayer;
+ }
+ else
+ {
+ inst._processLayers.Add(inst._handleToIndex[handle], newLayer);
+ }
+
+ if (inst._layeredProcesses.ContainsKey(newLayer))
+ inst._layeredProcesses[newLayer].Add(inst._handleToIndex[handle]);
+ else
+ inst._layeredProcesses.Add(newLayer, new HashSet<ProcessIndex> { inst._handleToIndex[handle] });
+
+ return true;
+ }
+
+ /// <summary>
+ /// Sets the segment for the coroutine with the given handle.
+ /// </summary>
+ /// <param name="handle">The handle to the coroutine.</param>
+ /// <param name="newSegment">The new segment to run the coroutine in.</param>
+ /// <returns>Whether the segment was set successfully.</returns>
+ public static bool SetSegment(CoroutineHandle handle, Segment newSegment)
+ {
+ Timing inst = GetInstance(handle.Key);
+ if (inst == null || !inst._handleToIndex.ContainsKey(handle) || inst.CoindexIsNull(inst._handleToIndex[handle]))
+ return false;
+
+ inst.RunCoroutineInternal(inst.CoindexExtract(inst._handleToIndex[handle]), newSegment, inst._processLayers.ContainsKey(inst._handleToIndex[handle])
+ ? inst._processLayers[inst._handleToIndex[handle]] : (int?)null, inst._processTags.ContainsKey(inst._handleToIndex[handle])
+ ? inst._processTags[inst._handleToIndex[handle]] : null, handle, false);
+
+ return true;
+ }
+
+ /// <summary>
+ /// Sets the coroutine that the handle points to to have the given tag.
+ /// </summary>
+ /// <param name="handle">The handle to the coroutine.</param>
+ /// <returns>Whether the tag was removed successfully.</returns>
+ public static bool RemoveTag(CoroutineHandle handle)
+ {
+ return SetTag(handle, null);
+ }
+
+ /// <summary>
+ /// Sets the coroutine that the handle points to to have the given layer.
+ /// </summary>
+ /// <param name="handle">The handle to the coroutine.</param>
+ /// <returns>Whether the layer was removed successfully.</returns>
+ public static bool RemoveLayer(CoroutineHandle handle)
+ {
+ Timing inst = GetInstance(handle.Key);
+ if (inst == null || !inst._handleToIndex.ContainsKey(handle) || inst.CoindexIsNull(inst._handleToIndex[handle]))
+ return false;
+
+ inst.RemoveLayer(inst._handleToIndex[handle]);
+
+ return true;
+ }
+
+ /// <summary>
+ /// Tests to see if the handle you have points to a valid coroutine.
+ /// </summary>
+ /// <param name="handle">The handle to test.</param>
+ /// <returns>Whether it's a valid coroutine.</returns>
+ public static bool IsRunning(CoroutineHandle handle)
+ {
+ Timing inst = GetInstance(handle.Key);
+ return inst != null && inst._handleToIndex.ContainsKey(handle) && !inst.CoindexIsNull(inst._handleToIndex[handle]);
+ }
+
+ /// <summary>
+ /// Tests to see if the handle you have points to a paused coroutine.
+ /// </summary>
+ /// <param name="handle">The handle to test.</param>
+ /// <returns>Whether it's a paused coroutine.</returns>
+ public static bool IsPaused(CoroutineHandle handle)
+ {
+ Timing inst = GetInstance(handle.Key);
+ return inst != null && inst._handleToIndex.ContainsKey(handle) && !inst.CoindexIsNull(inst._handleToIndex[handle]) &&
+ !inst.CoindexIsPaused(inst._handleToIndex[handle]);
+ }
+
+ private void AddTag(string tag, ProcessIndex coindex)
+ {
+ _processTags.Add(coindex, tag);
+
+ if (_taggedProcesses.ContainsKey(tag))
+ _taggedProcesses[tag].Add(coindex);
+ else
+ _taggedProcesses.Add(tag, new HashSet<ProcessIndex> { coindex });
+ }
+
+ private void AddLayer(int layer, ProcessIndex coindex)
+ {
+ _processLayers.Add(coindex, layer);
+
+ if (_layeredProcesses.ContainsKey(layer))
+ _layeredProcesses[layer].Add(coindex);
+ else
+ _layeredProcesses.Add(layer, new HashSet<ProcessIndex> { coindex });
+ }
+
+ private void RemoveTag(ProcessIndex coindex)
+ {
+ if (_processTags.ContainsKey(coindex))
+ {
+ if (_taggedProcesses[_processTags[coindex]].Count > 1)
+ _taggedProcesses[_processTags[coindex]].Remove(coindex);
+ else
+ _taggedProcesses.Remove(_processTags[coindex]);
+
+ _processTags.Remove(coindex);
+ }
+ }
+
+ private void RemoveLayer(ProcessIndex coindex)
+ {
+ if (_processLayers.ContainsKey(coindex))
+ {
+ if (_layeredProcesses[_processLayers[coindex]].Count > 1)
+ _layeredProcesses[_processLayers[coindex]].Remove(coindex);
+ else
+ _layeredProcesses.Remove(_processLayers[coindex]);
+
+ _processLayers.Remove(coindex);
+ }
+ }
+
+ private void RemoveGraffiti(ProcessIndex coindex)
+ {
+ if (_processLayers.ContainsKey(coindex))
+ {
+ if (_layeredProcesses[_processLayers[coindex]].Count > 1)
+ _layeredProcesses[_processLayers[coindex]].Remove(coindex);
+ else
+ _layeredProcesses.Remove(_processLayers[coindex]);
+
+ _processLayers.Remove(coindex);
+ }
+
+ if (_processTags.ContainsKey(coindex))
+ {
+ if (_taggedProcesses[_processTags[coindex]].Count > 1)
+ _taggedProcesses[_processTags[coindex]].Remove(coindex);
+ else
+ _taggedProcesses.Remove(_processTags[coindex]);
+
+ _processTags.Remove(coindex);
+ }
+
+ if (_indexToHandle.ContainsKey(coindex))
+ {
+ _handleToIndex.Remove(_indexToHandle[coindex]);
+ _indexToHandle.Remove(coindex);
+ }
+ }
+
+ private void MoveGraffiti(ProcessIndex coindexFrom, ProcessIndex coindexTo)
+ {
+ RemoveGraffiti(coindexTo);
+
+ int layer;
+ if (_processLayers.TryGetValue(coindexFrom, out layer))
+ {
+ _layeredProcesses[layer].Remove(coindexFrom);
+ _layeredProcesses[layer].Add(coindexTo);
+
+ _processLayers.Add(coindexTo, layer);
+ _processLayers.Remove(coindexFrom);
+ }
+
+ string tag;
+ if (_processTags.TryGetValue(coindexFrom, out tag))
+ {
+ _taggedProcesses[tag].Remove(coindexFrom);
+ _taggedProcesses[tag].Add(coindexTo);
+
+ _processTags.Add(coindexTo, tag);
+ _processTags.Remove(coindexFrom);
+ }
+
+ _handleToIndex[_indexToHandle[coindexFrom]] = coindexTo;
+ _indexToHandle.Add(coindexTo, _indexToHandle[coindexFrom]);
+ _indexToHandle.Remove(coindexFrom);
+ }
+
+ private IEnumerator<float> CoindexExtract(ProcessIndex coindex)
+ {
+ IEnumerator<float> retVal;
+
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ retVal = UpdateProcesses[coindex.i];
+ UpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.FixedUpdate:
+ retVal = FixedUpdateProcesses[coindex.i];
+ FixedUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.LateUpdate:
+ retVal = LateUpdateProcesses[coindex.i];
+ LateUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.SlowUpdate:
+ retVal = SlowUpdateProcesses[coindex.i];
+ SlowUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.RealtimeUpdate:
+ retVal = RealtimeUpdateProcesses[coindex.i];
+ RealtimeUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.EditorUpdate:
+ retVal = EditorUpdateProcesses[coindex.i];
+ EditorUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.EditorSlowUpdate:
+ retVal = EditorSlowUpdateProcesses[coindex.i];
+ EditorSlowUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.EndOfFrame:
+ retVal = EndOfFrameProcesses[coindex.i];
+ EndOfFrameProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.ManualTimeframe:
+ retVal = ManualTimeframeProcesses[coindex.i];
+ ManualTimeframeProcesses[coindex.i] = null;
+ return retVal;
+ default:
+ return null;
+ }
+ }
+
+ private bool CoindexIsNull(ProcessIndex coindex)
+ {
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ return UpdateProcesses[coindex.i] == null;
+ case Segment.FixedUpdate:
+ return FixedUpdateProcesses[coindex.i] == null;
+ case Segment.LateUpdate:
+ return LateUpdateProcesses[coindex.i] == null;
+ case Segment.SlowUpdate:
+ return SlowUpdateProcesses[coindex.i] == null;
+ case Segment.RealtimeUpdate:
+ return RealtimeUpdateProcesses[coindex.i] == null;
+ case Segment.EditorUpdate:
+ return EditorUpdateProcesses[coindex.i] == null;
+ case Segment.EditorSlowUpdate:
+ return EditorSlowUpdateProcesses[coindex.i] == null;
+ case Segment.EndOfFrame:
+ return EndOfFrameProcesses[coindex.i] == null;
+ case Segment.ManualTimeframe:
+ return ManualTimeframeProcesses[coindex.i] == null;
+ default:
+ return true;
+ }
+ }
+
+ private IEnumerator<float> CoindexPeek(ProcessIndex coindex)
+ {
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ return UpdateProcesses[coindex.i];
+ case Segment.FixedUpdate:
+ return FixedUpdateProcesses[coindex.i];
+ case Segment.LateUpdate:
+ return LateUpdateProcesses[coindex.i];
+ case Segment.SlowUpdate:
+ return SlowUpdateProcesses[coindex.i];
+ case Segment.RealtimeUpdate:
+ return RealtimeUpdateProcesses[coindex.i];
+ case Segment.EditorUpdate:
+ return EditorUpdateProcesses[coindex.i];
+ case Segment.EditorSlowUpdate:
+ return EditorSlowUpdateProcesses[coindex.i];
+ case Segment.EndOfFrame:
+ return EndOfFrameProcesses[coindex.i];
+ case Segment.ManualTimeframe:
+ return ManualTimeframeProcesses[coindex.i];
+ default:
+ return null;
+ }
+ }
+
+ private bool CoindexKill(ProcessIndex coindex)
+ {
+ bool retVal;
+
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ retVal = UpdateProcesses[coindex.i] != null;
+ UpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.FixedUpdate:
+ retVal = FixedUpdateProcesses[coindex.i] != null;
+ FixedUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.LateUpdate:
+ retVal = LateUpdateProcesses[coindex.i] != null;
+ LateUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.SlowUpdate:
+ retVal = SlowUpdateProcesses[coindex.i] != null;
+ SlowUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.RealtimeUpdate:
+ retVal = RealtimeUpdateProcesses[coindex.i] != null;
+ RealtimeUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.EditorUpdate:
+ retVal = UpdateProcesses[coindex.i] != null;
+ EditorUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.EditorSlowUpdate:
+ retVal = EditorSlowUpdateProcesses[coindex.i] != null;
+ EditorSlowUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.EndOfFrame:
+ retVal = EndOfFrameProcesses[coindex.i] != null;
+ EndOfFrameProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.ManualTimeframe:
+ retVal = ManualTimeframeProcesses[coindex.i] != null;
+ ManualTimeframeProcesses[coindex.i] = null;
+ return retVal;
+ default:
+ return false;
+ }
+ }
+
+ private bool CoindexSetPause(ProcessIndex coindex, bool newPausedState = true)
+ {
+ bool isPaused;
+
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ isPaused = UpdatePaused[coindex.i];
+ UpdatePaused[coindex.i] = newPausedState;
+ return isPaused;
+ case Segment.FixedUpdate:
+ isPaused = FixedUpdatePaused[coindex.i];
+ FixedUpdatePaused[coindex.i] = newPausedState;
+ return isPaused;
+ case Segment.LateUpdate:
+ isPaused = LateUpdatePaused[coindex.i];
+ LateUpdatePaused[coindex.i] = newPausedState;
+ return isPaused;
+ case Segment.SlowUpdate:
+ isPaused = SlowUpdatePaused[coindex.i];
+ SlowUpdatePaused[coindex.i] = newPausedState;
+ return isPaused;
+ case Segment.RealtimeUpdate:
+ isPaused = RealtimeUpdatePaused[coindex.i];
+ RealtimeUpdatePaused[coindex.i] = newPausedState;
+ return isPaused;
+ case Segment.EditorUpdate:
+ isPaused = EditorUpdatePaused[coindex.i];
+ EditorUpdatePaused[coindex.i] = newPausedState;
+ return isPaused;
+ case Segment.EditorSlowUpdate:
+ isPaused = EditorSlowUpdatePaused[coindex.i];
+ EditorSlowUpdatePaused[coindex.i] = newPausedState;
+ return isPaused;
+ case Segment.EndOfFrame:
+ isPaused = EndOfFramePaused[coindex.i];
+ EndOfFramePaused[coindex.i] = newPausedState;
+ return isPaused;
+ case Segment.ManualTimeframe:
+ isPaused = ManualTimeframePaused[coindex.i];
+ ManualTimeframePaused[coindex.i] = newPausedState;
+ return isPaused;
+ default:
+ return false;
+ }
+ }
+
+ private bool CoindexIsPaused(ProcessIndex coindex)
+ {
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ return UpdatePaused[coindex.i];
+ case Segment.FixedUpdate:
+ return FixedUpdatePaused[coindex.i];
+ case Segment.LateUpdate:
+ return LateUpdatePaused[coindex.i];
+ case Segment.SlowUpdate:
+ return SlowUpdatePaused[coindex.i];
+ case Segment.RealtimeUpdate:
+ return RealtimeUpdatePaused[coindex.i];
+ case Segment.EditorUpdate:
+ return EditorUpdatePaused[coindex.i];
+ case Segment.EditorSlowUpdate:
+ return EditorSlowUpdatePaused[coindex.i];
+ case Segment.EndOfFrame:
+ return EndOfFramePaused[coindex.i];
+ case Segment.ManualTimeframe:
+ return ManualTimeframePaused[coindex.i];
+ default:
+ return false;
+ }
+ }
+
+ private void CoindexReplace(ProcessIndex coindex, IEnumerator<float> replacement)
+ {
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ UpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.FixedUpdate:
+ FixedUpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.LateUpdate:
+ LateUpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.SlowUpdate:
+ SlowUpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.RealtimeUpdate:
+ RealtimeUpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.EditorUpdate:
+ EditorUpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.EditorSlowUpdate:
+ EditorSlowUpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.EndOfFrame:
+ EndOfFrameProcesses[coindex.i] = replacement;
+ return;
+ case Segment.ManualTimeframe:
+ ManualTimeframeProcesses[coindex.i] = replacement;
+ return;
+ }
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.WaitUntilDone(otherCoroutine);" to pause the current
+ /// coroutine until otherCoroutine is done.
+ /// </summary>
+ /// <param name="otherCoroutine">The coroutine to pause for.</param>
+ //public static float WaitUntilDone(CoroutineHandle otherCoroutine)
+ //{
+ // return Instance.WaitUntilDoneOnInstance(otherCoroutine);
+ //}
+
+ ///// <summary>
+ ///// Use the command "yield return Timing.WaitUntilDone(otherCoroutine);" to pause the current
+ ///// coroutine until otherCoroutine is done.
+ ///// </summary>
+ ///// <param name="otherCoroutine">The coroutine to pause for.</param>
+ ///// <param name="warnOnIssue">Post a warning to the console if no hold action was actually performed.</param>
+ //public static float WaitUntilDone(CoroutineHandle otherCoroutine, bool warnOnIssue)
+ //{
+ // return Instance.WaitUntilDoneOnInstance(otherCoroutine, warnOnIssue);
+ //}
+
+ ///// <summary>
+ ///// Use the command "yield return timingInstance.WaitUntilDoneOnInstance(otherCoroutine);" to pause the current
+ ///// coroutine until the otherCoroutine is done.
+ ///// </summary>
+ ///// <param name="otherCoroutine">The coroutine to pause for.</param>
+ ///// <param name="warnOnIssue">Post a warning to the console if no hold action was actually performed.</param>
+ //public float WaitUntilDoneOnInstance(CoroutineHandle otherCoroutine, bool warnOnIssue = true)
+ //{
+ // if (_handleToIndex.ContainsKey(otherCoroutine))
+ // {
+ // if (CoindexIsNull(_handleToIndex[otherCoroutine]))
+ // return 0f;
+
+ // if (!_waitingTriggers.ContainsKey(otherCoroutine))
+ // {
+ // CoindexReplace(_handleToIndex[otherCoroutine], _StartWhenDone(otherCoroutine, CoindexPeek(_handleToIndex[otherCoroutine])));
+ // _waitingTriggers.Add(otherCoroutine, new HashSet<ProcessData>());
+ // }
+
+ // ReplacementFunction = (coptr, instance, handle) =>
+ // {
+ // if (handle == otherCoroutine)
+ // {
+ // if (warnOnIssue)
+ // Debug.LogWarning("A coroutine attempted to wait for itself.");
+
+ // return coptr;
+ // }
+
+ // _waitingTriggers[otherCoroutine].Add(new ProcessData
+ // {
+ // Handle = handle,
+ // PauseTime = coptr.Current > GetSegmentTime(_handleToIndex[handle].seg)
+ // ? coptr.Current - (float)GetSegmentTime(_handleToIndex[handle].seg) : 0f
+ // });
+
+ // CoindexSetPause(_handleToIndex[handle]);
+
+ // return coptr;
+ // };
+
+ // return float.NaN;
+ // }
+
+ // if (warnOnIssue)
+ // Debug.LogWarning("WaitUntilDone cannot hold: The coroutine handle that was passed in is invalid.\n" + otherCoroutine);
+
+ // return 0f;
+ //}
+
+ private IEnumerator<float> _StartWhenDone(CoroutineHandle handle, IEnumerator<float> proc)
+ {
+ if (!_waitingTriggers.ContainsKey(handle)) yield break;
+
+ try
+ {
+ if (proc.Current > localTime)
+ yield return proc.Current;
+
+ while (proc.MoveNext())
+ yield return proc.Current;
+ }
+ finally
+ {
+ CloseWaitingProcess(handle);
+ }
+ }
+
+ private void CloseWaitingProcess(CoroutineHandle handle)
+ {
+ if (!_waitingTriggers.ContainsKey(handle)) return;
+
+ var tasksEnum = _waitingTriggers[handle].GetEnumerator();
+ _waitingTriggers.Remove(handle);
+
+ while (tasksEnum.MoveNext())
+ {
+ if (_handleToIndex.ContainsKey(tasksEnum.Current.Handle))
+ {
+ ProcessIndex coIndex = _handleToIndex[tasksEnum.Current.Handle];
+
+ //if (tasksEnum.Current.PauseTime > 0d)
+ //CoindexReplace(coIndex, _InjectDelay(CoindexPeek(coIndex), (float)(GetSegmentTime(coIndex.seg) + tasksEnum.Current.PauseTime)));
+
+ CoindexSetPause(coIndex, false);
+ }
+ }
+ }
+
+ private static IEnumerator<float> _InjectDelay(IEnumerator<float> proc, float returnAt)
+ {
+ yield return returnAt;
+
+ ReplacementFunction = delegate { return proc; };
+ yield return float.NaN;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.SwitchCoroutine(segment);" to switch this coroutine to
+ /// the given segment on the default instance.
+ /// </summary>
+ /// <param name="newSegment">The new segment to run in.</param>
+ public static float SwitchCoroutine(Segment newSegment)
+ {
+ ReplacementFunction = (coptr, instance, handle) =>
+ {
+ ProcessIndex index = instance._handleToIndex[handle];
+ instance.RunCoroutineInternal(coptr, newSegment, instance._processLayers.ContainsKey(index) ? instance._processLayers[index] : (int?)null,
+ instance._processTags.ContainsKey(index) ? instance._processTags[index] : null, handle, false);
+ return null;
+ };
+
+ return float.NaN;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.SwitchCoroutine(segment, tag);" to switch this coroutine to
+ /// the given values.
+ /// </summary>
+ /// <param name="newSegment">The new segment to run in.</param>
+ /// <param name="newTag">The new tag to apply, or null to remove this coroutine's tag.</param>
+ public static float SwitchCoroutine(Segment newSegment, string newTag)
+ {
+ ReplacementFunction = (coptr, instance, handle) =>
+ {
+ ProcessIndex index = instance._handleToIndex[handle];
+ instance.RunCoroutineInternal(coptr, newSegment,
+ instance._processLayers.ContainsKey(index) ? instance._processLayers[index] : (int?)null, newTag, handle, false);
+ return null;
+ };
+
+ return float.NaN;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.SwitchCoroutine(segment, layer);" to switch this coroutine to
+ /// the given values.
+ /// </summary>
+ /// <param name="newSegment">The new segment to run in.</param>
+ /// <param name="newLayer">The new layer to apply.</param>
+ public static float SwitchCoroutine(Segment newSegment, int newLayer)
+ {
+ ReplacementFunction = (coptr, instance, handle) =>
+ {
+ ProcessIndex index = instance._handleToIndex[handle];
+ instance.RunCoroutineInternal(coptr, newSegment, newLayer,
+ instance._processTags.ContainsKey(index) ? instance._processTags[index] : null, handle, false);
+ return null;
+ };
+
+ return float.NaN;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.SwitchCoroutine(segment, layer, tag);" to switch this coroutine to
+ /// the given values.
+ /// </summary>
+ /// <param name="newSegment">The new segment to run in.</param>
+ /// <param name="newLayer">The new layer to apply.</param>
+ /// <param name="newTag">The new tag to apply, or null to remove this coroutine's tag.</param>
+ public static float SwitchCoroutine(Segment newSegment, int newLayer, string newTag)
+ {
+ ReplacementFunction = (coptr, instance, handle) =>
+ {
+ instance.RunCoroutineInternal(coptr, newSegment, newLayer, newTag, handle, false);
+ return null;
+ };
+
+ return float.NaN;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.SwitchCoroutine(tag);" to switch this coroutine to
+ /// the given tag.
+ /// </summary>
+ /// <param name="newTag">The new tag to apply, or null to remove this coroutine's tag.</param>
+ public static float SwitchCoroutine(string newTag)
+ {
+ ReplacementFunction = (coptr, instance, handle) =>
+ {
+ instance.RemoveTag(instance._handleToIndex[handle]);
+ if (newTag != null)
+ instance.AddTag(newTag, instance._handleToIndex[handle]);
+ return coptr;
+ };
+ return float.NaN;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.SwitchCoroutine(layer);" to switch this coroutine to
+ /// the given layer.
+ /// </summary>
+ /// <param name="newLayer">The new layer to apply.</param>
+ public static float SwitchCoroutine(int newLayer)
+ {
+ ReplacementFunction = (coptr, instance, handle) =>
+ {
+ instance.RemoveLayer(instance._handleToIndex[handle]);
+ instance.AddLayer(newLayer, instance._handleToIndex[handle]);
+ return coptr;
+ };
+
+ return float.NaN;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.SwitchCoroutine(layer, tag);" to switch this coroutine to
+ /// the given tag.
+ /// </summary>
+ /// <param name="newLayer">The new layer to apply.</param>
+ /// <param name="newTag">The new tag to apply, or null to remove this coroutine's tag.</param>
+ public static float SwitchCoroutine(int newLayer, string newTag)
+ {
+ ReplacementFunction = (coptr, instance, handle) =>
+ {
+ instance.RemoveLayer(instance._handleToIndex[handle]);
+ instance.AddLayer(newLayer, instance._handleToIndex[handle]);
+ instance.RemoveTag(instance._handleToIndex[handle]);
+ if (newTag != null)
+ instance.AddTag(newTag, instance._handleToIndex[handle]);
+ return coptr;
+ };
+
+ return float.NaN;
+ }
+
+ ///// <summary>
+ ///// Use the command "yield return Timing.WaitUntilDone(wwwObject);" to pause the current
+ ///// coroutine until the wwwObject is done.
+ ///// </summary>
+ ///// <param name="wwwObject">The www object to pause for.</param>
+ //public static float WaitUntilDone(WWW wwwObject)
+ //{
+ // if(wwwObject == null || wwwObject.isDone) return 0f;
+ // ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(wwwObject, coptr);
+
+ // return float.NaN;
+ //}
+
+ private static IEnumerator<float> _StartWhenDone(WWW wwwObject, IEnumerator<float> pausedProc)
+ {
+ while (!wwwObject.isDone)
+ yield return 0f;
+
+ ReplacementFunction = delegate { return pausedProc; };
+ yield return float.NaN;
+ }
+
+ ///// <summary>
+ ///// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current
+ ///// coroutine until the operation is done.
+ ///// </summary>
+ ///// <param name="operation">The operation variable returned.</param>
+ //public static float WaitUntilDone(AsyncOperation operation)
+ //{
+ // if (operation == null || operation.isDone) return 0f;
+ // ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(operation, coptr);
+ // return float.NaN;
+ //}
+
+ private static IEnumerator<float> _StartWhenDone(AsyncOperation operation, IEnumerator<float> pausedProc)
+ {
+ while (!operation.isDone)
+ yield return 0f;
+
+ ReplacementFunction = delegate { return pausedProc; };
+ yield return float.NaN;
+ }
+
+#if !UNITY_4_6 && !UNITY_4_7 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2
+ /// <summary>
+ /// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current
+ /// coroutine until the operation is done.
+ /// </summary>
+ /// <param name="operation">The operation variable returned.</param>
+ //public static float WaitUntilDone(CustomYieldInstruction operation)
+ //{
+ // if (operation == null || !operation.keepWaiting) return 0f;
+ // ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(operation, coptr);
+ // return float.NaN;
+ //}
+
+ private static IEnumerator<float> _StartWhenDone(CustomYieldInstruction operation, IEnumerator<float> pausedProc)
+ {
+ while (operation.keepWaiting)
+ yield return 0f;
+
+ ReplacementFunction = delegate { return pausedProc; };
+ yield return float.NaN;
+ }
+#endif
+
+ /// <summary>
+ /// Use the command "yield return Timing.WaitUntilTrue(evaluatorFunc);" to pause the current
+ /// coroutine until the evaluator function returns true.
+ /// </summary>
+ /// <param name="evaluatorFunc">The evaluator function.</param>
+ public static float WaitUntilTrue(System.Func<bool> evaluatorFunc)
+ {
+ if (evaluatorFunc == null || evaluatorFunc()) return 0f;
+ ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(evaluatorFunc, false, coptr);
+ return float.NaN;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.WaitUntilFalse(evaluatorFunc);" to pause the current
+ /// coroutine until the evaluator function returns false.
+ /// </summary>
+ /// <param name="evaluatorFunc">The evaluator function.</param>
+ public static float WaitUntilFalse(System.Func<bool> evaluatorFunc)
+ {
+ if (evaluatorFunc == null || !evaluatorFunc()) return 0f;
+ ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(evaluatorFunc, true, coptr);
+ return float.NaN;
+ }
+
+ private static IEnumerator<float> _StartWhenDone(System.Func<bool> evaluatorFunc, bool continueOn, IEnumerator<float> pausedProc)
+ {
+ while (evaluatorFunc() == continueOn)
+ yield return 0f;
+
+ ReplacementFunction = delegate { return pausedProc; };
+ yield return float.NaN;
+ }
+
+
+
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallDelayed(float delay, System.Action action)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action));
+ }
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallDelayedOnInstance(float delay, System.Action action)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action));
+ }
+
+ private IEnumerator<float> _DelayedCall(float delay, System.Action action)
+ {
+ yield return WaitForSecondsOnInstance(delay);
+
+ action();
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallPeriodically(float timeframe, float period, System.Action action, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, period, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallPeriodicallyOnInstance(float timeframe, float period, System.Action action, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, period, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallPeriodically(float timeframe, float period, System.Action action, Segment timing, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, period, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallPeriodicallyOnInstance(float timeframe, float period, System.Action action, Segment timing, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, period, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallContinuously(float timeframe, System.Action action, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, 0f, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallContinuouslyOnInstance(float timeframe, System.Action action, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, 0f, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallContinuously(float timeframe, System.Action action, Segment timing, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, 0f, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallContinuouslyOnInstance(float timeframe, System.Action action, Segment timing, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, 0f, action, onDone), timing);
+ }
+
+ private IEnumerator<float> _CallContinuously(float timeframe, float period, System.Action action, System.Action onDone)
+ {
+ double startTime = localTime;
+ while (localTime <= startTime + timeframe)
+ {
+ yield return WaitForSecondsOnInstance(period);
+
+ action();
+ }
+
+ if (onDone != null)
+ onDone();
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallPeriodically<T>(T reference, float timeframe, float period,
+ System.Action<T> action, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallPeriodicallyOnInstance<T>(T reference, float timeframe, float period,
+ System.Action<T> action, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallPeriodically<T>(T reference, float timeframe, float period, System.Action<T> action,
+ Segment timing, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallPeriodicallyOnInstance<T>(T reference, float timeframe, float period, System.Action<T> action,
+ Segment timing, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallContinuously<T>(T reference, float timeframe, System.Action<T> action, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallContinuouslyOnInstance<T>(T reference, float timeframe, System.Action<T> action, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallContinuously<T>(T reference, float timeframe, System.Action<T> action,
+ Segment timing, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallContinuouslyOnInstance<T>(T reference, float timeframe, System.Action<T> action,
+ Segment timing, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), timing);
+ }
+
+ private IEnumerator<float> _CallContinuously<T>(T reference, float timeframe, float period,
+ System.Action<T> action, System.Action<T> onDone = null)
+ {
+ double startTime = localTime;
+ while (localTime <= startTime + timeframe)
+ {
+ yield return WaitForSecondsOnInstance(period);
+
+ action(reference);
+ }
+
+ if (onDone != null)
+ onDone(reference);
+ }
+
+ private struct ProcessData : System.IEquatable<ProcessData>
+ {
+ public CoroutineHandle Handle;
+ //public float PauseTime;
+
+ public bool Equals(ProcessData other)
+ {
+ return Handle == other.Handle;
+ }
+
+ public override bool Equals(object other)
+ {
+ if (other is ProcessData)
+ return Equals((ProcessData)other);
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return Handle.GetHashCode();
+ }
+ }
+
+ private struct ProcessIndex : System.IEquatable<ProcessIndex>
+ {
+ public Segment seg;
+ public int i;
+
+ public bool Equals(ProcessIndex other)
+ {
+ return seg == other.seg && i == other.i;
+ }
+
+ public override bool Equals(object other)
+ {
+ if (other is ProcessIndex)
+ return Equals((ProcessIndex)other);
+ return false;
+ }
+
+ public static bool operator ==(ProcessIndex a, ProcessIndex b)
+ {
+ return a.seg == b.seg && a.i == b.i;
+ }
+
+ public static bool operator !=(ProcessIndex a, ProcessIndex b)
+ {
+ return a.seg != b.seg || a.i != b.i;
+ }
+
+ public override int GetHashCode()
+ {
+ return (((int)seg - 4) * (int.MaxValue / 7)) + i;
+ }
+ }
+
+ }
+
+ public enum Segment
+ {
+ Invalid = -1,
+ Update,
+ FixedUpdate,
+ LateUpdate,
+ SlowUpdate,
+ RealtimeUpdate,
+ EditorUpdate,
+ EditorSlowUpdate,
+ EndOfFrame,
+ ManualTimeframe
+ }
+
+ /// <summary>
+ /// A handle for a MEC coroutine.
+ /// </summary>
+ public struct CoroutineHandle : System.IEquatable<CoroutineHandle>
+ {
+ private static int _nextIndex;
+ private readonly int _id;
+
+ public byte Key { get { return (byte)(_id & 0x1F); } }
+
+ public CoroutineHandle(byte ind)
+ {
+ if (ind > 0x1F)
+ ind -= 0x1F;
+
+ _id = _nextIndex + ind;
+ _nextIndex += 0x20;
+ }
+
+ public bool Equals(CoroutineHandle other)
+ {
+ return _id == other._id;
+ }
+
+ public override bool Equals(object other)
+ {
+ if (other is CoroutineHandle)
+ return Equals((CoroutineHandle)other);
+ return false;
+ }
+
+ public static bool operator ==(CoroutineHandle a, CoroutineHandle b)
+ {
+ return a._id == b._id;
+ }
+
+ public static bool operator !=(CoroutineHandle a, CoroutineHandle b)
+ {
+ return a._id != b._id;
+ }
+
+ public override int GetHashCode()
+ {
+ return _id;
+ }
+
+ /// <summary>
+ /// Get or set the corrosponding coroutine's tag. Null removes the tag or represents no tag assigned.
+ /// </summary>
+ public string Tag
+ {
+ get { return Timing.GetTag(this); }
+ set { Timing.SetTag(this, value); }
+ }
+
+ /// <summary>
+ /// Get or set the corrosponding coroutine's layer. Null removes the layer or represents no layer assigned.
+ /// </summary>
+ public int? Layer
+ {
+ get { return Timing.GetLayer(this); }
+ set
+ {
+ if (value == null)
+ Timing.RemoveLayer(this);
+ else
+ Timing.SetLayer(this, (int)value);
+ }
+ }
+
+ /// <summary>
+ /// Get or set the coorsponding coroutine's segment.
+ /// </summary>
+ public Segment Segment
+ {
+ get { return Timing.GetSegment(this); }
+ set { Timing.SetSegment(this, value); }
+ }
+
+ /// <summary>
+ /// Is true until the coroutine function ends or is killed. Setting this to false will kill the coroutine.
+ /// </summary>
+ public bool IsRunning
+ {
+ get { return Timing.IsRunning(this); }
+ set { if (!value) Timing.KillCoroutines(this); }
+ }
+
+ /// <summary>
+ /// Is true while the coroutine is paused (but not in a WaitUntilDone holding pattern). Setting this will pause and resume the coroutine.
+ /// </summary>
+ public bool IsPaused
+ {
+ get { return Timing.IsPaused(this); }
+ set { if (value) Timing.PauseCoroutines(this); else Timing.ResumeCoroutines(this); }
+ }
+ }
+}
+
+public static class MECExtensionMethods
+{
+ /// <summary>
+ /// Adds a delay to the beginning of this coroutine.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="timeToDelay">The number of seconds to delay this coroutine.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Delay(this IEnumerator<float> coroutine, float timeToDelay)
+ {
+ yield return MovementEffects.Timing.WaitForSeconds(timeToDelay);
+
+ while (coroutine.MoveNext())
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Adds a delay to the beginning of this coroutine until a function returns true.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="condition">The coroutine will be paused until this function returns true.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Delay(this IEnumerator<float> coroutine, System.Func<bool> condition)
+ {
+ while (!condition())
+ yield return 0f;
+
+ while (coroutine.MoveNext())
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Adds a delay to the beginning of this coroutine until a function returns true.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="data">A variable that will be passed into the condition function each time it is tested.</param>
+ /// <param name="condition">The coroutine will be paused until this function returns true.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Delay<T>(this IEnumerator<float> coroutine, T data, System.Func<T, bool> condition)
+ {
+ while (!condition(data))
+ yield return 0f;
+
+ while (coroutine.MoveNext())
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Cancels this coroutine when the supplied game object is destroyed or made inactive.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="gameObject">The GameObject to test.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, GameObject gameObject)
+ {
+ while (gameObject && gameObject.activeInHierarchy && coroutine.MoveNext())
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Cancels this coroutine when the supplied game objects are destroyed or made inactive.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="gameObject1">The first GameObject to test.</param>
+ /// <param name="gameObject2">The second GameObject to test</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, GameObject gameObject1, GameObject gameObject2)
+ {
+ while (gameObject1 && gameObject1.activeInHierarchy && gameObject2 && gameObject2.activeInHierarchy && coroutine.MoveNext())
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Cancels this coroutine when the supplied game objects are destroyed or made inactive.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="gameObject1">The first GameObject to test.</param>
+ /// <param name="gameObject2">The second GameObject to test</param>
+ /// <param name="gameObject3">The third GameObject to test.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine,
+ GameObject gameObject1, GameObject gameObject2, GameObject gameObject3)
+ {
+ while (gameObject1 && gameObject1.activeInHierarchy && gameObject2 && gameObject2.activeInHierarchy &&
+ gameObject3 && gameObject3.activeInHierarchy && coroutine.MoveNext())
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Cancels this coroutine when the supplied function returns false.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="condition">The test function. True for continue, false to stop.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, System.Func<bool> condition)
+ {
+ if (condition == null) yield break;
+
+ while (condition() && coroutine.MoveNext())
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Runs the supplied coroutine immediately after this one.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="nextCoroutine">The coroutine to run next.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Append(this IEnumerator<float> coroutine, IEnumerator<float> nextCoroutine)
+ {
+ while (coroutine.MoveNext())
+ yield return coroutine.Current;
+
+ if (nextCoroutine != null)
+ while (nextCoroutine.MoveNext())
+ yield return nextCoroutine.Current;
+ }
+
+ /// <summary>
+ /// Runs the supplied function immediately after this coroutine finishes.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="onDone">The action to run after this coroutine finishes.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Append(this IEnumerator<float> coroutine, System.Action onDone)
+ {
+ while (coroutine.MoveNext())
+ yield return coroutine.Current;
+
+ if (onDone != null)
+ onDone();
+ }
+
+ /// <summary>
+ /// Runs the supplied coroutine immediately before this one.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="lastCoroutine">The coroutine to run first.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Prepend(this IEnumerator<float> coroutine, IEnumerator<float> lastCoroutine)
+ {
+ if (lastCoroutine != null)
+ while (lastCoroutine.MoveNext())
+ yield return lastCoroutine.Current;
+
+ while (coroutine.MoveNext())
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Runs the supplied function immediately before this coroutine starts.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="onStart">The action to run before this coroutine starts.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Prepend(this IEnumerator<float> coroutine, System.Action onStart)
+ {
+ if (onStart != null)
+ onStart();
+
+ while (coroutine.MoveNext())
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Combines the this coroutine with another and runs them in a combined handle.
+ /// </summary>
+ /// <param name="coroutineA">The coroutine handle to act upon.</param>
+ /// <param name="coroutineB">The coroutine handle to combine.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Superimpose(this IEnumerator<float> coroutineA, IEnumerator<float> coroutineB)
+ {
+ return Superimpose(coroutineA, coroutineB, MovementEffects.Timing.Instance);
+ }
+
+ /// <summary>
+ /// Combines the this coroutine with another and runs them in a combined handle.
+ /// </summary>
+ /// <param name="coroutineA">The coroutine handle to act upon.</param>
+ /// <param name="coroutineB">The coroutine handle to combine.</param>
+ /// <param name="instance">The timing instance that this will be run in, if not the default instance.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Superimpose(this IEnumerator<float> coroutineA, IEnumerator<float> coroutineB, MovementEffects.Timing instance)
+ {
+ while (coroutineA != null || coroutineB != null)
+ {
+ if (coroutineA != null && !(instance.localTime < coroutineA.Current) && !coroutineA.MoveNext())
+ coroutineA = null;
+
+ if (coroutineB != null && !(instance.localTime < coroutineB.Current) && !coroutineB.MoveNext())
+ coroutineB = null;
+
+ if ((coroutineA != null && float.IsNaN(coroutineA.Current)) || (coroutineB != null && float.IsNaN(coroutineB.Current)))
+ yield return float.NaN;
+ else if (coroutineA != null && coroutineB != null)
+ yield return coroutineA.Current < coroutineB.Current ? coroutineA.Current : coroutineB.Current;
+ else if (coroutineA == null && coroutineB != null)
+ yield return coroutineB.Current;
+ else if (coroutineA != null)
+ yield return coroutineA.Current;
+ }
+ }
+
+ /// <summary>
+ /// Uses the passed in function to change the return values of this coroutine.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="newReturn">A function that takes the current return value and returns the new return.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> Hijack(this IEnumerator<float> coroutine, System.Func<float, float> newReturn)
+ {
+ if (newReturn == null) yield break;
+
+ while (coroutine.MoveNext())
+ yield return newReturn(coroutine.Current);
+ }
+}
+
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Timing.cs.meta
index 21e6c1b..21e6c1b 100644
--- a/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs.meta
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Trinary Software/Timing.cs.meta
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs b/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs
new file mode 100644
index 0000000..3005b27
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs
@@ -0,0 +1,128 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK
+{
+
+ public class UnityObjectPool<T> : System.IDisposable where T : UnityEngine.Object
+ {
+ public interface IPooledInstanceInitializer
+ {
+ void InitPooledInstance(T instance);
+ void DestroyPooledInstance(T instance);
+ }
+
+ private T _sourceObject;
+ private Transform _poolParent;
+ private int _initialSize;
+
+ private IPooledInstanceInitializer _initalizer;
+
+ private List<T> _usedInstances;
+ private Stack<T> _freeInstances;
+
+ public UnityObjectPool(T sourceObject, Transform poolParent, IPooledInstanceInitializer initializer, int initialSize = 0)
+ {
+ Debug.Assert(sourceObject != null);
+ Debug.Assert(poolParent != null);
+ Debug.Assert(initializer != null);
+ Debug.Assert(initialSize >= 0);
+
+ _sourceObject = sourceObject;
+ _poolParent = poolParent;
+ _initalizer = initializer;
+ _initialSize = initialSize;
+
+ _usedInstances = new List<T>();
+ _freeInstances = new Stack<T>(initialSize);
+
+ for (int i = 0; i < _initialSize; ++i)
+ {
+ T instance = CreateInstance();
+ _freeInstances.Push(instance);
+ }
+ }
+
+ public T Acquire()
+ {
+ T instance;
+ if (_freeInstances.Count > 0)
+ {
+ instance = _freeInstances.Pop();
+ }
+ else
+ {
+ instance = CreateInstance();
+ }
+
+ _usedInstances.Add(instance);
+
+ return instance;
+ }
+
+ public void Release(T instance)
+ {
+ Debug.Assert(instance != null);
+ Debug.Assert(!_freeInstances.Contains(instance));
+
+ bool res = _usedInstances.Remove(instance);
+ Debug.Assert(res);
+ _freeInstances.Push(instance);
+ }
+
+ private T CreateInstance()
+ {
+ T instance = Object.Instantiate(_sourceObject, _poolParent);
+
+ // Let the client code initialize the object however it want to
+ _initalizer.InitPooledInstance(instance);
+
+ return instance;
+ }
+
+ #region IDisposable Support
+ private bool _disposed = false;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (Application.isPlaying)
+ {
+ Debug.Assert(!_disposed, "Trying to dispose an pool twice!");
+ Debug.Assert(_usedInstances.Count == 0, "Disposing pool before releasing all objects!");
+ }
+
+ foreach (T instance in _freeInstances)
+ {
+ // We can't destroy a UnityEngine.Object without knowing if it's a Gameobject or Component. Calling Destroy(instance) directly here will give not destroy the Gameobject if it's a component
+ _initalizer.DestroyPooledInstance(instance);
+ }
+ _freeInstances.Clear();
+
+ _sourceObject = null;
+ _poolParent = null;
+ _initalizer = null;
+
+ _disposed = true;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ System.GC.SuppressFinalize(this);
+ }
+
+#if ENABLE_ASSERTS
+ ~UnityObjectPool()
+ {
+ MainThreadDispatcher.BeginInvoke(() => // Can't call Application.isPlaying in Unity's finalizer thread
+ {
+ if (Application.isPlaying)
+ {
+ DebugTools.Assert(false, string.Format("Failed to dispose a pool of type {0}!", typeof(T)));
+ }
+ });
+ }
+#endif
+ #endregion
+ }
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs.meta
new file mode 100644
index 0000000..b5da7d0
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9d3e19936e347184b9b193d4a0688a73
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/UI/PanelBase.cs b/WorldlineKeepers/Assets/Scripts/UI/PanelBase.cs
new file mode 100644
index 0000000..f0b25f7
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/UI/PanelBase.cs
@@ -0,0 +1,16 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK
+{
+
+ /// <summary>
+ ///
+ /// </summary>
+ public class PanelBase : MonoBehaviour
+ {
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/UI/PanelBase.cs.meta b/WorldlineKeepers/Assets/Scripts/UI/PanelBase.cs.meta
new file mode 100644
index 0000000..fbb8228
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/UI/PanelBase.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f1b7648b8de812a4b8c1fd40a9747c64
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Utils/LogHelper.cs b/WorldlineKeepers/Assets/Scripts/Utils/LogHelper.cs
index 5ffed1e..e019695 100644
--- a/WorldlineKeepers/Assets/Scripts/Utils/LogHelper.cs
+++ b/WorldlineKeepers/Assets/Scripts/Utils/LogHelper.cs
@@ -6,10 +6,18 @@ using UnityEngine;
namespace WK
{
- public class LogHelper
+ public static class LogHelper
{
+ public static void LogError(object msg)
+ {
+ Debug.LogError(msg);
+ }
+ public static void Log(object msg)
+ {
+ Debug.Log(msg);
+ }
}
diff --git a/WorldlineKeepers/Assets/Scripts/Utils/TransformUtils.cs b/WorldlineKeepers/Assets/Scripts/Utils/TransformUtils.cs
new file mode 100644
index 0000000..dcfb8c9
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Utils/TransformUtils.cs
@@ -0,0 +1,18 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK
+{
+
+ public static class TransformUtils
+ {
+ public static void ResetLocal(this Transform transform)
+ {
+ transform.localPosition = Vector3.zero;
+ transform.localRotation = Quaternion.identity;
+ transform.localScale = Vector3.one;
+ }
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Utils/TransformUtils.cs.meta b/WorldlineKeepers/Assets/Scripts/Utils/TransformUtils.cs.meta
new file mode 100644
index 0000000..ef5cea8
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Utils/TransformUtils.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 644de0d155567684eb770eafd8e91ac4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/ProjectSettings/EditorBuildSettings.asset b/WorldlineKeepers/ProjectSettings/EditorBuildSettings.asset
index 263d68c..ad91e94 100644
--- a/WorldlineKeepers/ProjectSettings/EditorBuildSettings.asset
+++ b/WorldlineKeepers/ProjectSettings/EditorBuildSettings.asset
@@ -6,6 +6,18 @@ EditorBuildSettings:
serializedVersion: 2
m_Scenes:
- enabled: 1
- path: Assets/Scenes/Test.unity
+ path: Assets/Scenes/0_Test.unity
guid: 6091fb2bc6977fe4da28c51e3e925b9e
+ - enabled: 1
+ path: Assets/Scenes/1_Entry.unity
+ guid: 112e175ba5ba1114ebabf31b55e3bdd5
+ - enabled: 1
+ path: Assets/Scenes/2_Lobby.unity
+ guid: ecdcfd6e9a5201c48b99a4fa4d0f9fd8
+ - enabled: 1
+ path: Assets/Scenes/3_Dojo.unity
+ guid: 43d444c8630a4cf43a5d69b05d63e08e
+ - enabled: 1
+ path: Assets/Scenes/4_Stage.unity
+ guid: ccc90f7a55ca31e4a820bc889ba35fec
m_configObjects: {}