Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Unity UI Toolkit Runtime Treeview

Discussion in 'UI Toolkit' started by equal, Jun 21, 2023.

  1. equal

    equal

    Joined:
    Dec 14, 2012
    Posts:
    77
    Hi,

    first off, thank you very much for helping me out in another Thread,LostDog-FoundCat .
    I have some more questions and figured this would be best packaged in a new one.

    Currently i managed to populate a TreeView for Runtime, so that it displays what i had in mind.
    upload_2023-6-21_13-3-31.png

    My questions are:
    • 1. I use a plain c# object instead of an interface for TreeViewItemData<T0> , is this alright or will i run into some Performance issues or other Problems? I do this to have different classes in 1 Treeview without the need for them to share 1 Interface (so i can add custom elements, depending on the classe later on).
      Here is the bindItem code for this:
    Code (CSharp):
    1.         // Set TreeView.bindItem to bind an initialized node to a data item.
    2.         treeV.bindItem = (VisualElement element, int index) =>
    3.         {
    4.             if (treeV.GetItemDataForIndex<object>(index) is sdGalaxy g)
    5.             {
    6.                 (element as Label).text = treeV.GetItemDataForIndex<sdGalaxy>(index).Name;
    7.             }
    8.             else if (treeV.GetItemDataForIndex<object>(index) is sdSector s)
    9.             {
    10.                 (element as Label).text = treeV.GetItemDataForIndex<sdSector>(index).Name;
    11.             }
    12.             // todo: add case for Cosmos HERE (this is why the screenshot has an unnamed element at top)
    13.             else if (treeV.GetItemDataForIndex<object>(index) is string G)
    14.             {
    15.                 (element as Label).text = G;
    16.             }
    17.         };
    • 2. I understand what the TreeViews item "Func<VisualElement>"'s do. But i couldnt find examples to when to use them or to ignore the.
    2.1 makeItem => clear, the Visualizer/Virtualizer of the Tree detected that this item is need AND visible, use this to Generate the Container for this Item. This is needed for Container and Display.
    2.2 bindItem => clear, the Visualizer/Virtualizer has detected some change that makes this Container visible AND/OR change Content. This is needed for Content Change and Display.
    2.3 unbindItem => not clear. When should i supply this Func with code? My simple example seems to work just fine without it.
    2.4 destroyItem => not clear. When should i supply this Func with code?​

    • 3. It is my understanding that when i screew up with those 4 itemFuncs properly, i can crash the application ? Like stuff gets bound without proper unbinding while the user scrolls wildly around?

    • 4. Feedback: The documentation should mention that 1 Treeview needs 1 unique key for each element in the Treeview, no matter the nesting levels. I hope i didnt miss this information somehow.
    • 5. Feedback 2 :) I would suggest to Rename "bindItem" and "unbindItem" dearly to something else, like "supplyItem" and "unsupplyItem". If Data Bindings are to come, this is begging for Problems and Support help requests, it also makes searching a bit harder.
     
  2. equal

    equal

    Joined:
    Dec 14, 2012
    Posts:
    77
    bump
     
  3. LostDog-FoundCat

    LostDog-FoundCat

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    19
    Hey there - thanks for bumping this up - for some reason I wasn't alerted to the first posting of this last week. Let me do some digging and see what I can find
     
  4. griendeau_unity

    griendeau_unity

    Unity Technologies

    Joined:
    Aug 25, 2020
    Posts:
    229
    1- There shouldn't be any problem using plain C# objects. One thing though; you can use the result of the
    is
    operation to avoid doing two queries:

    Code (CSharp):
    1. if (treeV.GetItemDataForIndex<object>(index) is sdGalaxy g)
    2. {
    3.     (element as Label).text = g.Name;
    4. }
    2.You would typically use
    unbindItem
    or
    destroyItem
    if you registered event callbacks during make/bind item that need unregistering, or if you are using additional element pooling on top of the virtualization for example.

    3. Do you have an example of code that would crash the editor? Items are virtualized so the binding code needs to watch out for any recursive paths or registering multiple times the same event.

    4. Sure, we can add a note in the scripting API and the manual. Thanks for the feedback!

    5. This is indeed an annoyance we have internally when talking about the multiple binding systems too :) . I can bring that concern to the team. API changes take a few versions to be completed entirely because we don't want to break user code, and these changes cannot be backported to older versions for the same reason, so this would most likely take some time to happen.
     
    LostDog-FoundCat likes this.
  5. equal

    equal

    Joined:
    Dec 14, 2012
    Posts:
    77
    Thank you very much for this detailed Information.
    For 3. i had in mind just the case you described in 3/2, where i would subscribe but not unsubscribe during scrolling.
    And with egnouth scrolling while subscribing to anything, i thought i would reach a cap.
    But Since you mentioned not only "unsubscribed" case but also recusrion, i think this covers it.

    So unless i understand it wrong, your awnser 3 tells me i could, but shouldnt, ignore unsubscribing in "unbind Item" ?
     
  6. equal

    equal

    Joined:
    Dec 14, 2012
    Posts:
    77
    Another problem showed up. The TreeView has indent levels, but i can not find a proper to way to manipulate them.
    When i use uss, it gets ignored ( based on this Info ) as it should because it say "inline" in the debugger.
    upload_2023-7-3_16-12-4.png

    While this is an ok width for the Editor TreeV (Above), its too much for Runtime TreeV (Below)

    upload_2023-7-3_16-15-19.png

    I figured a way to achive what i want, by drilling throu the VisualElements to reach the Indent Element.
    upload_2023-7-3_16-18-1.png

    Like this:
    Code (CSharp):
    1. // Set TreeView.bindItem to bind an initialized node to a data item.
    2.         treeV.bindItem = (VisualElement element, int index) =>
    3.         {
    4.             if (element is PlanetaryTreeElementRepresenter plListEntry)
    5.             {
    6.                 if (treeV.GetItemDataForIndex<object>(index) is sdCosmos cos)
    7.                 {
    8.                     plListEntry.sLabel.text = cos.Name;
    9.                     plListEntry.sToggle.visible = false;
    10.                     plListEntry.sImageVisualElement.style.backgroundImage = icon_cosmos;
    11.                     var childs = plListEntry.parent.Children();
    12.                     foreach (var item in childs)
    13.                     {
    14.                         item.style.width = 10;
    15.                         break;
    16.                     }
    17.                 }
    18.                 else if (treeV.GetItemDataForIndex<object>(index) is sdGalaxy g)
    19.                 {
    20.                     plListEntry.sLabel.text = g.Name;
    21.                     plListEntry.sToggle.visible = false;
    22.                     plListEntry.sImageVisualElement.style.backgroundImage = icon_galaxy;
    23.                     var childs = plListEntry.parent.parent.Children();
    24.                     foreach (var item in childs)  // HERE DRILLING //
    25.                     {
    26.                         item.style.width = 10;
    27.                         break;
    28.                     }
    29.                 }
    30.                 else if (treeV.GetItemDataForIndex<object>(index) is sdSector s)
    31.                 {
    32.                     plListEntry.sLabel.text = s.Name;
    33.                     plListEntry.sToggle.visible = true;
    34.                     plListEntry.sImageVisualElement.style.backgroundImage = icon_sector;
    35.                 }
    36.                 else if (treeV.GetItemDataForIndex<object>(index) is string G)
    37.                 {
    38.                     element.Q<Label>().text = G;
    39.                 }
    40.             }
    41.             else
    42.             {
    43.                 Label l = element.Q<Label>();
    44.                 if (l != null)
    45.                 {
    46.                     l.text = "ERROR:Element is not PlanetaryListEntryController";
    47.                 }
    48.             }
    49.         };
    50.  
    But that cant be right?
    In short: How to change indent level in general and how to change it per element?
     
    Last edited: Jul 3, 2023
  7. griendeau_unity

    griendeau_unity

    Unity Technologies

    Joined:
    Aug 25, 2020
    Posts:
    229
    The width of the indent needs to be computed because it can change from line to line as the items are reused and virtualized. We use the width of the foldout arrow to calculate this indent. That width seems to be a lot larger by default in Runtime, hence the large indent.
    By changing the style of the toggle arrow, you should automagically have an updated width for the indent.

    Though it's a good point that the relation is not clear between the two. We lack documentation there. We could also support to set indent width with a uss variable, maybe that would help (and would also allow users to have 2 different widths for indent and toggle. Feel free to submit a bug if that's a missing building block for you.
     
  8. equal

    equal

    Joined:
    Dec 14, 2012
    Posts:
    77
    Thank you for your time.
    I never reported a bug before, so i did it like this https://unity3d.atlassian.net/servicedesk/customer/portal/2/IN-46446
    Is this right?
    -----

    As you said the values are being reset, no matter what i tried.

    I just tried it and it works. I forgot the margin in the Bug Report tho.
    Code (CSharp):
    1. #unity-tree-view__item-toggle > VisualElement > VisualElement {
    2.     margin-left:0px;
    3.     width: 0px;
    4.     margin-right:0px;
    5. }


    This would be amazing, and there seems to be a bug that multiplies the values during runtime by 4.
     
  9. martinpa_unity

    martinpa_unity

    Unity Technologies

    Joined:
    Oct 18, 2017
    Posts:
    354
    Yes it is!

    It can take some time before it reaches us, but it will get there :)