I would like the functionality where the buttons Tab1, Tab2, Tab3 can be selected (only 1 of them at a time) and depending on which one is selected, the content belows it changes. The tabs are button elements.
I would store a variable for the tab index (0 for Tab 1, 1 for Tab 2, 2 for Tab 3), then for the clickable.clicked for each element, I would set the tab index variable to the index of the tab. So you could, if you wanted to, set the userData for each button to the index you want it to be.
Then you would want to update your style for the button. So before you change the tab index, you could revert the style of the old tab index element, then change the tab index, set the style for the new tab element, and then hide the old tabâs container element, and show the new tabâs container element.
UI Builder can only really build your UI layout/hierarchy and styles. You still have the use C# to control behavior.
Use a different UXML file for each âpaneâ or tab âcontainerâ, then you can work on the layouts individually and at runtime load them all up under your tabs.
Once you load all containers (via visualTreeAsset.CloneTree()), you should use style.display = DisplayStyle.None to hide the containers for the tabs that not active.
When you register for the Tab buttons clickables, use myTabButton.clickable.clickedWithEventInfo so you can get the EventBase in your callback.
You can use EventBase.target to get the Tab button that was clicked (so you can use a single callback for all 3 buttons)
In your Tab button callback, just set myElement.style.display = DisplayStyle.None on all containers and then set myElement.style.display = DisplayStyle.Flex on the newly active container.
Hey! I only just got back to working on this. Thank you very much for the help.
I got up to the point where I registered to the clickedWithEventInfo callback and the EventBase is properly passed but how would I differentiate between the tabs?
Using EventBase.target.ToString() I could maybe get the buttonâs text and differentiate based on that but is there a better way to get the buttonâs text in order to differentiate? Or should I not be looking at the buttonâs text at all but rather some ID? Button position? Something else?
Thank you in advance,
Alex
Edit: EventBase.target.ToString().Contains() is working perfectly but I imagine there must be a better way to differentiate between my tabs.
Edit2: I figured I could do the following: âButton b = tab.target as buttonâ and like that I can get the text which is a cleaner solution. Thank you!
Hello! New developer here. Getting better at navigating UIElements, but by chance is there anyway you can write this out in code so I can better see how this is structured (or should I create a new thread)?
I have been hammering away at google and in code trying to figure out how to get a UI Elements Button/Toggle on a Component Inspector to open up an Editor Window and havenât been able to piece it together. This thread seems very close to what I am hoping for.
I am gonna feel stupid for admitting this, but it doesnât help, but maybe I should be a bit more specific too.
Ideally Iâd like to have 10 toggles or set of buttons on a custom component inspector that each open up a new, but similar unique instance of an editor window.
I am looking for any documentation on how to call an Editor Window from a Monobehavior script.
Would love to figure out how to open and close all 10 editor windows via a single individual component/editor (instead of having to access each level window through the Unity toolbar at the top of the screen).
Iâm not sure why your clickable is not triggered. Your code looks ok, unless the many registrations conflict each other in some way. This is all you should need. I couldnât get it not to work for me.
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
public class SimpleBuggyWindow : EditorWindow
{
[MenuItem("bla/SimpleBuggyWindow")]
public static void ShowExample()
{
SimpleBuggyWindow wnd = GetWindow<SimpleBuggyWindow>();
wnd.titleContent = new GUIContent("SimpleBuggyWindow");
}
public void OnEnable()
{
// Each editor window contains a root VisualElement object
var root = rootVisualElement;
var tree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Button.uxml");
var treeElement = tree.CloneTree();
// Do not use .Query() for a single element.
//Button button = treeElement.Query<Button>();
// Use .Q():
var button = treeElement.Q<Button>();
button.clickable.clicked += () => Debug.Log("Clicked");
root.Add(button);
}
}
Please see if the exact C# and UXML I have above works or doesnât work for you. Also try restarting Unity in between. Come back if thereâs still an issue.
PS: Please use a code block next time instead of a screenshot. Itâs a bit easier for someone to test your code.
@FLDSMDFR2 If youâre using the runtime preview, make sure you have both a PanelRenderer and a EventSystem next to it, otherwise, no mouse or keyboard Events will be fired to your panelâs content, I got bit by that once
@FLDSMDFR2 Please try this within the Unite Copenhagen Demo project (which has buttons that are clickable and work at runtime):
The runtime support for UI Toolkit is not officially released nor supported so depending on which version of the unofficial code you have you may be running into bugs (that have since been fixed).
I am using the RuntimeDemo Assets and within the Demo Scene the buttons work correctly⌠So i update my original code to to follow the Demos implementation and it works for me.
Basically adding a reference to the in game PanelRenderer and called the postUxmlReload.
However if i am not referencing the in game PanelRenderer and try and grab the VisualTreeAsset from the AssetDatabase like so _assetTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Button.uxml");
it does not work.
Working Code
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
using System.Collections.Generic;
using Unity.UIElements.Runtime;
public class ShopManagerUIBuilder : MonoBehaviour
{
//private VisualElement _visualTree;
//private VisualTreeAsset _assetTree;
public PanelRenderer GameScreen;
public void OnEnable()
{
GameScreen.postUxmlReload = BindGameScreen;
}
private IEnumerable<Object> BindGameScreen()
{
var root = GameScreen.visualTree;
Button b = root.Q<Button>("Button");
b.clickable.clicked += ButtonClicked;
//_assetTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Button.uxml");
//_visualTree = _assetTree.CloneTree();
//Button b = _visualTree.Q<Button>("Button");
//b.clickable.clicked += ButtonClicked;
return null;
}
private void ButtonClicked()
{
TraceManager.WriteTrace(TraceChannel.Main, TraceType.info, "Button Clicked");
}
}
This is an Editor-only API which means that it âmightâ work at Runtime when running the game in Playmode inside the Editor but it will not work when you build the Player. You can either use the Resources.Load() API or try to reference all the UXML and USS assets you need in a MonoBehaviour at edit time.