-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Ensure health displays don't pile up transforms when off-screen #25076
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.
The fix side looks okay, just a few minor concerns / side notes
this.TransformTo(nameof(HealthBarValue), v.NewValue, time, Easing.OutQuint); | ||
if (resetMissBarDelegate == null) | ||
this.TransformTo(nameof(GlowBarValue), v.NewValue, time, Easing.OutQuint); | ||
// For some reason making the delegate inline here doesn't work correctly. |
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 to reiterate / explain - delegates with this
captures cannot be correctly used inline with AddOnce()
. Captures cause the compiler to generate code that allocates a new delegate every call, and that fails on the equality check framework-side.
If you didn't want (or couldn't for whatever reason) to use method groups, the only (and pretty cursed) alternative would be to write the delegate such that it doesn't require captures:
diff --git a/osu.Game/Screens/Play/HUD/ArgonHealthDisplay.cs b/osu.Game/Screens/Play/HUD/ArgonHealthDisplay.cs
index 9c7c0684b3..04e0307dc6 100644
--- a/osu.Game/Screens/Play/HUD/ArgonHealthDisplay.cs
+++ b/osu.Game/Screens/Play/HUD/ArgonHealthDisplay.cs
@@ -142,18 +142,18 @@ protected override void LoadComplete()
Current.BindValueChanged(v =>
{
- Scheduler.AddOnce(() =>
+ Scheduler.AddOnce(display =>
{
- if (v.NewValue >= GlowBarValue)
- finishMissDisplay();
+ if (display.Current.Value >= display.GlowBarValue)
+ display.finishMissDisplay();
- double time = v.NewValue > GlowBarValue ? 500 : 250;
+ double time = display.Current.Value > display.GlowBarValue ? 500 : 250;
// TODO: this should probably use interpolation in update.
- this.TransformTo(nameof(HealthBarValue), v.NewValue, time, Easing.OutQuint);
- if (resetMissBarDelegate == null)
- this.TransformTo(nameof(GlowBarValue), v.NewValue, time, Easing.OutQuint);
- });
+ display.TransformTo(nameof(HealthBarValue), display.Current.Value, time, Easing.OutQuint);
+ if (display.resetMissBarDelegate == null)
+ display.TransformTo(nameof(GlowBarValue), display.Current.Value, time, Easing.OutQuint);
+ }, this);
}, true);
BarLength.BindValueChanged(l => Width = l.NewValue, true);
This makes the compiler figure out that it can allocate just one instance of this delegate and re-use it across different ArgonHealthDisplay
instances, and makes AddOnce()
"magically" work again.
One for an analyser to check in the future maybe. If we ever get to writing those.
tl;dr: when in doubt about AddOnce()
, use method group
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 I don't think it's worth the proposed change. I may just remove the comment and add some safety comments framework side instead.
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 patch above was in no way a serious proposal mind. It was mostly supposed to be illustrative as to why sometimes inline delegates work and sometimes they don't. I wouldn't personally want to get caught committing such ugly code.
Closes #25050.
I noticed theres some other HUD elements with similar issues, but they are far less prominent. Will get to those another time.
Can be tested with: