sinister-kid / Rosalina

Rosalina is a code generation tool for Unity's UI documents. It generates C# code-behind script based on a UXML template.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rosalina

openupm

Rosalina is a code generation tool for Unity's UI documents make with the new UI Toolkit. It automatically generates C# UI binding scripts based on a UXML document template.

Key features

  • UI Documents
    • Automatic C# bindings generation
    • C# document script
  • EditorWindow support
    • Automatic C# bindings generation
    • C# document script

How to install

Rosalina can either be installed via OpenUPM: https://openupm.com/packages/com.eastylabs.rosalina/ Or by using the following git repository: https://github.com/Eastrall/Rosalina.git

Installing via OpenUPM

Rosalina is now available via OpenUPM: https://openupm.com/packages/com.eastylabs.rosalina/

OpenUPM provides a detailed explanation of how to add packages to unity.

Installing via git repository

In Unity, navigate to Window -> Package Manager:

image

In the Package Manager, click on the + on the top left and select Add package from git URL...

image

No use the following path to install Rosalina https://github.com/Eastrall/Rosalina.git

image

You can now start to work with Rosalina.

How it works

Rosalina watches your changes related to all *.uxml files contained in the Assets folder of your project, parses its content and generates the according C# UI binding code based on the element's names.

Take for instance the following UXML template:

SampleDocument.uxml

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"
         xsi="http://www.w3.org/2001/XMLSchema-instance"
         engine="UnityEngine.UIElements" editor="UnityEditor.UIElements"
         noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd"
         editor-extension-mode="False">
    <ui:VisualElement>
        <ui:Label text="Label" name="TitleLabel"/>
        <ui:Button text="Button" name="Button"/>
    </ui:VisualElement>
</ui:UXML>

Rosalina's AssetProcessor will automatically genearte the following C# UI bindings script:

ℹ️ Note: All generated files are located in the Assets/Rosalina/AutoGenerated/ folder.

SampleDocument.g.cs

// <autogenerated />
using UnityEngine;
using UnityEngine.UIElements;

public partial class SampleDocument
{
    [SerializeField]
    private UIDocument _document;
    public Label TitleLabel { get; private set; }

    public Button Button { get; private set; }

    public VisualElement Root
    {
        get
        {
            return _document?.rootVisualElement;
        }
    }

    public void InitializeDocument()
    {
        TitleLabel = (Label)Root?.Q("TitleLabel");
        Button = (Button)Root?.Q("Button");
    }
}

⚠️ This script behing an auto-generated code based on the UXML template, you should not write code inside this file. It will be overwritten everytime you update your UXML template file.

According to Unity's UI Builder warnings, a VisualElement names can only contains letters, numbers, underscores and dashes. Since a name with dashes is not a valid name within a C# context, during the code generation process, Rosalina will automatically convert dashed-names into PascalCase. Meaning that if you have the following UXML:

<ui:VisualElement>
    <ui:Button text="Button" name="confirm-button"/>
</ui:VisualElement>

Rosalina will generate the following property:

public Button ConfirmButton { get; private set; }

In case you already have a ConfirmButton as a VisualElement name, do not worry, Rosalina will detect it for you during the code generation process and throw an error letting you know there is a duplicate property in your UXML document.

How to use

Rosalina supports default UI Document meant to be displayed in-game and UI Documents for Unity's EditorWindow extensions.

After installing Rosalina, the plugin will automatically create a Bindings-Script when ever yous save a Visual Tree Asset. The generated file will be located at Assets/Rosalina/AutoGenerated and share it's name with a .g.cs extension.

You should NOT edit this file in any way or form, as it will be recreated on each change to the corresponding Visual Tree Asset document.

If this file is not generated automatically, you can generate it by right-clicking it the Visual Tree Asset file and select Rosalina -> Generate UI bindings

image

UI Script

To create the UI-Script, which will contain your code, right-click on the Visual Tree Asset file. There, choose Rosalina -> Generate UI script

image

UI Document

An UI Document is considered as an "in-game" / "runtime" UI when its editor-extension-mode XML attribute is set to False. Thus, the code generator knows that he needs to generate a UI Document component with a MonoBehavior.

When generating an UI Script, Rosalina will generate the following code:

using UnityEngine;

public partial class SampleDocument : MonoBehaviour
{
    private void OnEnable()
    {
        InitializeDocument();
    }
}

The InitializeDocument() method contains all the UI properties initialization. Every interaction with UI properties such as assigning a text to a label or an clicked event action to a button MUST be defined after the InitializeDocument() call. Otherwise, you will have a NullReferenceException.

using UnityEngine;

public partial class SampleDocument : MonoBehaviour
{
    private void OnEnable()
    {
        InitializeDocument();
        TitleLabel.text = "Hello world!";
        Button.clicked += OnConfirmButtonClicked;
    }

    private void OnButtonClicked()
    {
        TitleLabel.text = "Button clicked";
    }
}

Editor Window

To use a UI Document as an Unity's Editor Window, you will need to set the editor-extension-mode XML attribute to True.

<ui:UXML ... editor-extension-mode="True"> <!-- Set to TRUE -->
    <ui:Button text="Sample Button" display-tooltip-when-elided="true" name="SampleButton" />
</ui:UXML>

Or you can check the Editor Extension Authoring inside the UI Builder. Select you UI Document root node in the Hierarchy then check Editor Extension Authoring inside the Document settings section.

image

Thus, the Rosalina's code generator will generate you a class that extends the UnityEditor.EditorWindow:

// <autogenerated />
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public partial class CustomEditorWindow : EditorWindow
{
    public Button SampleButton { get; private set; }

    public void CreateGUI()
    {
        VisualTreeAsset asset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/...");
        VisualElement ui = asset.CloneTree();
        rootVisualElement.Add(ui);
        SampleButton = (Button)rootVisualElement?.Q("SampleButton");
        OnCreateGUI();
    }

    partial void OnCreateGUI();
}

When generating an UI Script, Rosalina will generate the following code:

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public partial class CustomEditorWindow : EditorWindow
{
    partial void OnCreateGUI()
    {
    }
}

Every interaction with UI properties such as assigning a text to a label or an clicked event action to a button MUST be defined inside the OnCreateGUI() method:

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public partial class CustomEditorWindow : EditorWindow
{
    partial void OnCreateGUI()
    {
        SampleButton.clicked += OnSampleButtonClicked;
    }

    private void OnSampleButtonClicked()
    {
        Debug.Log("Hello world!");
    }
}

If you want, you can also control the behavior of the window and tell Unity how to open it; for instance, with from a Menu Item:

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public partial class CustomEditorWindow : EditorWindow
{
    [MenuItem("Window/My Custom Editor Window")]
    public static void ShowWindow()
    {
        EditorWindow.CreateWindow<CustomEditorWindow>("My Custom Editor Window!");
    }

    partial void OnCreateGUI()
    {
        SampleButton.clicked += OnSampleButtonClicked;
    }

    private void OnSampleButtonClicked()
    {
        Debug.Log("Hello world!");
    }
}

This will add a new entry named My Custom Editor Window to the Window menu item:

image

And when clicking on that menu item, the custom editor window will appear and you can now interact with the elements:

image

Notes

As pointed out by JuliaP_Unity on Unity Forums the document initialization process (element queries) should be done on the OnEnable() hook, since the UIDocument visual tree asset is instancied at this moment. Thank you for the tip!

Known limitations

  • The generated files share the name of the Visual Tree Asset. Currently, it's not possible to change the script names.
  • Rosalina currently does not support namespaces.
  • It's currently not possible to deactivate the generation of UI-Bindings on Visual Tree Asset save.

For now, Rosalina only generates the UI Document bindings and code behind scripts based on the UI element names. You still need to create on your own the GameObject with a UIDocument component and then add the UI script (not the UI binding scripts).

ℹ️ In next versions, we could think of an extension that automatically creates a GameObject with the UI script attached to it. 😄

Final words

If you like the project, don't hesitate to contribute! All contributions are welcome!

About

Rosalina is a code generation tool for Unity's UI documents. It generates C# code-behind script based on a UXML template.

License:MIT License


Languages

Language:C# 100.0%