Skip to content

Conversation

@rossleonardy
Copy link
Contributor

Objective

Solution

I had to make some rather un-ergonomic changes I would like advice on, so I've left comments below.

Testing

  • Pending...

Showcase

Screenshot 2025-10-27 at 8 18 50 PM

Fixes issue with grid start and ends...

@rossleonardy rossleonardy changed the title Update taffy to 9.0 and fix Grid errors #21240 Update taffy to 0.9 and fix Grid errors #21240 Oct 28, 2025

# other
taffy = { version = "0.7" }
taffy = { version = "0.9", default-features = false, features = ["std", "block_layout", "flexbox", "grid", "content_size", "alloc", "taffy_tree"] }
Copy link
Contributor Author

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.

Copy link
Member

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?

Copy link
Contributor

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).

Copy link
Contributor

@nicoburns nicoburns Oct 29, 2025

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

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Contributor Author

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()
Copy link
Contributor Author

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.

Copy link
Contributor

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(),
Copy link
Contributor Author

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,
{
Copy link
Contributor Author

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

Copy link
Contributor

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.

@github-actions
Copy link
Contributor

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!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-21672

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>);
Copy link
Contributor Author

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

@JMS55 JMS55 requested a review from ickshonpe October 28, 2025 01:15
@github-actions
Copy link
Contributor

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!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-21672

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.

@github-actions
Copy link
Contributor

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!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-21672

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.

@github-actions
Copy link
Contributor

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!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-21672

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.

@github-actions
Copy link
Contributor

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!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-21672

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.

@ickshonpe
Copy link
Contributor

I'll try and make time to take a look at this later today, chase me up about it if I haven't.

@alice-i-cecile alice-i-cecile added C-Dependencies A change to the crates that Bevy depends on A-UI Graphical user interfaces, styles, layouts, and widgets X-Uncontroversial This work is generally agreed upon S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Oct 29, 2025
@alice-i-cecile alice-i-cecile added this to the 0.18 milestone Oct 29, 2025
@alice-i-cecile alice-i-cecile added X-Contentious There are nontrivial implications that should be thought through and removed X-Uncontroversial This work is generally agreed upon labels Oct 29, 2025
Comment on lines +208 to +212
// NOOP function used to call into taffy API
fn resolve_calc(_calc_ptr: *const (), _parent_size: f32) -> f32 {
0.0
}

Copy link
Contributor

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.

Comment on lines +357 to +360
Val::VMin(val)
.into_length_percentage(context)
.into_raw()
.value(),
Copy link
Contributor

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

Copy link
Contributor

@ickshonpe ickshonpe left a 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.

Comment on lines +337 to +341
MinTrackSizingFunction::Px(val) => taffy::style::MinTrackSizingFunction::length(
Val::Px(val)
.into_length_percentage(context)
.into_raw()
.value(),
Copy link
Contributor

Choose a reason for hiding this comment

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

I think just:

Suggested change
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.

Comment on lines +387 to 392
MaxTrackSizingFunction::Px(val) => taffy::style::MaxTrackSizingFunction::length(
Val::Px(val)
.into_length_percentage(context)
.into_raw()
.value(),
),
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here:

Suggested change
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>);
Copy link
Contributor

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:

Suggested change
pub(crate) struct BevyTaffyTree<T>(TaffyTree<T>);
pub(crate) struct UiTree<T>(TaffyTree<T>);

would be better, or something like that.

Comment on lines +36 to +42
#[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> {}
Copy link
Contributor

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?

Copy link
Contributor

@nicoburns nicoburns Oct 30, 2025

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.

Copy link
Contributor

@ickshonpe ickshonpe Oct 30, 2025

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.

Copy link
Contributor Author

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.

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-Dependencies A change to the crates that Bevy depends on S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Contentious There are nontrivial implications that should be thought through

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants