4 Commits

Author SHA1 Message Date
9637ea1df7 again**2 2025-12-16 19:51:36 +03:00
0940d61f7e try again 2025-12-16 19:47:28 +03:00
e6a6352a9c sync with master fully 2025-12-16 19:39:40 +03:00
e78c8fa03d (NOT STABLE!!) Added custom mode using music from MainMenu 2025-08-23 22:54:22 +03:00
54 changed files with 156 additions and 387 deletions

View File

@@ -21,7 +21,7 @@
] ]
}, },
"ppy.localisationanalyser.tools": { "ppy.localisationanalyser.tools": {
"version": "2025.1208.0", "version": "2024.802.0",
"commands": [ "commands": [
"localisation" "localisation"
] ]

View File

@@ -72,9 +72,6 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
leaderboard.Origin = Anchor.CentreLeft; leaderboard.Origin = Anchor.CentreLeft;
leaderboard.X = 10; leaderboard.X = 10;
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
Children = new Drawable[] Children = new Drawable[]

View File

@@ -57,9 +57,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
if (spectatorList != null) if (spectatorList != null)
spectatorList.Position = new Vector2(36, -66); spectatorList.Position = new Vector2(36, -66);
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
new DrawableGameplayLeaderboard(), new DrawableGameplayLeaderboard(),

View File

@@ -122,9 +122,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
leaderboard.Origin = Anchor.CentreLeft; leaderboard.Origin = Anchor.CentreLeft;
leaderboard.X = 10; leaderboard.X = 10;
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
new LegacyManiaComboCounter(), new LegacyManiaComboCounter(),

View File

@@ -103,9 +103,6 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
leaderboard.Origin = Anchor.BottomLeft; leaderboard.Origin = Anchor.BottomLeft;
leaderboard.Position = pos; leaderboard.Position = pos;
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
Children = new Drawable[] Children = new Drawable[]

View File

@@ -49,18 +49,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
/// </summary> /// </summary>
protected bool AllowPartRotation { get; set; } protected bool AllowPartRotation { get; set; }
private Vector2 cursorScale;
public Vector2 CursorScale
{
get => cursorScale;
set
{
cursorScale = value;
Invalidate(Invalidation.DrawNode);
}
}
/// <summary> /// <summary>
/// The trail part texture origin. /// The trail part texture origin.
/// </summary> /// </summary>
@@ -245,7 +233,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private float time; private float time;
private float fadeExponent; private float fadeExponent;
private float angle; private float angle;
private Vector2 cursorScale;
private readonly TrailPart[] parts = new TrailPart[max_sprites]; private readonly TrailPart[] parts = new TrailPart[max_sprites];
private Vector2 originPosition; private Vector2 originPosition;
@@ -266,7 +253,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
time = Source.time; time = Source.time;
fadeExponent = Source.FadeExponent; fadeExponent = Source.FadeExponent;
angle = Source.AllowPartRotation ? float.DegreesToRadians(Source.PartRotation) : 0; angle = Source.AllowPartRotation ? float.DegreesToRadians(Source.PartRotation) : 0;
cursorScale = Source.cursorScale;
originPosition = Vector2.Zero; originPosition = Vector2.Zero;
@@ -321,9 +307,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
vertexBatch.Add(new TexturedTrailVertex vertexBatch.Add(new TexturedTrailVertex
{ {
Position = rotateAround( Position = rotateAround(
new Vector2( new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y),
part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X * cursorScale.X,
part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y * cursorScale.Y),
part.Position, sin, cos), part.Position, sin, cos),
TexturePosition = textureRect.BottomLeft, TexturePosition = textureRect.BottomLeft,
TextureRect = new Vector4(0, 0, 1, 1), TextureRect = new Vector4(0, 0, 1, 1),
@@ -334,10 +318,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
vertexBatch.Add(new TexturedTrailVertex vertexBatch.Add(new TexturedTrailVertex
{ {
Position = rotateAround( Position = rotateAround(
new Vector2( new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X,
part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X * cursorScale.X, part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y), part.Position, sin, cos),
part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y * cursorScale.Y),
part.Position, sin, cos),
TexturePosition = textureRect.BottomRight, TexturePosition = textureRect.BottomRight,
TextureRect = new Vector4(0, 0, 1, 1), TextureRect = new Vector4(0, 0, 1, 1),
Colour = DrawColourInfo.Colour.BottomRight.Linear, Colour = DrawColourInfo.Colour.BottomRight.Linear,
@@ -347,9 +329,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
vertexBatch.Add(new TexturedTrailVertex vertexBatch.Add(new TexturedTrailVertex
{ {
Position = rotateAround( Position = rotateAround(
new Vector2( new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X * cursorScale.X,
part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y * cursorScale.Y),
part.Position, sin, cos), part.Position, sin, cos),
TexturePosition = textureRect.TopRight, TexturePosition = textureRect.TopRight,
TextureRect = new Vector4(0, 0, 1, 1), TextureRect = new Vector4(0, 0, 1, 1),
@@ -360,9 +340,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
vertexBatch.Add(new TexturedTrailVertex vertexBatch.Add(new TexturedTrailVertex
{ {
Position = rotateAround( Position = rotateAround(
new Vector2( new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X * cursorScale.X,
part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y * cursorScale.Y),
part.Position, sin, cos), part.Position, sin, cos),
TexturePosition = textureRect.TopLeft, TexturePosition = textureRect.TopLeft,
TextureRect = new Vector4(0, 0, 1, 1), TextureRect = new Vector4(0, 0, 1, 1),

View File

@@ -64,14 +64,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
var newScale = new Vector2(e.NewValue); var newScale = new Vector2(e.NewValue);
rippleVisualiser.CursorScale = newScale; rippleVisualiser.CursorScale = newScale;
updateTrailScale(); cursorTrail.Scale = newScale;
}, true); }, true);
cursorTrail.OnSkinChanged += updateTrailScale;
}
private void updateTrailScale()
{
if (cursorTrail.Drawable is CursorTrail trail) trail.CursorScale = new Vector2(ActiveCursor.CursorScale.Value);
} }
private int downCount; private int downCount;

View File

@@ -51,9 +51,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon
spectatorList.Anchor = Anchor.BottomLeft; spectatorList.Anchor = Anchor.BottomLeft;
spectatorList.Origin = Anchor.TopLeft; spectatorList.Origin = Anchor.TopLeft;
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,

View File

@@ -51,9 +51,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default
spectatorList.Origin = Anchor.TopLeft; spectatorList.Origin = Anchor.TopLeft;
spectatorList.Position = new Vector2(320, -280); spectatorList.Position = new Vector2(320, -280);
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,

View File

@@ -79,9 +79,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
spectatorList.Origin = Anchor.TopLeft; spectatorList.Origin = Anchor.TopLeft;
spectatorList.Position = pos; spectatorList.Position = pos;
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
new LegacyDefaultComboCounter(), new LegacyDefaultComboCounter(),

View File

@@ -79,8 +79,6 @@ namespace osu.Game.Tests.Skins
"Archives/modified-argon-20250424.osk", "Archives/modified-argon-20250424.osk",
// Covers "Argon" unstable rate counter // Covers "Argon" unstable rate counter
"Archives/modified-argon-20250809.osk", "Archives/modified-argon-20250809.osk",
// Covers legacy style performance points counter
"Archives/modified-classic-20250827.osk",
// Covers "Argon" judgement counter // Covers "Argon" judgement counter
"Archives/modified-argon-20250308.osk", "Archives/modified-argon-20250308.osk",
// Covers "Argon" clicks/s counter, longest combo counter, skinnable SR display and beatmap status pill // Covers "Argon" clicks/s counter, longest combo counter, skinnable SR display and beatmap status pill

View File

@@ -50,34 +50,6 @@ namespace osu.Game.Tests.Visual.Gameplay
sprites.All(sprite => sprite.ChildrenOfType<Sprite>().All(s => s.Texture == null))); sprites.All(sprite => sprite.ChildrenOfType<Sprite>().All(s => s.Texture == null)));
} }
[Test]
public void TestSpriteFadeOverflowBehaviour()
{
AddStep("create sprite", () => SetContents(_ =>
{
var layer = storyboard.GetLayer("Background");
var sprite = new StoryboardSprite(lookup_name, Anchor.TopLeft, new Vector2(256, 192));
sprite.Commands.AddAlpha(Easing.None, Time.Current, Time.Current + 2000, 0, 2);
layer.Elements.Clear();
layer.Add(sprite);
return new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
storyboard.CreateDrawable()
}
};
}));
AddUntilStep("sprite reached high opacity once", () => sprites.All(sprite => sprite.ChildrenOfType<Sprite>().All(s => s.Alpha > 0.8f)));
AddUntilStep("sprite reset to low opacity", () => sprites.All(sprite => sprite.ChildrenOfType<Sprite>().All(s => s.Alpha < 0.2f)));
AddUntilStep("sprite reached high opacity twice", () => sprites.All(sprite => sprite.ChildrenOfType<Sprite>().All(s => s.Alpha > 0.8f)));
}
[Test] [Test]
public void TestLookupFromStoryboard() public void TestLookupFromStoryboard()
{ {

View File

@@ -18,7 +18,6 @@ using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD;
using osu.Game.Skinning;
using osu.Game.Skinning.Triangles; using osu.Game.Skinning.Triangles;
using osu.Game.Tests.Gameplay; using osu.Game.Tests.Gameplay;
@@ -36,7 +35,7 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override Drawable CreateDefaultImplementation() => new TrianglesPerformancePointsCounter(); protected override Drawable CreateDefaultImplementation() => new TrianglesPerformancePointsCounter();
protected override Drawable CreateArgonImplementation() => new ArgonPerformancePointsCounter(); protected override Drawable CreateArgonImplementation() => new ArgonPerformancePointsCounter();
protected override Drawable CreateLegacyImplementation() => new LegacyPerformancePointsCounter(); protected override Drawable CreateLegacyImplementation() => Empty();
private Bindable<JudgementResult> lastJudgementResult => (Bindable<JudgementResult>)gameplayState.LastJudgementResult; private Bindable<JudgementResult> lastJudgementResult => (Bindable<JudgementResult>)gameplayState.LastJudgementResult;

View File

@@ -5,7 +5,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Newtonsoft.Json;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions; using osu.Framework.Extensions;
@@ -379,23 +378,6 @@ namespace osu.Game.Tests.Visual.Gameplay
() => Is.EqualTo(3)); () => Is.EqualTo(3));
} }
[Test]
public void TestCopyPasteIdempotency()
{
string state = null!;
AddStep("select everything", () => InputManager.Keys(PlatformAction.SelectAll));
AddStep("dump state", () =>
{
state = JsonConvert.SerializeObject(skinEditor.SelectedComponents.Cast<Drawable>().Select(s => s.CreateSerialisedInfo()).ToArray());
});
AddStep("copy", () => InputManager.Keys(PlatformAction.Copy));
AddStep("delete", () => InputManager.Keys(PlatformAction.Delete));
AddStep("paste", () => InputManager.Keys(PlatformAction.Paste));
AddAssert("pasted state equals dumped",
() => JsonConvert.SerializeObject(skinEditor.SelectedComponents.Cast<Drawable>().Select(s => s.CreateSerialisedInfo()).ToArray()),
() => Is.EqualTo(state));
}
private SkinnableContainer globalHUDTarget => Player.ChildrenOfType<SkinnableContainer>() private SkinnableContainer globalHUDTarget => Player.ChildrenOfType<SkinnableContainer>()
.Single(c => c.Lookup.Lookup == GlobalSkinnableContainers.MainHUDComponents && c.Lookup.Ruleset == null); .Single(c => c.Lookup.Lookup == GlobalSkinnableContainers.MainHUDComponents && c.Lookup.Ruleset == null);

View File

@@ -24,7 +24,6 @@ using osu.Game.Configuration;
using osu.Game.Extensions; using osu.Game.Extensions;
using osu.Game.Graphics.Carousel; using osu.Game.Graphics.Carousel;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.Notifications.WebSocket; using osu.Game.Online.Notifications.WebSocket;
@@ -34,7 +33,6 @@ using osu.Game.Overlays.BeatmapListing;
using osu.Game.Overlays.Mods; using osu.Game.Overlays.Mods;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
using osu.Game.Overlays.Toolbar; using osu.Game.Overlays.Toolbar;
using osu.Game.Overlays.Volume;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Configuration;
@@ -1338,34 +1336,6 @@ namespace osu.Game.Tests.Visual.Navigation
AddAssert("still nothing selected", () => Game.Beatmap.IsDefault); AddAssert("still nothing selected", () => Game.Beatmap.IsDefault);
} }
[Test]
public void TestVolumeMeterDragDoesNotDismissFocusedOverlay()
{
AddStep("show beatmap overlay", () => Game.ShowBeatmapSet(1));
AddUntilStep("beatmap overlay still visible",
() => Game.ChildrenOfType<BeatmapSetOverlay>().SingleOrDefault()?.State.Value,
() => Is.EqualTo(Visibility.Visible));
AddStep("set game volume to max", () => Game.Dependencies.Get<FrameworkConfigManager>().SetValue(FrameworkSetting.VolumeUniversal, 1d));
AddStep("move to centre", () => InputManager.MoveMouseTo(Game));
AddStep("alt-scroll down", () =>
{
InputManager.PressKey(Key.AltLeft);
InputManager.ScrollVerticalBy(-1);
InputManager.ReleaseKey(Key.AltLeft);
});
AddUntilStep("wait for volume overlay to show", () => Game.ChildrenOfType<VolumeOverlay>().SingleOrDefault()?.State.Value, () => Is.EqualTo(Visibility.Visible));
AddStep("start dragging meter", () =>
{
InputManager.MoveMouseTo(Game.ChildrenOfType<VolumeMeter>().First().ChildrenOfType<OsuSpriteText>().First());
InputManager.PressButton(MouseButton.Left);
});
AddStep("drag away", () => InputManager.MoveMouseTo(Game.ChildrenOfType<VolumeMeter>().First().ChildrenOfType<OsuSpriteText>().First(), new Vector2(0, -100)));
AddStep("release mouse", () => InputManager.ReleaseButton(MouseButton.Left));
AddAssert("beatmap overlay still visible",
() => Game.ChildrenOfType<BeatmapSetOverlay>().SingleOrDefault()?.State.Value,
() => Is.EqualTo(Visibility.Visible));
}
private Func<Player> playToResults() private Func<Player> playToResults()
{ {
var player = playToCompletion(); var player = playToCompletion();

View File

@@ -0,0 +1,11 @@
// 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.
namespace osu.Game.Configuration
{
public enum WelcomeMusicMode
{
Default,
Custom
}
}

View File

@@ -1,13 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Framework.Input.Handlers.Tablet;
using osu.Framework.Layout; using osu.Framework.Layout;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Screens; using osu.Framework.Screens;
@@ -52,8 +50,6 @@ namespace osu.Game.Graphics.Containers
private RectangleF? customRect; private RectangleF? customRect;
private bool customRectIsRelativePosition; private bool customRectIsRelativePosition;
private ITabletHandler? tabletHandler;
/// <summary> /// <summary>
/// Set a custom position and scale which overrides any user specification. /// Set a custom position and scale which overrides any user specification.
/// </summary> /// </summary>
@@ -127,7 +123,7 @@ namespace osu.Game.Graphics.Containers
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(GameHost host, OsuConfigManager config, ISafeArea safeArea) private void load(OsuConfigManager config, ISafeArea safeArea)
{ {
scalingMode = config.GetBindable<ScalingMode>(OsuSetting.Scaling); scalingMode = config.GetBindable<ScalingMode>(OsuSetting.Scaling);
scalingMode.ValueChanged += _ => Scheduler.AddOnce(updateSize); scalingMode.ValueChanged += _ => Scheduler.AddOnce(updateSize);
@@ -152,8 +148,6 @@ namespace osu.Game.Graphics.Containers
scalingMenuBackgroundDim = config.GetBindable<float>(OsuSetting.ScalingBackgroundDim); scalingMenuBackgroundDim = config.GetBindable<float>(OsuSetting.ScalingBackgroundDim);
scalingMenuBackgroundDim.ValueChanged += _ => Scheduler.AddOnce(updateSize); scalingMenuBackgroundDim.ValueChanged += _ => Scheduler.AddOnce(updateSize);
tabletHandler = host.AvailableInputHandlers.OfType<ITabletHandler>().SingleOrDefault();
} }
protected override void LoadComplete() protected override void LoadComplete()
@@ -228,13 +222,6 @@ namespace osu.Game.Graphics.Containers
// An example of how this can occur is when the skin editor is visible and the game screen scaling is set to "Everything". // An example of how this can occur is when the skin editor is visible and the game screen scaling is set to "Everything".
sizableContainer.TransformTo(nameof(CornerRadius), requiresMasking ? corner_radius : 0, TRANSITION_DURATION, requiresMasking ? Easing.OutQuart : Easing.None) sizableContainer.TransformTo(nameof(CornerRadius), requiresMasking ? corner_radius : 0, TRANSITION_DURATION, requiresMasking ? Easing.OutQuart : Easing.None)
.OnComplete(_ => { sizableContainer.Masking = requiresMasking; }); .OnComplete(_ => { sizableContainer.Masking = requiresMasking; });
// when "everything" scaling mode is active, tablets are expected to constrain output area to the scaled size of the game
if (tabletHandler != null)
{
tabletHandler.OutputAreaSize.Value = scalingMode.Value == ScalingMode.Everything ? new Vector2(sizeX.Value, sizeY.Value) : Vector2.One;
tabletHandler.OutputAreaOffset.Value = scalingMode.Value == ScalingMode.Everything ? new Vector2(posX.Value, posY.Value) : new Vector2(0.5f);
}
} }
private partial class ScalingBackgroundScreen : BackgroundScreenDefault private partial class ScalingBackgroundScreen : BackgroundScreenDefault

View File

@@ -0,0 +1,12 @@
// 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 osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetMusicCategoriesRequest : APIRequest<APIBackgroundCategories>
{
protected override string Target => @"https://osu.jvnko.boats/welcome-music/categories";
}
}

View File

@@ -0,0 +1,21 @@
// 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.Collections.Generic;
using System.Net;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetWelcomeMusicRequest : APIRequest<List<APIWelcomeMusic>>
{
private readonly string category;
public GetWelcomeMusicRequest(string category)
{
this.category = category;
}
protected override string Target => $"https://osu.jvnko.boats/welcome-music/list?category={WebUtility.UrlEncode(category)}";
}
}

View File

@@ -0,0 +1,17 @@
// 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 Newtonsoft.Json;
namespace osu.Game.Online.API.Requests.Responses
{
// Описывает один трек, как он приходит с сервера
public class APIWelcomeMusic
{
[JsonProperty("name")]
public string? Name { get; set; }
[JsonProperty("url")]
public string? Url { get; set; }
}
}

View File

@@ -16,6 +16,7 @@ namespace osu.Game.Online.Multiplayer
/// <summary> /// <summary>
/// Request to leave the currently joined room. /// Request to leave the currently joined room.
/// </summary> /// </summary>
/// <exception cref="NotJoinedRoomException">If the user is not in a room.</exception>
Task LeaveRoom(); Task LeaveRoom();
/// <summary> /// <summary>

View File

@@ -319,6 +319,9 @@ namespace osu.Game.Online.Multiplayer
public Task LeaveRoom() public Task LeaveRoom()
{ {
if (Room == null)
return Task.CompletedTask;
// The join may have not completed yet, so certain tasks that either update the room or reference the room should be cancelled. // The join may have not completed yet, so certain tasks that either update the room or reference the room should be cancelled.
// This includes the setting of Room itself along with the initial update of the room settings on join. // This includes the setting of Room itself along with the initial update of the room settings on join.
joinCancellationSource?.Cancel(); joinCancellationSource?.Cancel();

View File

@@ -33,27 +33,7 @@ namespace osu.Game.Overlays.Chat
{ {
var request = new ChatReportRequest(message.Id, reason, comments); var request = new ChatReportRequest(message.Id, reason, comments);
request.Success += () => request.Success += () => channelManager.CurrentChannel.Value.AddNewMessages(new InfoMessage(UsersStrings.ReportThanks.ToString()));
{
string thanksMessage;
switch (channelManager.CurrentChannel.Value.Type)
{
case ChannelType.PM:
thanksMessage = """
Chat moderators have been alerted. You have reported a private message so they will not be able to read history to maintain your privacy. Please make sure to include as much details as you can.
You can submit a second report with more details if required, or contact abuse@ppy.sh if a user is being extremely offensive.
You can also block a user via the block button on their user profile, or by right-clicking on their name in the chat and selecting "Block".
""";
break;
default:
thanksMessage = @"Chat moderators have been alerted. Thanks for your help.";
break;
}
channelManager.CurrentChannel.Value.AddNewMessages(new InfoMessage(thanksMessage));
};
api.Queue(request); api.Queue(request);
} }

View File

@@ -61,15 +61,10 @@ namespace osu.Game.Overlays
audio.Samples.AddAdjustment(AdjustableProperty.Volume, audioVolume); audio.Samples.AddAdjustment(AdjustableProperty.Volume, audioVolume);
} }
protected void RemoveAudioAdjustments() protected override void Dispose(bool isDisposing)
{ {
audio?.Tracks.RemoveAdjustment(AdjustableProperty.Volume, audioVolume); audio?.Tracks.RemoveAdjustment(AdjustableProperty.Volume, audioVolume);
audio?.Samples.RemoveAdjustment(AdjustableProperty.Volume, audioVolume); audio?.Samples.RemoveAdjustment(AdjustableProperty.Volume, audioVolume);
}
protected override void Dispose(bool isDisposing)
{
RemoveAudioAdjustments();
base.Dispose(isDisposing); base.Dispose(isDisposing);
} }
} }

View File

@@ -228,7 +228,7 @@ namespace osu.Game.Overlays
private void onSeek(double progress) private void onSeek(double progress)
{ {
if (!musicController.IsPlaying || lastSeekTime == null || Time.Current - lastSeekTime > TRACK_DRAG_SEEK_DEBOUNCE) if (lastSeekTime == null || Time.Current - lastSeekTime > TRACK_DRAG_SEEK_DEBOUNCE)
{ {
musicController.SeekTo(progress); musicController.SeekTo(progress);
lastSeekTime = Time.Current; lastSeekTime = Time.Current;

View File

@@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Rankings
case RankingsScope.Performance: case RankingsScope.Performance:
case RankingsScope.Score: case RankingsScope.Score:
case RankingsScope.Country: case RankingsScope.Country:
case RankingsScope.Playlists: case RankingsScope.Spotlights:
return true; return true;
default: default:

View File

@@ -17,8 +17,8 @@ namespace osu.Game.Overlays.Rankings
[LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCountry))] [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCountry))]
Country, Country,
[LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypePlaylists))] [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCharts))]
Playlists, Spotlights,
[LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeKudosu))] [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeKudosu))]
Kudosu, Kudosu,

View File

@@ -52,7 +52,7 @@ namespace osu.Game.Overlays
ruleset.BindValueChanged(_ => ruleset.BindValueChanged(_ =>
{ {
if (Header.Current.Value == RankingsScope.Playlists) if (Header.Current.Value == RankingsScope.Spotlights)
return; return;
Scheduler.AddOnce(triggerTabChanged); Scheduler.AddOnce(triggerTabChanged);
@@ -99,7 +99,7 @@ namespace osu.Game.Overlays
{ {
lastRequest?.Cancel(); lastRequest?.Cancel();
if (Header.Current.Value == RankingsScope.Playlists) if (Header.Current.Value == RankingsScope.Spotlights)
{ {
LoadDisplay(new SpotlightsLayout LoadDisplay(new SpotlightsLayout
{ {

View File

@@ -13,7 +13,6 @@ using osu.Framework.Input.Handlers.Tablet;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Threading; using osu.Framework.Threading;
using osu.Game.Configuration;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
@@ -35,8 +34,6 @@ namespace osu.Game.Overlays.Settings.Sections.Input
private readonly Bindable<Vector2> areaOffset = new Bindable<Vector2>(); private readonly Bindable<Vector2> areaOffset = new Bindable<Vector2>();
private readonly Bindable<Vector2> areaSize = new Bindable<Vector2>(); private readonly Bindable<Vector2> areaSize = new Bindable<Vector2>();
private readonly Bindable<Vector2> outputAreaSize = new Bindable<Vector2>();
private readonly Bindable<Vector2> outputAreaOffset = new Bindable<Vector2>();
private readonly IBindable<TabletInfo> tablet = new Bindable<TabletInfo>(); private readonly IBindable<TabletInfo> tablet = new Bindable<TabletInfo>();
private readonly BindableNumber<float> offsetX = new BindableNumber<float> { MinValue = 0, Precision = 1 }; private readonly BindableNumber<float> offsetX = new BindableNumber<float> { MinValue = 0, Precision = 1 };
@@ -49,10 +46,6 @@ namespace osu.Game.Overlays.Settings.Sections.Input
private readonly BindableNumber<float> pressureThreshold = new BindableNumber<float> { MinValue = 0.0f, MaxValue = 1.0f, Precision = 0.005f }; private readonly BindableNumber<float> pressureThreshold = new BindableNumber<float> { MinValue = 0.0f, MaxValue = 1.0f, Precision = 0.005f };
private Bindable<ScalingMode> scalingMode = null!;
private Bindable<float> scalingSizeX = null!;
private Bindable<float> scalingSizeY = null!;
[Resolved] [Resolved]
private GameHost host { get; set; } private GameHost host { get; set; }
@@ -84,12 +77,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours, LocalisationManager localisation, OsuConfigManager osuConfig) private void load(OsuColour colours, LocalisationManager localisation)
{ {
scalingMode = osuConfig.GetBindable<ScalingMode>(OsuSetting.Scaling);
scalingSizeX = osuConfig.GetBindable<float>(OsuSetting.ScalingSizeX);
scalingSizeY = osuConfig.GetBindable<float>(OsuSetting.ScalingSizeY);
Children = new Drawable[] Children = new Drawable[]
{ {
new SettingsCheckbox new SettingsCheckbox
@@ -163,16 +152,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
Text = TabletSettingsStrings.ConformToCurrentGameAspectRatio, Text = TabletSettingsStrings.ConformToCurrentGameAspectRatio,
Action = () => Action = () =>
{ {
float gameplayWidth = host.Window.ClientSize.Width; forceAspectRatio((float)host.Window.ClientSize.Width / host.Window.ClientSize.Height);
float gameplayHeight = host.Window.ClientSize.Height;
if (scalingMode.Value == ScalingMode.Everything)
{
gameplayWidth *= scalingSizeX.Value;
gameplayHeight *= scalingSizeY.Value;
}
forceAspectRatio(gameplayWidth / gameplayHeight);
}, },
CanBeShown = { BindTarget = enabled } CanBeShown = { BindTarget = enabled }
}, },
@@ -269,9 +249,6 @@ namespace osu.Game.Overlays.Settings.Sections.Input
sizeY.Value = val.NewValue.Y; sizeY.Value = val.NewValue.Y;
}), true); }), true);
outputAreaSize.BindTo(tabletHandler.OutputAreaSize);
outputAreaOffset.BindTo(tabletHandler.OutputAreaOffset);
sizeX.BindValueChanged(val => sizeX.BindValueChanged(val =>
{ {
areaSize.Value = new Vector2(val.NewValue, areaSize.Value.Y); areaSize.Value = new Vector2(val.NewValue, areaSize.Value.Y);

View File

@@ -529,9 +529,7 @@ namespace osu.Game.Overlays.SkinEditor
} }
SelectedComponents.Add(component); SelectedComponents.Add(component);
SkinSelectionHandler.ApplyClosestAnchorOrigin(drawableComponent);
if (!component.UsesFixedAnchor)
SkinSelectionHandler.ApplyClosestAnchorOrigin(drawableComponent);
return true; return true;
} }

View File

@@ -318,8 +318,6 @@ namespace osu.Game.Overlays.Volume
private float dragDelta; private float dragDelta;
protected override bool OnMouseDown(MouseDownEvent e) => true; // handle to prevent drawables behind from potentially receiving the mouse down
protected override bool OnDragStart(DragStartEvent e) protected override bool OnDragStart(DragStartEvent e)
{ {
dragDelta = 0; dragDelta = 0;

View File

@@ -13,14 +13,12 @@ using osu.Game.Beatmaps;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Backgrounds;
using osu.Game.Screens.Edit;
using osu.Game.Storyboards.Drawables; using osu.Game.Storyboards.Drawables;
namespace osu.Game.Screens.Backgrounds namespace osu.Game.Screens.Backgrounds
{ {
public partial class EditorBackgroundScreen : BackgroundScreen public partial class EditorBackgroundScreen : BackgroundScreen
{ {
private readonly EditorBeatmap editorBeatmap;
private readonly Container dimContainer; private readonly Container dimContainer;
private CancellationTokenSource? cancellationTokenSource; private CancellationTokenSource? cancellationTokenSource;
@@ -38,9 +36,8 @@ namespace osu.Game.Screens.Backgrounds
[Resolved] [Resolved]
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!; private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
public EditorBackgroundScreen(EditorBeatmap editorBeatmap) public EditorBackgroundScreen()
{ {
this.editorBeatmap = editorBeatmap;
InternalChild = dimContainer = new Container InternalChild = dimContainer = new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@@ -61,11 +58,10 @@ namespace osu.Game.Screens.Backgrounds
private IEnumerable<Drawable> createContent() => private IEnumerable<Drawable> createContent() =>
[ [
new BeatmapBackground(beatmap.Value) { RelativeSizeAxes = Axes.Both, }, new BeatmapBackground(beatmap.Value) { RelativeSizeAxes = Axes.Both, },
// one reason for this kooky container nesting being here is that the storyboard needs a custom clock // this kooky container nesting is here because the storyboard needs a custom clock
// but also needs it on an isolated-enough level that doesn't break screen stack expiry logic (which happens if the clock was put on `this`), // but also needs it on an isolated-enough level that doesn't break screen stack expiry logic (which happens if the clock was put on `this`),
// or doesn't make it literally impossible to fade the storyboard in/out in real time (which happens if the fade transforms were to be applied directly to the storyboard). // or doesn't make it literally impossible to fade the storyboard in/out in real time (which happens if the fade transforms were to be applied directly to the storyboard).
// another is that we need `EditorSkinProvidingContainer` so that storyboard sample lookups succeed. new Container
new EditorSkinProvidingContainer(editorBeatmap)
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Child = new DrawableStoryboard(beatmap.Value.Storyboard) Child = new DrawableStoryboard(beatmap.Value.Storyboard)

View File

@@ -67,7 +67,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
double seekDestination = markerPos / DrawWidth * editorClock.TrackLength; double seekDestination = markerPos / DrawWidth * editorClock.TrackLength;
marker.X = (float)seekDestination; marker.X = (float)seekDestination;
if (editorClock.IsRunning && !instant && lastSeekTime != null && Time.Current - lastSeekTime < NowPlayingOverlay.TRACK_DRAG_SEEK_DEBOUNCE) if (!instant && lastSeekTime != null && Time.Current - lastSeekTime < NowPlayingOverlay.TRACK_DRAG_SEEK_DEBOUNCE)
return; return;
editorClock.SeekSmoothlyTo(seekDestination); editorClock.SeekSmoothlyTo(seekDestination);

View File

@@ -481,7 +481,7 @@ namespace osu.Game.Screens.Edit
[Resolved] [Resolved]
private MusicController musicController { get; set; } private MusicController musicController { get; set; }
protected override BackgroundScreen CreateBackground() => new EditorBackgroundScreen(editorBeatmap); protected override BackgroundScreen CreateBackground() => new EditorBackgroundScreen();
protected override void LoadComplete() protected override void LoadComplete()
{ {

View File

@@ -169,20 +169,6 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Queue
{ {
Text = "Searching for opponents..."; Text = "Searching for opponents...";
Activated = () =>
{
performer?.PerformFromScreen(s =>
{
if (s is ScreenIntro || s is ScreenQueue)
return;
s.Push(new ScreenIntro());
}, [typeof(ScreenIntro), typeof(ScreenQueue)]);
// Closed when appropriate by SearchInForeground().
return false;
};
CompletionClickAction = () => CompletionClickAction = () =>
{ {
client.MatchmakingAcceptInvitation().FireAndForget(); client.MatchmakingAcceptInvitation().FireAndForget();

View File

@@ -354,9 +354,37 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Queue
break; break;
case MatchmakingScreenState.PendingAccept: case MatchmakingScreenState.PendingAccept:
client.MatchmakingAcceptInvitation().FireAndForget(); mainContent.Child = new FillFlowContainer
SetState(MatchmakingScreenState.AcceptedWaitingForRoom); {
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(20),
Children = new Drawable[]
{
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "Found a match!",
Font = OsuFont.GetFont(size: 32, weight: FontWeight.Regular, typeface: Typeface.TorusAlternate),
},
new SelectionButton(200)
{
DarkerColour = colours.YellowDark,
LighterColour = colours.YellowLight,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Action = () =>
{
client.MatchmakingAcceptInvitation().FireAndForget();
SetState(MatchmakingScreenState.AcceptedWaitingForRoom);
},
Text = "Join match!",
}
}
};
matchFoundSample?.Play(); matchFoundSample?.Play();
musicController.DuckMomentarily(1250); musicController.DuckMomentarily(1250);
break; break;
@@ -375,7 +403,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Queue
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Text = "Waiting for opponents...", Text = "Waiting for all players...",
Font = OsuFont.GetFont(size: 32, weight: FontWeight.Light, typeface: Typeface.TorusAlternate), Font = OsuFont.GetFont(size: 32, weight: FontWeight.Light, typeface: Typeface.TorusAlternate),
}, },
new LoadingSpinner new LoadingSpinner

View File

@@ -90,15 +90,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
client.ChangeState(MultiplayerUserState.Idle).FireAndForget(); client.ChangeState(MultiplayerUserState.Idle).FireAndForget();
} }
public override bool OnExiting(ScreenExitEvent e)
{
if (base.OnExiting(e))
return true;
client.LeaveRoom().FireAndForget();
return false;
}
protected override string ScreenTitle => "Multiplayer"; protected override string ScreenTitle => "Multiplayer";
protected override LoungeSubScreen CreateLounge() => new MultiplayerLoungeSubScreen(); protected override LoungeSubScreen CreateLounge() => new MultiplayerLoungeSubScreen();

View File

@@ -42,11 +42,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{ {
} }
protected override OsuClickableContainer CreateButton(IBindable<bool> inSkipPeriod) => skipButton = new Button protected override OsuClickableContainer CreateButton() => skipButton = new Button
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
InSkipPeriod = { BindTarget = inSkipPeriod },
}; };
protected override void LoadComplete() protected override void LoadComplete()
@@ -120,9 +119,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
public readonly BindableInt SkippedCount = new BindableInt(); public readonly BindableInt SkippedCount = new BindableInt();
public readonly BindableInt RequiredCount = new BindableInt(); public readonly BindableInt RequiredCount = new BindableInt();
public readonly BindableBool InSkipPeriod = new BindableBool();
private readonly BindableBool clicked = new BindableBool();
[Resolved] [Resolved]
private OsuColour colours { get; set; } = null!; private OsuColour colours { get; set; } = null!;
@@ -205,17 +201,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
SkippedCount.BindValueChanged(_ => updateCount()); SkippedCount.BindValueChanged(_ => updateCount());
RequiredCount.BindValueChanged(_ => updateCount(), true); RequiredCount.BindValueChanged(_ => updateCount(), true);
InSkipPeriod.BindValueChanged(_ => updateEnabledState());
clicked.BindValueChanged(_ => updateEnabledState(), true);
Enabled.BindValueChanged(_ => updateColours(), true); Enabled.BindValueChanged(_ => updateColours(), true);
FinishTransforms(true); FinishTransforms(true);
} }
private void updateEnabledState() => Enabled.Value = InSkipPeriod.Value && !clicked.Value;
private void updateChevronsSpacing() private void updateChevronsSpacing()
{ {
if (SkippedCount.Value > 0 && RequiredCount.Value > 1) if (SkippedCount.Value > 0 && RequiredCount.Value > 1)
@@ -310,7 +300,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
base.OnClick(e); base.OnClick(e);
clicked.Value = true; Enabled.Value = false;
return true; return true;
} }

View File

@@ -18,7 +18,7 @@ namespace osu.Game.Screens.Play
{ {
public partial class FailOverlay : GameplayMenuOverlay public partial class FailOverlay : GameplayMenuOverlay
{ {
public Func<Task<ScoreInfo>>? SaveReplay { get; init; } public Func<Task<ScoreInfo>>? SaveReplay;
public override LocalisableString Header => GameplayMenuOverlayStrings.FailedHeader; public override LocalisableString Header => GameplayMenuOverlayStrings.FailedHeader;

View File

@@ -357,7 +357,7 @@ namespace osu.Game.Screens.Play.HUD
else if (Tracked) else if (Tracked)
{ {
widthExtension = true; widthExtension = true;
setPanelColour(BackgroundColour ?? colours.Orange2); setTrackedPanelColour(BackgroundColour);
} }
else if (isFriend) else if (isFriend)
{ {
@@ -380,6 +380,13 @@ namespace osu.Game.Screens.Play.HUD
scorePanel.BorderColour = ColourInfo.GradientVertical(baseColour.Opacity(0.2f), baseColour); scorePanel.BorderColour = ColourInfo.GradientVertical(baseColour.Opacity(0.2f), baseColour);
} }
private void setTrackedPanelColour(Color4? backgroundColour)
{
leftLayerGradient.Colour = ColourInfo.GradientVertical((backgroundColour ?? colours.Blue2).Opacity(0.3f), backgroundColour ?? colours.Blue2);
rightLayerGradient.Colour = ColourInfo.GradientVertical((backgroundColour ?? colours.Blue4).Opacity(0.25f), (backgroundColour ?? colours.Blue3).Opacity(0.6f));
scorePanel.BorderColour = ColourInfo.GradientVertical((backgroundColour ?? colours.Blue1).Opacity(0.2f), backgroundColour ?? colours.Blue1);
}
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();

View File

@@ -27,14 +27,5 @@ namespace osu.Game.Screens.Play
AbortConfirm(); AbortConfirm();
} }
protected override void Confirm()
{
base.Confirm();
// Not removing immediately can lead to delays due to async disposal.
// This is done here rather than in `Player` because it's simpler to handle.
RemoveAudioAdjustments();
}
} }
} }

View File

@@ -27,14 +27,5 @@ namespace osu.Game.Screens.Play
AbortConfirm(); AbortConfirm();
} }
protected override void Confirm()
{
base.Confirm();
// Not removing immediately can lead to delays due to async disposal.
// This is done here rather than in `Player` because it's simpler to handle.
RemoveAudioAdjustments();
}
} }
} }

View File

@@ -319,7 +319,7 @@ namespace osu.Game.Screens.Play
}, },
FailOverlay = new FailOverlay FailOverlay = new FailOverlay
{ {
SaveReplay = Configuration.AllowUserInteraction ? async () => await prepareAndImportScoreAsync(true).ConfigureAwait(false) : null, SaveReplay = async () => await prepareAndImportScoreAsync(true).ConfigureAwait(false),
OnRetry = Configuration.AllowUserInteraction ? () => Restart() : null, OnRetry = Configuration.AllowUserInteraction ? () => Restart() : null,
OnQuit = () => PerformExitWithConfirmation(), OnQuit = () => PerformExitWithConfirmation(),
}, },

View File

@@ -18,7 +18,6 @@ using osu.Game.Scoring;
using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Screens.Play.PlayerSettings;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;
using osu.Game.Screens.Select.Leaderboards; using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Skinning;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Screens.Play namespace osu.Game.Screens.Play
@@ -101,18 +100,15 @@ namespace osu.Game.Screens.Play
playbackSettings.UserPlaybackRate.BindTo(master.UserPlaybackRate); playbackSettings.UserPlaybackRate.BindTo(master.UserPlaybackRate);
HUDOverlay.PlayerSettingsOverlay.AddAtStart(playbackSettings); HUDOverlay.PlayerSettingsOverlay.AddAtStart(playbackSettings);
AddInternal(new RulesetSkinProvidingContainer(GameplayState.Ruleset, GameplayState.Beatmap, Beatmap.Value.Skin) AddInternal(failIndicator = new ReplayFailIndicator(GameplayClockContainer)
{ {
Child = failIndicator = new ReplayFailIndicator(GameplayClockContainer) GoToResults = () =>
{ {
GoToResults = () => if (!this.IsCurrentScreen())
{ return;
if (!this.IsCurrentScreen())
return;
ValidForResume = false; ValidForResume = false;
this.Push(new SoloResultsScreen(Score.ScoreInfo)); this.Push(new SoloResultsScreen(Score.ScoreInfo));
}
} }
}); });
} }

View File

@@ -96,17 +96,8 @@ namespace osu.Game.Screens.Play
break; break;
default: default:
if (importFailedScore != null) button.TooltipText = @"save score";
{ button.Enabled.Value = true;
button.TooltipText = @"save score";
button.Enabled.Value = true;
}
else
{
button.TooltipText = @"replay unavailable";
button.Enabled.Value = false;
}
break; break;
} }
}, true); }, true);

View File

@@ -10,7 +10,6 @@ using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Colour;
@@ -53,9 +52,9 @@ namespace osu.Game.Screens.Play
private double displayTime; private double displayTime;
/// <summary> /// <summary>
/// Whether the gameplay clock is currently at the skippable period. /// Becomes <see langword="false"/> when the overlay starts fading out.
/// </summary> /// </summary>
private readonly BindableBool inSkipPeriod = new BindableBool(); private bool isClickable;
private bool skipQueued; private bool skipQueued;
@@ -93,7 +92,7 @@ namespace osu.Game.Screens.Play
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Children = new Drawable[] Children = new Drawable[]
{ {
button = CreateButton(inSkipPeriod), button = CreateButton(),
RemainingTimeBox = new Circle RemainingTimeBox = new Circle
{ {
Height = 5, Height = 5,
@@ -107,15 +106,10 @@ namespace osu.Game.Screens.Play
}; };
} }
/// <summary> protected virtual OsuClickableContainer CreateButton() => new Button
/// Creates a skip button.
/// </summary>
/// <param name="inSkipPeriod">Whether the gameplay clock is currently at the skippable period.</param>
protected virtual OsuClickableContainer CreateButton(IBindable<bool> inSkipPeriod) => new Button
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Enabled = { BindTarget = inSkipPeriod },
}; };
private const double fade_time = 300; private const double fade_time = 300;
@@ -193,13 +187,17 @@ namespace osu.Game.Screens.Play
RemainingTimeBox.Width = (float)Interpolation.Lerp(RemainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1)); RemainingTimeBox.Width = (float)Interpolation.Lerp(RemainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1));
inSkipPeriod.Value = progress > 0; isClickable = progress > 0;
buttonContainer.State.Value = inSkipPeriod.Value ? Visibility.Visible : Visibility.Hidden;
if (!isClickable)
button.Enabled.Value = false;
buttonContainer.State.Value = isClickable ? Visibility.Visible : Visibility.Hidden;
} }
protected override bool OnMouseMove(MouseMoveEvent e) protected override bool OnMouseMove(MouseMoveEvent e)
{ {
if (inSkipPeriod.Value && !e.HasAnyButtonPressed) if (isClickable && !e.HasAnyButtonPressed)
FadingContent.TriggerShow(); FadingContent.TriggerShow();
return base.OnMouseMove(e); return base.OnMouseMove(e);

View File

@@ -407,27 +407,15 @@ namespace osu.Game.Screens.SelectV2
private LeaderboardState displayedState; private LeaderboardState displayedState;
private ScheduledDelegate? loadingShowDelegate;
protected void SetState(LeaderboardState state) protected void SetState(LeaderboardState state)
{ {
if (state == displayedState) if (state == displayedState)
return; return;
if (state == LeaderboardState.Retrieving) if (state == LeaderboardState.Retrieving)
{ loading.Show();
// Slight delay so this doesn't display for a few silly frames for local score retrievals.
loadingShowDelegate ??= Scheduler.AddDelayed(() => loading.Show(), 200);
}
else else
{
loadingShowDelegate?.Cancel();
loadingShowDelegate = null;
loading.Hide(); loading.Hide();
}
loading.Hide();
displayedState = state; displayedState = state;

View File

@@ -128,9 +128,6 @@ namespace osu.Game.Skinning
if (spectatorList != null) if (spectatorList != null)
spectatorList.Position = pos; spectatorList.Position = pos;
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@@ -241,9 +238,6 @@ namespace osu.Game.Skinning
keyCounter.Position = new Vector2(-(hitError.Width + padding), -(padding * 2 + song_progress_offset_height)); keyCounter.Position = new Vector2(-(hitError.Width + padding), -(padding * 2 + song_progress_offset_height));
} }
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
} }
}) })
{ {

View File

@@ -412,9 +412,6 @@ namespace osu.Game.Skinning
leaderboard.Origin = Anchor.CentreLeft; leaderboard.Origin = Anchor.CentreLeft;
leaderboard.X = 10; leaderboard.X = 10;
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
new LegacyDefaultComboCounter(), new LegacyDefaultComboCounter(),
@@ -451,9 +448,6 @@ namespace osu.Game.Skinning
hitError.Origin = Anchor.CentreLeft; hitError.Origin = Anchor.CentreLeft;
hitError.Rotation = -90; hitError.Rotation = -90;
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
Children = new Drawable[] Children = new Drawable[]

View File

@@ -14,11 +14,6 @@ namespace osu.Game.Skinning
{ {
public sealed partial class LegacySpriteText : OsuSpriteText public sealed partial class LegacySpriteText : OsuSpriteText
{ {
/// <summary>
/// The Private Use Area character for internally representing the "pp" suffix for performance counters.
/// </summary>
public const char PP_SUFFIX_CHAR = '\uebd9';
public Vector2? MaxSizePerGlyph { get; init; } public Vector2? MaxSizePerGlyph { get; init; }
public bool FixedWidth { get; init; } public bool FixedWidth { get; init; }
@@ -28,7 +23,7 @@ namespace osu.Game.Skinning
protected override char FixedWidthReferenceCharacter => '5'; protected override char FixedWidthReferenceCharacter => '5';
protected override char[] FixedWidthExcludeCharacters => new[] { ',', '.', '%', 'x', PP_SUFFIX_CHAR }; protected override char[] FixedWidthExcludeCharacters => new[] { ',', '.', '%', 'x' };
// ReSharper disable once UnusedMember.Global // ReSharper disable once UnusedMember.Global
// being unused is the point here // being unused is the point here
@@ -121,9 +116,6 @@ namespace osu.Game.Skinning
case '%': case '%':
return "percent"; return "percent";
case PP_SUFFIX_CHAR:
return "pp";
default: default:
return character.ToString(); return character.ToString();
} }

View File

@@ -106,9 +106,6 @@ namespace osu.Game.Skinning
spectatorList.Origin = Anchor.BottomLeft; spectatorList.Origin = Anchor.BottomLeft;
spectatorList.Position = new Vector2(screen_edge_padding, -(song_progress_offset_height + screen_edge_padding)); spectatorList.Position = new Vector2(screen_edge_padding, -(song_progress_offset_height + screen_edge_padding));
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@@ -181,9 +178,6 @@ namespace osu.Game.Skinning
keyCounter.Origin = Anchor.BottomRight; keyCounter.Origin = Anchor.BottomRight;
keyCounter.Position = new Vector2(-screen_edge_padding, -(song_progress_offset_height + screen_edge_padding)); keyCounter.Position = new Vector2(-screen_edge_padding, -(song_progress_offset_height + screen_edge_padding));
} }
foreach (var d in container.OfType<ISerialisableDrawable>())
d.UsesFixedAnchor = true;
}) })
{ {
Children = new Drawable[] Children = new Drawable[]

View File

@@ -89,21 +89,6 @@ namespace osu.Game.Storyboards.Drawables
LifetimeEnd = animation.EndTimeForDisplay; LifetimeEnd = animation.EndTimeForDisplay;
} }
protected override void Update()
{
base.Update();
// In stable, alpha transforms exceeding values of 1 would result in sprites disappearing from view.
// See https://github.com/peppy/osu-stable-reference/blob/08e3dafd525934cf48880b08e91c24ce4ad8b761/osu!/Graphics/Sprites/pSprite.cs#L413-L414
//
// Over the years, storyboard(ers) have taken advantage of this to create "flicker" patterns.
// This is quite a common technique, so we are reproducing it here for now.
//
// NOTE TO FUTURE VISTIORS: If we do ever update the storyboard spec, we may want to move such flicker effects to their
// own transform type, and make this a legacy behaviour. It feels very flimsy.
if (Alpha > 1) Alpha %= 1;
}
[Resolved] [Resolved]
private ISkinSource skin { get; set; } private ISkinSource skin { get; set; }

View File

@@ -74,21 +74,6 @@ namespace osu.Game.Storyboards.Drawables
public override bool IsPresent public override bool IsPresent
=> !float.IsNaN(DrawPosition.X) && !float.IsNaN(DrawPosition.Y) && base.IsPresent; => !float.IsNaN(DrawPosition.X) && !float.IsNaN(DrawPosition.Y) && base.IsPresent;
protected override void Update()
{
base.Update();
// In stable, alpha transforms exceeding values of 1 would result in sprites disappearing from view.
// See https://github.com/peppy/osu-stable-reference/blob/08e3dafd525934cf48880b08e91c24ce4ad8b761/osu!/Graphics/Sprites/pSprite.cs#L413-L414
//
// Over the years, storyboard(ers) have taken advantage of this to create "flicker" patterns.
// This is quite a common technique, so we are reproducing it here for now.
//
// NOTE TO FUTURE VISITORS: If we do ever update the storyboard spec, we may want to move such flicker effects to their
// own transform type, and make this a legacy behaviour. It feels very flimsy.
if (Alpha > 1) Alpha %= 1;
}
[Resolved] [Resolved]
private ISkinSource skin { get; set; } = null!; private ISkinSource skin { get; set; } = null!;

View File

@@ -30,7 +30,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.2" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.2" />
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.1.2" /> <PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="ppy.LocalisationAnalyser" Version="2025.1208.0"> <PackageReference Include="ppy.LocalisationAnalyser" Version="2024.802.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>