Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

New UI Widgets

Discussion in 'Assets and Asset Store' started by ilih, Feb 11, 2015.

  1. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Yes, sorry, I missed that thing on refactoring.
    Fix:
    replace
    Init()
    method in ListViewIconsExt.cs with the following code:
    Code (CSharp):
    1.         public override void Init()
    2.         {
    3.             if (dataSourceExt == null)
    4.             {
    5.                 if (dataSource == null)
    6.                 {
    7.                     dataSource = new ObservableList<ListViewIconsItemDescriptionExt>(customItems);
    8.                     dataSource.OnChange += UpdateItems;
    9.                 }
    10.                 dataSourceExt = new ObservableList<ListViewIconsItemDescriptionExt>(dataSource);
    11.                 dataSourceExt.OnChange += CollectionChanged;
    12.                 CollectionChanged();
    13.             }
    14.  
    15.             base.Init();
    16.         }
     
  2. aggaton

    aggaton

    Joined:
    Jul 3, 2021
    Posts:
    113
    @ilih

    EDIT: Please disregard below issue, I am guessing this code is super old. Now that I got the other example working I don't need this.

    I have attempted to incorporate above code however I get an error indicating index is out of range. Am I missing something?

    When attempting to debug through the code, it seems like the Items list keeps changing size, i.e. it adds the first 2 elements, runs a bit and then suddenly the 2nd element is gone. It's at like it is working on an earlier version of the list without 2nd element.

    I have replaced all component with the new ones. BuyListViewIcons is the new ListViewIconsExt object, DefaultItem, ScrollRect and List has all been dropped on the component



    upload_2021-8-25_18-12-6.png

    upload_2021-8-25_18-13-15.png

    I am doing something like this to fill the list


    Code (CSharp):
    1.         var buyList = FindTransform("BuyListView").gameObject.GetComponent<UIWidgetsSamples.ListViewIconsExt>();
    2.         buyList.Clear();
    3.         foreach (KeyValuePair<string, int> ware in wares.WarePrices)
    4.         {
    5.             var new_item = new UIWidgetsSamples.ListViewIconsItemDescriptionExt()
    6.             {
    7.                 Icon = IconManager.Instance.GetWareIcon(ware.Key),
    8.                 Name = ware.Key + " " + ware.Value + "Cr",
    9.             };
    10.             buyList.DataSource.Add(new_item);
    11.         }
    12.  

    This is the stack trace.

    Code (CSharp):
    1. ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
    2. Parameter name: index
    3. System.ThrowHelper.ThrowArgumentOutOfRangeException (System.ExceptionArgument argument, System.ExceptionResource resource) (at <695d1cc93cca45069c528c15c9fdd749>:0)
    4. System.ThrowHelper.ThrowArgumentOutOfRangeException () (at <695d1cc93cca45069c528c15c9fdd749>:0)
    5. System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <695d1cc93cca45069c528c15c9fdd749>:0)
    6. UIWidgets.ObservableList`1[T].get_Item (System.Int32 index) (at Assets/New UI Widgets/Scripts/CollectionsUtilities/ObservableList.cs:407)
    7. UIWidgetsSamples.ListViewIconsExt.DefaultColoring (UIWidgetsSamples.ListViewIconsItemComponentExt component) (at Assets/Scripts/ListViewIconsExt.cs:58)
    8. UIWidgets.ListViewCustom`2[TComponent,TItem].DefaultColoring (UIWidgets.ListViewItem component) (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:1589)
    9. UIWidgets.ListViewCustom`2[TComponent,TItem].Coloring (UIWidgets.ListViewItem component) (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:1486)
    10. UIWidgets.ListViewCustom`2[TComponent,TItem].ComponentSetData (TComponent component) (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:1318)
    11. UIWidgets.ListViewBase+ListViewComponentPool`2[TComponent,TItem].DisplayedIndicesSet (System.Collections.Generic.List`1[T] newIndices, System.Action`1[T] action) (at Assets/New UI Widgets/Scripts/ListView/ListViewComponentPool.cs:201)
    12. UIWidgets.ListViewCustom`2[TComponent,TItem].SetDisplayedIndices (System.Boolean isNewData) (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:1291)
    13. UIWidgets.ListViewCustom`2[TComponent,TItem].UpdateView () (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:1340)
    14. UIWidgets.ListViewCustom`2[TComponent,TItem].SetNewItems (UIWidgets.ObservableList`1[T] newItems, System.Boolean updateView) (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:1401)
    15. UIWidgets.ListViewCustom`2[TComponent,TItem].UpdateItems () (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:815)
    16. UIWidgets.ObservableList`1[T].CollectionChanged (System.Boolean resort) (at Assets/New UI Widgets/Scripts/CollectionsUtilities/ObservableList.cs:265)
    17. UIWidgets.ObservableList`1[T].CollectionChanged () (at Assets/New UI Widgets/Scripts/CollectionsUtilities/ObservableList.cs:247)
    18. UIWidgets.ObservableList`1[T].Add (T item) (at Assets/New UI Widgets/Scripts/CollectionsUtilities/ObservableList.cs:442)
    19. Station.OpenTradeMenu () (at Assets/SpaceSimFramework/Code/Station/Station.cs:286)
    20. UnityEngine.Events.InvokableCall.Invoke () (at <adfa4b62400849189388df71c9e26e89>:0)
    21. UnityEngine.Events.UnityEvent.Invoke () (at <adfa4b62400849189388df71c9e26e89>:0)
    22. UnityEngine.UI.Button.Press () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70)
    23. UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114)
    24. UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57)
    25. UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272)
    26. UnityEngine.EventSystems.EventSystem:Update() (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:501)
    27.  
    28.  
     
    Last edited: Aug 26, 2021
  3. aggaton

    aggaton

    Joined:
    Jul 3, 2021
    Posts:
    113
    Thanks for rapid response! This seem to fix the issue with the example.
     
  4. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    ListViewIconsExt is an example of ListView where items can be disabled (
    Interactable
    property) and hidden (
    Visible
    property), and it uses two lists:
    • DataSourceExt to contain all items
    • DataSource to contain visible items, and it should not be used directly in this case
    So you should use DataSourceExt instead of the DataSource
    Code (CSharp):
    1. buyList.DataSourceExt.Add(new_item);
    If you do not need such functions then you can use the default ListViewIcons and DataSource.
     
    Last edited: Aug 26, 2021
  5. aggaton

    aggaton

    Joined:
    Jul 3, 2021
    Posts:
    113
    @ilih Using the fixed CustomColoring example, I was able to sort of get the list to display, however it seems to display the height as some kind of fibonacci sequence. How do I make the rows the same height and the icon to appear to the left and the text to the left? Maybe I should use a table instead?

    upload_2021-8-25_19-10-2.png
     
  6. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Looks like you have large icons and enabled "Set Native Size" in ListView.DefaultItem component.
    Please try to disable it, then icons will have a fixed size not be stretched to hide text and other items.
    upload_2021-8-26_3-39-7.png
     
    aggaton likes this.
  7. aggaton

    aggaton

    Joined:
    Jul 3, 2021
    Posts:
    113
    Thank you so much, that was exactly it, after unchecking that field, all icons shrunk to the right size, matching the size of the text.
     
  8. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,936
    AMAZING :D
     
  9. aggaton

    aggaton

    Joined:
    Jul 3, 2021
    Posts:
    113
    @ilih Hi, I am trying to figure out how to use List View Icons Drag Support. In particular I am trying to use the End Drag Event. How do I set it up in my code so, that when somebody drops an item in a list view I catch this event and it will give me a reference to the item dropped and the listview it came from and where it went? I guess I would like all the relevant event data to be passed in. I can trigger the event, but I have no idea how to get hold of that data.
     
  10. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    You should create a new component derived from ListViewIconsDragSupport with overridden
    Dropped()
    method and replace ListViewIconsDragSupport with this component.
    Code (CSharp):
    1.         UnityEvent<ListViewIconsItemDescription, ListViewIcons, ListViewIcons> DropEvent;
    2.  
    3.         public override void Dropped(bool success)
    4.         {
    5.             if (success)
    6.             {
    7.                 var item = Data; // dropped item
    8.                 var sourceListView = ListView; // source ListView
    9.                 var targetListView = (CurrentTarget as MonoBehaviour).GetComponent<ListViewIcons>();
    10.                 if (targetListView != null)
    11.                 {
    12.                     // do something with item, source ListView, targetListView
    13.                     // or raise event
    14.                     DropEvent.Invoke(Data, ListView, targetListView);
    15.                 }
    16.             }
    17.  
    18.             base.Dropped(success);
    19.         }
    If you want to control how to add the item to the target ListView then also override the
    Drop()
    method for the ListViewIconsDropSupport.
    Code (CSharp):
    1.         public override void Drop(ListViewIconsItemDescription data, PointerEventData eventData)
    2.         {
    3.             // do not add the item to the list
    4.  
    5.             HideDropIndicator();
    6.         }
    How Drag&Drop works:
    • there are two components: one process Drag and another process Drop
    • Drop component implements
      IDropSupport<TItem>
      interface (it can implement multiple interfaces with different types). It is used to check if the dragged item can be received and process drop (like add item to the ListView)
    • Drag component is inherited from
      DragSupport<TItem>
      and attached to a game object with data to drag (for the ListView, it's attached to ListView.DefaultItem)
    • when dragging, it looks for target with drop component that can accept a
      TItem
      and call
      bool CanReceiveDrop(TItem data, PointerEventData eventData);
      to check if target can receive dragged item
    • on end drag called
      Drop(TItem data, PointerEventData eventData)
      for the target (drop component) and then
      Dropped(bool success)
      for the drag component
     
  11. aggaton

    aggaton

    Joined:
    Jul 3, 2021
    Posts:
    113
    Thanks a bunch for this reply, this is exactly what I was looking for. I am trying to make an inventory and storage control, so I need to update the internal lists holding the various items.
     
  12. Smolli

    Smolli

    Joined:
    Mar 12, 2014
    Posts:
    84
    Hi, checking between your asset and the Optimized Scrollview Adapter. I tested the Demo on my Android tablet and noticed that some things don't work at all (Node part of Drag&Drop and Nodes in General, resizing is tricky to get the correct position and some more) and some more. Is this a known limitation for mobile platforms?
     
  13. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Sorry, I did not check the recent android version: there was not any platform-dependent code, and previous versions were working correctly.

    TreeView does not work because of some bug, I check it right now.
    Resize settings are the same as Windows and WebGL demo, because of it on a small screen with hi dpi in became difficult to touch active region to resize; I'll update those settings for the android demo.
     
    Last edited: Aug 30, 2021
  14. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Demo fixed, beta version packages will be available later today.
    The asset store package will be updated with the next release.
     
  15. Smolli

    Smolli

    Joined:
    Mar 12, 2014
    Posts:
    84
    Wow, that was fast!
    But I still have some weird behavior, like with the Drag&Drop example. When Dragging and Dropping Nodes I can't drag above the first node, or generally in between main nodes. It's always inside another node, Or it always adds to a selection if I not actively deselect an element. But the d&d is only with one selected item not all the selected ones.
    When using the auto-complete examples auto-complete works now, but the selection (eg deleting from the example Comboboxicons) is nearly impossible on my 10.5'' Tablet.
    Also Treeview example, problems with the selection, always adds to a selection.
    It works much better for Webgl but I need solid mobile support.
     
  16. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Drag above the first node fixed.
    Between nodes: it's difficult because the drop should be on empty space between nodes, the empty space value is configurable, by default it is 2.
    Added drop indicator, so visual feedback should make it easier.

    Default drag&drop components support only one item.
    You can add custom drag&drop support for multiple items.
    I cannot think of an implementation that is not questionable by the obtained result; especially when handling nodes that are in the same branch, for example, node and some nested node in it.

    Fixed.
    It is really was impossible, the android demo was done on the latest beta with not yet tested changes, unlike the WebGL version.

    ListView and TreeView have the option "Multiple Select" if enabled multiple items can be selected.

    Android demo updated to v1.15.0b22
     
    Last edited: Aug 30, 2021
  17. Smolli

    Smolli

    Joined:
    Mar 12, 2014
    Posts:
    84
    Impressed with your update speed, but again some weird behavior, sorry :)

    The drop indicator is very helpful. But there are still two errors. 1. There is no wait time before being able to drag, right now it's instant so I cannot scroll through the node list without accidentally dragging nodes. 2. The selection is still not only for the active item, meaning that every item I click on remains selected even though only the last selection can be dragged. This looks confusing. Selecting one item should deselect the other.
    And then there is some weird behavior when dragging the flags to the Nodes and outside to another node.

    Deleting in the auto-complete now works but not directly. I have to click outside first and then I can delete.
     
  18. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Please check v1.15.0b23

    Delay does not help with that because no difference between drag and scroll: touch will be always on the same item.
    I just added a drag handle (yellow) for the TreeView nodes, so nodes will be dragged by this handle.

    I disabled the "Multiple Select" option and increased empty space between nodes and items.

    What exactly?

    Is it when the onscreen keyboard is visible?
     
  19. aggaton

    aggaton

    Joined:
    Jul 3, 2021
    Posts:
    113
    @ilih When dragging into another listview container, there seem to be a lot of flickering going on, like header outline/border moves from bottom to top and also it seem like holding the left mouse bottom while in the listview also triggers scrolling, probably since it shares input with dragging and dropping. How can I get a "clean" looking way of dragging and droppping, without any animation on the containers and no flickering/animation of the header border, I am ok with having an outline on the receiving container and potentially the header, if there is no "flickering" involved as I drag and move the item inside the container. i.e. how do I turn off scrolling in the container while holding down the left mouse and moving (I think that is likely the main issue).
    Edit: I get a "quieter" drag if I turn off the Drop Indicator, however the scroll bar is still moving as I drag.
     
    Last edited: Aug 31, 2021
  20. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Flickering can be caused by DropIndicator (horizontal line to show the position where the item will be added); you can delete it from all Drop Support components:
    upload_2021-8-31_2-36-48.png
    Or by Selectable component (outline for the highlighted or selected widget), you can either remove it completely or delete highlighted sprite from options.
    upload_2021-8-31_2-33-31.png

    Change ListView.AutoScrollArea to zero to disable scrolling when cursor near borders:
    upload_2021-8-31_2-35-34.png
     
    aggaton likes this.
  21. Smolli

    Smolli

    Joined:
    Mar 12, 2014
    Posts:
    84
    Sorry, I missed your fast reply, I'm also impressed on how fast you are able to make changes.
    Is this multi selection thing an option? I ask because the flags on the right side of the panel are still multi selectable. I don't know the reason for this though as it is of no use there IMHO.

    The weird behavior when dragging a flag over to nodes and then moving it around is very easily reproduced. Drag the flag around and you will notice that the order of the nodes gets disturbed, i even managed to loose the flag completely.

    Drag and drop is vey important for me, what type of content is possible with it, also nested ui items eg?
     
  22. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Yes.

    I'll disable them in the next demo.

    Can you make a screenshot?
    I was only found a small bug with an automatic scroll when touching near the top or bottom borders of the ListView.

    There is no restriction on the type itself, but you need to create drag&drop components for the custom types.
    If you will use widgets generation then the drag&drop support components for the data type will be created automatically (widgets generation have restrictions on data type).

    Example of the custom drag&drop components:
    Code (CSharp):
    1.    [RequireComponent(typeof(InputField))]
    2.    public class InputFieldDragSupportBase : DragSupport<string>
    3.    {
    4.       protected override void InitDrag(PointerEventData eventData)
    5.       {
    6.          Data = GetComponent<InputField>().text;
    7.       }
    8.    }
    Code (CSharp):
    1.    [RequireComponent(typeof(InputField))]
    2.    public class InputFieldDropSupport : MonoBehaviour, IDropSupport<string>
    3.    {
    4.       public void Drop(string data, PointerEventData eventData)
    5.       {
    6.          var input = GetComponent<InputField>().text = data;
    7.       }
    8.  
    9.       public bool CanReceiveDrop(string data, PointerEventData eventData)
    10.       {
    11.          return true;
    12.       }
    13.  
    14.       public void DropCanceled(string data, PointerEventData eventData)
    15.       {
    16.       }
    17.    }
    I'll add some others drag&drop examples to the demo later.
     
    Last edited: Aug 31, 2021
  23. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Please check v1.15.0b25 demo.
    Fixed auto-scroll bug, disabled ListView's multi-select option, added more drag&drop examples.
     
  24. aggaton

    aggaton

    Joined:
    Jul 3, 2021
    Posts:
    113
    Thank you I will try this out!
     
  25. aggaton

    aggaton

    Joined:
    Jul 3, 2021
    Posts:
    113
    @ilih I implemented above and it works well. I have now found myself also needing to know what list item I am dropping onto (I assume null if nothing is under the cursor when dropping). Is this possible?
     
  26. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    If you need the exact item under the cursor then you can add such code to the your Drag class and use
    ItemUnderCursor
    in event invocation:
    (replace
    ListViewIconsItemDescription
    and
    ListViewIconsItemComponent
    with your types)
    Code (CSharp):
    1.         ListViewIconsItemDescription ItemUnderCursor;
    2.  
    3.         /// <inheritdoc/>
    4.         protected override void OnEndDrag(PointerEventData eventData)
    5.         {
    6.             if (!IsDragged)
    7.             {
    8.                 return;
    9.             }
    10.  
    11.             ItemUnderCursor = FindItem(eventData);
    12.  
    13.             base.OnEndDrag(eventData);
    14.         }
    15.  
    16.         readonly List<RaycastResult> ItemRaycasts = new List<RaycastResult>();
    17.  
    18.         protected virtual ListViewIconsItemDescription FindItem(PointerEventData eventData)
    19.         {
    20.             ItemRaycasts.Clear();
    21.  
    22.             EventSystem.current.RaycastAll(eventData, ItemRaycasts);
    23.  
    24.             foreach (var raycastResult in ItemRaycasts)
    25.             {
    26.                 if (!raycastResult.isValid)
    27.                 {
    28.                     continue;
    29.                 }
    30.  
    31.                 var target = raycastResult.gameObject.GetComponent<ListViewIconsItemComponent>();
    32.                 if (target != null)
    33.                 {
    34.                     return target.Item;
    35.                 }
    36.             }
    37.  
    38.             return null;
    39.         }
    40.  
     
    aggaton likes this.
  27. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,936
    Hi @ilih,

    Please explain these fields i recently noticed?

    upload_2021-9-8_17-55-20.png
     
  28. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Those two options are used by ListView.ScrollToAnimated methods:
    Scroll Unscaled Time: specify time type used by scroll animation
    if enabled then will be used Time.unscaledTime
    if disabled then will be used Time.time
    Scroll Movement: how long scroll animation will be and what speed will it have, you can check Animation Curve docs

    AutoScroll is a function to automatically scroll ListView during drag&drop when the cursor is near the border.
    Auto Scroll Area: distance from border to the cursor.
    Auto Scroll Speed: scroll speed

    Stop scroll is a function to replace ScrollRect inertia in such a way so that after the end of scrolling, the ListView item will be exactly in the center.
    It is intended to use with ListType = Ellipse but works with other types too.
    Stop Scroll At Item Center: enable Stop Scroll
    Stop Scroll Inertia: similar to Scroll Movement, but only for the Stop Scroll function
     
    Last edited: Sep 8, 2021
    jGate99 likes this.
  29. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    v1.15.0 released

    Changelog:
    • added ListViewEnum with ListViewEnum<T> wrapper to work with any enums
    • reduced memory allocations
    • all classes with INotifyPropertyChanged support now also implements IObservable which works without memory allocations
    • Autocomplete, Combobox: added field ParentCanvas, it used as ListView parent on open
    • Combobox: toggle-button is now full width
    • ContextMenu: now works correctly with all canvas render modes
    • DateScroller/DateTimeScroller/TimeScroller: ScrollBlock replaced with ScrollBlockBase
    • Dialog: added InactiveDialogs and AllDialogs properties to get access to the template instances
    • Dialog: DialogButton now support callback with Func<DialogBase dialog, int buttonIndex, bool closeDialog> type
    • EasyLayout: small improvements
    • EasyLayout: Filter property is obsolete and replaced with ShouldIgnore
    • Input System support: fixed bug on mobile devices
    • ListView: added property TemplateSelector, its allow to use of different templates (not only DefaultItem) depending on the item
    • ListView: added GetDebugInfo and PringDebugInfo methods
    • ListView: added "AnimationCurve animation, bool unscaledTime, Action after = null" parameters to the ScrollTo*Animated methods
    • ListView: StopScrollAtItemCenter and StopScrollInertia properties
    • ListView: fixed problem with not displayed items for ListType with variable sizes
    • ListView: added GetComponentsEnumerator to iterate through DefaultItems instances as allocation free replacement of the ForEachComponent method
    • ListView: added support of Container with custom scale
    • ListView: fixed AutoScroll bug
    • Notification: NotificationButton now support callback with Func<NotificationBase notification, int buttonIndex, bool closeNotification> type
    • Paginators: added OnMovement event
    • Popup: added content and onClose parameters to the Show method, added SetContent() method, added OnClose field, works the same way as dialog
    • Resizable: added UseCanvasScaler option, if enabled ActiveRegion will be changed according to the CanvasScaler settings
    • ScrollBlock: added OnItemChanged event to customize items depending on index and value
    • ScrollBlock: added ScrollBlockBase and ScrollBlockCustom<T> classes
    • TracksViewBase: ScrollBlock replaced with ScrollBlockBase
    • TreeView: fixed drop support bug
    • TreeView prefabs: toggle arrow is now nested
    • UICursor: added Replacement function to replace cursor (can be used to replace cursor on High DPI screens)
    • Utilities: more functions moved to the new UtilitiesUI and UtilitiesRectTransform classes
     
    jGate99 likes this.
  30. KitBarry1809

    KitBarry1809

    Joined:
    Jun 27, 2018
    Posts:
    34
    I'm getting multiple null reference errors in the context menu example in the New UI Widgets SampleScene, they happen when I click on the context menu button on the left of the scene:

    NullReferenceException: Object reference not set to an instance of an object
    UIWidgets.Menu.HotKey.op_Inequality (UIWidgets.Menu.HotKey hotkey1, UIWidgets.Menu.HotKey hotkey2) (at Assets/New UI Widgets/Scripts/ContextMenu/HotKey.cs:222)
    UIWidgets.Menu.MenuItem.set_HotKey (UIWidgets.Menu.HotKey value) (at Assets/New UI Widgets/Scripts/ContextMenu/MenuItem.cs:118)
    UIWidgets.Menu.ContextMenu+MenuItemSerialized.op_Implicit (UIWidgets.Menu.ContextMenu+MenuItemSerialized serialized) (at Assets/New UI Widgets/Scripts/ContextMenu/ContextMenu.cs:109)
    UIWidgets.Menu.ContextMenu.Deserialize (System.Collections.Generic.List`1[T] serialized) (at Assets/New UI Widgets/Scripts/ContextMenu/ContextMenu.cs:688)
    UIWidgets.Menu.ContextMenu.get_MenuItems () (at Assets/New UI Widgets/Scripts/ContextMenu/ContextMenu.cs:269)
    UIWidgets.Menu.ContextMenu.UpdateMenuItems () (at Assets/New UI Widgets/Scripts/ContextMenu/ContextMenu.cs:503)
    UIWidgets.Menu.ContextMenu.Init () (at Assets/New UI Widgets/Scripts/ContextMenu/ContextMenu.cs:447)
    UIWidgets.Menu.ContextMenu.Start () (at Assets/New UI Widgets/Scripts/ContextMenu/ContextMenu.cs:423)

    from the game objects:
    • ContextMenu 1
    • ContextMenu 2
    • InternalContextMenu
    Using Unity 2019.4.14f1
     
  31. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Sorry for the problem.

    You can update to v1.15.1b2 or change code:

    Replace the following methods in New UI Widgets/Scripts/ContextMenu/HotKey.cs
    Code (CSharp):
    1.         public bool Equals(HotKey other)
    2.         {
    3.             if (ReferenceEquals(other, null))
    4.             {
    5.                 return false;
    6.             }
    7.  
    8.             return (key == other.key) && (ctrl == other.ctrl) && (shift == other.shift) && (alt == other.alt);
    9.         }
    Code (CSharp):
    1.         public static bool operator ==(HotKey hotkey1, HotKey hotkey2)
    2.         {
    3.             if (ReferenceEquals(hotkey1, null))
    4.             {
    5.                 return ReferenceEquals(hotkey2, null);
    6.             }
    7.  
    8.             return hotkey1.Equals(hotkey2);
    9.         }
    10.  
    11.         public static bool operator !=(HotKey hotkey1, HotKey hotkey2)
    12.         {
    13.             return !(hotkey1 == hotkey2);
    14.         }
    HotKey type was struct originally, so null check was unnecessary, but I forgot to add it after changed type to class.
     
  32. KitBarry1809

    KitBarry1809

    Joined:
    Jun 27, 2018
    Posts:
    34
    Thanks for the quick response!

    Have to say this is the best asset I've bought in terms of quality of the implementation and documentation. Really appreciate the work that's gone into it. I wish more assets were like this :)
     
    jGate99 likes this.
  33. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,936
    100+ Agreed, @ilih is the best
     
  34. KitBarry1809

    KitBarry1809

    Joined:
    Jun 27, 2018
    Posts:
    34
    I have a item Soldier. When I drag it from a list view into another container, I want to instantiate a prefab and then set the instantiated game object as one of the item's variables.

    Looking at your post above:
    I've replaced the ListViewDropSupport script on the receiving ListView with:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3.  
    4. namespace UIWidgets.Custom.SoldierNS
    5. {
    6.     /// <summary>
    7.     /// ListView drop support for the Soldier.
    8.     /// </summary>
    9.     [UnityEngine.RequireComponent(typeof(ListViewSoldier))]
    10.     public partial class ListViewDropSupportSoldierInstantiator : ListViewDropSupportSoldier
    11.     {
    12.         public override void Drop(Soldier data, PointerEventData eventData)
    13.         {
    14.             //instantiate our dude
    15.             if (data.instantiation==null)
    16.             {
    17.                 data.instantiation = Instantiate(data.prefab, Vector3.zero, Quaternion.identity);
    18.             }
    19.             //and then do whatever needs doing
    20.             base.Drop(data, eventData);
    21.         }
    22.     }
    23. }
    It works if I drag an item from another ListView to the one with ListViewDropSupportSoldierInstantiator on it: the usual ListView stuff happens and the prefab gets instantiated. But, if I drag an item from a TreeView my code doesn't get triggered. The usual ListView stuff happens, but the prefab does not get instantiated.

    What am I missing?
     
  35. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    TreeView has its own DropSupport components: one for the TreeView itself and the other for the nodes (it is attached to the TreeView.DefaultItem), so you need to make similar changes to those components.
     
  36. KitBarry1809

    KitBarry1809

    Joined:
    Jun 27, 2018
    Posts:
    34
    Ah, no, my bad: I didn't have an override for
    Drop(TreeNode<Soldier> data, PointerEventData eventData)
    :oops:
     
  37. KitBarry1809

    KitBarry1809

    Joined:
    Jun 27, 2018
    Posts:
    34
    I'm trying to make an inventory system where one container has one of each type of item, and they're an infinite resource. Setting Delete After Drop to false on the Default Item works for this.

    I also want this container to act like a bin for deleting items dragged back to it...so you can drag out a dozen of the item into other containers, and then if you drag one back it gets removed from the container it came from but doesn't get added to the receiving container. In other words I only ever want one of each kind of item in this container.

    I have it working for dragging from another ListView, by overriding the DropSupport Drop() method and not calling base.Drop()

    I can't get it to work for dragging from a TreeView. I tried not calling base.Drop() and that doesn't work: the drop indicator never goes away, and it doesn't remove the item from the TreeView. I've tried this, which is all of base.Drop except AddItem:
    Code (CSharp):
    1. public override void Drop(TreeNode<Soldier> data, PointerEventData eventData)
    2.         {
    3.             HideDropIndicator();
    4.  
    5.             if (DeleteNodeAfterDrop)
    6.             {
    7.                 data.Parent = null;
    8.             }
    9.         }
    and it works almost all the time, except for some strange behaviour if I have multiple copies of the same item in the TreeView: video here. The left ListView is the one with the overridden Drop methods on it. The other two containers are as-generated by the widgets. If I drag A (1) into the TreeView, then another A (2) below it, and then another A (3) as a child of the first A (1) I dragged in...when I drag out the last item A (3) the wrong A (2) gets removed from the list and A (1) starts behaving as if Delete After Drop is set to false, until I drag a different item into the TreeView and then the odd behaviour stops.

    Is that a bug in my code, or is TreeView having trouble finding the correct item in its list?
     
  38. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    What New UI Widgets version are you use?
    A similar bug was in one of the v1.15.0 beta versions.
     
  39. KitBarry1809

    KitBarry1809

    Joined:
    Jun 27, 2018
    Posts:
    34
    Version 1.15.0(current) from the asset store.
     
  40. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Fix:
    Replace the following methods in New UI Widgets / Scripts / TreeView / TreeNode.cs:
    Code (CSharp):
    1.         /// <summary>
    2.         /// Determines whether the specified object is equal to the current object.
    3.         /// </summary>
    4.         /// <param name="other">The object to compare with the current object.</param>
    5.         /// <returns><c>true</c> if the specified object is equal to the current object; otherwise, <c>false</c>.</returns>
    6.         public override bool Equals(object other)
    7.         {
    8.             if (other is TreeNode<TItem>)
    9.             {
    10.                 return Equals((TreeNode<TItem>)other);
    11.             }
    12.  
    13.             return false;
    14.         }
    15.  
    16.         /// <summary>
    17.         /// Determines whether the specified object is equal to the current object.
    18.         /// </summary>
    19.         /// <param name="other">The object to compare with the current object.</param>
    20.         /// <returns><c>true</c> if the specified object is equal to the current object; otherwise, <c>false</c>.</returns>
    21.         public virtual bool Equals(TreeNode<TItem> other)
    22.         {
    23.             return ReferenceEquals(this, other);
    24.         }
    Code (CSharp):
    1.         /// <summary>
    2.         /// Returns true if the nodes items are equal, false otherwise.
    3.         /// </summary>
    4.         /// <param name="a">The first object.</param>
    5.         /// <param name="b">The second object.</param>
    6.         /// <returns>true if the objects equal; otherwise, false.</returns>
    7.         public static bool operator ==(TreeNode<TItem> a, TreeNode<TItem> b)
    8.         {
    9.             if (ReferenceEquals(a, null))
    10.             {
    11.                 return ReferenceEquals(b, null);
    12.             }
    13.  
    14.             return a.Equals(b);
    15.         }
    16.  
    17.         /// <summary>
    18.         /// Returns true if the nodes items are not equal, false otherwise.
    19.         /// </summary>
    20.         /// <param name="a">The first object.</param>
    21.         /// <param name="b">The second object.</param>
    22.         /// <returns>true if the objects not equal; otherwise, false.</returns>
    23.         public static bool operator !=(TreeNode<TItem> a, TreeNode<TItem> b)
    24.         {
    25.             return !(a == b);
    26.         }
     
  41. KitBarry1809

    KitBarry1809

    Joined:
    Jun 27, 2018
    Posts:
    34
    Fixed, thanks!:D
     
  42. KitBarry1809

    KitBarry1809

    Joined:
    Jun 27, 2018
    Posts:
    34
    Found another little bug in TreeViews: if I call SelectNode on a child that's not yet expanded, the node gets expanded to show the child but the child does not get selected. If I call SelectNode on a child that's already expanded it gets selected as expected.
     
  43. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    You need to disable the
    DeselectCollapsedNodes
    option to select collapsed nodes.
    upload_2021-9-19_19-31-9.png

    Or you can call
    ExpandParentNodes(node)
    first.
    Code (CSharp):
    1. TreeView.ExpandParentNodes(node);
    2. TreeView.Select(node);
     
  44. KitBarry1809

    KitBarry1809

    Joined:
    Jun 27, 2018
    Posts:
    34
    If I do that, the old selection doesn't get removed.

    If I have child nodes A and B, call Select(A) with node collapsed, A gets selected. If I collapse the node again and call Select(B) both are now selected.

    The second fix works.
     
  45. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    This is a bug.
    Fix:
    Replace the
    Select()
    method at New UI Widgets / Scripts / TreeView / TreeViewCustom.cs
    Code (CSharp):
    1.         public void Select(TreeNode<TItem> node)
    2.         {
    3.             if (!IsNodeInTree(node))
    4.             {
    5.                 return;
    6.             }
    7.  
    8.             var index = Node2Index(node);
    9.             if (IsValid(index))
    10.             {
    11.                 Select(index);
    12.             }
    13.             else if (index == -1 && !DeselectCollapsedNodes)
    14.             {
    15.                 if (!MultipleSelect)
    16.                 {
    17.                     foreach (var n in SelectedNodes)
    18.                     {
    19.                         Deselect(n);
    20.                     }
    21.                 }
    22.  
    23.                 selectedNodes.Add(node);
    24.             }
    25.         }
     
  46. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    v1.15.1 released

    Changelog:
    • COMPATIBILITY-BREAKING CHANGES: cursors fields at components (Resizable, Rotatable, Splitter, TableHeader, DragSupport) are no more used and replaced with Cursors asset and CursorsDPISelector component
    • Accordion: added Curve property to use in animations
    • ContextMenu: fixed HotKey null bug
    • ListView: added OnComponentCreated, OnComponentEnabled, OnComponentDisabled, OnComponentDestroyed events
    • ListView: renamed StopScrollAtItemCenter to ScrollInertiaUntilItemCenter and StopScrollInertia to ScrollInertia
    • TreeView: fixed node remove bug when different nodes using the same item
    • TreeView: fixed multiple selection bug when selecting a collapsed node
    • TreeViewNodeDropSupport: added “Expand Node On Hold” option with customizable delay
    • UICursors: static methods changed to fields so now they can be replaced
     
    jGate99 likes this.
  47. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,936
  48. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    jGate99 likes this.
  49. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,936
    Hi @ilih
    Double Carousel is using GridLayout for its content so its really hard to make it responsive
    what i want to do is each slide takes full width and height

    upload_2021-9-25_11-26-49.png
     
  50. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    1,402
    Fix:
    • replace GridLayout with HorizontalLayoutGroup
    • add an Image component to the slides gameobject (image can have transparent color), without it layout do not work properly (it does necessarily be Image, it can be any other Graphic component)
    • replace
      Start()
      and
      OnDestroy()
      methods with the following code:
      Code (CSharp):
      1.         [SerializeField]
      2.         protected bool ResizeSlides = true;
      3.  
      4.         ResizeListener resizeListener;
      5.  
      6.         RectTransform rectTransform;
      7.  
      8.         /// <summary>
      9.         /// Process the start event.
      10.         /// </summary>
      11.         protected void Start()
      12.         {
      13.             ReverseContent = ReverseScrollRect.content;
      14.  
      15.             // duplicate first and last slides
      16.             var first = ReverseContent.GetChild(0);
      17.             var last = ReverseContent.GetChild(ReverseContent.childCount - 1);
      18.             Instantiate(first, ReverseContent, true);
      19.             Instantiate(last, ReverseContent, true).SetAsFirstSibling();
      20.  
      21.             // init
      22.             DirectPaginator.OnMovement.AddListener(UpdateReverse);
      23.             DirectPaginator.Init();
      24.             UpdateReverse(DirectPaginator.CurrentPage, 0f);
      25.  
      26.             rectTransform = transform as RectTransform;
      27.             if (ResizeSlides)
      28.             {
      29.                 var resizeListener = Utilities.GetOrAddComponent<ResizeListener>(this);
      30.                 resizeListener.OnResize.AddListener(UpdateSlidesSize);
      31.                 UpdateSlidesSize();
      32.             }
      33.         }
      34.  
      35.         /// <summary>
      36.         /// Process the destroy event.
      37.         /// </summary>
      38.         [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "HAA0603:Delegate allocation from a method group", Justification = "Required.")]
      39.         protected void OnDestroy()
      40.         {
      41.             if (DirectPaginator != null)
      42.             {
      43.                 DirectPaginator.OnMovement.RemoveListener(UpdateReverse);
      44.             }
      45.  
      46.             if (resizeListener != null)
      47.             {
      48.                 resizeListener.OnResize.RemoveListener(UpdateSlidesSize);
      49.             }
      50.         }
      51.  
      52.         void UpdateSlidesSize()
      53.         {
      54.             SetSlidesSize(rectTransform.rect.size);
      55.         }
      56.  
      57.         void SetSlidesSize(Vector2 size)
      58.         {
      59.             var page = DirectPaginator.CurrentPage;
      60.             SetSlidesSize(size, DirectPaginator.GetScrollRect().content);
      61.             SetSlidesSize(size, ReverseContent);
      62.  
      63.             DirectPaginator.PageSizeType = PageSizeType.Fixed;
      64.             DirectPaginator.PageSize = DirectPaginator.IsHorizontal() ? size.x : size.y;
      65.             DirectPaginator.CurrentPage = page;
      66.         }
      67.  
      68.         void SetSlidesSize(Vector2 size, Transform container)
      69.         {
      70.             for (int i = 0; i < container.childCount; i++)
      71.             {
      72.                 var slide = container.GetChild(i) as RectTransform;
      73.                 slide.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size.x);
      74.                 slide.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y);
      75.             }
      76.         }
    Now slides will match DoubleCarousel game object size if
    ResizeSlides
    is enabled.
     
    jGate99 likes this.