UI-Toolkit-Plus icon indicating copy to clipboard operation
UI-Toolkit-Plus copied to clipboard

Exclude certain visual elements from code generation

Open SolidAlloy opened this issue 10 months ago • 1 comments

Hi, thanks for a great plugin! It certainly made using UI Toolkit easier.

When testing it out, I noticed I don't use all of the visual elements that are generated in the class. There are several reasons to generate only part of the fields:

  • Performance improvement (no need to run as many queries)
  • Code looks cleaner. When editing the class, IDE doesn't suggest a lot of unnecessary fields for auto-completion.
  • I can use the same names for multiple elements and not worry about compilation errors. Yes, I can avoid custom names for elements that I don't want to generate, but it's nice to name an element in the hierarchy to have a better understanding of what it does, e.g., "ButtonsContainer", "Spacer".

I experimented with the idea. The best implementation I found is to have an additional attribute in VisualElement that I can toggle to exclude an element from code generation. Let's name it "code-gen", for example. I rarely need a field generated for a simple VisualElement. Most often, we need fields generated for buttons, sliders, etc. We can do this by overriding a default value of the attribute in different classes - have code-gen attribute with a default value set to false in VisualElement, and override it with true in Button, Slider, etc.

Alas, UI Toolkit doesn't allow adding attributes to existing VisualElement classes. You can only inherit from VisualElement to have new attributes. I implemented a function that patches UnityEngine.UIElementsModule.dll. adding the new attribute to VisualElement with the help of Mono.Cecil. It all looks pretty nice, and the patching can be optional. Want to use the default UI Toolkit and generate fields for every visual element? Sure. Want to patch the UI Toolkit module and gain the ability to exclude some of the elements from code generation? Here's a button.

Unfortunately, I haven't found a better way to implement this feature without patching the UIElements module. It's not an issue for me. I'm using the feature, and if I upgrade the project to a new Unity version, I can patch the module again with a click of a button, and it'll work again. However, some users may be reluctant to patch the built-in library. Also, Unity may change its class or method names in the future, and the patching function will need to be updated.

I can share my implementation in a pull request if you would like to see it.

SolidAlloy avatar Aug 09 '23 12:08 SolidAlloy