Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@frenzibyte
Copy link
Member

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:

    return new Vector2(0, size * taikoPlayfield.Parent!.Scale.Y);
    and again in:
    if (GetPlayfieldScale != null)
    {
    Vector2 playfieldScale = GetPlayfieldScale();
    Debug.Assert(Precision.AlmostEquals(Math.Abs(playfieldScale.X), Math.Abs(playfieldScale.Y)),
    @"Playfield has non-proportional scaling. Flashlight implementations should be revisited with regard to balance.");
    size *= Math.Abs(playfieldScale.X);
    }

    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

@frenzibyte frenzibyte changed the title Fix flashlight Fix flashlight not always matching gameplay scaling Aug 21, 2025
@frenzibyte frenzibyte self-assigned this Aug 21, 2025
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.
@peppy
Copy link
Member

peppy commented Aug 22, 2025

@frenzibyte test failures look relevant

Copy link
Collaborator

@bdach bdach left a 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;
Copy link
Collaborator

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

Copy link
Member

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.

Copy link
Member Author

@frenzibyte frenzibyte Aug 23, 2025

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.

Copy link
Member

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.

Copy link
Member Author

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?

Copy link
Collaborator

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

Comment on lines 258 to 260
// scale the flashlight based on the playfield to match gameplay components scale.
Vector2 drawInfoScale = Source.Playfield.DrawInfo.Matrix.ExtractScale().Xy;
flashlightSize = Source.FlashlightSize * drawInfoScale;
Copy link
Collaborator

@bdach bdach Aug 22, 2025

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?

Copy link
Member Author

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.

Copy link
Member Author

@frenzibyte frenzibyte Aug 24, 2025

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.

@frenzibyte
Copy link
Member Author

frenzibyte commented Aug 23, 2025

@frenzibyte test failures look relevant

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 FlashlightDrawNode level.

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 FlashlightDrawNode.flashlightSize and manually create a drawnode from the test and ensure the field is populated as expected, but I'm not sure that's really necessary.

Note that this does not handle sizing/scaling changes applied directly
to `Playfield`, but it handles any changes within the layers inside
`PlayfieldAdjustmentContainer`.
@pull-request-size pull-request-size bot added size/L and removed size/M labels Aug 24, 2025
@frenzibyte
Copy link
Member Author

Below is a table of cross-comparisons between lazer master, this PR, this PR again but with mobile viewport (by manually modifying TargetDrawSize from 1024x768 to 1024x512, number is arbitrary but wide enough to match phones), and finally stable. Read notes below the table as there are oddities present.

master this PR "mobile" stable
osu! CleanShot 2025-08-25 at 05 18 12 CleanShot 2025-08-23 at 10 46 39 CleanShot 2025-08-25 at 06 06 22 BB3P4Bh
osu! + BR CleanShot 2025-08-25 at 05 20 57 CleanShot 2025-08-23 at 10 46 56 CleanShot 2025-08-23 at 10 48 18 n/a
taiko on ~16:9 osu_2025-08-25_05-47-25 osu_2025-08-25_05-57-39 CleanShot 2025-08-23 at 10 53 56 image
taiko on 21:9 osu_2025-08-25_05-48-01 osu_2025-08-25_05-42-05 osu_2025-08-25_05-41-53 screenshot007
taiko on 4:3 osu_2025-08-25_05-48-28 osu_2025-08-25_05-40-19 osu_2025-08-25_05-40-43 screenshot008
catch CleanShot 2025-08-25 at 06 14 39 CleanShot 2025-08-25 at 06 12 39 CleanShot 2025-08-25 at 06 11 09 Crm9C9i
mania CleanShot 2025-08-24 at 18 07 05 CleanShot 2025-08-23 at 10 53 35 CleanShot 2025-08-24 at 18 02 10 l1Zy2ZT

Notes:

  • Mania flashlight seems more strict on lazer in general than stable, maybe something that should be followed up on.

  • Taiko flashlight also appears to be shifted and somewhat smaller in stable than lazer, maybe also something that should be followed up on.

  • Taiko flashlight on this PR does not match master as already noted in OP, the behaviour in this PR matches lazer 2025.607.0 (last release before the regressing PR was merged). To save everyone's time, I've made a cross-comparison table between this PR and lazer 2025.607.0:

    this PR 2025.607.0
    osu_2025-08-25_05-57-39 osu_2025-08-25_05-45-14
    osu_2025-08-25_05-42-05 osu_2025-08-25_05-45-41
    osu_2025-08-25_05-40-19 osu_2025-08-25_05-46-09

Copy link
Collaborator

@bdach bdach left a comment

Choose a reason for hiding this comment

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

probably fine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flashlight (mod) have very different size depends on the device

3 participants