diff --git a/UnityEditor.UI/EventSystem/EventTriggerEditor.cs b/UnityEditor.UI/EventSystem/EventTriggerEditor.cs index 232d07e..37811df 100644 --- a/UnityEditor.UI/EventSystem/EventTriggerEditor.cs +++ b/UnityEditor.UI/EventSystem/EventTriggerEditor.cs @@ -16,7 +16,7 @@ public class EventTriggerEditor : Editor protected virtual void OnEnable() { - m_DelegatesProperty = serializedObject.FindProperty("delegates"); + m_DelegatesProperty = serializedObject.FindProperty("m_Delegates"); m_AddButonContent = new GUIContent("Add New Event Type"); m_EventIDName = new GUIContent(""); // Have to create a copy since otherwise the tooltip will be overwritten. diff --git a/UnityEditor.UI/UI/InputFieldEditor.cs b/UnityEditor.UI/UI/InputFieldEditor.cs index f724c7b..6d71d3f 100644 --- a/UnityEditor.UI/UI/InputFieldEditor.cs +++ b/UnityEditor.UI/UI/InputFieldEditor.cs @@ -58,13 +58,6 @@ public override void OnInspectorGUI() { EditorGUILayout.HelpBox("Using Rich Text with input is unsupported.", MessageType.Warning); } - - if (text.alignment != TextAnchor.UpperLeft && - text.alignment != TextAnchor.UpperCenter && - text.alignment != TextAnchor.UpperRight) - { - EditorGUILayout.HelpBox("Using a non upper alignment with input is unsupported.", MessageType.Warning); - } } EditorGUI.BeginDisabledGroup(m_TextComponent == null || m_TextComponent.objectReferenceValue == null); diff --git a/UnityEditor.UI/UI/MenuOptions.cs b/UnityEditor.UI/UI/MenuOptions.cs index 6d8f2ad..4729b00 100644 --- a/UnityEditor.UI/UI/MenuOptions.cs +++ b/UnityEditor.UI/UI/MenuOptions.cs @@ -79,9 +79,12 @@ private static GameObject CreateUIElementRoot(string name, MenuCommand menuComma { parent = GetOrCreateCanvasGameObject(); } - GameObject child = new GameObject(name); - Undo.RegisterCreatedObjectUndo(child, "Create " + name); + string uniqueName = GameObjectUtility.GetUniqueNameForSibling(parent.transform, name); + + GameObject child = new GameObject(uniqueName); + + Undo.RegisterCreatedObjectUndo(child, "Create " + uniqueName); Undo.SetTransformParent(child.transform, parent.transform, "Parent " + child.name); GameObjectUtility.SetParentAndAlign(child, parent); @@ -99,6 +102,7 @@ private static GameObject CreateUIElementRoot(string name, MenuCommand menuComma static public void AddPanel(MenuCommand menuCommand) { GameObject panelRoot = CreateUIElementRoot("Panel", menuCommand, s_ThickGUIElementSize); + panelRoot.layer = LayerMask.NameToLayer(kUILayerName); // Set RectTransform to stretch RectTransform rectTransform = panelRoot.GetComponent(); diff --git a/UnityEditor.UI/UI/SelectableEditor.cs b/UnityEditor.UI/UI/SelectableEditor.cs index 937561e..73d51d6 100644 --- a/UnityEditor.UI/UI/SelectableEditor.cs +++ b/UnityEditor.UI/UI/SelectableEditor.cs @@ -3,7 +3,6 @@ using System.Linq; using UnityEngine; using UnityEngine.UI; -using UnityEditorInternal; using UnityEditor.AnimatedValues; namespace UnityEditor.UI @@ -164,7 +163,7 @@ public override void OnInspectorGUI() if (animator == null) animator = (target as Selectable).gameObject.AddComponent(); - AnimatorController.SetAnimatorController(animator, controller); + Animations.AnimatorController.SetAnimatorController(animator, controller); } } } @@ -210,7 +209,7 @@ private bool IsDerivedSelectableEditor() return GetType() != typeof(SelectableEditor); } - private static AnimatorController GenerateSelectableAnimatorContoller(AnimationTriggers animationTriggers, Selectable target) + private static Animations.AnimatorController GenerateSelectableAnimatorContoller(AnimationTriggers animationTriggers, Selectable target) { if (target == null) return null; @@ -227,13 +226,14 @@ private static AnimatorController GenerateSelectableAnimatorContoller(AnimationT var disabledName = string.IsNullOrEmpty(animationTriggers.disabledTrigger) ? "Disabled" : animationTriggers.disabledTrigger; // Create controller and hook up transitions. - var controller = AnimatorController.CreateAnimatorControllerAtPath(path); - + var controller = Animations.AnimatorController.CreateAnimatorControllerAtPath(path); GenerateTriggerableTransition(normalName, controller); GenerateTriggerableTransition(highlightedName, controller); GenerateTriggerableTransition(pressedName, controller); GenerateTriggerableTransition(disabledName, controller); + AssetDatabase.ImportAsset(path); + return controller; } @@ -292,24 +292,22 @@ private static string BuildAnimationPath(Selectable target) return animPath.ToString(); } - private static AnimationClip GenerateTriggerableTransition(string name, AnimatorController controller) + private static AnimationClip GenerateTriggerableTransition(string name, Animations.AnimatorController controller) { // Create the clip - var clip = AnimatorController.AllocateAnimatorClip(name); + var clip = Animations.AnimatorController.AllocateAnimatorClip(name); AssetDatabase.AddObjectToAsset(clip, controller); // Create a state in the animatior controller for this clip - var state = AnimatorController.AddAnimationClipToController(controller, clip); + var state = controller.AddMotion(clip); // Add a transition property controller.AddParameter(name, AnimatorControllerParameterType.Trigger); // Add an any state transition - var stateMachine = controller.GetLayer(0).stateMachine; + var stateMachine = controller.layers[0].stateMachine; var transition = stateMachine.AddAnyStateTransition(state); - var condition = transition.GetCondition(0); - condition.mode = TransitionConditionMode.If; - condition.parameter = name; + transition.AddCondition(Animations.AnimatorConditionMode.If, 0, name); return clip; } diff --git a/UnityEditor.UI/UI/SpriteDrawUtility.cs b/UnityEditor.UI/UI/SpriteDrawUtility.cs index c810845..97ba526 100644 --- a/UnityEditor.UI/UI/SpriteDrawUtility.cs +++ b/UnityEditor.UI/UI/SpriteDrawUtility.cs @@ -6,9 +6,7 @@ namespace UnityEditor.UI // Tools for the editor internal class SpriteDrawUtility { - static Texture2D s_BackdropTex; static Texture2D s_ContrastTex; - static Texture2D s_GradientTex; // Returns a usable texture that looks like a high-contrast checker board. static Texture2D contrastTexture @@ -23,17 +21,6 @@ static Texture2D contrastTexture } } - // Gradient texture is used for title bars / headers. - static Texture2D gradientTexture - { - get - { - if (s_GradientTex == null) - s_GradientTex = CreateGradientTex(); - return s_GradientTex; - } - } - // Create a checker-background texture. static Texture2D CreateCheckerTex(Color c0, Color c1) { diff --git a/UnityEngine.UI/EventSystem/EventData/PointerEventData.cs b/UnityEngine.UI/EventSystem/EventData/PointerEventData.cs index 6c45656..d205c28 100644 --- a/UnityEngine.UI/EventSystem/EventData/PointerEventData.cs +++ b/UnityEngine.UI/EventSystem/EventData/PointerEventData.cs @@ -1,4 +1,6 @@ +using System; using System.Text; +using System.Collections.Generic; namespace UnityEngine.EventSystems { @@ -36,6 +38,8 @@ public enum FramePressState public RaycastResult pointerCurrentRaycast { get; set; } public RaycastResult pointerPressRaycast { get; set; } + public List hovered = new List(); + public bool eligibleForClick { get; set; } public int pointerId { get; set; } @@ -44,11 +48,13 @@ public enum FramePressState public Vector2 position { get; set; } // Delta since last update public Vector2 delta { get; set; } - // Delta since the event started being tracked + // Position of the press event public Vector2 pressPosition { get; set; } // World-space position where a ray cast into the screen hits something + [Obsolete("Use either pointerCurrentRaycast.worldPosition or pointerPressRaycast.worldPosition")] public Vector3 worldPosition { get; set; } // World-space normal where a ray cast into the screen hits something + [Obsolete("Use either pointerCurrentRaycast.worldNormal or pointerPressRaycast.worldNormal")] public Vector3 worldNormal { get; set; } // The last time a click event was sent out (used for double-clicks) public float clickTime { get; set; } @@ -69,8 +75,6 @@ public PointerEventData(EventSystem eventSystem) : base(eventSystem) position = Vector2.zero; // Current position of the mouse or touch event delta = Vector2.zero; // Delta since last update pressPosition = Vector2.zero; // Delta since the event started being tracked - worldPosition = Vector3.zero; // World-space position where a ray cast into the screen hits something - worldNormal = Vector3.zero; // World-space normal where a ray cast into the screen hits something clickTime = 0.0f; // The last time a click event was sent out (used for double-clicks) clickCount = 0; // Number of clicks in a row. 2 for a double-click for example. @@ -124,6 +128,8 @@ public override string ToString() sb.AppendLine("lastPointerPress: " + lastPress); sb.AppendLine("pointerDrag: " + pointerDrag); sb.AppendLine("Use Drag Threshold: " + useDragThreshold); + sb.AppendLine("Current Rayast:"); + sb.AppendLine(pointerCurrentRaycast.ToString()); return sb.ToString(); } } diff --git a/UnityEngine.UI/EventSystem/EventSystem.cs b/UnityEngine.UI/EventSystem/EventSystem.cs index cf30e83..93254ca 100644 --- a/UnityEngine.UI/EventSystem/EventSystem.cs +++ b/UnityEngine.UI/EventSystem/EventSystem.cs @@ -36,7 +36,6 @@ public int pixelDragThreshold } private GameObject m_CurrentSelected; - private GameObject m_LastSelected; public BaseInputModule currentInputModule { @@ -57,13 +56,14 @@ public GameObject currentSelectedGameObject get { return m_CurrentSelected; } } + [Obsolete("lastSelectedGameObject is no longer supported")] public GameObject lastSelectedGameObject { - get { return m_LastSelected; } + get { return null; } } protected EventSystem() - { } + {} public void UpdateModules() { @@ -100,7 +100,6 @@ public void SetSelectedGameObject(GameObject selected, BaseEventData pointer) // Debug.Log("Selection: new (" + selected + ") old (" + m_CurrentSelected + ")"); ExecuteEvents.Execute(m_CurrentSelected, pointer, ExecuteEvents.deselectHandler); - m_LastSelected = m_CurrentSelected; m_CurrentSelected = selected; ExecuteEvents.Execute(m_CurrentSelected, pointer, ExecuteEvents.selectHandler); m_SelectionGuard = false; @@ -289,7 +288,6 @@ public override string ToString() { var sb = new StringBuilder(); sb.AppendLine("Selected:" + currentSelectedGameObject); - sb.AppendLine("Last Selected:" + lastSelectedGameObject); sb.AppendLine(); sb.AppendLine(); sb.AppendLine(m_CurrentInputModule != null ? m_CurrentInputModule.ToString() : "No module"); diff --git a/UnityEngine.UI/EventSystem/EventTrigger.cs b/UnityEngine.UI/EventSystem/EventTrigger.cs index 4aff21a..47fe320 100644 --- a/UnityEngine.UI/EventSystem/EventTrigger.cs +++ b/UnityEngine.UI/EventSystem/EventTrigger.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using UnityEngine.Events; +using UnityEngine.Serialization; namespace UnityEngine.EventSystems { @@ -27,7 +28,7 @@ public class EventTrigger : { [Serializable] public class TriggerEvent : UnityEvent - { } + {} [Serializable] public class Entry @@ -36,21 +37,34 @@ public class Entry public TriggerEvent callback = new TriggerEvent(); } + [FormerlySerializedAs("delegates")] + [SerializeField] + private List m_Delegates; + + [Obsolete("Please use triggers instead (UnityUpgradable)", true)] public List delegates; protected EventTrigger() - { } + {} + + public List triggers + { + get + { + if (m_Delegates == null) + m_Delegates = new List(); + return m_Delegates; + } + set { m_Delegates = value; } + } private void Execute(EventTriggerType id, BaseEventData eventData) { - if (delegates != null) + for (int i = 0, imax = triggers.Count; i < imax; ++i) { - for (int i = 0, imax = delegates.Count; i < imax; ++i) - { - var ent = delegates[i]; - if (ent.eventID == id && ent.callback != null) - ent.callback.Invoke(eventData); - } + var ent = triggers[i]; + if (ent.eventID == id && ent.callback != null) + ent.callback.Invoke(eventData); } } diff --git a/UnityEngine.UI/EventSystem/ExecuteEvents.cs b/UnityEngine.UI/EventSystem/ExecuteEvents.cs index 608e571..b5b2191 100644 --- a/UnityEngine.UI/EventSystem/ExecuteEvents.cs +++ b/UnityEngine.UI/EventSystem/ExecuteEvents.cs @@ -247,8 +247,8 @@ public static bool Execute(GameObject target, BaseEventData eventData, EventF { var internalHandlers = s_HandlerListPool.Get(); GetEventList(target, internalHandlers); - // if (s_InternalHandlers.Count > 0) - // Debug.Log("Executinng " + typeof (T) + " on " + target); + // if (s_InternalHandlers.Count > 0) + // Debug.Log("Executinng " + typeof (T) + " on " + target); for (var i = 0; i < internalHandlers.Count; i++) { diff --git a/UnityEngine.UI/EventSystem/InputModules/BaseInputModule.cs b/UnityEngine.UI/EventSystem/InputModules/BaseInputModule.cs index faccb19..c6928e8 100644 --- a/UnityEngine.UI/EventSystem/InputModules/BaseInputModule.cs +++ b/UnityEngine.UI/EventSystem/InputModules/BaseInputModule.cs @@ -100,14 +100,29 @@ protected static GameObject FindCommonRoot(GameObject g1, GameObject g2) // (but not including the common root). protected void HandlePointerExitAndEnter(PointerEventData currentPointerData, GameObject newEnterTarget) { + // if we have no target / pointerEnter has been deleted + // just send exit events to anything we are tracking + // then exit + if (newEnterTarget == null || currentPointerData.pointerEnter == null) + { + for (var i = 0; i < currentPointerData.hovered.Count; ++i) + ExecuteEvents.Execute(currentPointerData.hovered[i], currentPointerData, ExecuteEvents.pointerExitHandler); + + currentPointerData.hovered.Clear(); + + if (newEnterTarget == null) + { + currentPointerData.pointerEnter = newEnterTarget; + return; + } + } + // if we have not changed hover target - if (currentPointerData.pointerEnter == newEnterTarget) + if (currentPointerData.pointerEnter == newEnterTarget && newEnterTarget) return; GameObject commonRoot = FindCommonRoot(currentPointerData.pointerEnter, newEnterTarget); -#if UNITY_EDITOR - // lastCommonRoot = commonRoot; -#endif + // and we already an entered object from last time if (currentPointerData.pointerEnter != null) { @@ -122,6 +137,7 @@ protected void HandlePointerExitAndEnter(PointerEventData currentPointerData, Ga break; ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerExitHandler); + currentPointerData.hovered.Remove(t.gameObject); t = t.parent; } } @@ -129,12 +145,13 @@ protected void HandlePointerExitAndEnter(PointerEventData currentPointerData, Ga // now issue the enter call up to but not including the common root if (newEnterTarget != null) { - Transform targetT = newEnterTarget.transform; + Transform t = newEnterTarget.transform; - while (targetT != null && targetT.gameObject != commonRoot) + while (t != null && t.gameObject != commonRoot) { - ExecuteEvents.Execute(targetT.gameObject, currentPointerData, ExecuteEvents.pointerEnterHandler); - targetT = targetT.parent; + ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerEnterHandler); + currentPointerData.hovered.Add(t.gameObject); + t = t.parent; } } currentPointerData.pointerEnter = newEnterTarget; @@ -171,13 +188,13 @@ public virtual bool ShouldActivateModule() } public virtual void DeactivateModule() - { } + {} public virtual void ActivateModule() - { } + {} public virtual void UpdateModule() - { } + {} public virtual bool IsModuleSupported() { diff --git a/UnityEngine.UI/EventSystem/InputModules/PointerInputModule.cs b/UnityEngine.UI/EventSystem/InputModules/PointerInputModule.cs index b1259c2..96c2ec0 100644 --- a/UnityEngine.UI/EventSystem/InputModules/PointerInputModule.cs +++ b/UnityEngine.UI/EventSystem/InputModules/PointerInputModule.cs @@ -69,6 +69,7 @@ private void CopyFromTo(PointerEventData @from, PointerEventData @to) @to.delta = @from.delta; @to.scrollDelta = @from.scrollDelta; @to.pointerCurrentRaycast = @from.pointerCurrentRaycast; + @to.pointerPressRaycast = @from.pointerPressRaycast; @to.pointerEnter = @from.pointerEnter; } @@ -194,7 +195,7 @@ protected virtual MouseState GetMousePointerEventData() leftData.pointerCurrentRaycast = raycast; m_RaycastResultCache.Clear(); - // copy the apropriate data into right and middle slots + // copy the appropriate data into right and middle slots PointerEventData rightData; GetPointerData(kMouseRightId, out rightData, true); CopyFromTo(leftData, rightData); diff --git a/UnityEngine.UI/EventSystem/InputModules/StandaloneInputModule.cs b/UnityEngine.UI/EventSystem/InputModules/StandaloneInputModule.cs index 50dc734..a6d4c90 100644 --- a/UnityEngine.UI/EventSystem/InputModules/StandaloneInputModule.cs +++ b/UnityEngine.UI/EventSystem/InputModules/StandaloneInputModule.cs @@ -5,13 +5,15 @@ namespace UnityEngine.EventSystems [AddComponentMenu("Event/Standalone Input Module")] public class StandaloneInputModule : PointerInputModule { - private float m_NextAction; + private float m_PrevActionTime; + Vector2 m_LastMoveVector; + int m_ConsecutiveMoveCount = 0; private Vector2 m_LastMousePosition; private Vector2 m_MousePosition; protected StandaloneInputModule() - { } + {} [Obsolete("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)] public enum InputMode @@ -50,6 +52,9 @@ public InputMode inputMode [SerializeField] private float m_InputActionsPerSecond = 10; + [SerializeField] + private float m_RepeatDelay = 0.5f; + [SerializeField] private bool m_AllowActivationOnMobileDevice; @@ -65,6 +70,12 @@ public float inputActionsPerSecond set { m_InputActionsPerSecond = value; } } + public float repeatDelay + { + get { return m_RepeatDelay; } + set { m_RepeatDelay = value; } + } + /// /// Name of the horizontal axis for movement (if axis events are used). /// @@ -130,8 +141,6 @@ public override void ActivateModule() m_LastMousePosition = Input.mousePosition; var toSelect = eventSystem.currentSelectedGameObject; - if (toSelect == null) - toSelect = eventSystem.lastSelectedGameObject; if (toSelect == null) toSelect = eventSystem.firstSelectedGameObject; @@ -177,14 +186,6 @@ private bool SendSubmitEventToSelectedObject() return data.used; } - private bool AllowMoveEventProcessing(float time) - { - bool allow = Input.GetButtonDown(m_HorizontalAxis); - allow |= Input.GetButtonDown(m_VerticalAxis); - allow |= (time > m_NextAction); - return allow; - } - private Vector2 GetRawMoveVector() { Vector2 move = Vector2.zero; @@ -215,18 +216,46 @@ private bool SendMoveEventToSelectedObject() { float time = Time.unscaledTime; - if (!AllowMoveEventProcessing(time)) + Vector2 movement = GetRawMoveVector(); + if (Mathf.Approximately(movement.x, 0f) && Mathf.Approximately(movement.y, 0f)) + { + m_ConsecutiveMoveCount = 0; + return false; + } + + // If user pressed key again, always allow event + bool allow = Input.GetButtonDown(m_HorizontalAxis) || Input.GetButtonDown(m_VerticalAxis); + bool similarDir = (Vector2.Dot(movement, m_LastMoveVector) > 0); + if (!allow) + { + // Otherwise, user held down key or axis. + // If direction didn't change at least 90 degrees, wait for delay before allowing consequtive event. + if (similarDir && m_ConsecutiveMoveCount == 1) + allow = (time > m_PrevActionTime + m_RepeatDelay); + // If direction changed at least 90 degree, or we already had the delay, repeat at repeat rate. + else + allow = (time > m_PrevActionTime + 1f / m_InputActionsPerSecond); + } + if (!allow) return false; - Vector2 movement = GetRawMoveVector(); // Debug.Log(m_ProcessingEvent.rawType + " axis:" + m_AllowAxisEvents + " value:" + "(" + x + "," + y + ")"); var axisEventData = GetAxisEventData(movement.x, movement.y, 0.6f); - if (!Mathf.Approximately(axisEventData.moveVector.x, 0f) - || !Mathf.Approximately(axisEventData.moveVector.y, 0f)) + + if (axisEventData.moveDir != MoveDirection.None) { ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, axisEventData, ExecuteEvents.moveHandler); + if (!similarDir) + m_ConsecutiveMoveCount = 0; + m_ConsecutiveMoveCount++; + m_PrevActionTime = time; + m_LastMoveVector = movement; } - m_NextAction = time + 1f / m_InputActionsPerSecond; + else + { + m_ConsecutiveMoveCount = 0; + } + return axisEventData.used; } @@ -236,15 +265,8 @@ private bool SendMoveEventToSelectedObject() private void ProcessMouseEvent() { var mouseData = GetMousePointerEventData(); - - var pressed = mouseData.AnyPressesThisFrame(); - var released = mouseData.AnyReleasesThisFrame(); - var leftButtonData = mouseData.GetButtonState(PointerEventData.InputButton.Left).eventData; - if (!UseMouse(pressed, released, leftButtonData.buttonData)) - return; - // Process the first mouse button fully ProcessMousePress(leftButtonData); ProcessMove(leftButtonData.buttonData); @@ -263,14 +285,6 @@ private void ProcessMouseEvent() } } - private static bool UseMouse(bool pressed, bool released, PointerEventData pointerData) - { - if (pressed || released || pointerData.IsPointerMoving() || pointerData.IsScrolling()) - return true; - - return false; - } - private bool SendUpdateEventToSelectedObject() { if (eventSystem.currentSelectedGameObject == null) diff --git a/UnityEngine.UI/EventSystem/InputModules/TouchInputModule.cs b/UnityEngine.UI/EventSystem/InputModules/TouchInputModule.cs index 5791369..89726cd 100644 --- a/UnityEngine.UI/EventSystem/InputModules/TouchInputModule.cs +++ b/UnityEngine.UI/EventSystem/InputModules/TouchInputModule.cs @@ -6,7 +6,7 @@ namespace UnityEngine.EventSystems public class TouchInputModule : PointerInputModule { protected TouchInputModule() - { } + {} private Vector2 m_LastMousePosition; private Vector2 m_MousePosition; diff --git a/UnityEngine.UI/EventSystem/RaycastResult.cs b/UnityEngine.UI/EventSystem/RaycastResult.cs index 3e17548..c1d3476 100644 --- a/UnityEngine.UI/EventSystem/RaycastResult.cs +++ b/UnityEngine.UI/EventSystem/RaycastResult.cs @@ -16,6 +16,10 @@ public GameObject gameObject public int depth; public int sortingLayer; public int sortingOrder; + // World-space position where a ray cast into the screen hits something + public Vector3 worldPosition; + // World-space normal where a ray cast into the screen hits something + public Vector3 worldNormal; public bool isValid { @@ -29,15 +33,25 @@ public void Clear() distance = 0; index = 0; depth = 0; + sortingLayer = 0; + sortingOrder = 0; + worldNormal = Vector3.up; + worldPosition = Vector3.zero; } public override string ToString() { - return "Name: " + gameObject.name + "\n" + - "module: " + module.camera + "\n" + + if (!isValid) + return ""; + + return "Name: " + gameObject + "\n" + + "module: " + module + "\n" + + "module camera: " + module.GetComponent() + "\n" + "distance: " + distance + "\n" + "index: " + index + "\n" + "depth: " + depth + "\n" + + "worldNormal: " + worldNormal + "\n" + + "worldPosition: " + worldPosition + "\n" + "module.sortOrderPriority: " + module.sortOrderPriority + "\n" + "module.renderOrderPriority: " + module.renderOrderPriority + "\n" + "sortingLayer: " + sortingLayer + "\n" + diff --git a/UnityEngine.UI/EventSystem/Raycasters/Physics2DRaycaster.cs b/UnityEngine.UI/EventSystem/Raycasters/Physics2DRaycaster.cs index 627959d..a6d9d3d 100644 --- a/UnityEngine.UI/EventSystem/Raycasters/Physics2DRaycaster.cs +++ b/UnityEngine.UI/EventSystem/Raycasters/Physics2DRaycaster.cs @@ -10,7 +10,7 @@ namespace UnityEngine.EventSystems public class Physics2DRaycaster : PhysicsRaycaster { protected Physics2DRaycaster() - { } + {} public override void Raycast(PointerEventData eventData, List resultAppendList) { @@ -25,17 +25,17 @@ public override void Raycast(PointerEventData eventData, List res if (hits.Length != 0) { - eventData.worldPosition = hits[0].point; - eventData.worldNormal = hits[0].normal; for (int b = 0, bmax = hits.Length; b < bmax; ++b) { - SpriteRenderer sr = hits[b].collider.gameObject.GetComponent(); + var sr = hits[b].collider.gameObject.GetComponent(); var result = new RaycastResult { gameObject = hits[b].collider.gameObject, module = this, distance = Vector3.Distance(eventCamera.transform.position, hits[b].transform.position), + worldPosition = hits[b].point, + worldNormal = hits[b].normal, index = resultAppendList.Count, sortingLayer = sr != null ? sr.sortingLayerID : 0, sortingOrder = sr != null ? sr.sortingOrder : 0 diff --git a/UnityEngine.UI/EventSystem/Raycasters/PhysicsRaycaster.cs b/UnityEngine.UI/EventSystem/Raycasters/PhysicsRaycaster.cs index 48ae98a..7d4e0cb 100644 --- a/UnityEngine.UI/EventSystem/Raycasters/PhysicsRaycaster.cs +++ b/UnityEngine.UI/EventSystem/Raycasters/PhysicsRaycaster.cs @@ -23,7 +23,7 @@ public class PhysicsRaycaster : BaseRaycaster protected LayerMask m_EventMask = kNoEventMaskSet; protected PhysicsRaycaster() - { } + {} public override Camera eventCamera { @@ -67,7 +67,6 @@ public override void Raycast(PointerEventData eventData, List res return; var ray = eventCamera.ScreenPointToRay(eventData.position); - float dist = eventCamera.farClipPlane - eventCamera.nearClipPlane; var hits = Physics.RaycastAll(ray, dist, finalEventMask); @@ -77,8 +76,6 @@ public override void Raycast(PointerEventData eventData, List res if (hits.Length != 0) { - eventData.worldPosition = hits[0].point; - eventData.worldNormal = hits[0].normal; for (int b = 0, bmax = hits.Length; b < bmax; ++b) { var result = new RaycastResult @@ -86,6 +83,8 @@ public override void Raycast(PointerEventData eventData, List res gameObject = hits[b].collider.gameObject, module = this, distance = hits[b].distance, + worldPosition = hits[b].point, + worldNormal = hits[b].normal, index = resultAppendList.Count, sortingLayer = 0, sortingOrder = 0 diff --git a/UnityEngine.UI/EventSystem/UIBehaviour.cs b/UnityEngine.UI/EventSystem/UIBehaviour.cs index 46c0ae8..39fea76 100644 --- a/UnityEngine.UI/EventSystem/UIBehaviour.cs +++ b/UnityEngine.UI/EventSystem/UIBehaviour.cs @@ -3,19 +3,19 @@ namespace UnityEngine.EventSystems public abstract class UIBehaviour : MonoBehaviour { protected virtual void Awake() - { } + {} protected virtual void OnEnable() - { } + {} protected virtual void Start() - { } + {} protected virtual void OnDisable() - { } + {} protected virtual void OnDestroy() - { } + {} public virtual bool IsActive() { @@ -24,26 +24,29 @@ public virtual bool IsActive() #if UNITY_EDITOR protected virtual void OnValidate() - { } + {} protected virtual void Reset() - { } + {} #endif protected virtual void OnRectTransformDimensionsChange() - { } + {} protected virtual void OnBeforeTransformParentChanged() - { } + {} protected virtual void OnTransformParentChanged() - { } + {} protected virtual void OnDidApplyAnimationProperties() - { } + {} protected virtual void OnCanvasGroupChanged() - { } + {} + + protected virtual void OnCanvasHierarchyChanged() + {} public bool IsDestroyed() { diff --git a/UnityEngine.UI/UI/Animation/CoroutineTween.cs b/UnityEngine.UI/UI/Animation/CoroutineTween.cs index aa2f526..0538fe1 100644 --- a/UnityEngine.UI/UI/Animation/CoroutineTween.cs +++ b/UnityEngine.UI/UI/Animation/CoroutineTween.cs @@ -27,7 +27,7 @@ public enum ColorTweenMode Alpha } - public class ColorTweenCallback : UnityEvent { } + public class ColorTweenCallback : UnityEvent {} private ColorTweenCallback m_Target; private Color m_StartColor; diff --git a/UnityEngine.UI/UI/Core/Button.cs b/UnityEngine.UI/UI/Core/Button.cs index 29d3f6c..de9608a 100644 --- a/UnityEngine.UI/UI/Core/Button.cs +++ b/UnityEngine.UI/UI/Core/Button.cs @@ -11,7 +11,7 @@ namespace UnityEngine.UI public class Button : Selectable, IPointerClickHandler, ISubmitHandler { [Serializable] - public class ButtonClickedEvent : UnityEvent { } + public class ButtonClickedEvent : UnityEvent {} // Event delegates triggered on click. [FormerlySerializedAs("onClick")] @@ -19,7 +19,7 @@ public class ButtonClickedEvent : UnityEvent { } private ButtonClickedEvent m_OnClick = new ButtonClickedEvent(); protected Button() - { } + {} public ButtonClickedEvent onClick { diff --git a/UnityEngine.UI/UI/Core/FontData.cs b/UnityEngine.UI/UI/Core/FontData.cs index 764ee8a..0b72deb 100644 --- a/UnityEngine.UI/UI/Core/FontData.cs +++ b/UnityEngine.UI/UI/Core/FontData.cs @@ -8,7 +8,7 @@ namespace UnityEngine.UI /// [Serializable] - public struct FontData : ISerializationCallbackReceiver + public class FontData : ISerializationCallbackReceiver { [SerializeField] [FormerlySerializedAs("font")] @@ -136,7 +136,7 @@ public float lineSpacing } void ISerializationCallbackReceiver.OnBeforeSerialize() - { } + {} void ISerializationCallbackReceiver.OnAfterDeserialize() { diff --git a/UnityEngine.UI/UI/Core/FontUpdateTracker.cs b/UnityEngine.UI/UI/Core/FontUpdateTracker.cs index 28eb6b0..900cb77 100644 --- a/UnityEngine.UI/UI/Core/FontUpdateTracker.cs +++ b/UnityEngine.UI/UI/Core/FontUpdateTracker.cs @@ -20,7 +20,7 @@ public static void TrackText(Text t) exists = new List(); m_Tracked.Add(t.font, exists); - t.font.textureRebuildCallback += RebuildForFont(t.font); + Font.textureRebuilt += RebuildForFont; } for (int i = 0; i < exists.Count; i++) @@ -32,19 +32,16 @@ public static void TrackText(Text t) exists.Add(t); } - private static Font.FontTextureRebuildCallback RebuildForFont(Font f) + private static void RebuildForFont(Font f) { - return () => - { - List texts; - m_Tracked.TryGetValue(f, out texts); + List texts; + m_Tracked.TryGetValue(f, out texts); - if (texts == null) - return; + if (texts == null) + return; - for (var i = 0; i < texts.Count; i++) - texts[i].FontTextureChanged(); - }; + for (var i = 0; i < texts.Count; i++) + texts[i].FontTextureChanged(); } public static void UntrackText(Text t) diff --git a/UnityEngine.UI/UI/Core/Graphic.cs b/UnityEngine.UI/UI/Core/Graphic.cs index 3d567f7..940a51c 100644 --- a/UnityEngine.UI/UI/Core/Graphic.cs +++ b/UnityEngine.UI/UI/Core/Graphic.cs @@ -291,6 +291,22 @@ private void SendGraphicEnabledDisabled() #endregion + protected override void OnCanvasHierarchyChanged() + { + if (!IsActive()) + return; + + // Use m_Cavas so we dont auto call CacheCanvas + Canvas currentCanvas = m_Canvas; + CacheCanvas(); + + if (currentCanvas != m_Canvas) + { + GraphicRegistry.UnregisterGraphicForCanvas(currentCanvas, this); + GraphicRegistry.RegisterGraphicForCanvas(canvas, this); + } + } + public virtual void Rebuild(CanvasUpdate update) { switch (update) @@ -386,7 +402,7 @@ protected override void OnDidApplyAnimationProperties() /// /// Make the Graphic have the native size of its content. /// - public virtual void SetNativeSize() { } + public virtual void SetNativeSize() {} public virtual bool Raycast(Vector2 sp, Camera eventCamera) { var t = transform; diff --git a/UnityEngine.UI/UI/Core/GraphicRaycaster.cs b/UnityEngine.UI/UI/Core/GraphicRaycaster.cs index 7222e9d..08614ea 100644 --- a/UnityEngine.UI/UI/Core/GraphicRaycaster.cs +++ b/UnityEngine.UI/UI/Core/GraphicRaycaster.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text; using UnityEngine.EventSystems; +using UnityEngine.Serialization; namespace UnityEngine.UI { @@ -42,8 +43,10 @@ public override int renderOrderPriority } } + [FormerlySerializedAs("ignoreReversedGraphics")] [SerializeField] private bool m_IgnoreReversedGraphics = true; + [FormerlySerializedAs("blockingObjects")] [SerializeField] private BlockingObjects m_BlockingObjects = BlockingObjects.None; @@ -56,7 +59,7 @@ public override int renderOrderPriority private Canvas m_Canvas; protected GraphicRaycaster() - { } + {} private Canvas canvas { @@ -151,8 +154,10 @@ public override void Raycast(PointerEventData eventData, List res distance = 0; else { + Transform trans = go.transform; + Vector3 transForward = trans.forward; // http://geomalgorithms.com/a06-_intersect-2.html - distance = (Vector3.Dot(go.transform.forward, go.transform.position - ray.origin) / Vector3.Dot(go.transform.forward, ray.direction)); + distance = (Vector3.Dot(transForward, trans.position - ray.origin) / Vector3.Dot(transForward, ray.direction)); // Check to see if the go is behind the camera. if (distance < 0) @@ -169,7 +174,7 @@ public override void Raycast(PointerEventData eventData, List res distance = distance, index = resultAppendList.Count, depth = m_RaycastResults[index].depth, - sortingLayer = canvas.sortingLayerID, + sortingLayer = canvas.cachedSortingLayerValue, sortingOrder = canvas.sortingOrder }; resultAppendList.Add(castResult); @@ -217,10 +222,10 @@ private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPo } s_SortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth)); - // StringBuilder cast = new StringBuilder(); + // StringBuilder cast = new StringBuilder(); for (int i = 0; i < s_SortedGraphics.Count; ++i) results.Add(s_SortedGraphics[i]); - // Debug.Log (cast.ToString()); + // Debug.Log (cast.ToString()); } } } diff --git a/UnityEngine.UI/UI/Core/Image.cs b/UnityEngine.UI/UI/Core/Image.cs index c10f8fa..5c4382f 100644 --- a/UnityEngine.UI/UI/Core/Image.cs +++ b/UnityEngine.UI/UI/Core/Image.cs @@ -104,7 +104,7 @@ public enum Origin360 public float eventAlphaThreshold { get { return m_EventAlphaThreshold; } set { m_EventAlphaThreshold = value; } } protected Image() - { } + {} /// /// Image's texture comes from the UnityEngine.Image. @@ -150,7 +150,7 @@ public float pixelsPerUnit } } - public virtual void OnBeforeSerialize() { } + public virtual void OnBeforeSerialize() {} public virtual void OnAfterDeserialize() { @@ -851,8 +851,8 @@ static void RadialCut(Vector2[] xy, float cos, float sin, bool invert, int corne #endregion - public virtual void CalculateLayoutInputHorizontal() { } - public virtual void CalculateLayoutInputVertical() { } + public virtual void CalculateLayoutInputHorizontal() {} + public virtual void CalculateLayoutInputVertical() {} public virtual float minWidth { get { return 0; } } diff --git a/UnityEngine.UI/UI/Core/InputField.cs b/UnityEngine.UI/UI/Core/InputField.cs index b51ac9f..7d8009b 100644 --- a/UnityEngine.UI/UI/Core/InputField.cs +++ b/UnityEngine.UI/UI/Core/InputField.cs @@ -64,10 +64,10 @@ public enum LineType public delegate char OnValidateInput(string text, int charIndex, char addedChar); [Serializable] - public class SubmitEvent : UnityEvent { } + public class SubmitEvent : UnityEvent {} [Serializable] - public class OnChangeEvent : UnityEvent { } + public class OnChangeEvent : UnityEvent {} static protected TouchScreenKeyboard m_Keyboard; static private readonly char[] kSeparators = { ' ', '.', ',' }; @@ -168,8 +168,8 @@ public class OnChangeEvent : UnityEvent { } protected string m_Text = string.Empty; [SerializeField] - [Range(0f, 8f)] - private float m_CaretBlinkRate = 1.7f; + [Range(0f, 4f)] + private float m_CaretBlinkRate = 0.85f; #endregion @@ -179,6 +179,7 @@ public class OnChangeEvent : UnityEvent { } protected UIVertex[] m_CursorVerts = null; private TextGenerator m_InputTextCache; private CanvasRenderer m_CachedInputRenderer; + private bool m_PreventFontCallback = false; private readonly List m_Vbo = new List(); private bool m_AllowInput = false; private bool m_ShouldActivateNextUpdate = false; @@ -187,7 +188,7 @@ public class OnChangeEvent : UnityEvent { } private const float kHScrollSpeed = 0.05f; private const float kVScrollSpeed = 0.10f; protected bool m_CaretVisible; - private Coroutine m_BlickCoroutine = null; + private Coroutine m_BlinkCoroutine = null; private float m_BlinkStartTime = 0.0f; protected int m_DrawStart = 0; protected int m_DrawEnd = 0; @@ -200,7 +201,7 @@ public class OnChangeEvent : UnityEvent { } const string kEmailSpecialCharacters = "!#$%&'*+-/=?^_`{|}~"; protected InputField() - { } + {} protected TextGenerator cachedInputTextGenerator @@ -334,11 +335,59 @@ protected void ClampPos(ref int pos) /// /// Current position of the cursor. + /// Getters are public Setters are protected /// - protected int caretPosition { get { return m_CaretPosition + Input.compositionString.Length; } set { m_CaretPosition = value; ClampPos(ref m_CaretPosition); } } - protected int caretSelectPos { get { return m_CaretSelectPosition + Input.compositionString.Length; } set { m_CaretSelectPosition = value; ClampPos(ref m_CaretSelectPosition); } } - private bool hasSelection { get { return caretPosition != caretSelectPos; } } + protected int caretPositionInternal { get { return m_CaretPosition + Input.compositionString.Length; } set { m_CaretPosition = value; ClampPos(ref m_CaretPosition); } } + protected int caretSelectPositionInternal { get { return m_CaretSelectPosition + Input.compositionString.Length; } set { m_CaretSelectPosition = value; ClampPos(ref m_CaretSelectPosition); } } + private bool hasSelection { get { return caretPositionInternal != caretSelectPositionInternal; } } + + /// + /// Get: Returns the focus position as thats the position that moves around even during selection. + /// Set: Set both the anchor and focus position such that a selection doesn't happen + /// + + public int caretPosition + { + get { return m_CaretSelectPosition + Input.compositionString.Length; } + set { selectionAnchorPosition = value; selectionFocusPosition = value; } + } + + /// + /// Get: Returns the fixed position of selection + /// Set: If Input.compositionString is 0 set the fixed position + /// + + public int selectionAnchorPosition + { + get { return m_CaretPosition + Input.compositionString.Length; } + set + { + if (Input.compositionString.Length != 0) + return; + + m_CaretPosition = value; + ClampPos(ref m_CaretPosition); + } + } + + /// + /// Get: Returns the variable position of selection + /// Set: If Input.compositionString is 0 set the variable position + /// + + public int selectionFocusPosition + { + get { return m_CaretSelectPosition + Input.compositionString.Length; } + set + { + if (Input.compositionString.Length != 0) + return; + + m_CaretSelectPosition = value; + ClampPos(ref m_CaretSelectPosition); + } + } #if UNITY_EDITOR // Remember: This is NOT related to text validation! @@ -347,6 +396,11 @@ protected override void OnValidate() { base.OnValidate(); EnforceContentType(); + + //This can be invoked before OnEnabled is called. So we shouldn't be accessing other objects, before OnEnable is called. + if (!IsActive()) + return; + UpdateLabel(); if (m_AllowInput) SetCaretActive(); @@ -371,6 +425,9 @@ protected override void OnEnable() protected override void OnDisable() { + // the coroutine will be terminated, so this will ensure it restarts when we are next activated + m_BlinkCoroutine = null; + DeactivateInputField(); if (m_TextComponent != null) { @@ -393,21 +450,21 @@ IEnumerator CaretBlink() while (isFocused && m_CaretBlinkRate > 0) { - // Update caret state as first thing after waiting. - // This also ensures m_CaretBlinkRate didn't get set to 0 in between - // checking it above and running this time comparison. - if (m_BlinkStartTime + (1f / m_CaretBlinkRate) < Time.unscaledTime) - { - m_CaretVisible = !m_CaretVisible; - m_BlinkStartTime = Time.unscaledTime; + // the blink rate is expressed as a frequency + float blinkPeriod = 1f / m_CaretBlinkRate; + // the caret should be ON if we are in the first half of the blink period + bool blinkState = (Time.unscaledTime - m_BlinkStartTime) % blinkPeriod < blinkPeriod / 2; + if (m_CaretVisible != blinkState) + { + m_CaretVisible = blinkState; UpdateGeometry(); } // Then wait again. yield return null; } - m_BlickCoroutine = null; + m_BlinkCoroutine = null; } void SetCaretVisible() @@ -429,8 +486,8 @@ void SetCaretActive() if (m_CaretBlinkRate > 0.0f) { - if (m_BlickCoroutine == null) - m_BlickCoroutine = StartCoroutine(CaretBlink()); + if (m_BlinkCoroutine == null) + m_BlinkCoroutine = StartCoroutine(CaretBlink()); } else { @@ -445,8 +502,8 @@ protected void OnFocus() protected void SelectAll() { - caretPosition = text.Length; - caretSelectPos = 0; + caretPositionInternal = text.Length; + caretSelectPositionInternal = 0; } public void MoveTextEnd(bool shift) @@ -455,12 +512,12 @@ public void MoveTextEnd(bool shift) if (shift) { - caretSelectPos = position; + caretSelectPositionInternal = position; } else { - caretPosition = position; - caretSelectPos = caretPosition; + caretPositionInternal = position; + caretSelectPositionInternal = caretPositionInternal; } UpdateLabel(); } @@ -471,12 +528,12 @@ public void MoveTextStart(bool shift) if (shift) { - caretSelectPos = position; + caretSelectPositionInternal = position; } else { - caretPosition = position; - caretSelectPos = caretPosition; + caretPositionInternal = position; + caretSelectPositionInternal = caretPositionInternal; } UpdateLabel(); @@ -571,7 +628,7 @@ protected virtual void LateUpdate() if (characterLimit > 0 && m_Text.Length > characterLimit) m_Text = m_Text.Substring(0, characterLimit); - caretPosition = caretSelectPos = m_Text.Length; + caretPositionInternal = caretSelectPositionInternal = m_Text.Length; // Set keyboard text before updating label, as we might have changed it with validation // and update label will take the old value from keyboard if we don't change it here @@ -696,7 +753,7 @@ public virtual void OnDrag(PointerEventData eventData) Vector2 localMousePos; RectTransformUtility.ScreenPointToLocalPointInRectangle(textComponent.rectTransform, eventData.position, eventData.pressEventCamera, out localMousePos); - caretSelectPos = GetCharacterIndexFromPosition(localMousePos) + m_DrawStart; + caretSelectPositionInternal = GetCharacterIndexFromPosition(localMousePos) + m_DrawStart; MarkGeometryAsDirty(); m_DragPositionOutOfBounds = !RectTransformUtility.RectangleContainsScreenPoint(textComponent.rectTransform, eventData.position, eventData.pressEventCamera); @@ -768,7 +825,7 @@ public override void OnPointerDown(PointerEventData eventData) if (hadFocusBefore) { Vector2 pos = ScreenToLocal(eventData.position); - caretSelectPos = caretPosition = GetCharacterIndexFromPosition(pos) + m_DrawStart; + caretSelectPositionInternal = caretPositionInternal = GetCharacterIndexFromPosition(pos) + m_DrawStart; } UpdateLabel(); eventData.Use(); @@ -787,6 +844,8 @@ protected EditState KeyPressed(Event evt) bool isMac = (rp == RuntimePlatform.OSXEditor || rp == RuntimePlatform.OSXPlayer || rp == RuntimePlatform.OSXWebPlayer); bool ctrl = isMac ? (currentEventModifiers & EventModifiers.Command) != 0 : (currentEventModifiers & EventModifiers.Control) != 0; bool shift = (currentEventModifiers & EventModifiers.Shift) != 0; + bool alt = (currentEventModifiers & EventModifiers.Alt) != 0; + bool ctrlOnly = ctrl && !alt && !shift; switch (evt.keyCode) { @@ -817,7 +876,7 @@ protected EditState KeyPressed(Event evt) // Select All case KeyCode.A: { - if (ctrl) + if (ctrlOnly) { SelectAll(); return EditState.Continue; @@ -828,7 +887,7 @@ protected EditState KeyPressed(Event evt) // Copy case KeyCode.C: { - if (ctrl) + if (ctrlOnly) { clipboard = GetSelectedString(); return EditState.Continue; @@ -839,7 +898,7 @@ protected EditState KeyPressed(Event evt) // Paste case KeyCode.V: { - if (ctrl) + if (ctrlOnly) { Append(clipboard); return EditState.Continue; @@ -850,7 +909,7 @@ protected EditState KeyPressed(Event evt) // Cut case KeyCode.X: { - if (ctrl) + if (ctrlOnly) { clipboard = GetSelectedString(); Delete(); @@ -979,8 +1038,8 @@ private string GetSelectedString() if (!hasSelection) return ""; - int startPos = caretPosition; - int endPos = caretSelectPos; + int startPos = caretPositionInternal; + int endPos = caretSelectPositionInternal; // Ensure pos is always less then selPos to make the code simpler if (startPos > endPos) @@ -1000,10 +1059,10 @@ private string GetSelectedString() private int FindtNextWordBegin() { - if (caretSelectPos + 1 >= text.Length) + if (caretSelectPositionInternal + 1 >= text.Length) return text.Length; - int spaceLoc = text.IndexOfAny(kSeparators, caretSelectPos + 1); + int spaceLoc = text.IndexOfAny(kSeparators, caretSelectPositionInternal + 1); if (spaceLoc == -1) spaceLoc = text.Length; @@ -1019,7 +1078,7 @@ private void MoveRight(bool shift, bool ctrl) { // By convention, if we have a selection and move right without holding shift, // we just place the cursor at the end. - caretPosition = caretSelectPos = Mathf.Max(caretPosition, caretSelectPos); + caretPositionInternal = caretSelectPositionInternal = Mathf.Max(caretPositionInternal, caretSelectPositionInternal); return; } @@ -1027,20 +1086,20 @@ private void MoveRight(bool shift, bool ctrl) if (ctrl) position = FindtNextWordBegin(); else - position = caretSelectPos + 1; + position = caretSelectPositionInternal + 1; if (shift) - caretSelectPos = position; + caretSelectPositionInternal = position; else - caretSelectPos = caretPosition = position; + caretSelectPositionInternal = caretPositionInternal = position; } private int FindtPrevWordBegin() { - if (caretSelectPos - 2 < 0) + if (caretSelectPositionInternal - 2 < 0) return 0; - int spaceLoc = text.LastIndexOfAny(kSeparators, caretSelectPos - 2); + int spaceLoc = text.LastIndexOfAny(kSeparators, caretSelectPositionInternal - 2); if (spaceLoc == -1) spaceLoc = 0; @@ -1056,7 +1115,7 @@ private void MoveLeft(bool shift, bool ctrl) { // By convention, if we have a selection and move left without holding shift, // we just place the cursor at the start. - caretPosition = caretSelectPos = Mathf.Min(caretPosition, caretSelectPos); + caretPositionInternal = caretSelectPositionInternal = Mathf.Min(caretPositionInternal, caretSelectPositionInternal); return; } @@ -1064,12 +1123,12 @@ private void MoveLeft(bool shift, bool ctrl) if (ctrl) position = FindtPrevWordBegin(); else - position = caretSelectPos - 1; + position = caretSelectPositionInternal - 1; if (shift) - caretSelectPos = position; + caretSelectPositionInternal = position; else - caretSelectPos = caretPosition = position; + caretSelectPositionInternal = caretPositionInternal = position; } private int DetermineCharacterLine(int charPos, TextGenerator generator) @@ -1151,15 +1210,15 @@ private void MoveDown(bool shift, bool goToLastChar) { // If we have a selection and press down without shift, // set caret position to end of selection before we move it down. - caretPosition = caretSelectPos = Mathf.Max(caretPosition, caretSelectPos); + caretPositionInternal = caretSelectPositionInternal = Mathf.Max(caretPositionInternal, caretSelectPositionInternal); } - int position = multiLine ? LineDownCharacterPosition(caretSelectPos, goToLastChar) : text.Length; + int position = multiLine ? LineDownCharacterPosition(caretSelectPositionInternal, goToLastChar) : text.Length; if (shift) - caretSelectPos = position; + caretSelectPositionInternal = position; else - caretPosition = caretSelectPos = position; + caretPositionInternal = caretSelectPositionInternal = position; } private void MoveUp(bool shift) @@ -1173,31 +1232,31 @@ private void MoveUp(bool shift, bool goToFirstChar) { // If we have a selection and press up without shift, // set caret position to start of selection before we move it up. - caretPosition = caretSelectPos = Mathf.Min(caretPosition, caretSelectPos); + caretPositionInternal = caretSelectPositionInternal = Mathf.Min(caretPositionInternal, caretSelectPositionInternal); } - int position = multiLine ? LineUpCharacterPosition(caretSelectPos, goToFirstChar) : 0; + int position = multiLine ? LineUpCharacterPosition(caretSelectPositionInternal, goToFirstChar) : 0; if (shift) - caretSelectPos = position; + caretSelectPositionInternal = position; else - caretSelectPos = caretPosition = position; + caretSelectPositionInternal = caretPositionInternal = position; } private void Delete() { - if (caretPosition == caretSelectPos) + if (caretPositionInternal == caretSelectPositionInternal) return; - if (caretPosition < caretSelectPos) + if (caretPositionInternal < caretSelectPositionInternal) { - m_Text = text.Substring(0, caretPosition) + text.Substring(caretSelectPos, text.Length - caretSelectPos); - caretSelectPos = caretPosition; + m_Text = text.Substring(0, caretPositionInternal) + text.Substring(caretSelectPositionInternal, text.Length - caretSelectPositionInternal); + caretSelectPositionInternal = caretPositionInternal; } else { - m_Text = text.Substring(0, caretSelectPos) + text.Substring(caretPosition, text.Length - caretPosition); - caretPosition = caretSelectPos; + m_Text = text.Substring(0, caretSelectPositionInternal) + text.Substring(caretPositionInternal, text.Length - caretPositionInternal); + caretPositionInternal = caretSelectPositionInternal; } } @@ -1210,9 +1269,9 @@ private void ForwardSpace() } else { - if (caretPosition < text.Length) + if (caretPositionInternal < text.Length) { - m_Text = text.Remove(caretPosition, 1); + m_Text = text.Remove(caretPositionInternal, 1); SendOnValueChangedAndUpdateLabel(); } } @@ -1227,10 +1286,10 @@ private void Backspace() } else { - if (caretPosition > 0) + if (caretPositionInternal > 0) { - m_Text = text.Remove(caretPosition - 1, 1); - caretSelectPos = caretPosition = caretPosition - 1; + m_Text = text.Remove(caretPositionInternal - 1, 1); + caretSelectPositionInternal = caretPositionInternal = caretPositionInternal - 1; SendOnValueChangedAndUpdateLabel(); } } @@ -1247,7 +1306,7 @@ private void Insert(char c) return; m_Text = text.Insert(m_CaretPosition, replaceString); - caretSelectPos = caretPosition += replaceString.Length; + caretSelectPositionInternal = caretPositionInternal += replaceString.Length; SendOnValueChanged(); } @@ -1301,9 +1360,9 @@ protected virtual void Append(char input) // If we have an input validator, validate the input first if (onValidateInput != null) - input = onValidateInput(text, caretPosition, input); + input = onValidateInput(text, caretPositionInternal, input); else if (characterValidation != CharacterValidation.None) - input = Validate(text, caretPosition, input); + input = Validate(text, caretPositionInternal, input); // If the input is invalid, skip it if (input == 0) @@ -1319,7 +1378,7 @@ protected virtual void Append(char input) protected void UpdateLabel() { - if (m_TextComponent != null && m_TextComponent.font != null) + if (m_TextComponent != null && m_TextComponent.font != null && !m_PreventFontCallback) { string fullText; if (Input.compositionString.Length > 0) @@ -1355,9 +1414,21 @@ protected void UpdateLabel() var settings = m_TextComponent.GetGenerationSettings(extents); settings.generateOutOfBounds = true; + + // TextGenerator.Populate invokes a callback that's called for anything + // that needs to be updated when the data for that font has changed. + // This makes all Text components that use that font update their vertices. + // In turn, this makes the InputField that's associated with that Text component + // update its label by calling this UpdateLabel method. + // This is a recursive call we want to prevent, since it makes the InputField + // update based on font data that didn't yet finish executing, or alternatively + // hang on infinite recursion, depending on whether the cached value is cached + // before or after the calculation. + m_PreventFontCallback = true; cachedInputTextGenerator.Populate(processed, settings); + m_PreventFontCallback = false; - SetDrawRangeToContainCaretPosition(cachedInputTextGenerator, caretSelectPos, ref m_DrawStart, ref m_DrawEnd); + SetDrawRangeToContainCaretPosition(cachedInputTextGenerator, caretSelectPositionInternal, ref m_DrawStart, ref m_DrawEnd); processed = processed.Substring(m_DrawStart, Mathf.Min(m_DrawEnd, processed.Length) - m_DrawStart); @@ -1371,10 +1442,10 @@ protected void UpdateLabel() private bool IsSelectionVisible() { - if (m_DrawStart > caretPosition || m_DrawStart > caretSelectPos) + if (m_DrawStart > caretPositionInternal || m_DrawStart > caretSelectPositionInternal) return false; - if (m_DrawEnd < caretPosition || m_DrawEnd < caretSelectPos) + if (m_DrawEnd < caretPositionInternal || m_DrawEnd < caretSelectPositionInternal) return false; return true; @@ -1450,6 +1521,7 @@ private void SetDrawRangeToContainCaretPosition(TextGenerator gen, int caretPos, if (height < lines[startLine].height) break; drawStart = GetLineStartPosition(gen, startLine); + height -= lines[startLine].height; } else @@ -1620,7 +1692,7 @@ private void GenerateCursor(List vbo, Vector2 roundingOffset) float width = 1f; float height = m_TextComponent.fontSize; - int adjustedPos = Mathf.Max(0, caretPosition - m_DrawStart); + int adjustedPos = Mathf.Max(0, caretPositionInternal - m_DrawStart); TextGenerator gen = m_TextComponent.cachedTextGenerator; if (gen == null) @@ -1631,11 +1703,12 @@ private void GenerateCursor(List vbo, Vector2 roundingOffset) Vector2 startPosition = Vector2.zero; - // Calculate startPosition.x + // Calculate startPosition if (gen.characterCountVisible + 1 > adjustedPos || adjustedPos == 0) { UICharInfo cursorChar = gen.characters[adjustedPos]; startPosition.x = cursorChar.cursorPos.x; + startPosition.y = cursorChar.cursorPos.y; } startPosition.x /= m_TextComponent.pixelsPerUnit; @@ -1643,11 +1716,6 @@ private void GenerateCursor(List vbo, Vector2 roundingOffset) if (startPosition.x > m_TextComponent.rectTransform.rect.xMax) startPosition.x = m_TextComponent.rectTransform.rect.xMax; - // Calculate startPosition.y - int characterLine = DetermineCharacterLine(adjustedPos, gen); - float lineHeights = SumLineHeights(characterLine, gen); - startPosition.y = m_TextComponent.rectTransform.rect.yMax - lineHeights / m_TextComponent.pixelsPerUnit; - m_CursorVerts[0].position = new Vector3(startPosition.x, startPosition.y - height, 0.0f); m_CursorVerts[1].position = new Vector3(startPosition.x + width, startPosition.y - height, 0.0f); m_CursorVerts[2].position = new Vector3(startPosition.x + width, startPosition.y, 0.0f); @@ -1700,8 +1768,8 @@ private float SumLineHeights(int endLine, TextGenerator generator) private void GenerateHightlight(List vbo, Vector2 roundingOffset) { - int startChar = Mathf.Max(0, caretPosition - m_DrawStart); - int endChar = Mathf.Max(0, caretSelectPos - m_DrawStart); + int startChar = Mathf.Max(0, caretPositionInternal - m_DrawStart); + int endChar = Mathf.Max(0, caretSelectPositionInternal - m_DrawStart); // Ensure pos is always less then selPos to make the code simpler if (startChar > endChar) @@ -1744,8 +1812,7 @@ private void GenerateHightlight(List vbo, Vector2 roundingOffset) { UICharInfo startCharInfo = gen.characters[startChar]; UICharInfo endCharInfo = gen.characters[currentChar]; - float lineHeights = SumLineHeights(currentLineIndex, gen); - Vector2 startPosition = new Vector2(startCharInfo.cursorPos.x / m_TextComponent.pixelsPerUnit, m_TextComponent.rectTransform.rect.yMax - (lineHeights / m_TextComponent.pixelsPerUnit)); + Vector2 startPosition = new Vector2(startCharInfo.cursorPos.x / m_TextComponent.pixelsPerUnit, startCharInfo.cursorPos.y); Vector2 endPosition = new Vector2((endCharInfo.cursorPos.x + endCharInfo.charWidth) / m_TextComponent.pixelsPerUnit, startPosition.y - height / m_TextComponent.pixelsPerUnit); // Checking xMin as well due to text generator not setting possition if char is not rendered. @@ -1927,7 +1994,7 @@ public void DeactivateInputField() m_HasDoneFocusTransition = false; m_AllowInput = false; - if (m_TextComponent != null && IsActive() && IsInteractable()) + if (m_TextComponent != null && IsInteractable()) { if (m_WasCanceled) text = m_OriginalText; diff --git a/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs b/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs index bb81bb6..1d15328 100644 --- a/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs +++ b/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs @@ -30,7 +30,7 @@ private RectTransform rectTransform private DrivenRectTransformTracker m_Tracker; - protected AspectRatioFitter() { } + protected AspectRatioFitter() {} #region Unity Lifetime calls @@ -127,9 +127,9 @@ private Vector2 GetParentSize() return parent.rect.size; } - public virtual void SetLayoutHorizontal() { } + public virtual void SetLayoutHorizontal() {} - public virtual void SetLayoutVertical() { } + public virtual void SetLayoutVertical() {} protected void SetDirty() { diff --git a/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs b/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs index 23707a8..9b5ef14 100644 --- a/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs +++ b/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs @@ -79,7 +79,7 @@ public enum Unit { Centimeters, Millimeters, Inches, Points, Picas } private float m_PrevReferencePixelsPerUnit = 100; - protected CanvasScaler() { } + protected CanvasScaler() {} protected override void OnEnable() { diff --git a/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs b/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs index 22a3367..c326a44 100644 --- a/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs +++ b/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs @@ -34,7 +34,7 @@ private RectTransform rectTransform private DrivenRectTransformTracker m_Tracker; protected ContentSizeFitter() - { } + {} #region Unity Lifetime calls diff --git a/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs b/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs index 50f9e5f..170e410 100644 --- a/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs +++ b/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs @@ -26,10 +26,19 @@ public enum Constraint { Flexible = 0, FixedColumnCount = 1, FixedRowCount = 2 } public Constraint constraint { get { return m_Constraint; } set { SetProperty(ref m_Constraint, value); } } [SerializeField] protected int m_ConstraintCount = 2; - public int constraintCount { get { return m_ConstraintCount; } set { SetProperty(ref m_ConstraintCount, value); } } + public int constraintCount { get { return m_ConstraintCount; } set { SetProperty(ref m_ConstraintCount, Mathf.Max(1, value)); } } protected GridLayoutGroup() - { } + {} + + #if UNITY_EDITOR + protected override void OnValidate() + { + base.OnValidate(); + constraintCount = constraintCount; + } + + #endif public override void CalculateLayoutInputHorizontal() { @@ -133,8 +142,15 @@ private void SetCellsAlongAxis(int axis) } else { - cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x))); - cellCountY = Mathf.Max(1, Mathf.FloorToInt((height - padding.vertical + spacing.y + 0.001f) / (cellSize.y + spacing.y))); + if (cellSize.x + spacing.x <= 0) + cellCountX = int.MaxValue; + else + cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x))); + + if (cellSize.y + spacing.y <= 0) + cellCountY = int.MaxValue; + else + cellCountY = Mathf.Max(1, Mathf.FloorToInt((height - padding.vertical + spacing.y + 0.001f) / (cellSize.y + spacing.y))); } int cornerX = (int)startCorner % 2; diff --git a/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs b/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs index 93f977f..efe8d8e 100644 --- a/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs +++ b/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs @@ -4,7 +4,7 @@ namespace UnityEngine.UI public class HorizontalLayoutGroup : HorizontalOrVerticalLayoutGroup { protected HorizontalLayoutGroup() - { } + {} public override void CalculateLayoutInputHorizontal() { diff --git a/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs b/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs index 715f1b0..dfcb35c 100644 --- a/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs +++ b/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs @@ -20,8 +20,8 @@ public class LayoutElement : UIBehaviour, ILayoutElement, ILayoutIgnorer public virtual bool ignoreLayout { get { return m_IgnoreLayout; } set { if (SetPropertyUtility.SetStruct(ref m_IgnoreLayout, value)) SetDirty(); } } - public virtual void CalculateLayoutInputHorizontal() { } - public virtual void CalculateLayoutInputVertical() { } + public virtual void CalculateLayoutInputHorizontal() {} + public virtual void CalculateLayoutInputVertical() {} public virtual float minWidth { get { return m_MinWidth; } set { if (SetPropertyUtility.SetStruct(ref m_MinWidth, value)) SetDirty(); } } public virtual float minHeight { get { return m_MinHeight; } set { if (SetPropertyUtility.SetStruct(ref m_MinHeight, value)) SetDirty(); } } public virtual float preferredWidth { get { return m_PreferredWidth; } set { if (SetPropertyUtility.SetStruct(ref m_PreferredWidth, value)) SetDirty(); } } @@ -32,7 +32,7 @@ public virtual void CalculateLayoutInputVertical() { } protected LayoutElement() - { } + {} #region Unity Lifetime calls diff --git a/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs b/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs index b11e2c4..a7961bd 100644 --- a/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs +++ b/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs @@ -4,6 +4,7 @@ namespace UnityEngine.UI { + [DisallowMultipleComponent] [ExecuteInEditMode] [RequireComponent(typeof(RectTransform))] public abstract class LayoutGroup : UIBehaviour, ILayoutElement, ILayoutGroup diff --git a/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs b/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs index acc947d..122cfb0 100644 --- a/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs +++ b/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs @@ -7,10 +7,18 @@ namespace UnityEngine.UI public struct LayoutRebuilder : ICanvasElement, IEquatable { private readonly RectTransform m_ToRebuild; + //There are a few of reasons we need to cache the Hash fromt he transform: + // - This is a ValueType (struct) and .Net calculates Hash from the Value Type fields. + // - The key of a Dictionary should have a constant Hash value. + // - It's possible for the Transform to get nulled from the Native side. + // We use this struct with the IndexedSet container, which uses a dictionary as part of it's implementation + // So this struct gets used as a key to a dictionary, so we need to guarantee a constant Hash value. + private readonly int m_CachedHashFromTransform; private LayoutRebuilder(RectTransform controller) { m_ToRebuild = controller; + m_CachedHashFromTransform = m_ToRebuild.GetHashCode(); } static LayoutRebuilder() @@ -172,6 +180,11 @@ public bool Equals(LayoutRebuilder other) return m_ToRebuild == other.m_ToRebuild; } + public override int GetHashCode() + { + return m_CachedHashFromTransform; + } + public override string ToString() { return "(Layout Rebuilder for) " + m_ToRebuild; diff --git a/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs b/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs index 2498025..e24b842 100644 --- a/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs +++ b/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs @@ -4,7 +4,7 @@ namespace UnityEngine.UI public class VerticalLayoutGroup : HorizontalOrVerticalLayoutGroup { protected VerticalLayoutGroup() - { } + {} public override void CalculateLayoutInputHorizontal() { diff --git a/UnityEngine.UI/UI/Core/MaterialModifiers/Mask.cs b/UnityEngine.UI/UI/Core/MaterialModifiers/Mask.cs index 350d83a..bfca56e 100644 --- a/UnityEngine.UI/UI/Core/MaterialModifiers/Mask.cs +++ b/UnityEngine.UI/UI/Core/MaterialModifiers/Mask.cs @@ -49,7 +49,7 @@ public RectTransform rectTransform } protected Mask() - { } + {} public virtual bool MaskEnabled() { diff --git a/UnityEngine.UI/UI/Core/RawImage.cs b/UnityEngine.UI/UI/Core/RawImage.cs index c5a466c..1c2e6de 100644 --- a/UnityEngine.UI/UI/Core/RawImage.cs +++ b/UnityEngine.UI/UI/Core/RawImage.cs @@ -16,7 +16,7 @@ public class RawImage : MaskableGraphic [SerializeField] Rect m_UVRect = new Rect(0f, 0f, 1f, 1f); protected RawImage() - { } + {} /// /// Returns the texture used to draw this Graphic. diff --git a/UnityEngine.UI/UI/Core/ScrollRect.cs b/UnityEngine.UI/UI/Core/ScrollRect.cs index 85eaab0..572fc67 100644 --- a/UnityEngine.UI/UI/Core/ScrollRect.cs +++ b/UnityEngine.UI/UI/Core/ScrollRect.cs @@ -18,7 +18,7 @@ public enum MovementType } [Serializable] - public class ScrollRectEvent : UnityEvent { } + public class ScrollRectEvent : UnityEvent {} [SerializeField] private RectTransform m_Content; @@ -123,7 +123,7 @@ protected RectTransform viewRect private bool m_HasRebuiltLayout = false; protected ScrollRect() - { } + {} public virtual void Rebuild(CanvasUpdate executing) { diff --git a/UnityEngine.UI/UI/Core/Scrollbar.cs b/UnityEngine.UI/UI/Core/Scrollbar.cs index 7333db5..2f7b0f0 100644 --- a/UnityEngine.UI/UI/Core/Scrollbar.cs +++ b/UnityEngine.UI/UI/Core/Scrollbar.cs @@ -18,7 +18,7 @@ public enum Direction } [Serializable] - public class ScrollEvent : UnityEvent { } + public class ScrollEvent : UnityEvent {} [SerializeField] private RectTransform m_HandleRect; @@ -30,7 +30,7 @@ public class ScrollEvent : UnityEvent { } public Direction direction { get { return m_Direction; } set { if (SetPropertyUtility.SetStruct(ref m_Direction, value)) UpdateVisuals(); } } protected Scrollbar() - { } + {} // Scroll bar's current value in 0 to 1 range. [Range(0f, 1f)] @@ -89,12 +89,17 @@ protected override void OnValidate() { base.OnValidate(); - size = size; + m_Size = Mathf.Clamp01(m_Size); + + //This can be invoked before OnEnabled is called. So we shouldn't be accessing other objects, before OnEnable is called. + if (IsActive()) + { + UpdateCachedReferences(); + Set(m_Value, false); + // Update rects since other things might affect them even if value didn't change. + UpdateVisuals(); + } - UpdateCachedReferences(); - Set(m_Value, false); - // Update rects since other things might affect them even if value didn't change. - UpdateVisuals(); var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this); if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying) CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this); @@ -157,6 +162,11 @@ void Set(float input, bool sendCallback) protected override void OnRectTransformDimensionsChange() { base.OnRectTransformDimensionsChange(); + + //This can be invoked before OnEnabled is called. So we shouldn't be accessing other objects, before OnEnable is called. + if (!IsActive()) + return; + UpdateVisuals(); } diff --git a/UnityEngine.UI/UI/Core/Selectable.cs b/UnityEngine.UI/UI/Core/Selectable.cs index 8aa31ea..21cb0a1 100644 --- a/UnityEngine.UI/UI/Core/Selectable.cs +++ b/UnityEngine.UI/UI/Core/Selectable.cs @@ -85,7 +85,7 @@ public enum Transition private bool hasSelection { get; set; } protected Selectable() - { } + {} // Convenience function that converts the Graphic to a Image, if possible public Image image diff --git a/UnityEngine.UI/UI/Core/Slider.cs b/UnityEngine.UI/UI/Core/Slider.cs index 20e9cd6..0f4e41d 100644 --- a/UnityEngine.UI/UI/Core/Slider.cs +++ b/UnityEngine.UI/UI/Core/Slider.cs @@ -17,7 +17,7 @@ public enum Direction } [Serializable] - public class SliderEvent : UnityEvent { } + public class SliderEvent : UnityEvent {} [SerializeField] private RectTransform m_FillRect; @@ -99,7 +99,7 @@ public float normalizedValue float stepSize { get { return wholeNumbers ? 1 : (maxValue - minValue) * 0.1f; } } protected Slider() - { } + {} #if UNITY_EDITOR protected override void OnValidate() @@ -111,10 +111,15 @@ protected override void OnValidate() m_MinValue = Mathf.Round(m_MinValue); m_MaxValue = Mathf.Round(m_MaxValue); } - UpdateCachedReferences(); - Set(m_Value, false); - // Update rects since other things might affect them even if value didn't change. - UpdateVisuals(); + + //Onvalidate is called before OnEnabled. We need to make sure not to touch any other objects before OnEnable is run. + if (IsActive()) + { + UpdateCachedReferences(); + Set(m_Value, false); + // Update rects since other things might affect them even if value didn't change. + UpdateVisuals(); + } var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this); if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying) @@ -199,6 +204,11 @@ void Set(float input, bool sendCallback) protected override void OnRectTransformDimensionsChange() { base.OnRectTransformDimensionsChange(); + + //This can be invoked before OnEnabled is called. So we shouldn't be accessing other objects, before OnEnable is called. + if (!IsActive()) + return; + UpdateVisuals(); } @@ -300,7 +310,6 @@ public virtual void OnDrag(PointerEventData eventData) { if (!MayDrag(eventData)) return; - UpdateDrag(eventData, eventData.pressEventCamera); } diff --git a/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs b/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs index d0ed7ec..bfdfa7c 100644 --- a/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs +++ b/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs @@ -19,7 +19,6 @@ internal class IndexedSet : IList //We use a Dictionary to speed up list lookup, this makes it cheaper to guarantee no duplicates (set) //When removing we move the last item to the removed item position, this way we only need to update the index cache of a single item. (fast removal) //Order of the elements is not guaranteed. A removal will change the order of the items. - //TODO: If we add support to sort, this could be used in the CanvasUpdateRegistry. readonly List m_List = new List(); Dictionary m_Dictionary = new Dictionary(); diff --git a/UnityEngine.UI/UI/Core/Text.cs b/UnityEngine.UI/UI/Core/Text.cs index 1a40c18..e1e337b 100644 --- a/UnityEngine.UI/UI/Core/Text.cs +++ b/UnityEngine.UI/UI/Core/Text.cs @@ -17,14 +17,13 @@ public class Text : MaskableGraphic, ILayoutElement private TextGenerator m_TextCache; private TextGenerator m_TextCacheForLayout; - private static float kEpsilon = 0.0001f; static protected Material s_DefaultText = null; // We use this flag instead of Unregistering/Registering the callback to avoid allocation. - [NonSerialized] private bool m_DisableFontTextureChangedCallback = false; + [NonSerialized] private bool m_DisableFontTextureRebuiltCallback = false; protected Text() - { } + {} /// /// Get or set the material used by this Text. @@ -76,7 +75,7 @@ public void FontTextureChanged() return; } - if (m_DisableFontTextureChangedCallback) + if (m_DisableFontTextureRebuiltCallback) return; cachedTextGenerator.Invalidate(); @@ -327,7 +326,7 @@ public FontStyle fontStyle } } - public float pixelsPerUnit + public float pixelsPerUnit { get { @@ -377,18 +376,17 @@ public TextGenerationSettings GetGenerationSettings(Vector2 extents) { var settings = new TextGenerationSettings(); - // Settings affected by pixels density - var pixelsPerUnitCached = pixelsPerUnit; - settings.generationExtents = extents * pixelsPerUnitCached + Vector2.one * kEpsilon; + settings.generationExtents = extents; if (font != null && font.dynamic) { - settings.fontSize = Mathf.Min(Mathf.FloorToInt(m_FontData.fontSize * pixelsPerUnitCached), 1000); - settings.resizeTextMinSize = Mathf.Min(Mathf.FloorToInt(m_FontData.minSize * pixelsPerUnitCached), 1000); - settings.resizeTextMaxSize = Mathf.Min(Mathf.FloorToInt(m_FontData.maxSize * pixelsPerUnitCached), 1000); + settings.fontSize = m_FontData.fontSize; + settings.resizeTextMinSize = m_FontData.minSize; + settings.resizeTextMaxSize = m_FontData.maxSize; } // Other settings settings.textAnchor = m_FontData.alignment; + settings.scaleFactor = pixelsPerUnit; settings.color = color; settings.font = font; settings.pivot = rectTransform.pivot; @@ -432,7 +430,7 @@ protected override void OnFillVBO(List vbo) // We dont care if we the font Texture changes while we are doing our Update. // The end result of cachedTextGenerator will be valid for this instance. // Otherwise we can get issues like Case 619238. - m_DisableFontTextureChangedCallback = true; + m_DisableFontTextureRebuiltCallback = true; Vector2 extents = rectTransform.rect.size; @@ -473,11 +471,11 @@ protected override void OnFillVBO(List vbo) vbo.Add(uiv); } } - m_DisableFontTextureChangedCallback = false; + m_DisableFontTextureRebuiltCallback = false; } - public virtual void CalculateLayoutInputHorizontal() { } - public virtual void CalculateLayoutInputVertical() { } + public virtual void CalculateLayoutInputHorizontal() {} + public virtual void CalculateLayoutInputVertical() {} public virtual float minWidth { diff --git a/UnityEngine.UI/UI/Core/Toggle.cs b/UnityEngine.UI/UI/Core/Toggle.cs index 1763836..284d9ec 100644 --- a/UnityEngine.UI/UI/Core/Toggle.cs +++ b/UnityEngine.UI/UI/Core/Toggle.cs @@ -20,7 +20,7 @@ public enum ToggleTransition [Serializable] public class ToggleEvent : UnityEvent - { } + {} /// /// Transition type. @@ -64,7 +64,7 @@ public ToggleGroup group private bool m_IsOn; protected Toggle() - { } + {} #if UNITY_EDITOR protected override void OnValidate() diff --git a/UnityEngine.UI/UI/Core/ToggleGroup.cs b/UnityEngine.UI/UI/Core/ToggleGroup.cs index 0154f3f..e678958 100644 --- a/UnityEngine.UI/UI/Core/ToggleGroup.cs +++ b/UnityEngine.UI/UI/Core/ToggleGroup.cs @@ -14,12 +14,12 @@ public class ToggleGroup : UIBehaviour private List m_Toggles = new List(); protected ToggleGroup() - { } + {} private void ValidateToggleIsInGroup(Toggle toggle) { if (toggle == null || !m_Toggles.Contains(toggle)) - throw new ArgumentException(string.Format("Toggle {0} is not part of ToggleGroup {1}", toggle, this)); + throw new ArgumentException(string.Format("Toggle {0} is not part of ToggleGroup {1}", new object[] {toggle, this})); } public void NotifyToggleOn(Toggle toggle) diff --git a/UnityEngine.UI/UI/Core/VertexModifiers/Outline.cs b/UnityEngine.UI/UI/Core/VertexModifiers/Outline.cs index 366d706..3d89255 100644 --- a/UnityEngine.UI/UI/Core/VertexModifiers/Outline.cs +++ b/UnityEngine.UI/UI/Core/VertexModifiers/Outline.cs @@ -6,7 +6,7 @@ namespace UnityEngine.UI public class Outline : Shadow { protected Outline() - { } + {} public override void ModifyVertices(List verts) { diff --git a/UnityEngine.UI/UI/Core/VertexModifiers/PositionAsUV1.cs b/UnityEngine.UI/UI/Core/VertexModifiers/PositionAsUV1.cs index dc9ca26..a3a0c5c 100644 --- a/UnityEngine.UI/UI/Core/VertexModifiers/PositionAsUV1.cs +++ b/UnityEngine.UI/UI/Core/VertexModifiers/PositionAsUV1.cs @@ -6,7 +6,7 @@ namespace UnityEngine.UI public class PositionAsUV1 : BaseVertexEffect { protected PositionAsUV1() - { } + {} public override void ModifyVertices(List verts) { diff --git a/UnityEngine.UI/UI/Core/VertexModifiers/Shadow.cs b/UnityEngine.UI/UI/Core/VertexModifiers/Shadow.cs index ac7c250..88bc5ff 100644 --- a/UnityEngine.UI/UI/Core/VertexModifiers/Shadow.cs +++ b/UnityEngine.UI/UI/Core/VertexModifiers/Shadow.cs @@ -15,7 +15,7 @@ public class Shadow : BaseVertexEffect private bool m_UseGraphicAlpha = true; protected Shadow() - { } + {} #if UNITY_EDITOR protected override void OnValidate() diff --git a/lib/UnityEditor.dll b/lib/UnityEditor.dll index 469d5ac..74db815 100644 Binary files a/lib/UnityEditor.dll and b/lib/UnityEditor.dll differ diff --git a/lib/UnityEditor.dll.mdb b/lib/UnityEditor.dll.mdb index 0824fa3..fbc04e0 100644 Binary files a/lib/UnityEditor.dll.mdb and b/lib/UnityEditor.dll.mdb differ diff --git a/lib/UnityEngine.dll b/lib/UnityEngine.dll index c8c820d..79217aa 100644 Binary files a/lib/UnityEngine.dll and b/lib/UnityEngine.dll differ diff --git a/lib/UnityEngine.dll.mdb b/lib/UnityEngine.dll.mdb index 5bf9b3d..ef39938 100644 Binary files a/lib/UnityEngine.dll.mdb and b/lib/UnityEngine.dll.mdb differ