diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/Progress.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/Progress.cs index ed11290..854941d 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/Progress.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/Progress.cs @@ -15,6 +15,12 @@ namespace Cysharp.Threading.Tasks return new AnonymousProgress(handler); } + public static IProgress Create(TState state, Action handler) + { + if (handler == null) return NullProgress.Instance; + return new AnonymousProgress(handler, state); + } + public static IProgress CreateOnlyValueChanged(Action handler, IEqualityComparer comparer = null) { if (handler == null) return NullProgress.Instance; @@ -25,6 +31,16 @@ namespace Cysharp.Threading.Tasks #endif } + public static IProgress CreateOnlyValueChanged(TState state, Action handler, IEqualityComparer comparer = null) + { + if (handler == null) return NullProgress.Instance; +#if UNITY_2018_3_OR_NEWER + return new OnlyValueChangedProgress(handler, state, comparer ?? UnityEqualityComparer.GetDefault()); +#else + return new OnlyValueChangedProgress(handler, state, comparer ?? EqualityComparer.Default); +#endif + } + sealed class NullProgress : IProgress { public static readonly IProgress Instance = new NullProgress(); @@ -54,6 +70,23 @@ namespace Cysharp.Threading.Tasks } } + sealed class AnonymousProgress : IProgress + { + readonly Action action; + readonly TState state; + + public AnonymousProgress(Action action, TState state) + { + this.action = action; + this.state = state; + } + + public void Report(T value) + { + action(value, state); + } + } + sealed class OnlyValueChangedProgress : IProgress { readonly Action action; @@ -83,5 +116,37 @@ namespace Cysharp.Threading.Tasks action(value); } } + + sealed class OnlyValueChangedProgress : IProgress + { + readonly Action action; + readonly TState state; + readonly IEqualityComparer comparer; + bool isFirstCall; + T latestValue; + + public OnlyValueChangedProgress(Action action, TState state, IEqualityComparer comparer) + { + this.action = action; + this.state = state; + this.comparer = comparer; + this.isFirstCall = true; + } + + public void Report(T value) + { + if (isFirstCall) + { + isFirstCall = false; + } + else if (comparer.Equals(value, latestValue)) + { + return; + } + + latestValue = value; + action(value, state); + } + } } } \ No newline at end of file