Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

New UI Widgets

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

  1. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    Thanks for all the updates Ilih, really appreciate your continuous support for making new ui widgets an indispensable part of unity life.
    so take your time to firist complete your existing roadmap.
     
    hopeful likes this.
  2. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    Please try v1.12.1b2.
    I added an automatic converter from default Unity text to TextMesh Pro and some changes to avoid performance degradation with Asset Pipeline V2.
    Converter available with context menu "UI/New UI Widgets/Replace Unity Text with TextMeshPro" or with "Window/New UI Widgets/Replace Unity Text with TextMeshPro."

    A lot of code was changed and tested, but please make a backup before update just in case if I missed something.
     
    Mazak and jGate99 like this.
  3. Mazak

    Mazak

    Joined:
    Mar 24, 2013
    Posts:
    222
    Quick comment-
    "ListView's: added Owner field to ListViewItem (base class for any DefaultItem), it contains link to parent ListView"

    I had owner in a data source and when I used Generate Widgets, it caused issues.

    I renamed it, but I thought you should know.
     

    Attached Files:

  4. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    Sorry for the problem and thanks for telling me about it.
    Here is a fix:
    Add following code to the New UI Widgets/Scripts/WidgetGeneration/Editor/ClassField.cs file.
    Code (CSharp):
    1.         static System.Collections.Generic.HashSet<string> prohibitedNames;
    2.  
    3.         protected bool HasDefinition(string name)
    4.         {
    5.             if (prohibitedNames == null)
    6.             {
    7.                 prohibitedNames = new System.Collections.Generic.HashSet<string>();
    8.  
    9.                 var type = typeof(TreeViewComponentBase<>);
    10.                 var flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
    11.                 foreach (var field in type.GetFields(flags))
    12.                 {
    13.                     prohibitedNames.Add(field.Name);
    14.                 }
    15.  
    16.                 foreach (var property in type.GetProperties(flags))
    17.                 {
    18.                     prohibitedNames.Add(property.Name);
    19.                 }
    20.  
    21.                 foreach (var method in type.GetMethods(flags))
    22.                 {
    23.                     prohibitedNames.Add(method.Name);
    24.                 }
    25.  
    26.                 // special cases for the TreeViewComponent
    27.                 prohibitedNames.Remove("Icon");
    28.                 prohibitedNames.Remove("TextAdapter");
    29.             }
    30.  
    31.             return prohibitedNames.Contains(name);
    32.         }
    And then add this code at the end
    SetWidgetByType
    method.
    Code (CSharp):
    1.             if (HasDefinition(WidgetFieldName))
    2.             {
    3.                 WidgetFieldName = WidgetFieldName + "Field";
    4.             }
     
    Mazak likes this.
  5. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    @ilih
    I'm using this Easy Layout as flow layout which works great.
    But i want to know if a given child is on 2nd row or 3rd row, how can i do that?
    Thanks
     
  6. Arcanor

    Arcanor

    Joined:
    Nov 4, 2009
    Posts:
    277
    PROBLEM SOLVED. Leaving this here for others to review, who might have similar issues.

    updated to latest version, using unity 2017.4.29f1 (LTS), imported new ui widgets v1.11.2, and now have errors:
    Assets/New UI Widgets/Scripts/Draggable/OnDragListener.cs(9,32): error CS0246: The type or namespace name `DragListener' could not be found. Are you missing an assembly reference?
    Assets/New UI Widgets/Scripts/ColorPicker/ColorPickerHSVPalette.cs(18,3): error CS0246: The type or namespace name `DragListener' could not be found. Are you missing an assembly reference?
    Assets/New UI Widgets/Scripts/ColorPicker/ColorPickerImagePalette.cs(22,3): error CS0246: The type or namespace name `DragListener' could not be found. Are you missing an assembly reference?
    Assets/New UI Widgets/Scripts/ColorPicker/ColorPickerRGBPalette.cs(18,3): error CS0246: The type or namespace name `DragListener' could not be found. Are you missing an assembly reference?


    Extra info: updated unity to the latest 2017.4.38f1 LTS release. same problem.

    Edit 2: I've fixed it by re-importing v1.11.2 after updating to 2017.4.38f1. Apparently the DragListener.cs script doesn't import into the earlier version, but does on the later release. The errors are now gone.
     
    Last edited: Apr 2, 2020
  7. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    For now, you can only try to calculate it using localPosition.y if all children have the same height:
    Code (CSharp):
    1. var row = (-item.localPosition.y + layout.spacing.y) / (item.height + layout.spacing.y)
    I'll add a function to get row and column of the child in the next update.
     
    jGate99 likes this.
  8. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    Unfortunately, such problems sometimes happen with unpacking package.
    Package re-import usually solves this.
     
    Last edited: Apr 2, 2020
  9. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    yes, that solves it, thanks :)
     
  10. tim44

    tim44

    Joined:
    May 15, 2019
    Posts:
    38
    After changing from android build to windows build, my tabs are all messed up.
    I've tried to disable-re-enable TextMesh Pro Support, Recompile

    One error is at: Name.text = tab.Name

    Code (CSharp):
    1. public class TabButtonComponentTMPro : TabButtonComponentBase
    2.     {
    3.         /// <summary>
    4.         /// The name.
    5.         /// </summary>
    6.         [SerializeField]
    7.         public TextMeshProUGUI Name;
    8.  
    9.         /// <summary>
    10.         /// Sets the data.
    11.         /// </summary>
    12.         /// <param name="tab">Tab.</param>
    13.         public override void SetButtonData(Tab tab)
    14.         {
    15.             Name.text = tab.Name; //error here
    16.         }
    17.     }
     
  11. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    Please, show the error message.
     
  12. tim44

    tim44

    Joined:
    May 15, 2019
    Posts:
    38
    NullReferenceException: Object reference not set to an instance of an object
    UIWidgets.TMProSupport.TabButtonComponentTMPro.SetButtonData (UIWidgets.Tab tab) (at Assets/New UI Widgets/Scripts/ThirdPartySupport/TMProSupport/Scripts/Tabs/TabButtonComponentTMPro.cs:26)
    UIWidgets.Tabs.SetButtonName (UnityEngine.UI.Button button, System.Int32 index) (at Assets/New UI Widgets/Scripts/Tabs/Tabs.cs:378)
    UIWidgets.Extensions.ForEach[T] (System.Collections.Generic.IEnumerable`1[T] enumerable, System.Action`2[T1,T2] handler) (at Assets/New UI Widgets/Scripts/Utilites/Extensions.cs:25)
    UIWidgets.Tabs.CreateButtons () (at Assets/New UI Widgets/Scripts/Tabs/Tabs.cs:354)
    UIWidgets.Tabs.UpdateButtons () (at Assets/New UI Widgets/Scripts/Tabs/Tabs.cs:159)
    UIWidgets.Tabs.Init () (at Assets/New UI Widgets/Scripts/Tabs/Tabs.cs:149)
    UIWidgets.Tabs.Start () (at Assets/New UI Widgets/Scripts/Tabs/Tabs.cs:123)


    If I comment out the error lines, it works fine, but the tabs aren't named correctly.
     
  13. tim44

    tim44

    Joined:
    May 15, 2019
    Posts:
    38
    Sorry about that, It wasn't clicking that I needed to setup the reference again. It's working now. These tabs have been great to use, thanks
     
  14. tim44

    tim44

    Joined:
    May 15, 2019
    Posts:
    38
    I had a lot of tabs, so changed it, seems to work:

    Code (CSharp):
    1. public override void SetButtonData(Tab tab)
    2.         {
    3.             Name = GetComponentInChildren<TextMeshProUGUI>();
    4.             Name.text = tab.Name;
    5.         }
     
  15. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    1. It's worth to add a null check to increase performance:
    Code (CSharp):
    1. if (Name == null)
    2. {
    3.    Name = GetComponentInChildren<TextMeshProUGUI>();
    4. }
    2. Can you tell what Unity version are you use?
    I'll try to reproduce the problem with lost references after a target platform changed and find a workaround for it.
     
  16. tim44

    tim44

    Joined:
    May 15, 2019
    Posts:
    38
    2018.4.17f1
     
    ilih likes this.
  17. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    Please check v1.12.1b4
    Replaced lambda functions with local functions in the main code (examples and editor code still use lambdas).
    Added Rotatable component and Scale option for the Resizable component.

    You need to disable Resizable.IncludeCorners to work it with Rotatable component.
     
    jGate99 likes this.
  18. tim44

    tim44

    Joined:
    May 15, 2019
    Posts:
    38
    I added this to SpinnerBase.cs to get going

    Code (CSharp):
    1. void Awake()
    2.         {
    3.             var inputPro = GetComponent<InputFieldTMProExtended>();
    4.             if (inputPro)
    5.             {
    6.                 inputPro.textComponent = gameObject.transform.GetChild(0).transform.Find("Text").GetComponent<TextMeshProUGUI>();
    7.                 inputPro.textViewport = gameObject.transform.Find("Text Area").GetComponent<RectTransform>();
    8.             }
    9.  
    10.             if (!plusButton)
    11.             {
    12.                 plusButton = gameObject.transform.parent.transform.Find("Plus").GetComponent<ButtonAdvanced>();
    13.             }
    14.             if (!minusButton)
    15.             {
    16.                 minusButton = gameObject.transform.parent.transform.Find("Minus").GetComponent<ButtonAdvanced>();
    17.             }
    18.         }
     
  19. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    A better way is to move such code OnValidate function and reopen affected scenes in the editor to apply validation and then save the scenes.
    This will restore references in the editor and you will not be needed to restore these code changes after the update.

    Example:
    Code (CSharp):
    1. #if UNITY_EDITOR
    2.         protected void OnValidate()
    3.         {
    4.             if (Name == null)
    5.             {
    6.                 UnityEditor.Undo.RecordObject(this, "Restore References");
    7.                 Name = GetComponentInChildren<Text>();
    8.             }
    9.         }
    10. #endif
    My assumptions about how the problem happened:
    1. #define directive (Scripting Define Symbols) to enable TMPro support was added only to the android settings, not to the windows settings.
    2. After the platform switch, TMPro support scripts was not compiled because of the missing directive
    3. The scene was saved, but references were lost because of the uncompiled scripts.
    4. TMPro support was enabled for the Windows platform, but references were already lost.

    Fixes:
    1. #define directive now added to all platforms instead of the currently active.
    But I am not sure if the added directive is actually saved for not installed platforms and what will be with the directive for the newly added platforms in the future Unity versions.
    2. TMPro support scripts are no more used, except one, so references lost should not happen more.

    Unfortunately, this will prevent problems only for the widgets created with the v1.12b1 and the next versions.
     
    tim44 likes this.
  20. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    Thanks :D
     
  21. tim44

    tim44

    Joined:
    May 15, 2019
    Posts:
    38
    That is much better, good to know!
     
  22. jGate99

    jGate99

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

    Can you please look at latest beta, it seems like list selection is not working anymore.
    I even checked sample scene and even there selection is not happening.

    I'm using Unity 2020.1b5

    Thanks
     
  23. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    Please replace SetOwnerItems function in Scripts/ListView/ListViewComponentPool.cs
    Code (CSharp):
    1.         protected void SetOwnerItems()
    2.         {
    3.             Owner.Items = new List<ListViewItem>(Components);
    4.         }
     
    jGate99 likes this.
  24. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    It worked :D
     
  25. MrIconic

    MrIconic

    Joined:
    Apr 5, 2013
    Posts:
    208
    Any reason why generate widgets button is greyed out even though I made a file similar to the one in the video?

    Fixed: I eventually changed parts of the file, moved the file, and then changed the file name itself and it worked. Then I reversed everything I did and it still works. So not sure why but it was probably my fault somewhere.
     
    Last edited: Apr 23, 2020
  26. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    Maybe the script was not compiled yet and the type definition was not available, so the button was disabled.
    Another reason can be the type is
    struct
    or
    interface
    inside a namespace, so Unity versions do not detect type in such cases.

    Beta version displays a message in case of error instead of the disabled button.
     
  27. MrIconic

    MrIconic

    Joined:
    Apr 5, 2013
    Posts:
    208
    I would assume there's no way to add/remove columns of a table at runtime since they're based on a pre-compiled class. However, would it be possible to hide (skip) a column from being displayed?

    I'm going to look around in the code but you might have a better idea before I figure it out where to go.
     
  28. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    You can use the TableHeader component (Table/Header gameobject).
    ColumnEnable/ColumnDisable/ColumnToggle methods to hide/show columns by the index.
     
    MrIconic likes this.
  29. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    It should be possible to add/remove columns at runtime, but I have not tested it yet.

    Something like this:
    Code (CSharp):
    1. var order = tableHeader.GetColumnsOrder();
    2. tableHeader.RestoreColumnsOrder();
    3. // add new column to the header
    4. new_column_header.SetParent(tableHeader.transform);
    5. new_column_header.SetSiblingIndex(...);
    6. // or remove column
    7. Destroy(tableHeader.transform.GetChild(index));
    8. tableHeader.Refresh()
    9.  
    10. // new DefaultItem with another set of cells
    11. listView.DefaultItem = newDefaultItem;
    12.  
    13. // modify order with new column index or deleted column index and set it back
    14. tableHeader.SetColumnsOrder(order);
     
    Last edited: Apr 24, 2020
  30. Petskus

    Petskus

    Joined:
    Jan 29, 2019
    Posts:
    23
    Can ScrollRectEvent have different thresholds sensitively?
    For example,
    50 on down (for list refresh)
    0 on up (for next list part fetch)
     
  31. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    You can update to the v1.12.1b7.
    In this version, RequiredMovement replaced with Thresholds to support different thresholds for the different pull directions.
     
    Petskus likes this.
  32. vutruc80

    vutruc80

    Joined:
    Jun 28, 2013
    Posts:
    55
    Hello i'm using Title View extensively in my project as a paged grid view.
    Assuming that i setup the view as 2x2 and i have 6 items.
    So the default behavior of TitleView with Paginator is:
    - Page 1 contains tiles 1,2,3,4
    - Page 2 contains tile 3,4,5,6
    What i want is page 2 (last page) only contains tiles 5,6 and doesn't intersect with the previous page but couldn't achieve it.
    Could you show me how to do it please? Thank you.
     
  33. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    This is caused by ScrollRect.MovementType.
    Unfortunately, there is no good solution at this moment.

    But here is a few possible workarounds:
    1. Disable ScrollRect.horizontal or ScrollRect.vertical after ListView.Init();
    Code (CSharp):
    1.             ListView.Init();
    2.             ListView.ScrollRect.horizontal = false;
    3.             ListView.ScrollRect.vertical = false;
    Disadvantages: mouse scroll and drag stop working.

    2. Change ScrollRect.MovementType to unrestricted.
    Disadvantages: scroll and drag can be done to the position where items not visible.

    3. Use the following script to automatically change ScrollRect.container size to avoid ScrollRect.MovementType restriction.
    This code will be added to the paginator in the next update.
    Code (CSharp):
    1. namespace UIWidgets.Examples
    2. {
    3.     using EasyLayoutNS;
    4.     using UIWidgets;
    5.     using UnityEngine;
    6.  
    7.     public class PaginatorFix : MonoBehaviour
    8.     {
    9.         public YourTileView ListView;
    10.         public ListViewPaginator Paginator;
    11.  
    12.         EasyLayout Layout;
    13.         float defaultMargin = 0f;
    14.  
    15.         protected void Start()
    16.         {
    17.             ListView.Init();
    18.             Layout = ListView.Layout;
    19.  
    20.             if (Layout.Symmetric)
    21.             {
    22.                 var m = Layout.Margin;
    23.                 Layout.Symmetric = false;
    24.                 Layout.MarginLeft = m.x;
    25.                 Layout.MarginRight = m.x;
    26.                 Layout.MarginTop = m.y;
    27.                 Layout.MarginBottom = m.y;
    28.             }
    29.  
    30.             defaultMargin = ListView.IsHorizontal() ? Layout.MarginRight : Layout.MarginBottom;
    31.  
    32.             AddListeners();
    33.         }
    34.  
    35.         protected void OnDestroy()
    36.         {
    37.             RemoveListeners();
    38.         }
    39.  
    40.         void AddListeners()
    41.         {
    42.             if (ListView.ScrollRect != null)
    43.             {
    44.                 var resizeListener = Utilities.GetOrAddComponent<ResizeListener>(ListView.ScrollRect);
    45.                 resizeListener.OnResize.AddListener(UpdateMargin);
    46.  
    47.             }
    48.  
    49.             if (ListView.Container != null)
    50.             {
    51.                 var contentResizeListener = Utilities.GetOrAddComponent<ResizeListener>(ListView.Container);
    52.                 if (contentResizeListener != null)
    53.                 {
    54.                     contentResizeListener.OnResize.AddListener(UpdateMargin);
    55.                 }
    56.             }
    57.         }
    58.  
    59.         void RemoveListeners()
    60.         {
    61.             if (ListView == null)
    62.             {
    63.                 return;
    64.             }
    65.  
    66.             if (ListView.ScrollRect != null)
    67.             {
    68.                 var resizeListener = ListView.ScrollRect.GetComponent<ResizeListener>();
    69.                 if (resizeListener != null)
    70.                 {
    71.                     resizeListener.OnResize.RemoveListener(UpdateMargin);
    72.                 }
    73.             }
    74.  
    75.             if (ListView.Container != null)
    76.             {
    77.                 var contentResizeListener = ListView.Container.GetComponent<ResizeListener>();
    78.                 if (contentResizeListener != null)
    79.                 {
    80.                     contentResizeListener.OnResize.RemoveListener(UpdateMargin);
    81.                 }
    82.             }
    83.         }
    84.  
    85.         void UpdateMargin()
    86.         {
    87.             var items_per_block = ListView.GetItemsPerBlock();
    88.             var items_per_page = items_per_block * Paginator.PerPage;
    89.             var items_at_last_page = ListView.GetItemsCount() % items_per_page;
    90.             var unexisted_items = items_per_page - items_at_last_page;
    91.             var unexisted_blocks = Mathf.FloorToInt(unexisted_items / items_per_block);
    92.  
    93.             var size = (ListView.DefaultItem.transform as RectTransform).rect.size;
    94.  
    95.             if (ListView.IsHorizontal())
    96.             {
    97.                 var margin = unexisted_blocks * size.x;
    98.                 if (unexisted_blocks > 0)
    99.                 {
    100.                     margin += (unexisted_blocks - 1) * Layout.Spacing.x;
    101.                 }
    102.                 Layout.MarginRight = margin + defaultMargin;
    103.             }
    104.             else
    105.             {
    106.                 var margin = unexisted_blocks * size.x;
    107.                 if (unexisted_blocks > 0)
    108.                 {
    109.                     margin += (unexisted_blocks - 1) * Layout.Spacing.y;
    110.                 }
    111.                 Layout.MarginBottom = margin + defaultMargin;
    112.             }
    113.         }
    114.     }
    115. }
     
  34. vutruc80

    vutruc80

    Joined:
    Jun 28, 2013
    Posts:
    55
    @ilih Thank you for the quick response!
    I tried your code but saw that UpdateMargin was never invoked so i removed your listener stuff and added a listener for ScrollRect onValueChanged then it works perfectly. Here is the updated code:

    Code (CSharp):
    1.     public class PaginatorFix : MonoBehaviour
    2.     {
    3.         public GameTileView ListView;
    4.         ScrollRectPaginator Paginator;
    5.  
    6.         EasyLayout Layout;
    7.         float defaultMargin = 0f;
    8.  
    9.         protected void Start()
    10.         {
    11.             Paginator = GetComponent<ScrollRectPaginator>();
    12.             ListView.Init();
    13.             Layout = ListView.Layout;
    14.  
    15.             if (Layout.Symmetric)
    16.             {
    17.                 var m = Layout.Margin;
    18.                 Layout.Symmetric = false;
    19.                 Layout.MarginLeft = m.x;
    20.                 Layout.MarginRight = m.x;
    21.                 Layout.MarginTop = m.y;
    22.                 Layout.MarginBottom = m.y;
    23.             }
    24.  
    25.             defaultMargin = ListView.IsHorizontal() ? Layout.MarginRight : Layout.MarginBottom;
    26.  
    27.             AddListeners();
    28.         }
    29.  
    30.         protected void OnDestroy()
    31.         {
    32.             RemoveListeners();
    33.         }
    34.  
    35.         void AddListeners()
    36.         {
    37.             if (ListView.ScrollRect != null)
    38.                 ListView.ScrollRect.onValueChanged.AddListener(OnScrollRect);
    39.         }
    40.  
    41.         void RemoveListeners()
    42.         {
    43.             if (ListView == null)
    44.             {
    45.                 return;
    46.             }
    47.  
    48.             if (ListView.ScrollRect != null)
    49.                 ListView.ScrollRect.onValueChanged.RemoveListener(OnScrollRect);
    50.         }
    51.  
    52.         void OnScrollRect(Vector2 value)
    53.         {
    54.             UpdateMargin();
    55.         }
    56.    
    57.         void UpdateMargin()
    58.         {
    59.             var items_per_block = ListView.GetItemsPerBlock();
    60.             var items_per_page = items_per_block * /*Paginator.PerPage*/ 4;
    61.             var items_at_last_page = ListView.GetItemsCount() % items_per_page;
    62.             var unexisted_items = items_per_page - items_at_last_page;
    63.             var unexisted_blocks = Mathf.FloorToInt(unexisted_items / items_per_block);
    64.  
    65.             var size = (ListView.DefaultItem.transform as RectTransform).rect.size;
    66.  
    67.             if (ListView.IsHorizontal())
    68.             {
    69.                 var margin = unexisted_blocks * size.x;
    70.                 if (unexisted_blocks > 0)
    71.                 {
    72.                     margin += unexisted_blocks * Layout.Spacing.x;
    73.                 }
    74.                 Layout.MarginRight = margin + defaultMargin;
    75.             }
    76.             else
    77.             {
    78.                 var margin = unexisted_blocks * size.x;
    79.                 if (unexisted_blocks > 0)
    80.                 {
    81.                     margin += unexisted_blocks * Layout.Spacing.y;
    82.                 }
    83.                 Layout.MarginBottom = margin + defaultMargin;
    84.             }
    85.         }
    86.     }
    One more thing i want to ask is because i'm using ScrollRectPaginater so i don't have
    Paginator.PerPage
    property (i assume that the block count per page) so i have to hardcode it. How to fix that hardcode?
     
  35. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    Sorry, I forgot to add
    UpdateMargin()
    call in the Start function, so if size never changes it will be never called.
    Code (CSharp):
    1.         protected void Start()
    2.         {
    3.            ...
    4.  
    5.             AddListeners();
    6.  
    7.             UpdateMargin();
    8.         }
    You can add serialized field with property:
    Code (CSharp):
    1.     public class PaginatorFix : MonoBehaviour
    2.     {
    3.         public GameTileView ListView;
    4.  
    5.         [SerializeField]
    6.         int blocksPerPage = 4;
    7.  
    8.         public int BlocksPerPage
    9.         {
    10.             get
    11.             {
    12.                 return blocksPerPage;
    13.             }
    14.  
    15.             set
    16.             {
    17.                 blocksPerPage = value;
    18.                 UpdateMargin();
    19.             }
    20.         }
    Or you replace
    UpdateMargin()
    to work with ScrollRectPaginator:
    Code (CSharp):
    1.         void UpdateMargin()
    2.         {
    3.             var list_view_size = ListView.IsHorizontal() ? ListView.ScrollRect.content.rect.width : ListView.ScrollRect.content.rect.height;
    4.             list_view_size -= ListView.IsHorizontal() ? Layout.MarginHorizontal : Layout.MarginVertical;
    5.  
    6.             var page_size = Paginator.PageSpacing;
    7.             if (Paginator.PageSizeType == PageSizeType.Fixed)
    8.             {
    9.                 page_size += Paginator.PageSize;
    10.             }
    11.             else if (ListView.IsHorizontal())
    12.             {
    13.                 page_size += (ListView.ScrollRect.transform as RectTransform).rect.width;
    14.             }
    15.             else
    16.             {
    17.                 page_size += (ListView.ScrollRect.transform as RectTransform).rect.height;
    18.             }
    19.  
    20.             var last_page_size = list_view_size % page_size;
    21.             var margin = last_page_size > 0.1f
    22.                 ? page_size - last_page_size - Paginator.PageSpacing
    23.                 : 0f;
    24.  
    25.             if (ListView.IsHorizontal())
    26.             {
    27.                 Layout.MarginRight = margin + defaultMargin;
    28.             }
    29.             else
    30.             {
    31.                 Layout.MarginBottom = margin + defaultMargin;
    32.             }
    33.         }
     
  36. uthon

    uthon

    Joined:
    Nov 23, 2015
    Posts:
    2
    Hi, just purchased this asset and I am trying to get started. I am very new to Unity and C#, lots of exp with C++.

    I figured out that I needed to create my own data class and generate the widgets from it, but I'm at a loss as to what to do next. Can someone post a *complete* code example of populating a list from C# dynamically?
     
  37. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    You can add/remove/change items with ListView.DataSource. It works almost the same way as List<T>.
    Code (CSharp):
    1. var item = new YourDataClass();
    2. ListView.DataSource.Add(item);
    Here is the script example.
    Create a new scene with ListView and Button, add this script to the button, then specify the ListView field.
    New item will be added on click.
    Code (CSharp):
    1.     using UIWidgets;
    2.     using UnityEngine;
    3.     using UnityEngine.UI;
    4.  
    5.     [RequireComponent(typeof(Button))]
    6.     public class TestListView : MonoBehaviour
    7.     {
    8.         [SerializeField]
    9.         public YourListView ListView;
    10.  
    11.         protected Button Button;
    12.  
    13.         protected virtual void Start()
    14.         {
    15.             Button = GetComponent<Button>();
    16.             Button.onClick.AddListener(Click);
    17.         }
    18.  
    19.         protected void Click()
    20.         {
    21.             var item = new YourDataClass();
    22.             ListView.DataSource.Add(item);
    23.         }
    24.  
    25.         protected virtual void OnDestroy()
    26.         {
    27.             if (Button != null)
    28.             {
    29.                 Button.onClick.RemoveListener(Click);
    30.             }
    31.         }
    32.     }
     
  38. uthon

    uthon

    Joined:
    Nov 23, 2015
    Posts:
    2
    Thank you very much, that was exactly what I needed. Your asset is excellent, as is your support.

     
  39. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    @ilih
    Im using same list view with multiple datasources (one at a time) which i reuse and i'm getting this error even though my observable sources are set to false in constructor.
    please advise


    Code (CSharp):
    1. MissingReferenceException: The object of type 'WSMultiParentViewComponent' has been destroyed but you are still trying to access it.
    2. Your script should either check if it is null or you should not destroy the object.
    3. UnityEngine.Object.Instantiate[T] (T original) (at <23e371e9422742b6a92a9f9bfb37a189>:0)
    4. UIWidgets.Compatibility.Instantiate[T] (T original) (at Assets/New UI Widgets/Scripts/Utilities/Compatibility.cs:365)
    5. UIWidgets.ListViewCustom`2[TComponent,TItem].get_DefaultItemCopy () (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:665)
    6. UIWidgets.ListViewCustom`2+ListViewTypeSize[TComponent,TItem].CalculateItemsSizes (UIWidgets.ObservableList`1[T] items, System.Boolean forceUpdate) (at Assets/New UI Widgets/Scripts/ListView/ListViewType/ListViewTypeSize.cs:302)
    7. UIWidgets.ListViewCustom`2[TComponent,TItem].SetNewItems (UIWidgets.ObservableList`1[T] newItems, System.Boolean updateView) (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:2081)
    8. UIWidgets.ListViewCustom`2[TComponent,TItem].UpdateItems () (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:1505)
    9. UIWidgets.ObservableList`1[T].CollectionChanged (System.Boolean reSort) (at Assets/New UI Widgets/Scripts/Utilities/ObservableList.cs:252)
    10. UIWidgets.ObservableList`1[T].CollectionChanged () (at Assets/New UI Widgets/Scripts/Utilities/ObservableList.cs:234)
    11. UIWidgets.ObservableList`1[T].Clear () (at Assets/New UI Widgets/Scripts/Utilities/ObservableList.cs:441)
     
  40. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    This is happening because of ListView.DefaultItem gameobject was destroyed.
    You should check your code: it may be destroyed directly or on scene change (possible if DefaultItem is outside ListView hierarchy and ListView is marked DontDestroyOnLoad)
     
  41. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    Thats what confusing me, i havent set this ObersverableList to ListView yet but still get this error. My ListView itself is originally is set with another ObersverableList.
     
  42. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    I think the problem is not related to ObservableList.
    Please try to add this line before the Clear() call:
    Debug.Assert(ListView.DefaultItem != null, "DefaultItem is destroyed.", ListView);

    If warning displayed in the console window then DefaultItem was destroyed earlier.
     
  43. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    Sorry to keep bothering, if i use BeginUpdate and EndUpdate then this error is not thrown (even though observablelist's observeItems = false)


    UPDATE
    please ignore, i was setting it and then clearing it in my code
    sorry for the blunder i made.
     
    Last edited: May 6, 2020
  44. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    This looks even more strange.
    Can you show code where you are working with DataSource?

    BeginUpdate()/EndUpdate() and ObserveItems are doing different things.

    BeginUpdate()/EndUpdate() are pack all change events on single event which raised with EndUpdate call.
    ListView is updated with every change event so it helps to avoid unnecessary updates.
    Change events are raised in cases:
    • item added
      list.Add(new_item);
    • item removed
      list.Remove(item);

    • item changed
      list[0] = new_item;
    • items order changed
      list.Sort();
    • item data changed
      list[0].Name = "new name";
    ObservableList<TItem>.ObserveItems is work only with the "item data changed" case and only if TItem with INotifyPropertyChanged and IObservable interfaces.
    If ObserveItems is enabled AND TItem has one of those interfaces then the event will be raised if item data are changed.
    If ObserveItems is disabled OR TItem has no interfaces then the event will not be raised.
     
  45. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    Released v1.12.1f1

    Changelog:
    • added converter from Unity Text to TextMeshPro text
    • added IUpgradeable interface to improve compatibility between versions
    • added Groupable component
    • added UIFlareTransparent shader
    • added ResizableHandles component
    • added Rotatable component
    • added RotatableHandle component
    • deleted a lot of lambda functions
    • other lambda functions replaced with local functions
    • renamed classes *Utilites to *Utilities
    • improved performance with Asset Pipeline V2
    • Combobox: fixed navigation support
    • Draggable: added Target property to drag the specified target instead of self
    • DragSupport: added AllowDrag field
    • DropSupport: added ReceiveItems and ReceiveNodes fields for the base classes
    • ListView: not selectable items are no more highlighted and navigated
    • ListViewPaginator, ScrollRectPaginator: added LastPageFullSize option to change the last page size to full-page size
    • Resizable: AllowResize renamed to Interactable
    • Resizable: added resize type to change between size and scale
    • Resizable: added Target property to resize the specified target instead of self
    • ScrollRectEvents: RequiredMovement replaced with Thresholds to support separate thresholds for each pull direction
    • Splitter: AllowResize renamed to Interactable
    • Widgets Generation: added option to manually specify the type name if the type cannot be detected from the MonoScript
     
    Petskus, hopeful and jGate99 like this.
  46. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    Another huge amazing update, congrats :)
     
    ilih and hopeful like this.
  47. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    @ilih
    This error came again, and it appears randomly

    why calling Clear () method triggers collection change all the way to above error even though this datasource is not observable = true, especially when im not even setting this data source. just calling Clear on it

    please advise


    Code (CSharp):
    1. MissingReferenceException: The object of type 'WSMultiParentViewComponent' has been destroyed but you are still trying to access it.
    2. Your script should either check if it is null or you should not destroy the object.
    3. UnityEngine.Object.Instantiate[T] (T original) (at <2ca68b418e8b4d85bdbca2257895a2ba>:0)
    4. UIWidgets.Compatibility.Instantiate[T] (T original) (at Assets/New UI Widgets/Scripts/Utilities/Compatibility.cs:365)
    5. UIWidgets.ListViewCustom`2[TComponent,TItem].get_DefaultItemCopy () (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:665)
    6. UIWidgets.ListViewCustom`2+ListViewTypeSize[TComponent,TItem].CalculateItemsSizes (UIWidgets.ObservableList`1[T] items, System.Boolean forceUpdate) (at Assets/New UI Widgets/Scripts/ListView/ListViewType/ListViewTypeSize.cs:302)
    7. UIWidgets.ListViewCustom`2[TComponent,TItem].SetNewItems (UIWidgets.ObservableList`1[T] newItems, System.Boolean updateView) (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:2081)
    8. UIWidgets.ListViewCustom`2[TComponent,TItem].UpdateItems () (at Assets/New UI Widgets/Scripts/ListView/ListViewCustom.cs:1505)
    9. UIWidgets.ObservableList`1[T].CollectionChanged (System.Boolean reSort) (at Assets/New UI Widgets/Scripts/Utilities/ObservableList.cs:252)
    10. UIWidgets.ObservableList`1[T].CollectionChanged () (at Assets/New UI Widgets/Scripts/Utilities/ObservableList.cs:234)
    11. UIWidgets.ObservableList`1[T].Clear () (at Assets/New UI Widgets/Scripts/Utilities/ObservableList.cs:441)
     
  48. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    This error has happened because of ListView.DefaultItem was destroyed before
    Clear()
    call, the error will also happen if it will be Add/Remove/Sort call.


    Clear()
    raise the "collection changed" event.

    ObservableList<T>(false)
    or
    ObservableList<T>.ObserveItems = false;
    is used only to disable "collection item changed" events in cases like
    list[index].Name = "value";
    .
    It does not disable "collection changed" events.

    "Collection changed" events cannot be disabled, only delayed with BeginUpdate() and EndUpdate() methods.

    You can create tempopary collection and work with it and then copy data back to DataSource.
    Code (CSharp):
    1. // tempopary collection
    2. var original_list = ListView.DataSource;
    3. var temp_list = new List<T>(original_list);
    4. // works with temp_list
    5. ...
    6.  
    7. // copy data back
    8. original_list.BeginUpdate();
    9. original_list.Clear();
    10. original_list.AddRange(temp_list);
    11. original_list.EndUpdate();
     
    Last edited: May 9, 2020
    jGate99 likes this.
  49. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,029
    Problem is, i havnt even assigned this datasource to listview yet and still i get this error RANDMOLY and thats why its annoying. Here is the problem:

    I have 2 observable lists
    ObservableList<WSMultiItem> MainMenu = {My Matches, Help, Settings};
    ObservableList<WSMultiItem> TurnBasedMatches = {items will come from server}

    Now currently MainMenu is set to ListView, and when user selects an item for matches, then i request server to get me list of matches, i clear the TurnBasedMatches datasource, i saved those matches in this DS, and then i assign to Listview which was previously using MainMenu.

    Now what happens is that this error caused on clear WAY BEFORE i assigned it to listview, so i checked the code why its doing that and i saw this

    /// Occurs when data changed.
    /// </summary>
    public event OnChange OnChange = Utilities.DefaultHandler;

    So this DefaultHandler seems to be called for a listview whether that listview has that Datasource assigned or not.

    Please let me know if im able to explain the problem.
    Thanks
     
    Last edited: May 10, 2020
  50. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    796
    How is user selection is detected? What happens in case DataSource != MainMenu?
    Maybe after you assign TurnBasedMatches to Listview selection happens again and because of this things go wrong.

    You should check if it really assigned to any ListView with Visual Studio debugger or with following code:
    Add this function to
    ObservableList<T>
    :
    Code (CSharp):
    1.         public string OnChangeInfo()
    2.         {
    3.             var delegates = OnChange.GetInvocationList();
    4.             var result = string.Empty;
    5.             result += "Delegates: " + delegates.Length + "\r\n";
    6.             for (int i = 0; i < delegates.Length; i++)
    7.             {
    8.                 result += i + ". Method: " + delegates[i].Method.Name +  ". Class: " + delegates[i].Method.DeclaringType + "\r\n";
    9.             }
    10.  
    11.             return result;
    12.         }
    Then check with:
    Code (CSharp):
    1. Debug.Log(TurnBasedMatches.OnChangeInfo());
    If TurnBasedMatches not assigned to ListView:
    Code (CSharp):
    1. Delegates: 1
    2. 0. Method: DefaultHandler. Class: UIWidgets.Utilities
    If TurnBasedMatches assigned to ListView:
    Code (CSharp):
    1. Delegates: 2
    2. 0. Method: DefaultHandler. Class: UIWidgets.Utilities
    3. 1. Method: UpdateItems. Class: UIWidgets.ListViewCustom`2[UIWidgets.ListViewIconsItemComponent,UIWidgets.ListViewIconsItemDescription]
    Utilities.DefaultHandler is just an empty function and does nothing. It is needed to avoid the null checks for events.
    So I can use raise events like this:
    Code (CSharp):
    1. OnChange();
    But without Utilities.DefaultHandler event will be null by default and should be raised like this:
    Code (CSharp):
    1. var evs = OnChange;
    2. if (evs != null)
    3. {
    4.    evs();
    5. }
    And this is how event should not be raised, despite nothing wrong on the first look:
    Code (CSharp):
    1. if (OnChange != null)
    2. {
    3.    OnChange();
    4. }
    You should check how TurnBasedMatches used, I am sure it was assigned to ListView before Clear() call. I do not have any other explanation.

    Add checks like this before all ListView assigns to make sure it work as planned
    Code (CSharp):
    1. Debug.Log("DataSource is MainMenu: " + ReferenceEquals(ListView.DataSource, MainMenu));
    2. Debug.Log("DataSource is TurnBasedMatches: " + ReferenceEquals(ListView.DataSource, TurnBasedMatches));
    3. ListView.DataSource = TurnBasedMatches;
    And I never saw the full stack trace, only after Clear() call which is not enough.
     
    jGate99 likes this.
unityunity