UIComponents
Namespace: Vortex.Unity.UI.UIComponents
Assembly: ru.vortex.unity.ui.misc
Purpose
Modular UI component system. UIComponent (MonoBehaviour) manages arrays of typed UIComponentPart, providing a unified API for working with texts, buttons, graphics, and states.
Capabilities:
- Bulk and targeted UI updates via
PutData()/SetText()/SetSprite()/SetAction()/SetSwitcher() - Programmatic press and release of a part's button via
CallPress()/CallRelease() - Support for Text, TextMeshPro, TextMeshProUGUI, Button, AdvancedButton, SpriteRenderer, Image, UIStateSwitcher
- Position-based part addressing for multi-part components
[UIComponentLink]attribute for type-safe position selection in Inspector- Optional text localization (enabled by default) with re-application on locale change
Out of scope:
- Data display logic (layer 3/4)
- Interface lifecycle management (
UIProviderSystem)
Dependencies
| Dependency | Purpose |
|---|---|
Vortex.Unity.UI.StateSwitcher |
UIStateSwitcher — integration via UIComponentSwitcher |
Vortex.Unity.EditorTools |
[AutoLink] — component auto-binding |
Vortex.Core.LocalizationSystem |
StringExt.Translate() — text localization |
| Odin Inspector | [ShowInInspector], [Button], [TitleGroup] |
| TextMeshPro | TMP components |
Architecture
UIComponents/
├── UIComponent.cs # Central orchestrator (partial)
├── UIComponentExtEditor.cs # Editor: Init(), Test(), GetLinks(), "Text alignment" block
├── UIComponentData.cs # Data struct for PutData()
├── Parts/
│ ├── UIComponentPart.cs # Abstract part base
│ ├── UIComponentText.cs # Text, TMP, TMPUGUI
│ ├── UIComponentButton.cs # Button, AdvancedButton
│ ├── UIComponentGraphic.cs # SpriteRenderer, Image (+ Texture2D→Sprite)
│ └── UIComponentSwitcher.cs # UIStateSwitcher
├── Attributes/
│ └── UIComponentLinkAttribute.cs # Type-safe part position
└── Editor/
└── UIComponentLinkAttributeDrawer.cs # Slider + validation
UIComponent
Partial MonoBehaviour. Stores four part arrays:
| Array | Part Type | Purpose |
|---|---|---|
uiComponentTexts[] |
UIComponentText |
Text elements |
uiComponentButtons[] |
UIComponentButton |
Buttons |
uiComponentGraphics[] |
UIComponentGraphic |
Graphics |
uiComponentSwitchers[] |
UIComponentSwitcher |
States |
Init() — part auto-discovery
The Init button in Inspector runs recursive GetComponentsInChildren for all four part types. When nested UIComponent containers exist in the hierarchy — first recursively calls Init() on each child UIComponent, then excludes all parts already owned by child containers. Each part belongs to exactly one UIComponent.
After collecting parts, Init() populates _testData with current values (texts, sprites, switcher states) for debugging via the Test button.
Text alignment
The inspector block "Text alignment" (TMP TextAlignmentOptions) sets the alignment of all linked texts at once: reading — from the first linked text, writing — to all of them (with Undo and prefab override recording). The value is not serialized in UIComponent — it is always taken from the texts themselves. The block is hidden when no texts are linked. Legacy Text gets the nearest of the 9 anchors (justified/flush → left, baseline → bottom, capline → top, geometry → center). Editor only: the UIComponentText system methods (GetAlignment/SetAlignment) are internal under #if UNITY_EDITOR.
Localization
useLocalization is on by default: texts pass through StringExt.Translate(). The component remembers the last values passed to SetText per part position — the parts hold the translation, and only the component knows the key. On OnEnable (and only when useLocalization is on) it subscribes to Localization.OnLocalizationChanged and re-applies the cached texts on the event; on OnDisable it unsubscribes.
Texts set only in the prefab are not updated on a locale change: the component never set them and does not know the key. For that case there is SetTextComponent with its [LocalizationKey] field.
UIComponentPart (abstract)
Base class for all parts. In Editor, automatically fills RectTransform to container size (unless onlyNativeSize is checked).
Implementations
UIComponentText — supports Text (legacy), TextMeshPro, TextMeshProUGUI. Auto-discovers components in Editor ([OnInspectorInit]).
UIComponentButton — supports Button and AdvancedButton. Tracks _currentAction, removes old listener before setting new. Cleanup in OnDestroy.
Programmatic control: CallPress() — AdvancedButton gets its Press() (visuals and press logic by its click registration mode), Button gets PointerDown ("pressed" visuals; Button has no press API of its own). CallRelease() — AdvancedButton gets its Release() (click by its mode rules; nothing without a preceding press), Button gets PointerUp and onClick if the button is active and interactable.
UIComponentGraphic — supports SpriteRenderer and Image. Accepts both Sprite and Texture2D (auto-converts to Sprite). Editor-time type validation: only SpriteRenderer and Image are accepted.
UIComponentSwitcher — bridge to UIStateSwitcher. Accepts int or Enum for state switching.
API
// Bulk data application
component.PutData(new UIComponentData {
texts = new[] { "Title", "Subtitle" },
sprites = new[] { icon },
actions = new[] { OnClick }
});
// Direct access
component.SetText("Title");
component.SetText("Subtitle", 1); // by position
component.SetSprite(icon);
component.SetSprite(texture2D); // auto-conversion
component.SetAction(OnClick);
component.SetAction(OnClick, 2); // by position
component.CallPress(); // programmatic press of part 0's button
component.CallRelease(); // programmatic release (click by the button's rules)
component.SetSwitcher(SwitcherState.On);
UIComponentData (struct)
| Field | Type | Description |
|---|---|---|
texts |
string[] |
Texts for each UIComponentText |
actions |
UnityAction[] |
Callbacks for each UIComponentButton |
sprites |
Sprite[] |
Sprites for each UIComponentGraphic |
enumValues |
int[] |
States for each UIComponentSwitcher |
UIComponentLinkAttribute
Type-safe part position selection in Inspector. Renders a slider 0..N with target part name:
[SerializeField, UIComponentLink(typeof(UIComponentText), "uiComponent")]
private int position = -1; // -1 = default, 0..N = specific part
The default -1 value is labeled "The setting will be applied to all components". If -1 means something else for the field, the third parameter sets a custom hint: UIComponentLink(typeof(UIComponentGraphic), "component", "Sprite is not shown").
Edge Cases
| Situation | Behavior |
|---|---|
SetText("x", pos) without UIComponentText or out of range |
Debug.LogError, return |
SetText("x") when uiComponentTexts == null or the array is empty |
Debug.LogError, return |
SetAction(null) |
Current listener removed |
CallPress / CallRelease with no button at the position |
Debug.LogWarning, return |
CallRelease on AdvancedButton without a preceding CallPress |
Nothing happens |
PutData() with array shorter than part count |
Texts/buttons/graphics: missing entries are nullified (empty string / null / null). Switchers: processing breaks early |
SetSprite(Texture2D) |
Sprite created via Sprite.Create() |
position out of range |
Debug.LogError + return (positional methods), IndexOutOfRangeException (direct array access) |
useLocalization = true (default) |
Texts pass through StringExt.Translate(); the component subscribes to locale changes |
| Locale change, no text was set from code | Nothing happens: the cache is empty, prefab text is left alone |
Locale change, the part set changed after the last SetText |
Warning in the log, texts are not re-applied |
| Linked texts with different alignments | The "Text alignment" block shows the first one's alignment; changing it applies the chosen one to all |
Locale change, null was written into a position |
The position is cleared: Translate(null) returns an empty string |
UIComponentLinkAttribute
| Situation | Behavior |
|---|---|
position = -1 |
Drawer shows warning "applies to all components" |
position out of range |
Drawer shows error |
position in range |
Drawer shows disabled ObjectField with target GameObject |