- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 4.2k
Update taffy to 0.9 and fix Grid errors #21240 #21672
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
base: main
Are you sure you want to change the base?
Conversation
        
          
                crates/bevy_ui/Cargo.toml
              
                Outdated
          
        
      |  | ||
| # other | ||
| taffy = { version = "0.7" } | ||
| taffy = { version = "0.9", default-features = false, features = ["std", "block_layout", "flexbox", "grid", "content_size", "alloc", "taffy_tree"] } | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The calc feature puts !Send+!Sync stuff everywhere, so it breaks derive(Resource) among other things. Manually excluding it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's quite unfortunate. This worked previously, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we have never supported calc in Bevy (although many people have asked for it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI the only reason this is !Send or !Sync is because the Calc expression type itself may be !Send or !Sync, and we can't tell because we're type-erasing the type (we accept *const ()). If you're either not using the calc feature or your Calc implementation is Send+Sync (which it really should be) then you can safely wrap the TaffyTree and unsafe impl Send + Sync
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rossleonardy You should enable one of std and alloc, but not both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent: I'd like to restrict users to that and implement calc support in a follow-up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just tagging #5893 here as the open issue about this so it has a reference back here.
| .collect::<Vec<_>>(), | ||
| grid_row: node.grid_row.into(), | ||
| grid_column: node.grid_column.into(), | ||
| ..Default::default() | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fields added are dummy, item_is_replaced, grid_template_areas, grid_template_column_names, grid_template_row_names. Not sure if this should be using their default or we should add these fields and have our own default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dummy is just phantomdata. grid_template_areas, grid_template_column_names, and grid_template_row_names should all be left at their default values for now.
I'm confused about is_replaced. The CoreStyle trait seems to map it to is_compressible_replaced which isn't quite same thing as a replaced element, like a form field isn't compressible normally?
| Val::Px(val) | ||
| .into_length_percentage(context) | ||
| .into_raw() | ||
| .value(), | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These rather verbose conversions are due to the fact that we do some math in into_length_percentage and into_length_percentage_auto, I would like to refactor the Val type story but this keeps the behavior the same
| ) -> taffy::style::GridTemplateComponent<S> | ||
| where | ||
| S: CheapCloneStr, | ||
| { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was an add things until it compiles moment, if anyone can explain what the generics mean here I would appreciate it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Taffy is now generic over a String-like type (which allows for named grid lines and named grid areas to be specified). Bevy should feel free to pick a concrete type such as Arc<str>, string_cache::Atom (or even String, but the idea is that such strings are cheaply cloneable).
If you're not actually using the named lines/areas feature (and thus such types will never actually be constructed) then you might consider Box<String> which would keep the size impact minimal.
| Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. | 
| } | ||
| } | ||
|  | ||
| pub(crate) struct BevyTaffyTree<T>(TaffyTree<T>); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is sort of a patch for an issue with Taffy:
ccbrown/iocraft#119 (comment)
Eventually it will be fixed in
DioxusLabs/taffy#823
| Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. | 
| Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. | 
| Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. | 
| Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. | 
| I'll try and make time to take a look at this later today, chase me up about it if I haven't. | 
| // NOOP function used to call into taffy API | ||
| fn resolve_calc(_calc_ptr: *const (), _parent_size: f32) -> f32 { | ||
| 0.0 | ||
| } | ||
|  | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is exactly what you should do here.
| Val::VMin(val) | ||
| .into_length_percentage(context) | ||
| .into_raw() | ||
| .value(), | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe Taffy has an Into implementation for this conversion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, performance is normal, examples all seem to be working fine. Don't see any major problems, just got a couple of notes.
| MinTrackSizingFunction::Px(val) => taffy::style::MinTrackSizingFunction::length( | ||
| Val::Px(val) | ||
| .into_length_percentage(context) | ||
| .into_raw() | ||
| .value(), | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think just:
| MinTrackSizingFunction::Px(val) => taffy::style::MinTrackSizingFunction::length( | |
| Val::Px(val) | |
| .into_length_percentage(context) | |
| .into_raw() | |
| .value(), | |
| MinTrackSizingFunction::Px(val) => Val::Px(val).into_length_percentage(context).into(), | 
should work, and so on for the rest.
| MaxTrackSizingFunction::Px(val) => taffy::style::MaxTrackSizingFunction::length( | ||
| Val::Px(val) | ||
| .into_length_percentage(context) | ||
| .into_raw() | ||
| .value(), | ||
| ), | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here:
| MaxTrackSizingFunction::Px(val) => taffy::style::MaxTrackSizingFunction::length( | |
| Val::Px(val) | |
| .into_length_percentage(context) | |
| .into_raw() | |
| .value(), | |
| ), | |
| MaxTrackSizingFunction::Px(val) => Val::Px(val).into_length_percentage(context).into(), | 
| } | ||
| } | ||
|  | ||
| pub(crate) struct BevyTaffyTree<T>(TaffyTree<T>); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name's a bit too long and ugly, maybe just:
| pub(crate) struct BevyTaffyTree<T>(TaffyTree<T>); | |
| pub(crate) struct UiTree<T>(TaffyTree<T>); | 
would be better, or something like that.
| #[expect(unsafe_code, reason = "TaffyTree is safe as long as calc is not used")] | ||
| /// SAFETY: Taffy Tree becomes thread unsafe when you use the calc feature, which we do not implement | ||
| unsafe impl Send for BevyTaffyTree<NodeMeasure> {} | ||
|  | ||
| #[expect(unsafe_code, reason = "TaffyTree is safe as long as calc is not used")] | ||
| /// SAFETY: Taffy Tree becomes thread unsafe when you use the calc feature, which we do not implement | ||
| unsafe impl Sync for BevyTaffyTree<NodeMeasure> {} | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't we just implement the traits for UiSurface itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably better to do it like it's already being done here I think. Lest we accidently add some non-Send field to another part of UiSurface. Implementing Deref and DerefMut for BevyTaffyTree would probably make this more ergonomic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it's not a user facing API anyway, so the extra friction doesn't really matter. We could hide it completely even, and add an accessor to UiSurface that returns a reference to the inner TaffyTree value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it will be removed after DioxusLabs/taffy#855 or similar work goes through, I think its nicer if it's a little separated like this.
Objective
Solution
I had to make some rather un-ergonomic changes I would like advice on, so I've left comments below.
Testing
Showcase
Fixes issue with grid start and ends...