ppy / osu

rhythm is just a *click* away!
https://osu.ppy.sh
MIT License
15.18k stars 2.26k forks source link

Mania (or catch) red tint should display to the sides #9376

Closed enoslayd closed 4 years ago

enoslayd commented 4 years ago

Describe the feature:

Originally posted by @LittleEndu in https://github.com/ppy/osu/issues/8789#issuecomment-615744131

Essentially red tint when failing should be on the side like the comment.

And maybe catch too.

peppy commented 4 years ago

I would hope we can come up with an effect that can be applied globally. Maybe it should be a radial inner glow from all four corners?

ynjoe commented 4 years ago

I think side borders works pretty well for all modes; maybe size could be tweaked.

image image image

peppy commented 4 years ago

You forgot about taiko, where the opposite is probably better.

ynjoe commented 4 years ago

I'm not too familiar with taiko gameplay, but from what I can see, failure only happens at the very end when the song finishes, and the failing layer is never displayed during/after gameplay.

Is it intended that the failing layer is supposed to display for taiko as well?

enoslayd commented 4 years ago

Actually, what im thinking is that standard either retain the current implementation or have them at 4 sides, taiko will also retain the current implementation and catch and mania will have them at side

bdach commented 4 years ago

As it stands taiko does not show this layer at all due to using an accumulating health processor (it would look weird if it started red). However there is a possibility of moving away from accumulating health to draining health in the future there to unify behaviour.

ynjoe commented 4 years ago

I'm assuming a global border would be best then? Unless theres a clean way to retrieve the game mode and generate the horizontal/vertical border styles.

I'm not too familiar with the framework yet, but it seems difficult to make other border styles from the available shapes. Right now, the only way I can think of making a radial glow is layering a circle on top of a square and making the circle's blending mode erase below it. Otherwise, constructing a shape in each corner to create a similar effect.

smoogipoo commented 4 years ago

You're right in thinking subtractive blending is the way to do. Something like the following will work (try it out in a test scene):

public class TestSceneTesting : FrameworkTestScene
{
    public TestSceneTesting()
    {
        Child = new Container
        {
            RelativeSizeAxes = Axes.Both,
            Children = new Drawable[]
            {
                // Background
                new Box
                {
                    RelativeSizeAxes = Axes.Both,
                    Colour = Color4.SlateGray
                },
                new BufferedContainer
                {
                    RelativeSizeAxes = Axes.Both,
                    CacheDrawnFrameBuffer = true,
                    // We'll be reverse-blending against the background of this FBO.
                    BackgroundColour = Color4.Red,
                    Children = new Drawable[]
                    {
                        new BufferedContainer
                        {
                            RelativeSizeAxes = Axes.Both,
                            CacheDrawnFrameBuffer = true,
                            // The default FBO colour is transparent black, but we want to match the outer colour for subtractive blending to look good.
                            BackgroundColour = Color4.Red.Opacity(0),
                            Blending = new BlendingParameters
                            {
                                // Take the inverse alpha of the glow effect.
                                AlphaEquation = BlendingEquation.Add,
                                SourceAlpha = BlendingType.Zero,
                                DestinationAlpha = BlendingType.OneMinusSrcAlpha,
                            },
                            // Any additional insetting (without this only the corners will be shaded).
                            Padding = new MarginPadding(40),
                            Child = new CircularContainer
                            {
                                RelativeSizeAxes = Axes.Both,
                                Masking = true,
                                EdgeEffect = new EdgeEffectParameters
                                {
                                    Type = EdgeEffectType.Glow,
                                    Colour = Color4.Red,
                                    // Consider this the "smoothness" of the effect - how many pixels from the edge of the circle to the edge of the parent.
                                    // If this is < corner radius, the effect will be more pronounced towards the edges.
                                    // If this is > corner radius, the effect will not reach full opacity by the edges.
                                    Radius = 400,
                                },
                                Child = new Box
                                {
                                    RelativeSizeAxes = Axes.Both,
                                    Alpha = 0,
                                    AlwaysPresent = true
                                }
                            }
                        }
                    }
                }
            }
        };
    }
}

I had to experiment with it a little bit myself, which reveals an interesting quirk of the framework - that we can't currently change the blending mode of effects to anything other than additive/mix which means that this example requires a nested BufferedContainer.

Otherwise, a shader could also work.

ynjoe commented 4 years ago

Thank you very much for the help.

After some tweaking, this is what the radial glow looks like during each game mode (and potentially Taiko) image

For the code, I took out the child box in the circular container and nothing seemed to be affected. Is it supposed to be doing something? Also, the current falling layer dynamically sets the color in the load() method using the passed in color param. Is there way to update the color in the circular container's EdgeEffectParameters for the radial glow?

peppy commented 4 years ago

That looks pretty bad. Maybe need tweaking, maybe needs re-thinking.

ynjoe commented 4 years ago

What direction would be best to go in?

I played around with some values:

Increased padding, increased radius image White layer: image Less opaque (Colored background for reference): image image

peppy commented 4 years ago

Let's just switch to left/right sides for now, I think.

ynjoe commented 4 years ago

Ok, I will submit a pull request.