Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Text styles should be inheritable #13511

Open
viridia opened this issue May 25, 2024 · 2 comments
Open

Text styles should be inheritable #13511

viridia opened this issue May 25, 2024 · 2 comments
Labels
A-Text Rendering and layout for characters C-Enhancement A new feature X-Controversial There is active debate or serious implications around merging this PR

Comments

@viridia
Copy link
Contributor

viridia commented May 25, 2024

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

In the HTML/CSS standard, certain style properties are inheritable, meaning that if you set the style on a parent element, the style applies to the descendants of that element as well (unless explicitly overridden).

The number of styles that are inheritable is fairly small, and are mostly the ones that deal with text, such as font face, font size, font style, and text color. The reasoning is fairly simple: there are typically many text spans and it's cumbersome and inefficient to have to style each one, especially given the fact that most spans have identical or at least similar properties.

Although games typically have fewer text nodes than a web page, the problem still comes up in practice, especially in character dialogs, help pages and tutorials - but even simple uses of text such as buttons and menus can benefit.

What solution would you like?

The basic properties we want to inherit are:

  • Font family
  • Font size
  • Font style (italic)
  • Font weight (bold)
  • Text color
  • Text decoration (underscore and strikethrough).

The basic suggestion is that you'd have a set of standard ECS components: either a single combined component such as TextStyles or individual components for the various style properties like FontWeight. When preparing text for rendering, it would look up the node hierarchy to see whether or not there were any styles defined on the ancestors of the text node.

Having to do an entity ancestor traversal might seem like it might be inefficient, but it should be possible to optimize this, and similar issues have been overcome for things like node transforms and visibility.

There are potential efficiency gains to be considered as well: particularly around font handles. Most games only need one font, and it is far easier for users to be able to configure the font a single time, at the root of the hierarchy, than to have to insert the font handle into every text node. This of course assumes we have also implement font-families and dynamic font selection by style: being able to specify "MyCoolFont" at the root level does little good if you also have to override "MyCoolFont_Italic" every time you have an italic span.

Alternatively, this behavior could be "opt in": users would have to add a special component into their text sections to enable this behavior.

What alternative(s) have you considered?

It's possible to implement this as an external crate, using a system to update the text styles; in fact I have done this. However, it would be better if this was standard Bevy behavior so that everyone could use the same API for specifying text styles.

Additional context

I'm bringing this up now because of the recent Discord discussion around text rendering, but it's something I have been thinking about for a long time.

@viridia viridia added C-Enhancement A new feature S-Needs-Triage This issue needs to be labelled A-Text Rendering and layout for characters labels May 25, 2024
@alice-i-cecile alice-i-cecile added X-Controversial There is active debate or serious implications around merging this PR and removed S-Needs-Triage This issue needs to be labelled labels May 25, 2024
@alice-i-cecile
Copy link
Member

alice-i-cecile commented May 25, 2024

I would much prefer other tools for composition: I have been endlessly frustrated by style-inheritance in the past due to how poorly organized and difficult to reason about it is. That said, we need to at least demonstrate patterns to show how to build and compose styles, both for text and other UI elements.

I really like the list of text properties though, and want to have first class primitives (components maybe?) for all of those so users can quickly modify one property independently.

@viridia
Copy link
Contributor Author

viridia commented Jun 21, 2024

@alice-i-cecile I suspect that for many users, the reason CSS inheritance is hard to understand has to do more with the rules of cascade priority (which we are not proposing to add here) than inheritance.

However, as a compromise, we could make this behavior opt-in at the entity level. That is, in order to get inheritable text styles, you would add a marker component (e.g. UseInheritedStyle) to your Text entity that indicates that it wants to participate in inherited styling. This marker component would be used just like any other style component.

This is still an improvement over the current situation, particularly for font families. Loading a font asset from the asset system involves a non-trivial amount of code. Since most games only use a single font family, ideally you should only have to do this once at the top level of your app. Yes, you could store the font handle in a resource and inject the resource every place you create a text span; but it would be even better not to have to do this at all. Except in the case of image assets, style properties ideally should be standalone and not require references to things other than the entity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Text Rendering and layout for characters C-Enhancement A new feature X-Controversial There is active debate or serious implications around merging this PR
Projects
None yet
Development

No branches or pull requests

2 participants