Search Unity

Resolved ScrollView With Drag Scrolling

Discussion in 'UI Toolkit' started by Monogenesis, Nov 10, 2021.

  1. Monogenesis

    Monogenesis

    Joined:
    Dec 30, 2019
    Posts:
    56
    Hello everybody,

    I'm farely new to the UI Toolkit. I want to implement a scrollview element with the possibility to drag scroll instead of using the mousewheel or dragging the scrollbar.

    The ScrollView Component seems to support this functionality but I am not sure why it does not work in my in game UI.

    It would be much appreciate if i got a hint or reference to some information on how to make this work.

    Kindly,

    Monogenesis
     
    sandolkakos and DragonCoder like this.
  2. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    578
    The "drag scroll" is a behavior present in the ScrollView only with the touch input, and not the mouse inputs.

    Just to be clear, you want to achieve the same behavior with a regular mouse?
     
    Monogenesis likes this.
  3. Monogenesis

    Monogenesis

    Joined:
    Dec 30, 2019
    Posts:
    56
    Yes, that is what i want to achieve!
     
    Protagonist likes this.
  4. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    578
    I checked with the implementer and this is really the wanted behaviors on our side as it is the default behavior on all platform with a mouse.

    That being said, you can always process the event yourself. To get you started, I would recommend taking the scrollview.cs class from the package and rename the class, and then you could remove the check for mouse and use this scrollView whenever needed.

    upload_2021-11-12_12-30-32.png
     
  5. Monogenesis

    Monogenesis

    Joined:
    Dec 30, 2019
    Posts:
    56
    Thank you for your help! I will take a look at the class and see how i want to reuse it.
     
  6. RunninglVlan

    RunninglVlan

    Joined:
    Nov 6, 2018
    Posts:
    182
    Did I understand you correctly? You mean that ScrollView is not draggable with the mouse by design?
    It's just strange that uGUI ScrollRect is draggable with the mouse and UITK ScrollView isn't
    And your solution doesn't work - class uses a lot of internal functionality
     
    Last edited: Jun 13, 2022
  7. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
    +1 we need this functionality
     
  8. fxlange

    fxlange

    Joined:
    Dec 20, 2016
    Posts:
    45

    @SimonDufour I understand that it is default behaviour for mouse an many platforms but as mentioned in the thread it was still possible with uGUI and I'm wondering why it can't be a configuration option?
     
    sandolkakos and AlceoMazza like this.
  9. lilacsky824

    lilacsky824

    Joined:
    May 19, 2018
    Posts:
    171
    We need this functionality like UGUI.
    It should be a configuration option.
     
    sandolkakos, jGate99 and AlceoMazza like this.
  10. lilacsky824

    lilacsky824

    Joined:
    May 19, 2018
    Posts:
    171
    Trying to make a draggable scrollview with snapping function.
    But I just can't drag if I drag on children element.
    Seems children element like buttons block OnPointerDown events. :(
     
    Last edited: Oct 26, 2022
  11. lilacsky824

    lilacsky824

    Joined:
    May 19, 2018
    Posts:
    171
    cnsjjj, WongKit and Monogenesis like this.
  12. WongKit

    WongKit

    Joined:
    Apr 27, 2017
    Posts:
    26
    Thank you for sharing the sample code! I noticed, that dragging on a button will still trigger its click event on release. Do you have any idea on how to prevent this?
    I assumed, there was meant to be a handling with the _dragged variable, but it is never checked.
     
  13. lilacsky824

    lilacsky824

    Joined:
    May 19, 2018
    Posts:
    171
    I only have a temporary workaround, is disable button in a short time then enable again when dragged and released. :oops:
    Code (CSharp):
    1.        if (_dragged && evt.currentTarget is Button)
    2.         {
    3.             Button element = evt.currentTarget as Button;
    4.             if (_elementsInitialEnabled[element])
    5.             {
    6.                 element.SetEnabled(false);
    7.                 element.schedule.Execute(() => element.SetEnabled(true));
    8.             }
    9.         }
     
  14. WongKit

    WongKit

    Joined:
    Apr 27, 2017
    Posts:
    26
    Thanks for the workaround. This is an interesting approach, but unfortunately, it did not work for me. The click event is still executed - even after the button was disabled in OnPointerUp.

    Maybe, the click callback handler could be temporarily removed or something like that. I am also going to tinker with this approach.
     
    lilacsky824 likes this.
  15. jasursadikov

    jasursadikov

    Joined:
    Feb 25, 2020
    Posts:
    17
    Hello! @SimonDufour I would like to try your approach, but I can't find a source code for UIElements. By some reason. packages cache is also clear...

    @WongKit have you found a solution?
     
  16. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    578
  17. WongKit

    WongKit

    Joined:
    Apr 27, 2017
    Posts:
    26
    Unfortunately, no. I found other quirks with UI Toolkit and I am reconsidering switching my existing project to it.
     
    jasursadikov likes this.
  18. jasursadikov

    jasursadikov

    Joined:
    Feb 25, 2020
    Posts:
    17
  19. jasursadikov

    jasursadikov

    Joined:
    Feb 25, 2020
    Posts:
    17
    You're switching back to uGUI? What options do you have?
     
  20. luispedrofonseca

    luispedrofonseca

    Joined:
    Aug 29, 2012
    Posts:
    945
    I just found out about this issue and this is a deal breaker to me. Anyone with a proper solution to allow using the mouse to drag a scrollview?

    cc @jasursadikov @SimonDufour
     
  21. Arkenhammer

    Arkenhammer

    Joined:
    Nov 10, 2019
    Posts:
    51
    Here's mine with a DRAG_LOGGING feature you can enable if you need it. YMMV:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UIElements;
    3.  
    4. namespace Robants.UI.VisualElements
    5. {
    6.     public class DragScrollView : ScrollView
    7.     {
    8.         public bool Interactable = true;
    9.         public bool ContainsMouse { get; private set; } = false;
    10.         public bool MouseDown { get; private set; } = false;
    11.         public Vector2 ScrollRootOffset { get; private set; }
    12.         public Vector2 MouseDownLocation { get; private set; }
    13.  
    14. #if DRAG_LOGGING
    15.         static int _nextId;
    16.         int _id;
    17. #endif
    18.  
    19.         public DragScrollView(ScrollViewMode mode) : base(mode)
    20.         {
    21.             horizontalScrollerVisibility = ScrollerVisibility.Hidden;
    22.             verticalScrollerVisibility = ScrollerVisibility.Hidden;
    23.             DoRegisterCallbacks();
    24. #if DRAG_LOGGING
    25.             _id = _nextId++;
    26. #endif
    27.         }
    28.  
    29.         VisualElement MouseOwner => this;
    30.  
    31.         protected virtual void DoRegisterCallbacks()
    32.         {
    33.             MouseOwner.RegisterCallback<MouseUpEvent>(OnMouseUp);
    34.             MouseOwner.RegisterCallback<MouseDownEvent>(OnMouseDown);
    35.             MouseOwner.RegisterCallback<MouseMoveEvent>(OnMouseMove);
    36.         }
    37.  
    38.         void HandleDrag(IMouseEvent e)
    39.         {
    40.             Vector2 deltaPos = e.mousePosition - MouseDownLocation;
    41. #if DRAG_LOGGING
    42.             Debug.Log($"DragScroll #{_id}: Drag delta = {deltaPos}");
    43. #endif
    44.             scrollOffset = ScrollRootOffset - deltaPos;
    45.         }
    46.  
    47.         protected virtual void OnMouseMove(MouseMoveEvent e)
    48.         {
    49.             if (MouseDown && Interactable)
    50.             {
    51.                 if (MouseCaptureController.HasMouseCapture(MouseOwner))
    52.                     HandleDrag(e);
    53.                 else
    54.                 {
    55. #if DRAG_LOGGING
    56.                     Debug.Log($"DragScroll #{_id}: Lost Mouse Capture; IsMouseCaptured = {MouseCaptureController.IsMouseCaptured()}");
    57. #endif
    58.                 }
    59.             }
    60.             e.StopPropagation();
    61.         }
    62.  
    63.         protected virtual void OnMouseUp(MouseUpEvent e)
    64.         {
    65. #if DRAG_LOGGING
    66.             Debug.Log($"DragScroll #{_id}: OnMouseUp {e.mousePosition}");
    67. #endif
    68.             MouseCaptureController.ReleaseMouse(MouseOwner);
    69.             MouseDown = false;
    70.             e.StopPropagation();
    71.         }
    72.  
    73.         protected virtual void OnMouseDown(MouseDownEvent e)
    74.         {
    75. #if DRAG_LOGGING
    76.             Debug.Log($"DragScroll #{_id}: OnMouseDown {e.mousePosition}");
    77. #endif
    78.             if (!worldBound.Contains(e.mousePosition))
    79.             {
    80. #if DRAG_LOGGING
    81.                 Debug.Log($"DragScroll #{_id}: Release Mouse {e.mousePosition}");
    82. #endif
    83.                 MouseCaptureController.ReleaseMouse(MouseOwner);
    84.             }
    85.             else if (Interactable)
    86.             {
    87. #if DRAG_LOGGING
    88.                 Debug.Log($"DragScroll #{_id}: Capture Mouse {e.mousePosition}");
    89. #endif
    90.                 MouseOwner.CaptureMouse();
    91.                 MouseDownLocation = e.mousePosition;
    92.                 ScrollRootOffset = scrollOffset;
    93.                 MouseDown = true;
    94.                 e.StopPropagation();
    95.             }
    96.         }
    97.     }
    98. }
    99.  
    This was basically a copy/paste from my base draggable element into a scroll view. It's got a few things in it (like MouseOwner) you can simplify.

    If you have passive child elements in your scroll view you need to turn off PickingMode on those to let the clicks get through to the scroll view:
    https://docs.unity3d.com/2021.3/Doc...nce/UIElements.VisualElement-pickingMode.html
     
    Last edited: Jan 3, 2023
  22. jasursadikov

    jasursadikov

    Joined:
    Feb 25, 2020
    Posts:
    17
    Last edited: Jan 4, 2023
  23. lilacsky824

    lilacsky824

    Joined:
    May 19, 2018
    Posts:
    171
  24. FhyDay

    FhyDay

    Joined:
    Oct 1, 2018
    Posts:
    2
    @Arkenhammer your solution works nicely.
    I also did some improvements to handle dragging on children elements and scrolling out of the bound.

    Now you should see this Control on the UI Builder.

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.UIElements;
    4.  
    5. namespace UI.Components
    6. {
    7.     public class DragScrollView : ScrollView
    8.     {
    9.         public new class UxmlFactory : UxmlFactory<DragScrollView, UxmlTraits> { }
    10.  
    11.         public new class UxmlTraits : ScrollView.UxmlTraits
    12.         {
    13.             UxmlBoolAttributeDescription Interactable = new UxmlBoolAttributeDescription { name = "Interactable", defaultValue = true };
    14.             UxmlBoolAttributeDescription IgnoreChildren = new UxmlBoolAttributeDescription { name = "IgnoreChildren", defaultValue = false };
    15.  
    16.             public UxmlTraits() : base() { Interactable.defaultValue = true; }
    17.  
    18.             public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
    19.             {
    20.                 get
    21.                 {
    22.                     yield return new UxmlChildElementDescription(typeof(VisualElement));
    23.                 }
    24.             }
    25.  
    26.             public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
    27.             {
    28.                 base.Init(ve, bag, cc);
    29.                 ((DragScrollView)ve).Interactable = Interactable.GetValueFromBag(bag, cc);
    30.                 ((DragScrollView)ve).IgnoreChildren = IgnoreChildren.GetValueFromBag(bag, cc);
    31.             }
    32.         }
    33.  
    34.         public bool Interactable = true;
    35.         public bool IgnoreChildren
    36.         {
    37.             get => ignoreChildren; set
    38.             {
    39.                 if (ignoreChildren != value)
    40.                 {
    41.                     if (value) UnregisterChildrenCallbacks(); else RegisterChildrenCallbacks();
    42.                 }
    43.                 ignoreChildren = value;
    44.             }
    45.         }
    46.         public bool ContainsMouse { get; private set; } = false;
    47.         public bool MouseDown { get; private set; } = false;
    48.         public Vector2 ScrollRootOffset { get; private set; }
    49.         public Vector2 MouseDownLocation { get; private set; }
    50.  
    51.         private bool ignoreChildren;
    52.         private List<VisualElement> registered = new();
    53.  
    54. #if DRAG_LOGGING
    55.     static int _nextId;
    56.     int _id;
    57. #endif
    58.  
    59.         public DragScrollView() : this(ScrollViewMode.Vertical) { }
    60.         public DragScrollView(ScrollViewMode scrollViewMode) : base(scrollViewMode)
    61.         {
    62.             DoRegisterCallbacks();
    63.         }
    64.  
    65.         VisualElement MouseOwner => this;
    66.  
    67.         protected virtual void DoRegisterCallbacks()
    68.         {
    69.             MouseOwner.RegisterCallback<MouseUpEvent>(OnMouseUp);
    70.             MouseOwner.RegisterCallback<MouseDownEvent>(OnMouseDown);
    71.             MouseOwner.RegisterCallback<MouseMoveEvent>(OnMouseMove);
    72.  
    73.             if (!IgnoreChildren)
    74.             {
    75.                 RegisterChildrenCallbacks();
    76.             }
    77.         }
    78.         protected virtual void UnregisterCallbacks()
    79.         {
    80.             MouseOwner.RegisterCallback<MouseUpEvent>(OnMouseUp);
    81.             MouseOwner.RegisterCallback<MouseDownEvent>(OnMouseDown);
    82.             MouseOwner.RegisterCallback<MouseMoveEvent>(OnMouseMove);
    83.  
    84.             if (!IgnoreChildren)
    85.             {
    86.                 UnregisterChildrenCallbacks();
    87.             }
    88.         }
    89.  
    90.         protected virtual void RegisterChildrenCallbacks()
    91.         {
    92.             List<VisualElement> childrenVE = this.Query().ToList();
    93.  
    94.             foreach (var b in childrenVE)
    95.             {
    96.                 b.RegisterCallback<MouseUpEvent>(OnMouseUp, TrickleDown.TrickleDown);
    97.                 b.RegisterCallback<MouseDownEvent>(OnMouseDown, TrickleDown.TrickleDown);
    98.                 b.RegisterCallback<MouseMoveEvent>(OnMouseMove, TrickleDown.TrickleDown);
    99.                 registered.Add(b);
    100.             }
    101.         }
    102.         protected virtual void UnregisterChildrenCallbacks()
    103.         {
    104.             List<VisualElement> childrenVE = this.Query().ToList();
    105.  
    106.             foreach (var b in childrenVE)
    107.             {
    108.                 b.UnregisterCallback<MouseUpEvent>(OnMouseUp, TrickleDown.TrickleDown);
    109.                 b.UnregisterCallback<MouseDownEvent>(OnMouseDown, TrickleDown.TrickleDown);
    110.                 b.UnregisterCallback<MouseMoveEvent>(OnMouseMove, TrickleDown.TrickleDown);
    111.                 registered.Remove(b);
    112.             }
    113.             registered.Clear();
    114.         }
    115.  
    116.         void HandleDrag(IMouseEvent e)
    117.         {
    118.             Vector2 deltaPos = e.mousePosition - MouseDownLocation;
    119. #if DRAG_LOGGING
    120.         Debug.Log($"DragScroll #{_id}: Drag delta = {deltaPos}");
    121. #endif
    122.  
    123.             deltaPos = ScrollRootOffset - deltaPos;
    124.             switch (mode)
    125.             {
    126.                 case ScrollViewMode.Vertical:
    127.                     deltaPos.x = scrollOffset.x;
    128.                     break;
    129.                 case ScrollViewMode.Horizontal:
    130.                     deltaPos.y = scrollOffset.y;
    131.                     break;
    132.                 default:
    133.                     break;
    134.             }
    135.             scrollOffset = deltaPos;
    136.         }
    137.  
    138.         protected virtual void OnMouseMove(MouseMoveEvent e)
    139.         {
    140.             if (MouseDown && Interactable)
    141.             {
    142.                 if (MouseCaptureController.HasMouseCapture(MouseOwner))
    143.                     HandleDrag(e);
    144.                 else
    145.                 {
    146. #if DRAG_LOGGING
    147.                 Debug.Log($"DragScroll #{_id}: Lost Mouse Capture; IsMouseCaptured = {MouseCaptureController.IsMouseCaptured()}");
    148. #endif
    149.                 }
    150.             }
    151.             e.StopPropagation();
    152.         }
    153.  
    154.         protected virtual void OnMouseUp(MouseUpEvent e)
    155.         {
    156. #if DRAG_LOGGING
    157.         Debug.Log($"DragScroll #{_id}: OnMouseUp {e.mousePosition}");
    158. #endif
    159.             MouseCaptureController.ReleaseMouse(MouseOwner);
    160.  
    161.             // Update elastic behavior
    162.             if (touchScrollBehavior == TouchScrollBehavior.Elastic)
    163.             {
    164.                 m_LowBounds = new Vector2(
    165.                     Mathf.Min(horizontalScroller.lowValue, horizontalScroller.highValue),
    166.                     Mathf.Min(verticalScroller.lowValue, verticalScroller.highValue));
    167.                 m_HighBounds = new Vector2(
    168.                     Mathf.Max(horizontalScroller.lowValue, horizontalScroller.highValue),
    169.                     Mathf.Max(verticalScroller.lowValue, verticalScroller.highValue));
    170.  
    171.                 ExecuteElasticSpringAnimation();
    172.             }
    173.  
    174.             MouseDown = false;
    175.             e.StopPropagation();
    176.         }
    177.  
    178.         protected virtual void OnMouseDown(MouseDownEvent e)
    179.         {
    180. #if DRAG_LOGGING
    181.         Debug.Log($"DragScroll #{_id}: OnMouseDown {e.mousePosition}");
    182. #endif
    183.             if (!worldBound.Contains(e.mousePosition))
    184.             {
    185. #if DRAG_LOGGING
    186.             Debug.Log($"DragScroll #{_id}: Release Mouse {e.mousePosition}");
    187. #endif
    188.                 MouseCaptureController.ReleaseMouse(MouseOwner);
    189.             }
    190.             else if (Interactable)
    191.             {
    192. #if DRAG_LOGGING
    193.             Debug.Log($"DragScroll #{_id}: Capture Mouse {e.mousePosition}");
    194. #endif
    195.                 MouseOwner.CaptureMouse();
    196.                 MouseDownLocation = e.mousePosition;
    197.                 ScrollRootOffset = scrollOffset;
    198.                 MouseDown = true;
    199.                 e.StopPropagation();
    200.             }
    201.         }
    202.  
    203.         // Copied from Unity scource code: https://github.com/Unity-Technologies/UnityCsReference/blob/master/ModuleOverrides/com.unity.ui/Core/Controls/ScrollView.cs
    204.         private bool hasInertia => scrollDecelerationRate > 0f;
    205.         private Vector2 m_Velocity;
    206.         private Vector2 m_SpringBackVelocity;
    207.         private Vector2 m_LowBounds;
    208.         private Vector2 m_HighBounds;
    209.         private IVisualElementScheduledItem m_PostPointerUpAnimation;
    210.  
    211.         void ExecuteElasticSpringAnimation()
    212.         {
    213.             ComputeInitialSpringBackVelocity();
    214.  
    215.             if (m_PostPointerUpAnimation == null)
    216.             {
    217.                 m_PostPointerUpAnimation = schedule.Execute(PostPointerUpAnimation).Every(30);
    218.             }
    219.             else
    220.             {
    221.                 m_PostPointerUpAnimation.Resume();
    222.             }
    223.         }
    224.  
    225.         private void PostPointerUpAnimation()
    226.         {
    227.             ApplyScrollInertia();
    228.             SpringBack();
    229.  
    230.             // This compares with epsilon.
    231.             if (m_SpringBackVelocity == Vector2.zero && m_Velocity == Vector2.zero)
    232.             {
    233.                 m_PostPointerUpAnimation.Pause();
    234.             }
    235.         }
    236.  
    237.         private void ComputeInitialSpringBackVelocity()
    238.         {
    239.             if (touchScrollBehavior != TouchScrollBehavior.Elastic)
    240.             {
    241.                 m_SpringBackVelocity = Vector2.zero;
    242.                 return;
    243.             }
    244.  
    245.             if (scrollOffset.x < m_LowBounds.x)
    246.             {
    247.                 m_SpringBackVelocity.x = m_LowBounds.x - scrollOffset.x;
    248.             }
    249.             else if (scrollOffset.x > m_HighBounds.x)
    250.             {
    251.                 m_SpringBackVelocity.x = m_HighBounds.x - scrollOffset.x;
    252.             }
    253.             else
    254.             {
    255.                 m_SpringBackVelocity.x = 0;
    256.             }
    257.  
    258.             if (scrollOffset.y < m_LowBounds.y)
    259.             {
    260.                 m_SpringBackVelocity.y = m_LowBounds.y - scrollOffset.y;
    261.             }
    262.             else if (scrollOffset.y > m_HighBounds.y)
    263.             {
    264.                 m_SpringBackVelocity.y = m_HighBounds.y - scrollOffset.y;
    265.             }
    266.             else
    267.             {
    268.                 m_SpringBackVelocity.y = 0;
    269.             }
    270.         }
    271.  
    272.         private void SpringBack()
    273.         {
    274.             if (touchScrollBehavior != TouchScrollBehavior.Elastic)
    275.             {
    276.                 m_SpringBackVelocity = Vector2.zero;
    277.                 return;
    278.             }
    279.  
    280.             var newOffset = scrollOffset;
    281.  
    282.             if (newOffset.x < m_LowBounds.x)
    283.             {
    284.                 newOffset.x = Mathf.SmoothDamp(newOffset.x, m_LowBounds.x, ref m_SpringBackVelocity.x, elasticity,
    285.                     Mathf.Infinity, Time.unscaledDeltaTime);
    286.                 if (Mathf.Abs(m_SpringBackVelocity.x) < 1)
    287.                 {
    288.                     m_SpringBackVelocity.x = 0;
    289.                 }
    290.             }
    291.             else if (newOffset.x > m_HighBounds.x)
    292.             {
    293.                 newOffset.x = Mathf.SmoothDamp(newOffset.x, m_HighBounds.x, ref m_SpringBackVelocity.x, elasticity,
    294.                     Mathf.Infinity, Time.unscaledDeltaTime);
    295.                 if (Mathf.Abs(m_SpringBackVelocity.x) < 1)
    296.                 {
    297.                     m_SpringBackVelocity.x = 0;
    298.                 }
    299.             }
    300.             else
    301.             {
    302.                 m_SpringBackVelocity.x = 0;
    303.             }
    304.  
    305.             if (newOffset.y < m_LowBounds.y)
    306.             {
    307.                 newOffset.y = Mathf.SmoothDamp(newOffset.y, m_LowBounds.y, ref m_SpringBackVelocity.y, elasticity,
    308.                     Mathf.Infinity, Time.unscaledDeltaTime);
    309.                 if (Mathf.Abs(m_SpringBackVelocity.y) < 1)
    310.                 {
    311.                     m_SpringBackVelocity.y = 0;
    312.                 }
    313.             }
    314.             else if (newOffset.y > m_HighBounds.y)
    315.             {
    316.                 newOffset.y = Mathf.SmoothDamp(newOffset.y, m_HighBounds.y, ref m_SpringBackVelocity.y, elasticity,
    317.                     Mathf.Infinity, Time.unscaledDeltaTime);
    318.                 if (Mathf.Abs(m_SpringBackVelocity.y) < 1)
    319.                 {
    320.                     m_SpringBackVelocity.y = 0;
    321.                 }
    322.             }
    323.             else
    324.             {
    325.                 m_SpringBackVelocity.y = 0;
    326.             }
    327.  
    328.             scrollOffset = newOffset;
    329.         }
    330.  
    331.         // Internal for tests.
    332.         internal void ApplyScrollInertia()
    333.         {
    334.             if (hasInertia && m_Velocity != Vector2.zero)
    335.             {
    336.                 m_Velocity *= Mathf.Pow(scrollDecelerationRate, Time.unscaledDeltaTime);
    337.  
    338.                 if (Mathf.Abs(m_Velocity.x) < 1 ||
    339.                     touchScrollBehavior == TouchScrollBehavior.Elastic && (scrollOffset.x < m_LowBounds.x || scrollOffset.x > m_HighBounds.x))
    340.                 {
    341.                     m_Velocity.x = 0;
    342.                 }
    343.  
    344.                 if (Mathf.Abs(m_Velocity.y) < 1 ||
    345.                     touchScrollBehavior == TouchScrollBehavior.Elastic && (scrollOffset.y < m_LowBounds.y || scrollOffset.y > m_HighBounds.y))
    346.                 {
    347.                     m_Velocity.y = 0;
    348.                 }
    349.  
    350.                 scrollOffset += m_Velocity * Time.unscaledDeltaTime;
    351.             }
    352.             else
    353.             {
    354.                 m_Velocity = Vector2.zero;
    355.             }
    356.         }
    357.  
    358.     }
    359. }
     
    DarkRewar and SergeyKhanin like this.
  25. UNSH

    UNSH

    Joined:
    Jul 2, 2012
    Posts:
    51
    My clicked events for the buttons inside the scrollview do not seem to register unless I use ignore children but then the scrollview does not work. What am I missing? I just stated out with ui toolkit so I might be missing open doors.

     
  26. UNSH

    UNSH

    Joined:
    Jul 2, 2012
    Posts:
    51
    Still unsure if I'm not missing something, but this fixed the clicked events of my buttons not coming through. Still needs some testing but I need something that works right now and I'm not sure this is the way so.

    Code (CSharp):
    1.  
    2.         private static IEventHandler clickedObj;
    3.         private long startTime;
    4.         private const long clickTime = 130;
    5.  
    6.         void CheckClickTime(MouseUpEvent e)
    7.         {  
    8.             if ( (e.timestamp - startTime) < clickTime && clickedObj != null)
    9.             {
    10.                 using ( var ev = new NavigationSubmitEvent() {target = clickedObj} ) clickedObj.SendEvent(ev);
    11.             }
    12.             clickedObj = null;
    13.         }
    14.  
    15.         void SetClickTime(MouseDownEvent e)
    16.         {
    17.             startTime = e.timestamp;
    18.             clickedObj = e.target;
    19.         }
    20.  
    21.         protected virtual void OnMouseUp(MouseUpEvent e)
    22.         {
    23. #if DRAG_LOGGING
    24.     Debug.Log($"DragScroll #{_id}: OnMouseUp {e.mousePosition}");
    25. #endif
    26.  
    27.             CheckClickTime(e);
    28.        
    29.             MouseCaptureController.ReleaseMouse(MouseOwner);
    30.             // Update elastic behavior
    31.             if (touchScrollBehavior == TouchScrollBehavior.Elastic)
    32.             {
    33.                 m_LowBounds = new Vector2(
    34.                     Mathf.Min(horizontalScroller.lowValue, horizontalScroller.highValue),
    35.                     Mathf.Min(verticalScroller.lowValue, verticalScroller.highValue));
    36.                 m_HighBounds = new Vector2(
    37.                     Mathf.Max(horizontalScroller.lowValue, horizontalScroller.highValue),
    38.                     Mathf.Max(verticalScroller.lowValue, verticalScroller.highValue));
    39.                 ExecuteElasticSpringAnimation();
    40.             }
    41.             MouseDown = false;
    42.             e.StopPropagation();
    43.         }
    44.         protected virtual void OnMouseDown(MouseDownEvent e)
    45.         {
    46. #if DRAG_LOGGING
    47. Debug.Log($"DragScroll #{_id}: OnMouseDown {e.mousePosition}");
    48. #endif
    49.  
    50.             SetClickTime(e);
    51.          
    52.             if (!worldBound.Contains(e.mousePosition))
    53.             {
    54. #if DRAG_LOGGING
    55.     Debug.Log($"DragScroll #{_id}: Release Mouse {e.mousePosition}");
    56. #endif
    57.  
    58.                 MouseCaptureController.ReleaseMouse(MouseOwner);
    59.  
    60.             } else if (Interactable) {
    61.            
    62. #if DRAG_LOGGING
    63.     Debug.Log($"DragScroll #{_id}: Capture Mouse {e.mousePosition}");
    64. #endif
    65.  
    66.                 MouseOwner.CaptureMouse();
    67.                 MouseDownLocation = e.mousePosition;
    68.                 ScrollRootOffset = scrollOffset;
    69.                 MouseDown = true;
    70.                 e.StopPropagation();
    71.             }
    72.         }
     
  27. manuelgoellnitz

    manuelgoellnitz

    Joined:
    Feb 15, 2017
    Posts:
    397
    This is not possible, since a lot of references in this class can only be accessed from inside the package (which since it is integrated into unity, cannot be modified).

    I created my own solution a long time ago, where there was not even a drag scrolling for touch implemented.
    Now with the Unity version 2022.3.18, there was a bugfix related to the scrollmode "elastic".
    I tried it out and it worked sort of, even with my custom scrolling script.
    BUT: the elastic scrolling only works if there was one Touchscroll or Mousewheel action.
    Probably because there is some initalisation code on that events.
    But since most Methods are private or internal, I can't access them from outside.

    Could you please:
    A - Yes this behavior is not the default one, but it is fairly common. Just give us the option to decide for our selfs
    B - Give more access for us to create our own extensions (by dont make everything private or internal)
    C - Fix the bug :D
     
    MousePods and fxlange like this.
  28. manuelgoellnitz

    manuelgoellnitz

    Joined:
    Feb 15, 2017
    Posts:
    397
  29. sandolkakos

    sandolkakos

    Joined:
    Jun 3, 2009
    Posts:
    285
    After weeks of fighting with UI Toolkit in my game prototype and finding too many hidden limitations like this one here, I'm deciding to go back to uGUI.

    I gave UI Toolkit a chance after reading a lot about it and watching nice videos. Over these weeks I could confirm how nice it is to work on the UI elements detached from the GameObjects in the scene and would really love to replace uGUI with UI Toolkit one day, but it still has a long path for this to be a reality. :(

    In the meantime, I will just keep an eye on its evolution and hope it gets better and better with every update.
     
    VenetianFox likes this.