// marker for CatchIgnore and Catch avoid iOS AOT problem. public static IObservable <TSource> CatchIgnore <TSource>(Exception ex) { return(Observable.Empty <TSource>()); }
/// <summary> /// Publish target property when value is changed. If source is destroyed/destructed, publish OnCompleted. /// </summary> public static IObservable <TProperty> ObserveEveryValueChanged <TSource, TProperty>(this TSource source, Func <TSource, TProperty> propertySelector, FrameCountType frameCountType, IEqualityComparer <TProperty> comparer) where TSource : class { if (source == null) { return(Observable.Empty <TProperty>()); } if (comparer == null) { comparer = UnityEqualityComparer.GetDefault <TProperty>(); } var unityObject = source as UnityEngine.Object; var isUnityObject = source is UnityEngine.Object; if (isUnityObject && unityObject == null) { return(Observable.Empty <TProperty>()); } // MicroCoroutine does not publish value immediately, so publish value on subscribe. if (isUnityObject) { return(ObservableUnity.FromMicroCoroutine <TProperty>((observer, cancellationToken) => { if (unityObject != null) { var firstValue = default(TProperty); try { firstValue = propertySelector((TSource)(object)unityObject); } catch (Exception ex) { observer.OnError(ex); return EmptyEnumerator(); } observer.OnNext(firstValue); return PublishUnityObjectValueChanged(unityObject, firstValue, propertySelector, comparer, observer, cancellationToken); } else { observer.OnCompleted(); return EmptyEnumerator(); } }, frameCountType)); } else { var reference = new WeakReference(source); source = null; return(ObservableUnity.FromMicroCoroutine <TProperty>((observer, cancellationToken) => { var target = reference.Target; if (target != null) { var firstValue = default(TProperty); try { firstValue = propertySelector((TSource)target); } catch (Exception ex) { observer.OnError(ex); return EmptyEnumerator(); } finally { target = null; } observer.OnNext(firstValue); return PublishPocoValueChanged(reference, firstValue, propertySelector, comparer, observer, cancellationToken); } else { observer.OnCompleted(); return EmptyEnumerator(); } }, frameCountType)); } }
private static IObservable <T> Tween <T>(Func <OperatableBase <T> > start, Func <OperatableBase <T> > finish, Func <float> duration, EaseType easeType, LoopType loopType, Action onCompleteTween) where T : struct { T startValue = default(T); T finishValue = default(T); onCompleteTween = onCompleteTween ?? (() => { }); Func <IObserver <T>, IDisposable> returnStartValue = (observer) => { observer.OnNext(startValue); return(null); }; Func <IObserver <T>, IDisposable> returnFinishValue = (observer) => { observer.OnNext(finishValue); return(null); }; IObservable <T> stream = Observable.Empty <TweenInformation <T> >() // Repeat() のために、毎回初期値を生成 .StartWith(() => new TweenInformation <T>(Time.time, start(), finish(), duration(), easeType, out startValue, out finishValue)) // Update のストリームに変換 .SelectMany(information => Observable.EveryUpdate().Do(_ => information.Time = Time.time - information.StartTime).Select(_ => information)) // Tween 時間が処理時間よりも小さい間流し続ける .TakeWhile(information => information.Time <= information.Duration) // 実際の Easing 処理実行 .Select(information => Easing(information.Time, information.Start, (information.Finish - information.Start), information.Duration, information.EaseType).Value) // 最終フレームの値を確実に流すために OnCompleted が来たら値を一つ流すストリームに繋ぐ // 1回分の Tween が終わったらコールバックを呼ぶ .Concat(Observable.Create(returnFinishValue).Take(1).Do(_ => onCompleteTween())); switch (loopType) { case LoopType.None: // Do nothing. break; case LoopType.Repeat: stream = stream.Repeat(); break; case LoopType.PingPong: stream = stream .Concat( Observable.Empty <TweenInformation <T> >() // Repeat() のために、毎回初期値を生成 .StartWith(() => new TweenInformation <T>(Time.time, start(), finish(), duration(), easeType, out startValue, out finishValue)) // Update のストリームに変換 .SelectMany(information => Observable.EveryUpdate().Do(_ => information.Time = Time.time - information.StartTime).Select(_ => information)) // Tween 時間が処理時間よりも小さい間流し続ける .TakeWhile(information => information.Time <= information.Duration) // start と finish を入れ替えて、実際の Easing 処理実行 .Select(information => Easing(information.Time, information.Finish, (information.Start - information.Finish), information.Duration, information.EaseType).Value) // 最終フレームの値を確実に流すために OnCompleted が来たら最終値を一つ流すストリームに繋ぐ // 1回分の Tween が終わったらコールバックを呼ぶ .Concat(Observable.Create(returnStartValue).Take(1).Do(_ => onCompleteTween())) ) .Repeat(); break; case LoopType.Mirror: stream = stream .Concat( Observable.Empty <TweenInformation <T> >() // Repeat() のために、毎回初期値を生成 .StartWith(() => new TweenInformation <T>(Time.time, start(), finish(), duration(), easeType, out startValue, out finishValue)) // Update のストリームに変換 .SelectMany(information => Observable.EveryUpdate().Do(_ => information.Time = Time.time - information.StartTime).Select(_ => information)) // Tween 時間が処理時間よりも小さい間流し続ける .TakeWhile(information => information.Time <= information.Duration) // start と finish を入れ替えて、実際の Easing 処理実行 .Select(information => Easing(information.Time, information.Finish, (information.Start - information.Finish), information.Duration, MirrorEaseTypeMap[information.EaseType]).Value) // 最終フレームの値を確実に流すために OnCompleted が来たら最終値を一つ流すストリームに繋ぐ // 1回分の Tween が終わったらコールバックを呼ぶ .Concat(Observable.Create(returnStartValue).Take(1).Do(_ => onCompleteTween())) ) .Repeat(); break; } return(stream); }
public static UniRx.IObservable <TProperty> ObserveEveryValueChanged <TSource, TProperty>(this TSource source, Func <TSource, TProperty> propertySelector, FrameCountType frameCountType, IEqualityComparer <TProperty> comparer, bool fastDestroyCheck) where TSource : class { if (source == null) { return(Observable.Empty <TProperty>()); } if (comparer == null) { comparer = UnityEqualityComparer.GetDefault <TProperty>(); } UnityEngine.Object unityObject = source as UnityEngine.Object; bool flag = source is UnityEngine.Object; if (flag && unityObject == null) { return(Observable.Empty <TProperty>()); } if (flag) { return(Observable.FromMicroCoroutine(delegate(UniRx.IObserver <TProperty> observer, CancellationToken cancellationToken) { if (unityObject != null) { TProperty val2 = default(TProperty); try { val2 = propertySelector((TSource)(object)unityObject); } catch (Exception error2) { observer.OnError(error2); return EmptyEnumerator(); } observer.OnNext(val2); return PublishUnityObjectValueChanged(unityObject, val2, propertySelector, comparer, observer, cancellationToken, fastDestroyCheck); } observer.OnCompleted(); return EmptyEnumerator(); }, frameCountType)); } WeakReference reference = new WeakReference(source); source = (TSource)null; return(Observable.FromMicroCoroutine(delegate(UniRx.IObserver <TProperty> observer, CancellationToken cancellationToken) { object target = reference.Target; if (target != null) { TProperty val = default(TProperty); try { val = propertySelector((TSource)target); } catch (Exception error) { observer.OnError(error); return EmptyEnumerator(); } finally { target = null; } observer.OnNext(val); return PublishPocoValueChanged(reference, val, propertySelector, comparer, observer, cancellationToken); } observer.OnCompleted(); return EmptyEnumerator(); }, frameCountType)); }
/// <summary>Catch exception and return Observable.Empty.</summary> public static IObservable <TSource> CatchIgnore <TSource>(this IObservable <TSource> source) { var result = source.Catch <TSource, Exception>(ex => Observable.Empty <TSource>()); return(result); }