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

[Merged by Bors] - Implement rotation for Text2d #2084

Closed
wants to merge 5 commits into from

Conversation

nside
Copy link
Contributor

@nside nside commented May 3, 2021

Fixes #2080

CleanShot 2021-05-02 at 22 50 09

@nside nside mentioned this pull request May 3, 2021
@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior C-Feature A new feature, making something new possible A-UI Graphical user interfaces, styles, layouts, and widgets S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it labels May 3, 2021
@nside
Copy link
Contributor Author

nside commented May 3, 2021

note that scale_factor could potentially be replaced by transform.scale but I wasn't clear if their semantic is the same

@CleanCut
Copy link
Member

CleanCut commented May 3, 2021

note that scale_factor could potentially be replaced by transform.scale but I wasn't clear if their semantic is the same

scale_factor represents the scaling of the screen (old screens are typically 1.0, newer hi-dpi screens are typically 2.0, but other values are possible), so you would want to use the transform's scale on top of that if you're going to handle scaling the text visually.

A decision on the semantics of scaling would need to be made first, though. If the desire is that scaling up the text results in blocky, pixelized (perhaps blurry?) text similar to how the SNES handled scaling, then that could be done right here I think. If the desire is that the font is actually scaled smoothly when text scales, then new glyphs will need to be generated--maybe by scaling the font size itself? Anyway, scaling is probably best left for another discussion / PR.

Copy link
Member

@CleanCut CleanCut left a comment

Choose a reason for hiding this comment

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

This is an excellent start! Thank you for working on this. 😄

I don't think this should be merged as-is. There are a couple issues with alignment_vertical and alignment_horizontal that I think should be resolved first:

  • The names are confusing. These are not alignments, they are offsets. The names lead me to expect variants of HorizontalAlign or VerticalAlign.
  • There is unnecessary overhead. The offsets are always passed in separate Vec3s which are already capable of representing offsets in 3 dimensions, but treated as single dimension offsets that are unconditionally added together to form a single offset. In other words, there's only a single offset and we're splitting it into two variables to pass in and recombine.

Off the top of my head, I can think of two good ways to fix this:

Suggestion 1

  • Pass in a single offset Vec3, perhaps named offset or translation_offset. You'll notice the entire addition of Vec3::ZERO to the other Vec3 disappears entirely. 🎉

Suggestion 2

  • Pass in the entire alignment (text.alignment) to DrawableText::draw() and do the calculations there -- then the callers no longer need to do their own redundant alignment-to-offset calculations for each thing that uses a DrawableText.
    • This will require researching why the UI code is hard-coding alignment to top-aligned, horizontally-centered. If that's what the value of text.alignment already is there, then we can stop hard-coding and pass in text.alignment instead. If that's not what the value of text.alignment is then we should find out why that's hard-coded and either a) if it is intended then preserve the hard-coding by passing in a hard-coded top-aligned, horizontally-centered alignment, or b) if that was not intended, just pass in the actual value text.alignment

Having said this, I'm only moderately acquainted with the text rendering code, so there may be even better options.

/cc @AlisCode @blunted2night @cart @julhe @Neo-Zhixing @tigregalis @zicklag - You've all touched code near here. Any opinions? I'd basically love a meta-review of my review for my own education. I may learn more about the rendering design in the process. 😄

@nside
Copy link
Contributor Author

nside commented May 3, 2021

suggestion 1) sounds fine to me. 2) seems more involving as you need the calculated size to compute the offset

@nside
Copy link
Contributor Author

nside commented May 3, 2021

updated

Copy link
Member

@CleanCut CleanCut left a comment

Choose a reason for hiding this comment

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

😄

@zicklag
Copy link
Member

zicklag commented May 3, 2021

@CleanCut I don't have time to do a proper review of your review, but I think your reasoning is sound. 🙂

Copy link
Member

@CleanCut CleanCut left a comment

Choose a reason for hiding this comment

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

The way the text was rotating seemed a bit off to me, so I dug into it a bit further and it doesn't seem to be rotating correctly. If you remove the position changes from the text2d example, you can see that though the rotation is supposed to be center-aligned both horizontally and vertically, the pivot point for the rotation seems to actually be at the bottom of the text between the "e" and the "x" in "This text...". There must be some bad math somewhere...

With the following code in lines 36-38 in the text2d example it looks like this:

        //transform.translation.x = 100.0 * time.seconds_since_startup().sin() as f32;
        //transform.translation.y = 100.0 * time.seconds_since_startup().cos() as f32;
        transform.rotation = Quat::from_rotation_z(time.seconds_since_startup() as f32);
BadPivot.mp4

@nside
Copy link
Contributor Author

nside commented May 3, 2021

it's as if the width was off. will check tonight

@nside
Copy link
Contributor Author

nside commented May 4, 2021

strangely I get different results
CleanShot 2021-05-03 at 17 02 36

@CleanCut
Copy link
Member

CleanCut commented May 4, 2021

@nside It's probably the scale_factor. I've got a hi-dpi screen with scale_factor == 2.0.

@nside
Copy link
Contributor Author

nside commented May 4, 2021

that's it!

@nside
Copy link
Contributor Author

nside commented May 4, 2021

I was able to remove scale_factor from DrawableText when fixing this

@CleanCut
Copy link
Member

CleanCut commented May 4, 2021

I meant you should add handling for scale_factor into the rotation calculations, not attempt to remove scale_factor handling from DrawableText. Now text is differently-sized depending on the DPI of the screen. 😢
Screen Shot 2021-05-04 at 9 22 33 AM

@nside
Copy link
Contributor Author

nside commented May 4, 2021

how do you recommend testing this on non-hi-dpi screens?

@nside nside force-pushed the text2d-rotation branch from a65837f to c4580c4 Compare May 4, 2021 19:09
@nside
Copy link
Contributor Author

nside commented May 4, 2021

@CleanCut I brought it back, let me know if that works. Dealing with the glyphs scale on the main transform feels a bit confusing IMO

@CleanCut
Copy link
Member

CleanCut commented May 5, 2021

@nside Much better! I spent a couple hours going over this. The remaining problems I see are:

  1. The offsets you compute for alignment are backwards--left/right and top/bottom need to be swapped.
  2. Requiring the call-site to do the scale_factor computation tightly couples the text2d and bevy_ui::widget::text modules to the implementation of DrawableText::draw.

I put together fixes for both of those and added handling for scaling in #2103 -- please take a look and let me know what path you would like to take forward. in this PR to merge that into this PR here!

Handle rotation, fix alignment, update example
Copy link
Member

@CleanCut CleanCut left a comment

Choose a reason for hiding this comment

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

At this point, I think the PR is done:

  • Added rotation handling
  • Added scale handling based off of Transform.scale
    • The chosen approach is to scale the entire quad, resulting in pixellated text when you scale it up. This may be a desirable effect for retro 2D games. For "smooth scaling", change the font size instead.
  • Updated the text2d example to demonstrate translation, rotation, and scale separately
    • We used a QuerySet to handle all the queries in a single system. Would it be simpler for the user to understand if we used three separate systems instead?

text2d-trs

@nside
Copy link
Contributor Author

nside commented May 5, 2021

very nice

@CleanCut
Copy link
Member

CleanCut commented May 5, 2021

very nice

@nside Wouldn't have gotten done without your effort! Thanks for providing a good distraction after my root canal. 🦷

fn animate(
time: Res<Time>,
mut queries: QuerySet<(
Query<&mut Transform, WithBundle<(Text, AnimateTranslation)>>,
Copy link
Member

Choose a reason for hiding this comment

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

I think these Queries should use the Query<&mut Transform, (With<Text>, With<AnimateTranslation>)> style instead. WithBundle isn't a pattern I want to encourage generally (and the behavior of it might change in the future to be "spawned with this specific bundle" instead of "has the components in this bundle"). For now, I want examples to focus on individual components.

Copy link
Member

Choose a reason for hiding this comment

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

Ah! I had first (unsuccessfully) tried With<(Text, AnimateTranslation)> -- now I know the correct approach, I can use it!

// size of the text via `Text.style.font_size`)
for mut transform in query.iter_mut() {
transform.translation.x = 100.0 * time.seconds_since_startup().sin() as f32;
fn animate(
Copy link
Member

Choose a reason for hiding this comment

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

I personally think this should be three separate systems. It is functionally three separate behaviors and separate systems removes the need for the QuerySet.

@cart
Copy link
Member

cart commented May 6, 2021

This looks good to me! Just some minor style nits in the example.

@CleanCut
Copy link
Member

CleanCut commented May 6, 2021

I'll make the change!

Update: Done in a PR to this PR

@cart
Copy link
Member

cart commented May 6, 2021

bors r+

bors bot pushed a commit that referenced this pull request May 6, 2021
@bors bors bot changed the title Implement rotation for Text2d [Merged by Bors] - Implement rotation for Text2d May 6, 2021
@bors bors bot closed this May 6, 2021
ostwilkens pushed a commit to ostwilkens/bevy that referenced this pull request Jul 27, 2021
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-Bug An unexpected or incorrect behavior C-Feature A new feature, making something new possible S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Text2D doesn't rotate
7 participants