Skip to content

Conversation

ickshonpe
Copy link
Contributor

@ickshonpe ickshonpe commented Oct 10, 2025

Objective

Retire the TextSpan component, use Text and Text2d entities for both root and non-root text entities.

Solution

Identify text roots by checking their parent, if a text entity's parent is a non-text entity, it's a root.
Text layouts are now stored on a separate entity that is automatically spawned and associated with the root via a new relation TextRoot.

Testing

All existing examples (I hope) should work be working without any changes except renaming TextSpan to Text or Text2d depending on context.

* Added query filters to queries in `ui_layout_system`, so that non-root text nodes are ignored by layout, otherwise text composed from multiple sections isn't rendered.
#[reflect(Component, Default, Debug, PartialEq, Clone)]
#[require(Node, TextLayout, TextFont, TextColor, TextNodeFlags, ContentSize)]
#[require(
Node,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changeset feels weird to me because Text is a Node, which logically takes up space in the layout, has a style, etc. However in the "Text serving the role of TextSpan" case , we really don't want it to behave like one, as that would produce confusing results. It also creates a new class of internal (or external) bug where we forget to exclude "textspan-like Text" when considering a collection of Nodes. Likewise, Text2d behaves logically like a "sprite". Making it not behave like one when nested feels very odd to me, and is also a new potential source of bugs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, the PR description doesn't include the (rather lengthy) justification for this change.

Copy link
Contributor Author

@ickshonpe ickshonpe Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I just published this last night after I got it working and then went to bed, this does need more explanation. I'll write something up.

mut targets_query: Query<&mut TextTarget>,
children_query: Query<&Children, With<TextSection>>,
) {
for (output_entity, mut entities, layout) in entities_query.iter_mut() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing this "scan, build list, and compare" every frame for every text tree in the UI feels overly expensive to me. I don't believe we were paying this price in the previous system.

Copy link
Contributor Author

@ickshonpe ickshonpe Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's deliberately simple, walking and collecting the entities is easy to understand and test. I'm not sure heavily optimising everything is worth it atm until all the new text features are added.

Needs more profiling, but even so I think overall this branch is slightly more efficient than main. A problem with the old design is that it can't tell in isolation whether a TextSpan entity is part of a Text or Text2d hierarchy, so it processes them twice.

Copy link
Contributor Author

@ickshonpe ickshonpe Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are probably ways to improve the TextSpan implementation too though, I just don't feel it's worth the effort because I dislike the API so much.

@alice-i-cecile alice-i-cecile added A-UI Graphical user interfaces, styles, layouts, and widgets C-Usability A targeted quality-of-life change that makes Bevy easier to use X-Controversial There is active debate or serious implications around merging this PR M-Needs-Release-Note Work that should be called out in the blog due to impact S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Oct 11, 2025
Copy link
Contributor

It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note.

Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-UI Graphical user interfaces, styles, layouts, and widgets C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Needs-Release-Note Work that should be called out in the blog due to impact S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged X-Controversial There is active debate or serious implications around merging this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants