Make each TextSection its own entity.#14572
Make each TextSection its own entity.#14572Olle-Lukowski wants to merge 24 commits intobevyengine:mainfrom
TextSection its own entity.#14572Conversation
Context for why this should be done, from Discord |
|
This work was previously mentioned in #14437. As discussed above, bringing text sections into the entity hierarchy is required to make them play nicely with scenes, and thus the BSN entity-spawning tools. |
|
I think I will wait with porting over all examples for two reasons:
I did port some of the examples to show the new API, and those will be kept up to date for any changes that happen. |
crates/bevy_ui/src/widget/text.rs
Outdated
| let sections = if let Some(children) = children { | ||
| children_changed = children.is_changed(); | ||
|
|
||
| text2d_section_query.iter_many(&children).collect() |
There was a problem hiding this comment.
This vec can be cached in a Local. Then use .clear() and .extend().
There was a problem hiding this comment.
Ah right, will do that!
crates/bevy_ui/src/widget/text.rs
Outdated
| let sections = if let Some(children) = children { | ||
| children_changed = children.is_changed(); | ||
| text_section_query.iter_many(&children).collect() | ||
| } else { | ||
| vec![] | ||
| }; |
| let section = text2d_section_query | ||
| .get(children.unwrap()[*section_index]) | ||
| .unwrap(); |
There was a problem hiding this comment.
It is not valid to access via [] here, because non-TextSection children may be interleaved. You need to find the position in the children that filters for entities with TextSection.
There was a problem hiding this comment.
Hmm, I guess that's true. What would be the best approach for that?
crates/bevy_text/src/text2d.rs
Outdated
| let sections = if let Some(children) = children { | ||
| children_changed = children.is_changed(); | ||
| section_query.iter_many(children.iter()).collect() | ||
| } else { | ||
| vec![] | ||
| }; |
There was a problem hiding this comment.
Here as well, cache the vec.
| let section = text2d_section_query | ||
| .get(children.unwrap()[*section_index]) | ||
| .unwrap(); |
There was a problem hiding this comment.
Invalid children access, need to filter for entities with TextSection.
crates/bevy_ui/src/accessibility.rs
Outdated
| let values = text | ||
| .sections | ||
| if let Ok(maybe_children) = texts.get(*child) { | ||
| let mut sections = Vec::new(); |
There was a problem hiding this comment.
Cache this vec if possible. Or convert to a chained iterator for the values collection.
| .spawn(TextBundle { | ||
| style: Style { | ||
| position_type: PositionType::Absolute, | ||
| top: Val::Px(12.0), | ||
| left: Val::Px(12.0), | ||
| ..default() | ||
| }), | ||
| ); | ||
| }, | ||
| ..default() | ||
| }) | ||
| .with_child(TextSection::new( | ||
| "Press space to toggle wireframes", | ||
| TextStyle::default(), | ||
| )); |
There was a problem hiding this comment.
It might be nice if you could optionally put the first text section on the parent entity.
There was a problem hiding this comment.
We initially had this supported, but in discord we decided to not do it.
|
Marking this as ready for review, the main thing that we still need to do is find a way to prevent repeated allocations in the systems where the text is enqueued. |
TextSection its own entity.TextSection its own entity.
| #[derive(Debug, Default, Clone, Reflect)] | ||
| #[derive(Component, Debug, Default, Clone, Reflect)] | ||
| #[reflect(Default)] | ||
| pub struct TextSection { |
There was a problem hiding this comment.
This should be split up I think, TextStyle needs to be a separate elidable component imo.
There was a problem hiding this comment.
Not sure how I feel about that, it would require a LOT more changes, that I don't want to update 100 examples for again.
There was a problem hiding this comment.
I know but I think it's really necessary.
Maybe if TextSection is made into a bundle with Text (and rename the existing component, I agree with TotalKrill that it's potentially confusing) and TextStyle components it would just work without any changes to most of the examples?
There was a problem hiding this comment.
honestly great idea!
There was a problem hiding this comment.
I know but I think it's really necessary.
Could you elaborate on this?
There was a problem hiding this comment.
I know but I think it's really necessary.
Could you elaborate on this?
Different styling options, with Text2d style propagation and responsive sizes might not make sense or need different solutions. More granular change detection.
There was a problem hiding this comment.
@ickshonpe
That sounds good to me, but it also sounds like something that should be discussed/designed. Would be it acceptable to catalog this in an issue and implement it in a followup PR?
There was a problem hiding this comment.
Totally agree on splitting this, strongly feel this should be moved to followup.
There was a problem hiding this comment.
Yep I've no problem with moving this to a followup, it would be good if we can avoid multiple rewrites of the api and examples though.
There was a problem hiding this comment.
It probably should be split up more even, previously it's really bugged me how changing the colour of a single section causes a relayout of the whole text node. Separate TextColor component disappears that problem.
There was a problem hiding this comment.
The docs should really indicate the new relationship between the components. And the component should be renamed since it has completely changed its meaning with this change.
And the newly created issue for this should indicate what was lost and point to this PR so it can be tracked
| @@ -127,7 +52,7 @@ impl Text { | |||
| } | |||
|
|
|||
| /// Contains the value of the text in a section and how it should be styled. | |||
There was a problem hiding this comment.
This is the first time we are adding a parent/child hierarchy requirement as far as I know, the docs should indicate this relationship on the related components.
Also with this change, the name "Text" is actually more confusing than helping, since it only contains the information for how text will be justified, and contains no text whatsoever
| } | ||
|
|
||
| /// Contains the value of the text in a section and how it should be styled. | ||
| #[derive(Debug, Default, Clone, Reflect)] |
There was a problem hiding this comment.
Same on this component, should probably indicate that this component is required to be a child of the other Component.
|
|
||
| #[cfg(feature = "bevy_text")] | ||
| impl TextBundle { | ||
| /// Create a [`TextBundle`] from a single section. |
There was a problem hiding this comment.
As discussed in discord.
The removal of these ergonomics is a huge loss. both on TextBundle and on Text and should be addressed before 0.15 if this PR is to land
| @@ -29,8 +29,6 @@ impl Default for CosmicBuffer { | |||
| #[derive(Component, Debug, Clone, Default, Reflect)] | |||
| #[reflect(Component, Default)] | |||
| pub struct Text { | |||
There was a problem hiding this comment.
| pub struct Text { | |
| pub struct TextNode { |
There was a problem hiding this comment.
This suggestion seems confusing because the component is also used in Text2dBundle, and we don't use this naming convention in any other UI bundles.
There was a problem hiding this comment.
What do we think of TextLayout?
There was a problem hiding this comment.
I'll go with TextLayout, makes the most sense to me.
|
There are currently warnings about the children of a UI node not having UI components themselves, how do I fix these? |
Not tested it but changing these queries in to filter for the text bundle's marker component with: should be sufficient. |
|
Can you do a pass on the comments and resolve those that are addressed to make this easier to review? :) |
|
Is this the right time to rename sections to spans? |
|
Text entity tidy
|
See this discussion for a required-components-based redesign. |
|
Merging #15591, which continued this work. |
Objective
This change makes each
TextSectionits own entity, which was discussed to be the next step forbevy_textin Discord.Fixes #7714
Solution
Textcomponent to hold no sections instead of aVecofTextSection.TextSectiona component that should be added to children of aText.Testing
Tested out some of the examples that I ported to the new API, they all look fine.
Migration Guide
Any usage of
TextBundle::from_sectionorText::from_sectionshould be replaced with something like this:Same goes for the
from_sectionsmethods.