-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Fix flashlight not always matching gameplay scaling #34761
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
Conversation
Because the flashlight is made to be scaled by playfield, there are
constant scale factors applied somewhere in the
`PlayfieldAdjustmentContainer` which needs to be reflected in the
flashlight size to keep the size the same.
The factor is specifically 1.6x, computed in {Osu,Catch}PlayfieldAdjustmentContainer.ScalingContainer`.
More generally, I've deduced these factors by logging the difference
between the `flashlightSize` before and after b78abe2.
36579e1 to
73624e4
Compare
|
@frenzibyte test failures look relevant |
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 would expect screenshots with cross-comparison with stable (and lazer master) in this PR if the flashlight constants are being touched, please provide them
| public override BindableBool ComboBasedSize { get; } = new BindableBool(true); | ||
|
|
||
| public override float DefaultFlashlightSize => 325; | ||
| public override float DefaultFlashlightSize => 203.125f; |
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.
not sure how to feel about this 1.6 thing being just directly baked into constants rather than 325 * 1.6f or similar
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.
100% has to be a constant, hopefully in the place its primarily used.
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.
Do these numbers bare any meaning before the constant is applied? If not, I see no reason to try extracting a constant for this. If anything, I would tweak DefaultFlashlightSize 3 pixels down to 200 and make this feel more natural to read 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.
1.6 is the playfield and stable scale factor, if that's what you're asking. it's like, the meaning-of-life as far as stable is concerned.
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 meant to ask about the current numbers of the DefaultFlashlightSize (200 in osu! and 325 in catch before this PR), if they're not referenced anywhere else and they only represent themselves, I'm not sure it's necessary to split the constant away from them rather than just inline the computation?
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.
based on #20566 it looks like the numbers are arbitrary constants anyway, so I guess I don't really care that much. that said 1.6 is used allllll over if you grep for it
| // scale the flashlight based on the playfield to match gameplay components scale. | ||
| Vector2 drawInfoScale = Source.Playfield.DrawInfo.Matrix.ExtractScale().Xy; | ||
| flashlightSize = Source.FlashlightSize * drawInfoScale; |
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.
while I haven't found a way to exploit this, this is highly suspicious, because this type of dependency means that any invalidation of the playfield's drawinfo should invalidate this drawnode (like all of the other properties such as FlashlightSize or FlashlightDim etc. do) but I don't see anything setting that up.
is there something that I'm missing that makes this automagically work somehow?
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.
Hmm, good point. If the playfield was to begin scaling up/down at an internal level (somewhere from PlayfieldAdjustmentContainer down to Playfield itself) then I can imagine it would break the flashlight due to not receiving invalidations as well. It's likely that it works fine right now because window resizes apply invalidations from a very high level down into both the playfield hierarchy and the flashlight drawable.
I think this is best fixed by carving a way for the flashlight to be inserted in the Playfield hierarchy instead, I'll look into that.
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.
Multiple things:
-
I've checked why the flashlight draw node always gets invalidated, and that's because of this particular line in the osu! mod flashlight implementation. Commenting that exposes a potential scenario where this can be broken, by e.g. gradually scaling down the playfield adjustment container in update (I tried it on barrel roll) then observing the flashlight size doesn't update.
-
I've attempted adding the flashlight directly in the
PlayfieldAdjustmentContainer, and while that showed positive results on osu!, taiko, and mania, it didn't work quite well with catch. This is because catch applies masking somewhere in its adjustment container to limit fruits visibility, and that masks the black layer added by the flashlight from reaching the entire screen.It is possible to override that by altering the masking info in the flashlight draw node, but I can't really rely on such finicky / flaky logic for a critical mod like this.
-
Finally, I've chosen to fix this by explicitly planting a component which gets invalidated on changes to the playfield draw info, and hook that up to invalidate the flashlight draw node. Testing this fix with the scenario described in bullet one confirms the fix to work as intended. See bc59270.
The failed test is essentially impossible to fix with this PR as the test attempts to ensure the flashlight size is smaller when barrel mod is active, but the flashlight size is only getting smaller by calculations done at a I don't see any path forward than removing it and making it an assumption that the flashlight always scales with the playfield from now on, at least until this becomes a problem enough for us to begin inventing drawnode-level tests. I can also expose |
Note that this does not handle sizing/scaling changes applied directly to `Playfield`, but it handles any changes within the layers inside `PlayfieldAdjustmentContainer`.
|
Below is a table of cross-comparisons between lazer master, this PR, this PR again but with mobile viewport (by manually modifying
Notes:
|
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 fine
This fix essentially expands on #33910 by extracting scale directly from the playfield rather than just reading
PlayfieldAdjustmentContainer.Scale(which does not cover any scaling factor applied in nested containers between the playfield adjustment container and the playfield itself).This also required size adjustments in osu! and catch, as well as a minor change in taiko flashlight:
In osu!, because I'm now scaling the flashlight based on the playfield, there's a constant 1.6x factor applied directly by
OsuPlayfieldAdjustmentContainer.ScalingContainer. To keep the flashlight size from visually getting 1.6x larger, I've adjusted the default flashlight size to counter that. Applied in 29b2a71.In osu!catch, same as osu!, there's a 1.6x factor applied by
CatchPlayfieldAdjustmentContainer.ScalingContainer. Also applied in 29b2a71.In osu!taiko, since Fix Flashlight having increased radius when Barrel Roll is active #33910 was merged, the flashlight size became scaled twice by the playfield, once in:
osu/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs
Line 66 in 30f7da8
osu/osu.Game/Rulesets/Mods/ModFlashlight.cs
Lines 159 to 166 in 30f7da8
This made the flashlight grow its view as the playfield widens:
CleanShot.2025-08-21.at.17.28.35.mp4
This is fixed in 5a84c07 by removing the local logic in favour of the main scaling logic added by this PR in the flashlight draw node. PR:
CleanShot.2025-08-21.at.17.41.47.mp4
For comparison, this is how the flashlight size is with just the changes in Fix Flashlight having increased radius when Barrel Roll is active #33910 reverted (point is to show that it matches what I have in this PR, i.e. the correct behaviour):
CleanShot.2025-08-21.at.17.49.39.mp4
In osu!mania, no direct changes were made, but it seems this PR fixes an issue with flashlight that has existed since mobile mania was improved. Before:
CleanShot.2025-08-21.at.17.58.51.mp4
After:
CleanShot.2025-08-21.at.18.00.14.mp4