public RadicalCoroutine StartRadicalCoroutine(System.Collections.IEnumerator routine, RadicalCoroutineDisableMode disableMode = RadicalCoroutineDisableMode.Default)
        {
            if (routine == null) throw new System.ArgumentNullException("routine");

            var co = new RadicalCoroutine(routine);
            co.Start(this, disableMode);
            return co;
        }
        internal void RegisterCoroutine(MonoBehaviour component, RadicalCoroutine routine)
        {
            if (_routines.Contains(routine)) return;

            if (!(component is SPComponent) && routine.DisableMode.HasFlag(RadicalCoroutineDisableMode.StopOnDisable)) Debug.LogWarning("A RadicalCoroutine started by a component that doesn't inherit from SPComponent can not pause the coroutine 'OnDisable'.", component);

            if(component is SPComponent && !_routines.ContainsKey(component))
            {
                (component as SPComponent).OnEnabled -= this.OnComponentEnabled;
                (component as SPComponent).OnDisabled -= this.OnComponentDisabled;
                (component as SPComponent).OnEnabled += this.OnComponentEnabled;
                (component as SPComponent).OnDisabled += this.OnComponentDisabled;
            }

            routine.OnFinished -= this.OnRoutineFinished;
            routine.OnFinished += this.OnRoutineFinished;
            _routines.Add(component, routine);
        }
        private static IEnumerator WaitUntilDone_Routine(RadicalCoroutine routine)
        {
            if (routine._owner != null)
            {
                routine._owner.AddOrGetComponent<RadicalCoroutineManager>().RegisterCoroutine(routine._owner, routine);
            }

            while (!routine.Finished)
            {
                yield return null;
            }
        }
        public RadicalCoroutine Schedule(MonoBehaviour behaviour, CoroutineMethod routine, RadicalCoroutineDisableMode disableMode = RadicalCoroutineDisableMode.Default)
        {
            if (behaviour == null) throw new System.ArgumentNullException("behaviour");
            if (routine == null) throw new System.ArgumentNullException("routine");

            var co = new RadicalCoroutine(routine().GetEnumerator());
            this.OnComplete += (s, e) =>
            {
                if (co._state == RadicalCoroutineOperatingState.Inactive) co.Start(behaviour, disableMode);
            };
            return co;
        }
        public void Schedule(MonoBehaviour behaviour, RadicalCoroutine routine, RadicalCoroutineDisableMode disableMode = RadicalCoroutineDisableMode.Default)
        {
            if (behaviour == null) throw new System.ArgumentNullException("behaviour");
            if (routine == null) throw new System.ArgumentNullException("routine");

            this.OnComplete += (s, e) =>
            {
                if (routine._state == RadicalCoroutineOperatingState.Inactive) routine.Start(behaviour, disableMode);
            };
        }
        public RadicalCoroutine StartRadicalCoroutine(CoroutineMethod routine, RadicalCoroutineDisableMode disableMode = RadicalCoroutineDisableMode.Default)
        {
            if (routine == null) throw new System.ArgumentNullException("routine");

            var co = new RadicalCoroutine(routine().GetEnumerator());
            co.Start(this, disableMode);
            return co;
        }
        /// <summary>
        /// Returns a YieldInstruction that can be used to have a standard Unity Coroutine wait for a RadicalCoroutine to complete.
        /// </summary>
        /// <param name="behaviour"></param>
        /// <param name="routine"></param>
        /// <returns></returns>
        public static YieldInstruction WaitUntilDone(MonoBehaviour behaviour, RadicalCoroutine routine)
        {
            if (behaviour == null) throw new System.ArgumentNullException("behaviour");
            if (routine == null) throw new System.ArgumentNullException("routine");

            if (routine._token != null) return routine._token;

            if (routine.Finished) return null;
            return behaviour.StartCoroutine(WaitUntilDone_Routine(routine));
        }
 void System.IDisposable.Dispose()
 {
     _owner = null;
     _handle = null;
     _yieldObject = null;
     _enumCurrentValue = null;
 }
        /// <summary>
        /// Must be only called by RadicalCoroutine itself.
        /// </summary>
        /// <param name="routine"></param>
        internal void UnregisterCoroutine(RadicalCoroutine routine)
        {
            _routines.Remove(routine);

            if(_naiveTrackerTable != null)
            {
                var comp = routine.Operator;
                if(_naiveTrackerTable.ContainsKey(comp) && !this.GetComponentIsCurrentlyManaged(comp))
                {
                    _naiveTrackerTable.Remove(comp);
                }
            }
        }
            public static string GetDerivativeID(RadicalCoroutine routine)
            {
                if (routine._stack.Count <= 1) return "";

                return GetIterableID(routine._stack.Peek());
            }
 public static string GetYieldID(RadicalCoroutine routine)
 {
     if (routine._currentIEnumeratorYieldValue is WaitForSeconds)
     {
         float dur = ConvertUtil.ToSingle(ObjUtil.GetValue(routine._currentIEnumeratorYieldValue, "m_Seconds"));
         return string.Format("WaitForSeconds[{0:0.00}]", dur);
     }
     else if (routine._currentIEnumeratorYieldValue is YieldInstruction)
     {
         return routine._currentIEnumeratorYieldValue.GetType().Name;
     }
     else if (routine._currentIEnumeratorYieldValue is WWW)
     {
         return string.Format("WWW[{0}%]", (routine._currentIEnumeratorYieldValue as WWW).progress * 100);
     }
     else
     {
         return "WaitOneFrame";
     }
 }
        internal void RegisterCoroutine(SPComponent component, RadicalCoroutine routine)
        {
            if (_routines.Contains(routine)) return;

            if(!_routines.ContainsKey(component))
            {
                component.OnEnabled -= this.OnComponentEnabled;
                component.OnDisabled -= this.OnComponentDisabled;
                component.ComponentDestroyed -= this.OnComponentDestroyed;
                component.OnEnabled += this.OnComponentEnabled;
                component.OnDisabled += this.OnComponentDisabled;
                component.ComponentDestroyed += this.OnComponentDestroyed;
            }

            routine.OnFinished -= this.OnRoutineFinished;
            routine.OnFinished += this.OnRoutineFinished;
            _routines.Add(component, routine);
        }
 public ManagedCoroutineInfo(MonoBehaviour c, RadicalCoroutine r)
 {
     this.Component = c;
     this.Routine = r;
 }
        private static IEnumerator WaitUntilDone_Routine(RadicalCoroutine routine)
        {
            //if (routine._owner != null && routine._owner is SPComponent)
            //{
            //    routine._owner.AddOrGetComponent<RadicalCoroutineManager>().RegisterCoroutine(routine._owner as SPComponent, routine);
            //}

            while (!routine.Finished)
            {
                yield return null;
            }
        }
            public static string GetDerivativeID(RadicalCoroutine routine)
            {
                if (routine.OperationStack.Count <= 1) return "";

                return GetIterableID(routine.OperationStack.CurrentOperation);
            }
 public static string GetYieldID(RadicalCoroutine routine)
 {
     if (routine._currentIEnumeratorYieldValue is WaitForSeconds)
     {
         //float dur = ConvertUtil.ToSingle(DynamicUtil.GetValue(routine._currentIEnumeratorYieldValue, "m_Seconds"));
         var field = typeof(WaitForSeconds).GetField("m_Seconds", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
         float dur = (float)field.GetValue(routine._currentIEnumeratorYieldValue);
         return string.Format("WaitForSeconds[{0:0.00}]", dur);
     }
     else if (routine._currentIEnumeratorYieldValue is YieldInstruction)
     {
         return routine._currentIEnumeratorYieldValue.GetType().Name;
     }
     else if (routine._currentIEnumeratorYieldValue is WWW)
     {
         return string.Format("WWW[{0}%]", (routine._currentIEnumeratorYieldValue as WWW).progress * 100);
     }
     else
     {
         return "WaitOneFrame";
     }
 }
 public static string GetInternalRoutineID(RadicalCoroutine routine)
 {
     if (routine.OperationStack.Count == 0) return "";
     var r = routine.OperationStack.Last(); //the bottom of the stack is the actual routine
     if (r is IRadicalYieldInstruction)
     {
         return GetIterableID(r as IRadicalYieldInstruction);
     }
     else
     {
         return r.GetType().FullName.Split('.').Last();
     }
 }
 internal RadicalOperationStack(RadicalCoroutine owner)
 {
     _owner = owner;
 }
 public static string GetInternalRoutineID(RadicalCoroutine routine)
 {
     if (routine._stack.Count == 0) return "";
     var r = routine._stack.Last(); //the bottom of the stack is the actual routine
     if (r is IRadicalYieldInstruction)
     {
         if (r is WaitForDuration)
         {
             var wait = r as WaitForDuration;
             return string.Format("WaitForDuration[{0:0.00}, {1:0.00}]", wait.CurrentTime, wait.Duration);
         }
         else
         {
             return r.GetType().Name;
         }
     }
     else
     {
         return r.GetType().FullName.Split('.').Last();
     }
 }
        /// <summary>
        /// Must be only called by RadicalCoroutine itself.
        /// </summary>
        /// <param name="component"></param>
        /// <param name="routine"></param>
        internal void RegisterCoroutine(RadicalCoroutine routine)
        {
            if (routine == null) throw new System.ArgumentNullException("routine");

            //if (_routines.Contains(routine)) throw new System.InvalidOperationException("Attempted to register a routine that is already operating.");
            if (_routines.Contains(routine)) return;

            var component = routine.Operator;
            if (component == null) throw new System.InvalidOperationException("Attempted to register a routine with a null component.");

            if (component is SPComponent)
            {
                var spc = component as SPComponent;
                spc.OnDisabled -= _onDisableHandler;
                spc.OnEnabled -= _onEnabledHandler;
                spc.ComponentDestroyed -= _onDestroyHandler;
                spc.OnDisabled += _onDisableHandler;
                spc.OnEnabled += _onEnabledHandler;
                spc.ComponentDestroyed += _onDestroyHandler;

                _routines.Add(routine);
            }
            else
            {
                if (_naiveTrackerTable == null) _naiveTrackerTable = new Dictionary<MonoBehaviour, bool>();
                _naiveTrackerTable[component] = component.isActiveAndEnabled;
                _routines.Add(routine);
                if (!this.enabled) this.enabled = true;
            }

        }
 public ManualWaitForGeneric(RadicalCoroutine owner, MonoBehaviour handle, object yieldObj)
 {
     _owner = owner;
     _handle = handle;
     _yieldObject = yieldObj;
 }
 public static ManualWaitForGeneric Create(RadicalCoroutine owner, MonoBehaviour handle, object yieldObj)
 {
     var w = _pool.GetInstance();
     w._owner = owner;
     w._handle = handle;
     w._yieldObject = yieldObj;
     return w;
 }