Skip to content

Text should not store a flat list of sections #7714

@alice-i-cecile

Description

@alice-i-cecile

What problem does this solve or what need does it fill?

Currently, the Text component stores TextSection objects in a simple vector. Each entity with a Text component represents a contiguously laid out block of text that can be used to make a text node in the UI (or in your game): the distinct sections are required to be able to change the style within this block text.

This leads to very brittle, hard to read code, as seen in this real world example.
This uses a classic "retained-mode" pattern to initialize text, and then only update the segments that need updating.

There are three key problems here:

  1. It is very hard to tell which section is being modified, without looking at a non-local initialiatization.
  2. It's very easy to accidentally index out of bounds, causing a crash.
  3. When we modify the order or number of text sections, any code that reads or mutates these fields will be silently broken.

This is particularly troublesome as automated testing of UI is unusually hard: both because of the visual nature and because of the large number of possible states to check.

Proposal: HashMap in Text

The simplest solution: just replace the Vec<TextSection> with a Hashmap<TextSection>.
This works reasonably well, but forces us to always store keys and may increase verbosity.

Hashmaps are also pretty silly to use for large numbers of objects with a median count of 2 or so.

Proposal: Text sections as entities

Text becomes a marker component. TextSection becomes a component, each stored on a distinct child of the Text entity.
Then use the Name component to differentiate these text sections.
Either use marker components or something like get_child_by_name to access the text sections.

Verbose, fragile, much more ECS.
Like all things in life, really would be easier and more reliable if we had #3742.

Additional context

We should consider how this fits in with #6874: the desire to name the text sections reminds me a lot of the element labels that AccesKit wants.

This "text sections" problem is commonly encountered when working with localization. We could force all text to be easily localized, and store a fluent-rs data type as part of our TextSection type, along with style data.

May be better tackled as part of or after #7616.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-AccessibilityA problem that prevents users with disabilities from using BevyA-TextRendering and layout for charactersA-UIGraphical user interfaces, styles, layouts, and widgetsC-UsabilityA targeted quality-of-life change that makes Bevy easier to use

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions