Open ickshonpe opened 1 year ago
That is true. color
s are the only parts of Text
that don't affect layout.
Text {
sections: vec![
TextSection {
style: TextStyle {
color: // ...
// ...
}
// ...
}
],
// ...
}
Just exploring the many possible solutions:
color
only and don't re-layoutAdapt the text layout system to special-case for color-only changes, but does change detection even have this level of granularity? Can it?
color
lifted out of Text
into its own componentBut then how do you link the individual text sections to the various colors? e.g. would you have
#[derive(Component)]
struct TextSectionColors(Vec<Color>);
but this would be painful to synchronise with the entity's text sections.
color
is a handle to an assetstruct TextStyle {
color: ColorInstance
}
struct ColorInstance(Color);
This makes creating the text and changing the color less nice.
fn add_color_and_spawn(
mut colors: ResMut<Assets<ColorInstance>>,
) {
let handle = colors.add(ColorInstance(Color::RED));
// do something with the handle
}
fn change_color(text_query: Query<Text>, mut colors: ResMut<Assets<ColorInstance>>) {
text_query.for_each_mut(|mut text| {
if let Some(color) = colors.get(&text.sections[0].style.color) {
color.0 = new_color;
}
});
}
On the other hand, you could potentially reuse that color for other sections (even in other entities). Still, if someone actually swaps out the referenced color handle (for whatever reason), it can still result in a re-layout, so best practice would be to always only have one color handle to one section. You'd also want to destroy these assets as sections are destroyed. Perhaps it could be made more ergonomic to provide some type of special garbage collected asset and/or some type of "unique" handle.
TextColor
could be an enumstruct TextStyle {
color: TextColor
}
enum TextColor {
Plain(Color)
Handle(Handle<ColorInstance>)
}
It could be a plain color, or a handle to an asset, so you get to choose (and you document the tradeoff).
TextSections
are their own entities, as children of Text
entitiesThen you could have
#[derive(Component)]
struct TextSectionColor(Color);
// Parent
struct Text {
sections: Vec<Entity>,
alignment:
}
// Child
The challenge is ensuring you only use TextSection
as children*. This is the kinded entities problem.
*On the other hand, at this point, the only thing from Text
that's still relevant is TextAlignment
, but this starts to look simply like a Block
and InlineChildAlignment
, and there's no reason you can't have other inline elements (other than implementation).
This is probably the "correct" solution (and some of the explorations above can be orthogonal), but the ergonomics are a bit lacking (compared to the current status quo) and it's the most work.
Bevy version
0.9.1
What went wrong
Changing the
Color
of aTextSection
trips change detection causing the entireText
to be needlessly recomputed.Additional information
Workaround:
related: #6956, #5935