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