diff --git a/playground-unity/Assets/PoolAndBinding/PoolAndBinding.cs b/playground-unity/Assets/PoolAndBinding/PoolAndBinding.cs index e4c0165..a9bc6d4 100644 --- a/playground-unity/Assets/PoolAndBinding/PoolAndBinding.cs +++ b/playground-unity/Assets/PoolAndBinding/PoolAndBinding.cs @@ -26,10 +26,10 @@ void Awake() items = new List(); } - void Start() - { - var globalInt = Observable.State(1); - var nextId = 1; + void Start() + { + var globalInt = Observable.State(1); + var nextId = 1; addButton.onClick.AddListener(() => { @@ -55,5 +55,5 @@ void Start() }); increaseButton.onClick.AddListener(() => globalInt.Value++); - } + } } diff --git a/playground-unity/Assets/PoolAndBinding/PoolAndBinding_Item.cs b/playground-unity/Assets/PoolAndBinding/PoolAndBinding_Item.cs index 45be7e8..361660b 100644 --- a/playground-unity/Assets/PoolAndBinding/PoolAndBinding_Item.cs +++ b/playground-unity/Assets/PoolAndBinding/PoolAndBinding_Item.cs @@ -6,26 +6,26 @@ public class PoolAndBinding_Item : MonoBehaviour { [SerializeField] TMP_Text label; - public void Init(Observable model) - { - gameObject.RunOnActive(() => - { - return model.Bind(text => - { - Debug.Log($"Setting label for {gameObject.name} to: {text}", gameObject); - label.text = text; - }); - }); - } + public void Init(Observable model) + { + gameObject.RunOnActive(() => + { + return model.Bind(text => + { + Debug.Log($"Setting label for {gameObject.name} to: {text}", gameObject); + label.text = text; + }); + }); + } - public void OnPoolGet() - { - gameObject.SetActive(true); - } + public void OnPoolGet() + { + gameObject.SetActive(true); + } - public void OnPoolRelease() - { - gameObject.ClearOnActiveRuns(); - gameObject.SetActive(false); - } + public void OnPoolRelease() + { + gameObject.ClearOnActiveRuns(); + gameObject.SetActive(false); + } } diff --git a/playground-unity/Assets/Scripts/PaginationView.cs b/playground-unity/Assets/Scripts/PaginationView.cs index 4e7303e..6cdc729 100644 --- a/playground-unity/Assets/Scripts/PaginationView.cs +++ b/playground-unity/Assets/Scripts/PaginationView.cs @@ -11,7 +11,7 @@ public class PaginationView : MonoBehaviour [SerializeField] Button nextButton; public void Init(PaginationModel model) - { + { var pageIndicatorText = Observable.Auto(() => (model.CurrentPageIndex.Value + 1) + " / " + model.NumPages.Value); gameObject.DisposeOnDestroy(pageIndicatorText.Bind(text => label.text = text)); diff --git a/playground-unity/Assets/Scripts/SampleItem.cs b/playground-unity/Assets/Scripts/SampleItem.cs index 926f552..32fa618 100644 --- a/playground-unity/Assets/Scripts/SampleItem.cs +++ b/playground-unity/Assets/Scripts/SampleItem.cs @@ -6,7 +6,7 @@ public class SampleItem : MonoBehaviour [SerializeField] TMP_Text text; public void Init(string data) - { + { text.text = data; - } + } } diff --git a/playground/Playground.cs b/playground/Playground.cs index 61cb373..497a760 100644 --- a/playground/Playground.cs +++ b/playground/Playground.cs @@ -5,31 +5,31 @@ class Playground { - static async Task Main() - { - var stateA = Observable.State("hello"); - var stateB = Observable.State("world"); + static async Task Main() + { + var stateA = Observable.State("hello"); + var stateB = Observable.State("world"); - var o = Observable.Auto(async () => - { - Console.WriteLine("computing"); - var a = stateA.Value; - await Task.Delay(1000); - var b = stateB.Value; - return a + " " + b; - }); + var o = Observable.Auto(async () => + { + Console.WriteLine("computing"); + var a = stateA.Value; + await Task.Delay(1000); + var b = stateB.Value; + return a + " " + b; + }); - o.Bind(result => Console.WriteLine(result.Status switch - { - AsyncComputeStatus.Loading => "Loading...", - AsyncComputeStatus.Done => "Done: " + result.Result, - AsyncComputeStatus.Failed => "Failed: " + result.Exception, - })); + o.Bind(result => Console.WriteLine(result.Status switch + { + AsyncComputeStatus.Loading => "Loading...", + AsyncComputeStatus.Done => "Done: " + result.Result, + AsyncComputeStatus.Failed => "Failed: " + result.Exception, + })); - await Task.Delay(1500); + await Task.Delay(1500); - stateB.Value = "Dan"; + stateB.Value = "Dan"; - Process.GetCurrentProcess().WaitForExit(); - } + Process.GetCurrentProcess().WaitForExit(); + } } diff --git a/src/TinkState-Unity/Runtime/UnityBatchScheduler.cs b/src/TinkState-Unity/Runtime/UnityBatchScheduler.cs index a3009fe..f5d654a 100644 --- a/src/TinkState-Unity/Runtime/UnityBatchScheduler.cs +++ b/src/TinkState-Unity/Runtime/UnityBatchScheduler.cs @@ -9,100 +9,100 @@ namespace TinkState { - public class UnityBatchScheduler : Scheduler - { - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] - static void Init() - { - Observable.Scheduler = Instance; - PlayerLoopHelper.ModifyPlayerLoop(typeof(PostLateUpdate), typeof(UnityBatchScheduler), OnUpdate); - } + public class UnityBatchScheduler : Scheduler + { + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void Init() + { + Observable.Scheduler = Instance; + PlayerLoopHelper.ModifyPlayerLoop(typeof(PostLateUpdate), typeof(UnityBatchScheduler), OnUpdate); + } - static void OnUpdate() - { - var scheduler = Instance; - if (scheduler.scheduled) - { - scheduler.Progress(0.1f); - } - } + static void OnUpdate() + { + var scheduler = Instance; + if (scheduler.scheduled) + { + scheduler.Progress(0.1f); + } + } - static readonly UnityBatchScheduler Instance = new UnityBatchScheduler(); + static readonly UnityBatchScheduler Instance = new UnityBatchScheduler(); - List queue = new List(); - List nextQueue = new List(); - bool scheduled; + List queue = new List(); + List nextQueue = new List(); + bool scheduled; - UnityBatchScheduler() { } + UnityBatchScheduler() { } - public void Schedule(Schedulable schedulable) - { - queue.Add(schedulable); - scheduled = true; - } + public void Schedule(Schedulable schedulable) + { + queue.Add(schedulable); + scheduled = true; + } - void Progress(float maxSeconds) - { - var end = GetTimeStamp() + maxSeconds; - do - { - // to handle the unfortunate case where a binding invocation schedules another one - // we have two queues and swap between them to avoid allocating a new list every time - var currentQueue = queue; - queue = nextQueue; - foreach (var o in currentQueue) o.Run(); - currentQueue.Clear(); - nextQueue = currentQueue; - } - while (queue.Count > 0 && GetTimeStamp() < end); + void Progress(float maxSeconds) + { + var end = GetTimeStamp() + maxSeconds; + do + { + // to handle the unfortunate case where a binding invocation schedules another one + // we have two queues and swap between them to avoid allocating a new list every time + var currentQueue = queue; + queue = nextQueue; + foreach (var o in currentQueue) o.Run(); + currentQueue.Clear(); + nextQueue = currentQueue; + } + while (queue.Count > 0 && GetTimeStamp() < end); - if (queue.Count == 0) - { - scheduled = false; - } - } + if (queue.Count == 0) + { + scheduled = false; + } + } - float GetTimeStamp() - { - return Time.realtimeSinceStartup; - } - } + float GetTimeStamp() + { + return Time.realtimeSinceStartup; + } + } - static class PlayerLoopHelper - { - public static void ModifyPlayerLoop(Type where, Type what, PlayerLoopSystem.UpdateFunction updateFunction) - { - var newSystem = new PlayerLoopSystem - { - type = what, - updateDelegate = updateFunction - }; - var playerLoop = PlayerLoop.GetCurrentPlayerLoop(); - var index = FindLoopSystemIndex(playerLoop.subSystemList, where); - var postLateUpdateSystem = playerLoop.subSystemList[index]; - postLateUpdateSystem.subSystemList = AppendLoopSystem(postLateUpdateSystem.subSystemList, newSystem); - playerLoop.subSystemList[index] = postLateUpdateSystem; - PlayerLoop.SetPlayerLoop(playerLoop); - } + static class PlayerLoopHelper + { + public static void ModifyPlayerLoop(Type where, Type what, PlayerLoopSystem.UpdateFunction updateFunction) + { + var newSystem = new PlayerLoopSystem + { + type = what, + updateDelegate = updateFunction + }; + var playerLoop = PlayerLoop.GetCurrentPlayerLoop(); + var index = FindLoopSystemIndex(playerLoop.subSystemList, where); + var postLateUpdateSystem = playerLoop.subSystemList[index]; + postLateUpdateSystem.subSystemList = AppendLoopSystem(postLateUpdateSystem.subSystemList, newSystem); + playerLoop.subSystemList[index] = postLateUpdateSystem; + PlayerLoop.SetPlayerLoop(playerLoop); + } - static PlayerLoopSystem[] AppendLoopSystem(PlayerLoopSystem[] subSystemList, PlayerLoopSystem system) - { - var newSubSystemList = new PlayerLoopSystem[subSystemList.Length + 1]; - Array.Copy(subSystemList, 0, newSubSystemList, 0, subSystemList.Length); - newSubSystemList[subSystemList.Length] = system; - return newSubSystemList; - } + static PlayerLoopSystem[] AppendLoopSystem(PlayerLoopSystem[] subSystemList, PlayerLoopSystem system) + { + var newSubSystemList = new PlayerLoopSystem[subSystemList.Length + 1]; + Array.Copy(subSystemList, 0, newSubSystemList, 0, subSystemList.Length); + newSubSystemList[subSystemList.Length] = system; + return newSubSystemList; + } - static int FindLoopSystemIndex(PlayerLoopSystem[] subSystemList, Type systemType) - { - for (int i = 0; i < subSystemList.Length; i++) - { - if (subSystemList[i].type == systemType) - { - return i; - } - } - throw new Exception("Target PlayerLoopSystem does not found. Type:" + systemType.FullName); - } - } + static int FindLoopSystemIndex(PlayerLoopSystem[] subSystemList, Type systemType) + { + for (int i = 0; i < subSystemList.Length; i++) + { + if (subSystemList[i].type == systemType) + { + return i; + } + } + throw new Exception("Target PlayerLoopSystem does not found. Type:" + systemType.FullName); + } + } } diff --git a/src/TinkState-Unity/Tests/TestUnityBatchScheduler.cs b/src/TinkState-Unity/Tests/TestUnityBatchScheduler.cs index 7ea1bbf..7557e05 100644 --- a/src/TinkState-Unity/Tests/TestUnityBatchScheduler.cs +++ b/src/TinkState-Unity/Tests/TestUnityBatchScheduler.cs @@ -6,102 +6,102 @@ public class TestUnityBatchScheduler { - [UnityTest] - public IEnumerator TestBindingDelayed() - { - var state = Observable.State(10); - var bindingCalls = 0; - var expectedValue = 10; - state.Bind(value => - { - bindingCalls++; - Assert.That(value, Is.EqualTo(expectedValue)); - }); - Assert.That(bindingCalls, Is.EqualTo(1)); - state.Value = 15; - Assert.That(bindingCalls, Is.EqualTo(1)); - expectedValue = 15; - yield return null; - Assert.That(bindingCalls, Is.EqualTo(2)); - } + [UnityTest] + public IEnumerator TestBindingDelayed() + { + var state = Observable.State(10); + var bindingCalls = 0; + var expectedValue = 10; + state.Bind(value => + { + bindingCalls++; + Assert.That(value, Is.EqualTo(expectedValue)); + }); + Assert.That(bindingCalls, Is.EqualTo(1)); + state.Value = 15; + Assert.That(bindingCalls, Is.EqualTo(1)); + expectedValue = 15; + yield return null; + Assert.That(bindingCalls, Is.EqualTo(2)); + } - [UnityTest] - public IEnumerator TestBindingInvokedOnceForMultipleChanges() - { - var state = Observable.State(10); - var bindingCalls = 0; - var expectedValue = 10; - state.Bind(value => - { - bindingCalls++; - Assert.That(value, Is.EqualTo(expectedValue)); - }); - Assert.That(bindingCalls, Is.EqualTo(1)); - state.Value = 15; - state.Value = 50; - state.Value = 5; - Assert.That(bindingCalls, Is.EqualTo(1)); - expectedValue = 5; - yield return null; - Assert.That(bindingCalls, Is.EqualTo(2)); - } + [UnityTest] + public IEnumerator TestBindingInvokedOnceForMultipleChanges() + { + var state = Observable.State(10); + var bindingCalls = 0; + var expectedValue = 10; + state.Bind(value => + { + bindingCalls++; + Assert.That(value, Is.EqualTo(expectedValue)); + }); + Assert.That(bindingCalls, Is.EqualTo(1)); + state.Value = 15; + state.Value = 50; + state.Value = 5; + Assert.That(bindingCalls, Is.EqualTo(1)); + expectedValue = 5; + yield return null; + Assert.That(bindingCalls, Is.EqualTo(2)); + } - [UnityTest] - public IEnumerator TestBindingNotInvokedIfFinalValueIsSame() - { - var state = Observable.State(10); - var bindingCalls = 0; - var expectedValue = 10; - state.Bind(value => - { - bindingCalls++; - Assert.That(value, Is.EqualTo(expectedValue)); - }); - Assert.That(bindingCalls, Is.EqualTo(1)); - state.Value = 15; - state.Value = 50; - state.Value = 10; - Assert.That(bindingCalls, Is.EqualTo(1)); - yield return null; - Assert.That(bindingCalls, Is.EqualTo(1)); - } + [UnityTest] + public IEnumerator TestBindingNotInvokedIfFinalValueIsSame() + { + var state = Observable.State(10); + var bindingCalls = 0; + var expectedValue = 10; + state.Bind(value => + { + bindingCalls++; + Assert.That(value, Is.EqualTo(expectedValue)); + }); + Assert.That(bindingCalls, Is.EqualTo(1)); + state.Value = 15; + state.Value = 50; + state.Value = 10; + Assert.That(bindingCalls, Is.EqualTo(1)); + yield return null; + Assert.That(bindingCalls, Is.EqualTo(1)); + } - // NOTE: this is not an intended usage for bindings, as one shouldn't - // trigger bindings from other bindings (e.g. by changing a State) and - // instead make use of auto-Observables and such, but we still test - // that this works as expected and doesn't hang - [UnityTest] - public IEnumerator TestTriggerBindingFromBinding() - { - var s = Observable.State(2); - var s2 = Observable.State(2); + // NOTE: this is not an intended usage for bindings, as one shouldn't + // trigger bindings from other bindings (e.g. by changing a State) and + // instead make use of auto-Observables and such, but we still test + // that this works as expected and doesn't hang + [UnityTest] + public IEnumerator TestTriggerBindingFromBinding() + { + var s = Observable.State(2); + var s2 = Observable.State(2); - var bindingCalls = 0; - var expectedValue = 2; - void BindCallback(int value) - { - bindingCalls++; - Assert.That(value, Is.EqualTo(expectedValue)); - } + var bindingCalls = 0; + var expectedValue = 2; + void BindCallback(int value) + { + bindingCalls++; + Assert.That(value, Is.EqualTo(expectedValue)); + } - s2.Bind(BindCallback); - Assert.That(bindingCalls, Is.EqualTo(1)); + s2.Bind(BindCallback); + Assert.That(bindingCalls, Is.EqualTo(1)); - s.Bind(v => s2.Value = v * 2); + s.Bind(v => s2.Value = v * 2); - // first binding was still not called because it's scheduled! - Assert.That(bindingCalls, Is.EqualTo(1)); + // first binding was still not called because it's scheduled! + Assert.That(bindingCalls, Is.EqualTo(1)); - // it will be called as scheduled though - expectedValue = 4; - yield return null; - Assert.That(bindingCalls, Is.EqualTo(2)); + // it will be called as scheduled though + expectedValue = 4; + yield return null; + Assert.That(bindingCalls, Is.EqualTo(2)); - // changing the value will invoke the binding for `s` which will in its turn schedule the binding for `s2`, - // which should be processed right after, let's check that - s.Value = 3; - expectedValue = 6; - yield return null; - Assert.That(bindingCalls, Is.EqualTo(3)); - } + // changing the value will invoke the binding for `s` which will in its turn schedule the binding for `s2`, + // which should be processed right after, let's check that + s.Value = 3; + expectedValue = 6; + yield return null; + Assert.That(bindingCalls, Is.EqualTo(3)); + } } \ No newline at end of file diff --git a/src/TinkState/Tests/BaseTest.cs b/src/TinkState/Tests/BaseTest.cs index 84a052f..8f7aa9a 100644 --- a/src/TinkState/Tests/BaseTest.cs +++ b/src/TinkState/Tests/BaseTest.cs @@ -6,22 +6,22 @@ namespace Test // since our binding tests currently rely on the direct scheduler // we want to explicitly set it to be direct for the test in case // we're running from an environment that provides batching (e.g. Unity) - class BaseTest - { + class BaseTest + { Scheduler prevScheduler; - [SetUp] - public void SetUp() - { + [SetUp] + public void SetUp() + { prevScheduler = Observable.Scheduler; Observable.Scheduler = Scheduler.Direct; - } + } - [TearDown] - public void TearDown() - { + [TearDown] + public void TearDown() + { Observable.Scheduler = prevScheduler; prevScheduler = null; - } - } + } + } }