ErnSur / UI-Toolkit-Plus

Boilerplate Code Generation, Tabs, Reorderable Manipulator, Built-in USS Exporter
MIT License
182 stars 8 forks source link

Exclude certain visual elements from code generation #25

Open SolidAlloy opened 10 months ago

SolidAlloy commented 10 months ago

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:

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.

ErnSur commented 10 months ago

Hello! I'm happy that you're enjoying the package!

I noticed I don't use all of the visual elements that are generated in the class.

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".

As Unity docs states, the element names should be unique within a panel. Similar to the HTMLs id attribute. I believe that sticking to that rule enforces good practices. For that reason I wouldn't modify the package so that it's easier to avoid this rule. If the script becomes bloated with the amount of generated fields, it is a good indicator that user should extract parts of the UI into their own UXML files. These issues are good issues to have- they remind you about the way you structure your code.

I'm also open to hear any challenges to my views.

I implemented a function that patches UnityEngine.UIElementsModule.dll. adding the new attribute to VisualElement with the help of Mono.Cecil.

I will avoid adding dependencies to this package. I value simplicity, so a feature would have to bring a really good amount of value for it to be worth adding code weaving.

Saying that, I really appreciate the input!