The goal
- Create a resizable Material component, using only UI constraints
- Resizing requires no further scripting, nor running the game, to function (it’s all handled from within Studio)
This is an elegant way to instantly display changes to the developer, without any plugins needed, and without having to run the game every time. Although many other attributes (such as style) may not instantly take effect, one of the key aspects of UI design to perfect (in my opinion) is composition. If you have an incorrect scaling value, bad positioning, or a wonky padding, it can make your UIs feel cramped and unprofessional in an instant.
Under normal circumstances (assuming everything about the appearance is implemented on the scripting side), the developer would have to playtest their game to see every change they made. If your place is more than a barren baseplate and/or you have slower hardware, you can waste precious seconds of your life waiting for Studio to behave. A normal playtest can take anywhere from 5–10, even 15 seconds to load!
With the addition of AutomaticSize, this finally becomes possible! Right?
However, there’s a problem
So, what went wrong?
This baby relies entirely on AutomaticSize to hold its shape. It kinda works, until you click on it. Things get taboo from there. This is because two main components, namely the shadow and ripple, both extend out of the button’s bounds: The shadow always remains slightly larger than the button’s hitbox, causing the parent to compensate while also off-centering itself. The ripple, using Scale
as its sizing mechanism, causes the size to recursively multiply, quickly creating an appendage that pierces through the fabric of spacetime.
Elemental visualization: shadow offset, ripple darkened and unclipped
As it stands, there’s currently no way to exclude these objects from influencing their parents’ size. This was quite unfortunate when I’d found out, as this feature has the potential to be a massive QoL improvement. Seriously! This is a game-changer.
However, I’ve got an idea:
Class : UIAutomaticSize
Inherited from: Instance
Instead of AutomaticSize being a property of GuiObject, why not turn it into a UI constraint? This has a couple added benefits, such as:
Accessibility
UI constraints are physical objects in the game hierarchy. This makes them more hands-on; easier to work with. Instead of scrolling through every property of a GuiObject, you can quickly spot a stray UIAutomaticSize in your explorer.
Customizability
Instead of adding several properties to the GuiObject class, you can instead add properties to the UIAutomaticSize. This allows for an acceptable way to fine-tune your automatic sizing. A few examples of such properties include:
bool
Recursive
Whether children of children should influence the size of the parent, or in other words, whether the bounding box of each child will respect their descendants or not. Small performance benefit most of the time, but could massively help when (potentially) thousands of GUIs are parented to an automatically-sized object.
bool
IgnoreScale
When true, any children using Scale
as their sizing method will not influence the final size, and instead will use the final size to determine their own size proportionally. Helps defend against the recursive nature of using it.
AutomaticSize
AutomaticSizingMode
The AutomaticSize enumeration used for GuiObjects, functionality doesn’t change.
Blacklisting
The most critical part. As you may or may not know, you can use folders to blacklist certain objects from the effects of a UI constraint, as shown here:
Intentional or not, this is a handy quirk that allows one to hide certain objects while (generally) keeping the hierarchy intact. GUIs parented to folders are still influenced by the folder’s parent as you would expect, but are not influenced by UI constraints.
This quirk alone would solve both of my problems: I could simply parent my ripple + shadow to its own folder, then the constraint would treat it like it wasn’t there. This would preserve the physical bounding box of my button, while allowing for things to exceed it visually.
Overall, I’m very pleased with this feature. At the very least, I no longer need TextService to automatically size my TextLabels, which in itself is a massive step in the right direction. Anything not too complex can easily find a way to use AutomaticSize, which is what I love about it.
However, for those who want to go above and beyond, or generally want to use (and abuse) this feature to the fullest extent possible, it lacks the very fundamental capability of ignoring certain objects. I hope this can be resolved one way or another, and I seriously look forward to using this feature as a daily driver in my UI-designing extravaganza.