1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-17 18:13:18 +08:00

Merge branch 'master' into ssv2-score-opens-results

This commit is contained in:
Bartłomiej Dach
2025-05-16 13:23:38 +02:00
Unverified
4 changed files with 82 additions and 15 deletions
@@ -108,6 +108,21 @@ namespace osu.Game.Tests.Visual.SongSelectV2
AddAssert("beatmap set deleted", () => Beatmaps.GetAllUsableBeatmapSets().Any(), () => Is.False);
}
[Test]
public void TestClearModsViaModButtonRightClick()
{
LoadSongSelect();
AddStep("select NC", () => SelectedMods.Value = new[] { new OsuModNightcore() });
AddAssert("mods selected", () => SelectedMods.Value, () => Has.Count.EqualTo(1));
AddStep("right click mod button", () =>
{
InputManager.MoveMouseTo(Footer.ChildrenOfType<FooterButtonMods>().Single());
InputManager.Click(MouseButton.Right);
});
AddAssert("not mods selected", () => SelectedMods.Value, () => Has.Count.EqualTo(0));
}
[Test]
public void TestSpeedChange()
{
+44 -14
View File
@@ -623,7 +623,7 @@ namespace osu.Game.Graphics.Carousel
if (c.Item == null)
continue;
float normalisedDepth = (float)(Math.Abs(selectedYPos - c.DrawYPosition) / DrawHeight);
float normalisedDepth = (float)(Math.Abs(selectedYPos - c.Item.CarouselYPosition) / DrawHeight);
Scroll.Panels.ChangeChildDepth(panel, c.Item.DepthLayer + normalisedDepth);
if (c.DrawYPosition != c.Item.CarouselYPosition)
@@ -695,6 +695,12 @@ namespace osu.Game.Graphics.Carousel
{
var carouselPanel = (ICarouselPanel)panel;
if (carouselPanel.Item == null)
{
// Item is null when a panel is already fading away from existence; should be ignored for tracking purposes.
continue;
}
// The case where we're intending to display this panel, but it's already displayed.
// Note that we **must compare the model here** as the CarouselItems may be fresh instances due to a filter operation.
//
@@ -710,7 +716,7 @@ namespace osu.Game.Graphics.Carousel
}
// If the new display range doesn't contain the panel, it's no longer required for display.
expirePanelImmediately(panel);
expirePanel(panel);
}
// Add any new items which need to be displayed and haven't yet.
@@ -721,12 +727,36 @@ namespace osu.Game.Graphics.Carousel
if (drawable is not ICarouselPanel carouselPanel)
throw new InvalidOperationException($"Carousel panel drawables must implement {typeof(ICarouselPanel)}");
carouselPanel.DrawYPosition = item.CarouselYPosition;
carouselPanel.Item = item;
Scroll.Add(drawable);
}
if (toDisplay.Any())
{
// To make transitions of items appearing in the flow look good, do a pass and make sure newly added items spawn from
// just beneath the *current interpolated position* of the previous panel.
var orderedPanels = Scroll.Panels
.OfType<ICarouselPanel>()
.Where(p => p.Item != null)
.OrderBy(p => p.Item!.CarouselYPosition)
.ToList();
for (int i = 0; i < orderedPanels.Count; i++)
{
var panel = orderedPanels[i];
if (toDisplay.Contains(panel.Item!))
{
// Don't apply to the last because animating the tail of the list looks bad.
// It's usually off-screen anyway.
if (i > 0 && i < orderedPanels.Count - 1)
panel.DrawYPosition = orderedPanels[i - 1].DrawYPosition;
else
panel.DrawYPosition = panel.Item!.CarouselYPosition;
}
}
}
// Update the total height of all items (to make the scroll container scrollable through the full height even though
// most items are not displayed / loaded).
if (carouselItems.Count > 0)
@@ -738,13 +768,18 @@ namespace osu.Game.Graphics.Carousel
Scroll.SetLayoutHeight(0);
}
private static void expirePanelImmediately(Drawable panel)
private void expirePanel(Drawable panel)
{
panel.FinishTransforms();
panel.Expire();
var carouselPanel = (ICarouselPanel)panel;
// expired panels should have a depth behind all other panels to make the transition not look weird.
Scroll.Panels.ChangeChildDepth(panel, panel.Depth + 1024);
panel.FadeOut(150, Easing.OutQuint);
panel.MoveToX(panel.X + 100, 200, Easing.Out);
panel.Expire();
carouselPanel.Item = null;
carouselPanel.Selected.Value = false;
carouselPanel.KeyboardSelected.Value = false;
@@ -801,12 +836,7 @@ namespace osu.Game.Graphics.Carousel
base.OffsetScrollPosition(offset);
foreach (var panel in Panels)
{
var c = (ICarouselPanel)panel;
Debug.Assert(c.Item != null);
c.DrawYPosition += offset;
}
((ICarouselPanel)panel).DrawYPosition += offset;
}
public override void Clear(bool disposeChildren)
@@ -14,6 +14,7 @@ using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Game.Configuration;
using osu.Game.Graphics;
@@ -27,11 +28,14 @@ using osu.Game.Screens.Play.HUD;
using osu.Game.Utils;
using osuTK;
using osuTK.Graphics;
using osuTK.Input;
namespace osu.Game.Screens.SelectV2
{
public partial class FooterButtonMods : ScreenFooterButton, IHasCurrentValue<IReadOnlyList<Mod>>
{
public Action? RequestDeselectAllMods { get; init; }
private const float bar_height = 30f;
private const float mod_display_portion = 0.65f;
@@ -172,6 +176,18 @@ namespace osu.Game.Screens.SelectV2
FinishTransforms(true);
}
protected override bool OnMouseDown(MouseDownEvent e)
{
// should probably be OnClick but right mouse button clicks isn't setup well.
if (e.Button == MouseButton.Right)
{
RequestDeselectAllMods?.Invoke();
return true;
}
return base.OnMouseDown(e);
}
private const double duration = 240;
private const Easing easing = Easing.OutQuint;
+7 -1
View File
@@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -22,6 +23,7 @@ using osu.Game.Input.Bindings;
using osu.Game.Overlays;
using osu.Game.Overlays.Mods;
using osu.Game.Overlays.Volume;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Footer;
@@ -197,7 +199,11 @@ namespace osu.Game.Screens.SelectV2
public override IReadOnlyList<ScreenFooterButton> CreateFooterButtons() => new ScreenFooterButton[]
{
new FooterButtonMods(modSelectOverlay) { Current = Mods },
new FooterButtonMods(modSelectOverlay)
{
Current = Mods,
RequestDeselectAllMods = () => Mods.Value = Array.Empty<Mod>()
},
new FooterButtonRandom(),
new FooterButtonOptions(),
};