From 6350f72e80f115cba0efe4c0d958a80efe04af84 Mon Sep 17 00:00:00 2001
From: "Simon (darkside) Jackson" <darkside@zenithmoon.com>
Date: Mon, 28 Sep 2020 23:43:03 +0100
Subject: [PATCH] Final roll-up and fix. Resolved race condition for associated
 pagination controls.

---
 .../Scripts/Layout/HorizontalScrollSnap.cs    |  4 +-
 Runtime/Scripts/Layout/ScrollSnapBase.cs      | 40 +++++++++++++------
 Runtime/Scripts/Layout/VerticalScrollSnap.cs  |  2 +-
 .../Scripts/Utilities/PaginationManager.cs    |  2 +-
 4 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/Runtime/Scripts/Layout/HorizontalScrollSnap.cs b/Runtime/Scripts/Layout/HorizontalScrollSnap.cs
index a441183..e3123b0 100644
--- a/Runtime/Scripts/Layout/HorizontalScrollSnap.cs
+++ b/Runtime/Scripts/Layout/HorizontalScrollSnap.cs
@@ -41,7 +41,7 @@ namespace UnityEngine.UI.Extensions
             else if (_lerp)
             {
                 _screensContainer.anchoredPosition = Vector3.Lerp(_screensContainer.anchoredPosition, _lerp_target, transitionSpeed * (UseTimeScale ? Time.deltaTime : Time.unscaledDeltaTime));
-                if (Vector3.Distance(_screensContainer.anchoredPosition, _lerp_target) < 0.1f)
+                if (Vector3.Distance(_screensContainer.anchoredPosition, _lerp_target) < 0.2f)
                 {
                     _screensContainer.anchoredPosition = _lerp_target;
                     _lerp = false;
@@ -238,7 +238,7 @@ namespace UnityEngine.UI.Extensions
             if (JumpOnEnable || !RestartOnEnable)
                 SetScrollContainerPosition();
             if (RestartOnEnable)
-                GoToScreen(StartingScreen, true);
+                GoToScreen(StartingScreen);
         }
 
         /// <summary>
diff --git a/Runtime/Scripts/Layout/ScrollSnapBase.cs b/Runtime/Scripts/Layout/ScrollSnapBase.cs
index 893ba29..ff75bae 100644
--- a/Runtime/Scripts/Layout/ScrollSnapBase.cs
+++ b/Runtime/Scripts/Layout/ScrollSnapBase.cs
@@ -5,6 +5,7 @@
 using System;
 using UnityEngine.Events;
 using UnityEngine.EventSystems;
+using UnityEngine.UIElements;
 
 namespace UnityEngine.UI.Extensions
 {
@@ -30,11 +31,13 @@ namespace UnityEngine.UI.Extensions
         internal int _currentPage;
         internal int _previousPage;
         internal int _halfNoVisibleItems;
-        internal bool _moveStarted;
         internal bool _isInfinite; // Is a UI Infinite scroller attached to the control
         internal int _infiniteWindow; // The infinite window the control is in
         internal float _infiniteOffset; // How much to offset a repositioning
-         private int _bottomItem, _topItem;
+        private int _bottomItem, _topItem;
+        internal bool _startEventCalled = false;
+        internal bool _endEventCalled = false;
+        internal bool _suspendEvents = false; 
 
         [Serializable]
         public class SelectionChangeStartEvent : UnityEvent { }
@@ -357,7 +360,7 @@ namespace UnityEngine.UI.Extensions
         /// *Note, this is based on a 0 starting index - 0 to x
         /// </summary>
         /// <param name="screenIndex">0 starting index of page to jump to</param>
-        public void GoToScreen(int screenIndex, bool local = false)
+        public void GoToScreen(int screenIndex)
         {
             if (screenIndex <= _screens - 1 && screenIndex >= 0)
             {
@@ -366,7 +369,7 @@ namespace UnityEngine.UI.Extensions
                 _lerp = true;
                 CurrentPage = screenIndex;
                 GetPositionforPage(_currentPage, ref _lerp_target);
-                if(local) ScreenChange();
+                ScreenChange();
             }
         }
 
@@ -443,14 +446,16 @@ namespace UnityEngine.UI.Extensions
         private void ChangeBulletsInfo(int targetScreen)
         {
             if (Pagination)
+            {
                 for (int i = 0; i < Pagination.transform.childCount; i++)
                 {
-                    Pagination.transform.GetChild(i).GetComponent<Toggle>().isOn = (targetScreen == i)
-            ? true
-                        : false;
+                    Pagination.transform.GetChild(i).GetComponent<Toggle>().isOn = (targetScreen == i) ? true : false;
                 }
+            }
         }
 
+        // Make a lock function for pagination, to prevent event leaking
+
         /// <summary>
         /// disables the page navigation buttons when at the first or last screen
         /// </summary>
@@ -531,9 +536,12 @@ namespace UnityEngine.UI.Extensions
         /// </summary>
         public void StartScreenChange()
         {
-            if (!_moveStarted)
+            if (!_startEventCalled)
             {
-                _moveStarted = true;
+                _suspendEvents = true;
+
+                _startEventCalled = true;
+                _endEventCalled = false;
                 OnSelectionChangeStartEvent.Invoke();
             }
         }
@@ -551,9 +559,15 @@ namespace UnityEngine.UI.Extensions
         /// </summary>
         internal void EndScreenChange()
         {
-            OnSelectionChangeEndEvent.Invoke(_currentPage);
-            _settled = true;
-            _moveStarted = false;
+            if (!_endEventCalled)
+            {
+                _suspendEvents = false;
+
+                _endEventCalled = true;
+                _startEventCalled = false;
+                _settled = true;
+                OnSelectionChangeEndEvent.Invoke(_currentPage);
+            }
         }
 
         /// <summary>
@@ -623,7 +637,7 @@ namespace UnityEngine.UI.Extensions
         /// </summary>
         public void ChangePage(int page)
         {
-            GoToScreen(page, true);
+            GoToScreen(page);
         }
 
         public void OnPointerClick(PointerEventData eventData)
diff --git a/Runtime/Scripts/Layout/VerticalScrollSnap.cs b/Runtime/Scripts/Layout/VerticalScrollSnap.cs
index 0093daa..58bde93 100644
--- a/Runtime/Scripts/Layout/VerticalScrollSnap.cs
+++ b/Runtime/Scripts/Layout/VerticalScrollSnap.cs
@@ -234,7 +234,7 @@ namespace UnityEngine.UI.Extensions
             if (JumpOnEnable || !RestartOnEnable)
                 SetScrollContainerPosition();
             if (RestartOnEnable)
-                GoToScreen(StartingScreen, true);
+                GoToScreen(StartingScreen);
         }
 
         /// <summary>
diff --git a/Runtime/Scripts/Utilities/PaginationManager.cs b/Runtime/Scripts/Utilities/PaginationManager.cs
index c80b21f..9f0ca61 100644
--- a/Runtime/Scripts/Utilities/PaginationManager.cs
+++ b/Runtime/Scripts/Utilities/PaginationManager.cs
@@ -100,7 +100,7 @@ namespace UnityEngine.UI.Extensions
             {
                 for (int i = 0; i < m_PaginationChildren.Count; i++)
                 {
-                    if (m_PaginationChildren[i].isOn)
+                    if (m_PaginationChildren[i].isOn && !scrollSnap._suspendEvents)
                     {
                         GoToScreen(i);
                         break;