-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Prevent ImageBundles from causing constant layout recalculations #1299
Conversation
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.
Seems sensible to me. I wonder if we could add something similar as a method to Mut
, i.e.
impl<'a, T: PartialEq<T>> Mut<'a, T> {
fn set_if_new(&mut self, value: T) -> Option<T>{
if &*self == &value {
*self = value;
None
} else {
Some(value)
}
}
}
In theory, we could make a version which just returns T
and returns the old value in the first branch, but I suspect that the return value of this function used often anyway.
Obviously to use it here we'd need to derive PartialEq
for CalculatedSize
, but that isn't the end of the world. I'm also not sure if just plain Eq
would be more correct in this case
You definitely could, but I don't think it's worth expanding the API to save some pretty simple code?
Eq is more correct here IMO: trying to figure out what the correct behavior is for when |
Does this work? (Sorry, bit rude of me not to check myself.) Seems like you'd still be mut dereferencing This seems related to something that goes on with text, where we re-layout text on any At one point I wrote some code like this which seems to help but it's not exactly ergonomic. fn test(mut queries: QuerySet<(Query<&Text>, Query<&mut Text>)>, state: Res<State>) {
if let Some(text) = queries.q0().iter().next() {
let score_text = format!("Score: {}", state.score);
if (text.value != score_text) {
if let Some(mut text) = queries.q1_mut().iter_mut().next() {
text.value = score_text;
}
}
}
} Something like that could perhaps go on in TextSystem, but there's already a |
I can say with confidence that if the diagnosis of the problem is correct, this solution works. The line |
Cool. I'm very happy that it's just my understanding of |
width: texture.size.width as f32, | ||
height: texture.size.height as f32, | ||
}; | ||
if size != calculated_size.size { |
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.
Its probably a good idea to leave a comment here about why we're doing this check. People with less context might look at this and say "this check isn't needed".
Nice catch!
I think the one benefit of adding a new method to Mut for this is that it self-documents intent. Otherwise i think we need comments everywhere to ensure people don't try to "remove an unnecessary branch" |
Should I add |
As @rparrett pointed out, this issue is present everywhere. It's most notable in any UI component like Text, Style and Image since the layout calculations take so long in any non trivial app. I expect
Yes, I tested it. |
Hmm yeah lets do a separate pr to make it clearer / easier to point to in the changelog. We should also discuss the name as this will be used everywhere. For now lets just add a comment above the if statement. |
…yengine#1299) Prevent ImageBundles from causing constant layout recalculations
The complete UI layout is recalculated when a
CalculatedSize
is updated, andimage_node_system
updates them every frame for images. The fix checks if the size has actually changed.