1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 08:27:49 +08:00

Merge branch 'master' into c-sharp-10

This commit is contained in:
Dean Herbert 2022-06-24 21:22:33 +09:00
commit 30eebf3511
38 changed files with 130 additions and 303 deletions

View File

@ -17,3 +17,5 @@ M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Collections.Gen
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks.
M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever.
M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.

View File

@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Catch
protected override string RulesetPrefix => "catch"; // todo: use CatchRuleset.SHORT_NAME;
protected override string ComponentName => Component.ToString().ToLower();
protected override string ComponentName => Component.ToString().ToLowerInvariant();
}
}

View File

@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania
protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME;
protected override string ComponentName => Component.ToString().ToLower();
protected override string ComponentName => Component.ToString().ToLowerInvariant();
}
public enum ManiaSkinComponents

View File

@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Osu
protected override string RulesetPrefix => OsuRuleset.SHORT_NAME;
protected override string ComponentName => Component.ToString().ToLower();
protected override string ComponentName => Component.ToString().ToLowerInvariant();
}
}

View File

@ -144,7 +144,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
createDrawableRuleset();
assertStateAfterResult(new JudgementResult(new Swell(), new TaikoSwellJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Clear);
AddUntilStep($"state reverts to {expectedStateAfterClear.ToString().ToLower()}", () => allMascotsIn(expectedStateAfterClear));
AddUntilStep($"state reverts to {expectedStateAfterClear.ToString().ToLowerInvariant()}", () => allMascotsIn(expectedStateAfterClear));
}
private void setBeatmap(bool kiai = false)
@ -195,7 +195,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
{
TaikoMascotAnimationState[] mascotStates = null;
AddStep($"{judgementResult.Type.ToString().ToLower()} result for {judgementResult.Judgement.GetType().Name.Humanize(LetterCasing.LowerCase)}",
AddStep($"{judgementResult.Type.ToString().ToLowerInvariant()} result for {judgementResult.Judgement.GetType().Name.Humanize(LetterCasing.LowerCase)}",
() =>
{
applyNewResult(judgementResult);
@ -204,7 +204,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
Schedule(() => mascotStates = animatedMascots.Select(mascot => mascot.State.Value).ToArray());
});
AddAssert($"state is {expectedState.ToString().ToLower()}", () => mascotStates.All(state => state == expectedState));
AddAssert($"state is {expectedState.ToString().ToLowerInvariant()}", () => mascotStates.All(state => state == expectedState));
}
private void applyNewResult(JudgementResult judgementResult)

View File

@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Taiko
protected override string RulesetPrefix => TaikoRuleset.SHORT_NAME;
protected override string ComponentName => Component.ToString().ToLower();
protected override string ComponentName => Component.ToString().ToLowerInvariant();
}
}

View File

@ -139,10 +139,10 @@ namespace osu.Game.Rulesets.Taiko.UI
private static Texture getAnimationFrame(ISkin skin, TaikoMascotAnimationState state, int frameIndex)
{
var texture = skin.GetTexture($"pippidon{state.ToString().ToLower()}{frameIndex}");
var texture = skin.GetTexture($"pippidon{state.ToString().ToLowerInvariant()}{frameIndex}");
if (frameIndex == 0 && texture == null)
texture = skin.GetTexture($"pippidon{state.ToString().ToLower()}");
texture = skin.GetTexture($"pippidon{state.ToString().ToLowerInvariant()}");
return texture;
}

View File

@ -192,7 +192,7 @@ namespace osu.Game.Tests.Gameplay
AddStep("apply perfect hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = HitResult.Perfect }));
AddAssert("not failed", () => !processor.HasFailed);
AddStep($"apply {resultApplied.ToString().ToLower()} hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = resultApplied }));
AddStep($"apply {resultApplied.ToString().ToLowerInvariant()} hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = resultApplied }));
AddAssert("failed", () => processor.HasFailed);
}

View File

@ -254,7 +254,7 @@ namespace osu.Game.Tests.NonVisual
Assert.That(File.Exists(Path.Combine(customPath, OsuGameBase.CLIENT_DATABASE_FILENAME)));
Directory.CreateDirectory(customPath2);
File.Copy(Path.Combine(customPath, OsuGameBase.CLIENT_DATABASE_FILENAME), Path.Combine(customPath2, OsuGameBase.CLIENT_DATABASE_FILENAME));
File.WriteAllText(Path.Combine(customPath2, OsuGameBase.CLIENT_DATABASE_FILENAME), "I am a text");
// Fails because file already exists.
Assert.Throws<ArgumentException>(() => osu.Migrate(customPath2));

View File

@ -872,10 +872,10 @@ namespace osu.Game.Tests.Visual.SongSelect
return set != null;
});
FilterableGroupedDifficultyIcon groupIcon = null;
GroupedDifficultyIcon groupIcon = null;
AddUntilStep("Find group icon for different ruleset", () =>
{
return (groupIcon = set.ChildrenOfType<FilterableGroupedDifficultyIcon>()
return (groupIcon = set.ChildrenOfType<GroupedDifficultyIcon>()
.FirstOrDefault(icon => icon.Items.First().BeatmapInfo.Ruleset.OnlineID == 3)) != null;
});

View File

@ -66,14 +66,14 @@ namespace osu.Game.Tournament.Models
{
// use a sane default flag name based on acronym.
if (val.OldValue.StartsWith(FlagName.Value, StringComparison.InvariantCultureIgnoreCase))
FlagName.Value = val.NewValue.Length >= 2 ? val.NewValue?.Substring(0, 2).ToUpper() : string.Empty;
FlagName.Value = val.NewValue.Length >= 2 ? val.NewValue?.Substring(0, 2).ToUpperInvariant() : string.Empty;
};
FullName.ValueChanged += val =>
{
// use a sane acronym based on full name.
if (val.OldValue.StartsWith(Acronym.Value, StringComparison.InvariantCultureIgnoreCase))
Acronym.Value = val.NewValue.Length >= 3 ? val.NewValue?.Substring(0, 3).ToUpper() : string.Empty;
Acronym.Value = val.NewValue.Length >= 3 ? val.NewValue?.Substring(0, 3).ToUpperInvariant() : string.Empty;
};
}

View File

@ -49,10 +49,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
};
name = round.Name.GetBoundCopy();
name.BindValueChanged(n => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpper(), true);
name.BindValueChanged(n => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpperInvariant(), true);
description = round.Description.GetBoundCopy();
description.BindValueChanged(n => textDescription.Text = round.Description.Value?.ToUpper(), true);
description.BindValueChanged(n => textDescription.Text = round.Description.Value?.ToUpperInvariant(), true);
}
}
}

View File

@ -198,7 +198,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro
{
row.Add(new Sprite
{
Texture = textures.Get($"Mods/{mods.ToLower()}"),
Texture = textures.Get($"Mods/{mods.ToLowerInvariant()}"),
Scale = new Vector2(0.5f)
});
}

View File

@ -64,13 +64,13 @@ namespace osu.Game.Beatmaps
{
base.LoadComplete();
currentRuleset.BindValueChanged(_ => updateTrackedBindables());
currentRuleset.BindValueChanged(_ => Scheduler.AddOnce(updateTrackedBindables));
currentMods.BindValueChanged(mods =>
{
modSettingChangeTracker?.Dispose();
updateTrackedBindables();
Scheduler.AddOnce(updateTrackedBindables);
modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue);
modSettingChangeTracker.SettingChanged += _ =>
@ -89,7 +89,9 @@ namespace osu.Game.Beatmaps
/// <returns>A bindable that is updated to contain the star difficulty when it becomes available. Will be null while in an initial calculating state (but not during updates to ruleset and mods if a stale value is already propagated).</returns>
public IBindable<StarDifficulty?> GetBindableDifficulty(IBeatmapInfo beatmapInfo, CancellationToken cancellationToken = default)
{
var bindable = createBindable(beatmapInfo, currentRuleset.Value, currentMods.Value, cancellationToken);
var bindable = new BindableStarDifficulty(beatmapInfo, cancellationToken);
updateBindable(bindable, currentRuleset.Value, currentMods.Value, cancellationToken);
lock (bindableUpdateLock)
trackedBindables.Add(bindable);
@ -97,21 +99,6 @@ namespace osu.Game.Beatmaps
return bindable;
}
/// <summary>
/// Retrieves a bindable containing the star difficulty of a <see cref="IBeatmapInfo"/> with a given <see cref="RulesetInfo"/> and <see cref="Mod"/> combination.
/// </summary>
/// <remarks>
/// The bindable will not update to follow the currently-selected ruleset and mods or its settings.
/// </remarks>
/// <param name="beatmapInfo">The <see cref="IBeatmapInfo"/> to get the difficulty of.</param>
/// <param name="rulesetInfo">The <see cref="IRulesetInfo"/> to get the difficulty with. If <c>null</c>, the <paramref name="beatmapInfo"/>'s ruleset is used.</param>
/// <param name="mods">The <see cref="Mod"/>s to get the difficulty with. If <c>null</c>, no mods will be assumed.</param>
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> which stops updating the star difficulty for the given <see cref="IBeatmapInfo"/>.</param>
/// <returns>A bindable that is updated to contain the star difficulty when it becomes available. Will be null while in an initial calculating state.</returns>
public IBindable<StarDifficulty?> GetBindableDifficulty(IBeatmapInfo beatmapInfo, IRulesetInfo? rulesetInfo, IEnumerable<Mod>? mods,
CancellationToken cancellationToken = default)
=> createBindable(beatmapInfo, rulesetInfo, mods, cancellationToken);
/// <summary>
/// Retrieves the difficulty of a <see cref="IBeatmapInfo"/>.
/// </summary>
@ -200,22 +187,6 @@ namespace osu.Game.Beatmaps
}
}
/// <summary>
/// Creates a new <see cref="BindableStarDifficulty"/> and triggers an initial value update.
/// </summary>
/// <param name="beatmapInfo">The <see cref="IBeatmapInfo"/> that star difficulty should correspond to.</param>
/// <param name="initialRulesetInfo">The initial <see cref="IRulesetInfo"/> to get the difficulty with.</param>
/// <param name="initialMods">The initial <see cref="Mod"/>s to get the difficulty with.</param>
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> which stops updating the star difficulty for the given <see cref="IBeatmapInfo"/>.</param>
/// <returns>The <see cref="BindableStarDifficulty"/>.</returns>
private BindableStarDifficulty createBindable(IBeatmapInfo beatmapInfo, IRulesetInfo? initialRulesetInfo, IEnumerable<Mod>? initialMods,
CancellationToken cancellationToken)
{
var bindable = new BindableStarDifficulty(beatmapInfo, cancellationToken);
updateBindable(bindable, initialRulesetInfo, initialMods, cancellationToken);
return bindable;
}
/// <summary>
/// Updates the value of a <see cref="BindableStarDifficulty"/> with a given ruleset + mods.
/// </summary>

View File

@ -418,22 +418,24 @@ namespace osu.Game.Beatmaps
#region Implementation of IWorkingBeatmapCache
public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo? importedBeatmap)
public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo? beatmapInfo)
{
// Detached sets don't come with files.
// If we seem to be missing files, now is a good time to re-fetch.
if (importedBeatmap?.BeatmapSet?.Files.Count == 0)
if (beatmapInfo?.IsManaged == true || beatmapInfo?.BeatmapSet?.Files.Count == 0)
{
Realm.Run(r =>
{
var refetch = r.Find<BeatmapInfo>(importedBeatmap.ID)?.Detach();
var refetch = r.Find<BeatmapInfo>(beatmapInfo.ID)?.Detach();
if (refetch != null)
importedBeatmap = refetch;
beatmapInfo = refetch;
});
}
return workingBeatmapCache.GetWorkingBeatmap(importedBeatmap);
Debug.Assert(beatmapInfo?.IsManaged != true);
return workingBeatmapCache.GetWorkingBeatmap(beatmapInfo);
}
void IWorkingBeatmapCache.Invalidate(BeatmapSetInfo beatmapSetInfo) => workingBeatmapCache.Invalidate(beatmapSetInfo);

View File

@ -64,7 +64,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
};
favouriteRequest.Failure += e =>
{
Logger.Error(e, $"Failed to {actionType.ToString().ToLower()} beatmap: {e.Message}");
Logger.Error(e, $"Failed to {actionType.ToString().ToLowerInvariant()} beatmap: {e.Message}");
Enabled.Value = true;
};

View File

@ -1,12 +1,6 @@
// 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.
#nullable disable
using System;
using System.Collections.Generic;
using System.Threading;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
@ -16,19 +10,17 @@ using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Beatmaps.Drawables
{
public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip<DifficultyIconTooltipContent>
public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip<DifficultyIconTooltipContent>, IHasCurrentValue<StarDifficulty>
{
private readonly Container iconContainer;
/// <summary>
/// Size of this difficulty icon.
/// </summary>
@ -38,57 +30,53 @@ namespace osu.Game.Beatmaps.Drawables
set => iconContainer.Size = value;
}
[NotNull]
private readonly IBeatmapInfo beatmapInfo;
/// <summary>
/// Whether to display a tooltip on hover. Only works if a beatmap was provided at construction time.
/// </summary>
public bool ShowTooltip { get; set; } = true;
private readonly IBeatmapInfo? beatmap;
[CanBeNull]
private readonly IRulesetInfo ruleset;
[CanBeNull]
private readonly IReadOnlyList<Mod> mods;
private Drawable background = null!;
private readonly bool shouldShowTooltip;
private readonly Container iconContainer;
private readonly bool performBackgroundDifficultyLookup;
private readonly BindableWithCurrent<StarDifficulty> difficulty = new BindableWithCurrent<StarDifficulty>();
private readonly Bindable<StarDifficulty> difficultyBindable = new Bindable<StarDifficulty>();
private Drawable background;
/// <summary>
/// Creates a new <see cref="DifficultyIcon"/> with a given <see cref="RulesetInfo"/> and <see cref="Mod"/> combination.
/// </summary>
/// <param name="beatmapInfo">The beatmap to show the difficulty of.</param>
/// <param name="ruleset">The ruleset to show the difficulty with.</param>
/// <param name="mods">The mods to show the difficulty with.</param>
/// <param name="shouldShowTooltip">Whether to display a tooltip when hovered.</param>
/// <param name="performBackgroundDifficultyLookup">Whether to perform difficulty lookup (including calculation if necessary).</param>
public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, [CanBeNull] IRulesetInfo ruleset, [CanBeNull] IReadOnlyList<Mod> mods, bool shouldShowTooltip = true, bool performBackgroundDifficultyLookup = true)
: this(beatmapInfo, shouldShowTooltip, performBackgroundDifficultyLookup)
public virtual Bindable<StarDifficulty> Current
{
this.ruleset = ruleset ?? beatmapInfo.Ruleset;
this.mods = mods ?? Array.Empty<Mod>();
}
/// <summary>
/// Creates a new <see cref="DifficultyIcon"/> that follows the currently-selected ruleset and mods.
/// </summary>
/// <param name="beatmapInfo">The beatmap to show the difficulty of.</param>
/// <param name="shouldShowTooltip">Whether to display a tooltip when hovered.</param>
/// <param name="performBackgroundDifficultyLookup">Whether to perform difficulty lookup (including calculation if necessary).</param>
public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, bool shouldShowTooltip = true, bool performBackgroundDifficultyLookup = true)
{
this.beatmapInfo = beatmapInfo ?? throw new ArgumentNullException(nameof(beatmapInfo));
this.shouldShowTooltip = shouldShowTooltip;
this.performBackgroundDifficultyLookup = performBackgroundDifficultyLookup;
AutoSizeAxes = Axes.Both;
InternalChild = iconContainer = new Container { Size = new Vector2(20f) };
get => difficulty.Current;
set => difficulty.Current = value;
}
[Resolved]
private IRulesetStore rulesets { get; set; }
private IRulesetStore rulesets { get; set; } = null!;
/// <summary>
/// Creates a new <see cref="DifficultyIcon"/>. Will use provided beatmap's <see cref="BeatmapInfo.StarRating"/> for initial value.
/// </summary>
/// <param name="beatmap">The beatmap to be displayed in the tooltip, and to be used for the initial star rating value.</param>
/// <param name="ruleset">An optional ruleset to be used for the icon display, in place of the beatmap's ruleset.</param>
public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null)
: this(ruleset ?? beatmap.Ruleset)
{
this.beatmap = beatmap;
Current.Value = new StarDifficulty(beatmap.StarRating, 0);
}
/// <summary>
/// Creates a new <see cref="DifficultyIcon"/> without an associated beatmap.
/// </summary>
/// <param name="ruleset">The ruleset to be used for the icon display.</param>
public DifficultyIcon(IRulesetInfo ruleset)
{
this.ruleset = ruleset;
AutoSizeAxes = Axes.Both;
InternalChild = iconContainer = new Container { Size = new Vector2(20f) };
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
@ -111,7 +99,6 @@ namespace osu.Game.Beatmaps.Drawables
Child = background = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colours.ForStarDifficulty(beatmapInfo.StarRating) // Default value that will be re-populated once difficulty calculation completes
},
},
new ConstrainedIconContainer
@ -124,17 +111,12 @@ namespace osu.Game.Beatmaps.Drawables
},
};
if (performBackgroundDifficultyLookup)
iconContainer.Add(new DelayedLoadUnloadWrapper(() => new DifficultyRetriever(beatmapInfo, ruleset, mods) { StarDifficulty = { BindTarget = difficultyBindable } }, 0));
else
difficultyBindable.Value = new StarDifficulty(beatmapInfo.StarRating, 0);
difficultyBindable.BindValueChanged(difficulty => background.Colour = colours.ForStarDifficulty(difficulty.NewValue.Stars));
Current.BindValueChanged(difficulty => background.Colour = colours.ForStarDifficulty(difficulty.NewValue.Stars), true);
}
private Drawable getRulesetIcon()
{
int? onlineID = (ruleset ?? beatmapInfo.Ruleset).OnlineID;
int? onlineID = ruleset.OnlineID;
if (onlineID >= 0 && rulesets.GetRuleset(onlineID.Value)?.CreateInstance() is Ruleset rulesetInstance)
return rulesetInstance.CreateIcon();
@ -142,51 +124,10 @@ namespace osu.Game.Beatmaps.Drawables
return new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle };
}
ITooltip<DifficultyIconTooltipContent> IHasCustomTooltip<DifficultyIconTooltipContent>.GetCustomTooltip() => new DifficultyIconTooltip();
ITooltip<DifficultyIconTooltipContent> IHasCustomTooltip<DifficultyIconTooltipContent>.
GetCustomTooltip() => new DifficultyIconTooltip();
DifficultyIconTooltipContent IHasCustomTooltip<DifficultyIconTooltipContent>.TooltipContent => shouldShowTooltip ? new DifficultyIconTooltipContent(beatmapInfo, difficultyBindable) : null;
private class DifficultyRetriever : Component
{
public readonly Bindable<StarDifficulty> StarDifficulty = new Bindable<StarDifficulty>();
private readonly IBeatmapInfo beatmapInfo;
private readonly IRulesetInfo ruleset;
private readonly IReadOnlyList<Mod> mods;
private CancellationTokenSource difficultyCancellation;
[Resolved]
private BeatmapDifficultyCache difficultyCache { get; set; }
public DifficultyRetriever(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset, IReadOnlyList<Mod> mods)
{
this.beatmapInfo = beatmapInfo;
this.ruleset = ruleset;
this.mods = mods;
}
private IBindable<StarDifficulty?> localStarDifficulty;
[BackgroundDependencyLoader]
private void load()
{
difficultyCancellation = new CancellationTokenSource();
localStarDifficulty = ruleset != null
? difficultyCache.GetBindableDifficulty(beatmapInfo, ruleset, mods, difficultyCancellation.Token)
: difficultyCache.GetBindableDifficulty(beatmapInfo, difficultyCancellation.Token);
localStarDifficulty.BindValueChanged(d =>
{
if (d.NewValue is StarDifficulty diff)
StarDifficulty.Value = diff;
});
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
difficultyCancellation?.Cancel();
}
}
DifficultyIconTooltipContent IHasCustomTooltip<DifficultyIconTooltipContent>.
TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current) : null)!;
}
}

View File

@ -1,39 +0,0 @@
// 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.
#nullable disable
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets;
using osuTK.Graphics;
namespace osu.Game.Beatmaps.Drawables
{
/// <summary>
/// A difficulty icon that contains a counter on the right-side of it.
/// </summary>
/// <remarks>
/// Used in cases when there are too many difficulty icons to show.
/// </remarks>
public class GroupedDifficultyIcon : DifficultyIcon
{
public GroupedDifficultyIcon(IEnumerable<IBeatmapInfo> beatmaps, IRulesetInfo ruleset, Color4 counterColour)
: base(beatmaps.OrderBy(b => b.StarRating).Last(), ruleset, null, false)
{
AddInternal(new OsuSpriteText
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Padding = new MarginPadding { Left = Size.X },
Margin = new MarginPadding { Left = 2, Right = 5 },
Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold),
Text = beatmaps.Count().ToString(),
Colour = counterColour,
});
}
}
}

View File

@ -26,7 +26,7 @@ namespace osu.Game.Database
/// <summary>
/// A user displayable name for the model type associated with this manager.
/// </summary>
string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLower()}";
string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLowerInvariant()}";
/// <summary>
/// Fired when the user requests to view the resulting import.

View File

@ -201,6 +201,6 @@ namespace osu.Game.Database
public Action<Notification>? PostNotification { get; set; }
public virtual string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLower()}";
public virtual string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLowerInvariant()}";
}
}

View File

@ -549,6 +549,6 @@ namespace osu.Game.Database
yield return f.Filename;
}
public virtual string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLower()}";
public virtual string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLowerInvariant()}";
}
}

View File

@ -26,7 +26,7 @@ namespace osu.Game.Online.API.Requests
var req = base.CreateWebRequest();
req.AddParameter("spotlight", spotlight.ToString());
req.AddParameter("filter", sort.ToString().ToLower());
req.AddParameter("filter", sort.ToString().ToLowerInvariant());
return req;
}

View File

@ -45,7 +45,7 @@ namespace osu.Game.Online.API.Requests
Ruleset = ruleset;
}
protected override string Target => Lookup != null ? $@"users/{Lookup}/{Ruleset?.ShortName}?key={lookupType.ToString().ToLower()}" : $@"me/{Ruleset?.ShortName}";
protected override string Target => Lookup != null ? $@"users/{Lookup}/{Ruleset?.ShortName}?key={lookupType.ToString().ToLowerInvariant()}" : $@"me/{Ruleset?.ShortName}";
private enum LookupType
{

View File

@ -48,7 +48,7 @@ namespace osu.Game.Online.Leaderboards
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Text = @"your personal best".ToUpper(),
Text = @"your personal best".ToUpperInvariant(),
Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold),
},
scoreContainer = new Container

View File

@ -274,8 +274,10 @@ namespace osu.Game.Overlays.BeatmapSet
Alpha = 0.5f
}
},
icon = new DifficultyIcon(beatmapInfo, shouldShowTooltip: false)
icon = new DifficultyIcon(beatmapInfo)
{
ShowTooltip = false,
Current = { Value = new StarDifficulty(beatmapInfo.StarRating, 0) },
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(size - tile_icon_padding * 2),

View File

@ -3,6 +3,7 @@
using System;
using osu.Framework.Allocation;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
@ -79,7 +80,7 @@ namespace osu.Game.Overlays.Chat
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Text = time.ToLocalTime().ToString("dd MMMM yyyy").ToUpper(),
Text = time.ToLocalTime().ToLocalisableString(@"dd MMMM yyyy").ToUpper(),
Font = OsuFont.Torus.With(size: TextSize, weight: FontWeight.SemiBold),
Colour = colourProvider?.Content1 ?? Colour4.White,
},

View File

@ -7,6 +7,7 @@ using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
@ -146,7 +147,7 @@ namespace osu.Game.Overlays.News
},
new OsuSpriteText
{
Text = date.ToString("d MMM yyyy").ToUpper(),
Text = date.ToLocalisableString(@"d MMM yyyy").ToUpper(),
Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold),
Margin = new MarginPadding
{

View File

@ -109,15 +109,15 @@ namespace osu.Game.Overlays
: base(value)
{
if (!(Value is Enum enumValue))
Text.Text = Value.ToString().ToLower();
Text.Text = Value.ToString().ToLowerInvariant();
else
{
var localisableDescription = enumValue.GetLocalisableDescription();
string nonLocalisableDescription = enumValue.GetDescription();
// If localisable == non-localisable, then we must have a basic string, so .ToLower() is used.
// If localisable == non-localisable, then we must have a basic string, so .ToLowerInvariant() is used.
Text.Text = localisableDescription.Equals(nonLocalisableDescription)
? nonLocalisableDescription.ToLower()
? nonLocalisableDescription.ToLowerInvariant()
: localisableDescription;
}

View File

@ -74,7 +74,7 @@ namespace osu.Game.Rulesets.Edit.Checks
if (edgeType == EdgeType.None)
yield break;
string postfix = hitObject is IHasDuration ? edgeType.ToString().ToLower() : null;
string postfix = hitObject is IHasDuration ? edgeType.ToString().ToLowerInvariant() : null;
if (maxVolume <= muted_threshold)
{

View File

@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Edit.Checks
}
}
private bool hasAudioExtension(string filename) => audioExtensions.Any(filename.ToLower().EndsWith);
private bool hasAudioExtension(string filename) => audioExtensions.Any(filename.ToLowerInvariant().EndsWith);
private bool probablyHasAudioData(Stream data) => data.Length > min_bytes_threshold;
public class IssueTemplateTooShort : IssueTemplate

View File

@ -1,78 +0,0 @@
// 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.
#nullable disable
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Rulesets;
using osuTK;
namespace osu.Game.Screens.OnlinePlay.Components
{
public class ModeTypeInfo : OnlinePlayComposite
{
private const float height = 28;
private const float transition_duration = 100;
[Resolved]
private RulesetStore rulesets { get; set; }
private Container drawableRuleset;
public ModeTypeInfo()
{
AutoSizeAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load()
{
Container gameTypeContainer;
InternalChild = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(5f, 0f),
LayoutDuration = 100,
Children = new[]
{
drawableRuleset = new Container
{
AutoSizeAxes = Axes.Both,
},
gameTypeContainer = new Container
{
AutoSizeAxes = Axes.Both,
},
},
};
Type.BindValueChanged(type => gameTypeContainer.Child = new DrawableGameType(type.NewValue) { Size = new Vector2(height) }, true);
Playlist.CollectionChanged += (_, __) => updateBeatmap();
updateBeatmap();
}
private void updateBeatmap()
{
var item = Playlist.FirstOrDefault();
var ruleset = item == null ? null : rulesets.GetRuleset(item.RulesetID)?.CreateInstance();
if (item?.Beatmap != null && ruleset != null)
{
var mods = item.RequiredMods.Select(m => m.ToMod(ruleset)).ToArray();
drawableRuleset.FadeIn(transition_duration);
drawableRuleset.Child = new DifficultyIcon(item.Beatmap, ruleset.RulesetInfo, mods) { Size = new Vector2(height) };
}
else
drawableRuleset.FadeOut(transition_duration);
}
}
}

View File

@ -266,7 +266,7 @@ namespace osu.Game.Screens.OnlinePlay
}
if (beatmap != null)
difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(icon_height) };
difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset) { Size = new Vector2(icon_height) };
else
difficultyIconContainer.Clear();

View File

@ -135,7 +135,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
new OsuSpriteText
{
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12),
Text = title.ToUpper(),
Text = title.ToUpperInvariant(),
},
content = new Container
{

View File

@ -53,7 +53,9 @@ namespace osu.Game.Screens.Select.Carousel
private Action<BeatmapInfo> hideRequested;
private Triangles triangles;
private StarCounter starCounter;
private DifficultyIcon difficultyIcon;
[Resolved(CanBeNull = true)]
private BeatmapSetOverlay beatmapOverlay { get; set; }
@ -113,8 +115,9 @@ namespace osu.Game.Screens.Select.Carousel
Origin = Anchor.CentreLeft,
Children = new Drawable[]
{
new DifficultyIcon(beatmapInfo, shouldShowTooltip: false)
difficultyIcon = new DifficultyIcon(beatmapInfo)
{
ShowTooltip = false,
Scale = new Vector2(1.8f),
},
new FillFlowContainer
@ -216,6 +219,8 @@ namespace osu.Game.Screens.Select.Carousel
starDifficultyBindable.BindValueChanged(d =>
{
starCounter.Current = (float)(d.NewValue?.Stars ?? 0);
if (d.NewValue != null)
difficultyIcon.Current.Value = d.NewValue.Value;
}, true);
}

View File

@ -19,7 +19,7 @@ namespace osu.Game.Screens.Select.Carousel
public readonly CarouselBeatmap Item;
public FilterableDifficultyIcon(CarouselBeatmap item)
: base(item.BeatmapInfo, performBackgroundDifficultyLookup: false)
: base(item.BeatmapInfo)
{
filtered.BindTo(item.Filtered);
filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100));

View File

@ -8,23 +8,42 @@ using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets;
using osuTK.Graphics;
namespace osu.Game.Screens.Select.Carousel
{
public class FilterableGroupedDifficultyIcon : GroupedDifficultyIcon
/// <summary>
/// A difficulty icon that contains a counter on the right-side of it.
/// </summary>
/// <remarks>
/// Used in cases when there are too many difficulty icons to show.
/// </remarks>
public class GroupedDifficultyIcon : DifficultyIcon
{
public readonly List<CarouselBeatmap> Items;
public FilterableGroupedDifficultyIcon(List<CarouselBeatmap> items, RulesetInfo ruleset)
: base(items.Select(i => i.BeatmapInfo).ToList(), ruleset, Color4.White)
public GroupedDifficultyIcon(List<CarouselBeatmap> items, RulesetInfo ruleset)
: base(items.OrderBy(b => b.BeatmapInfo.StarRating).Last().BeatmapInfo, ruleset)
{
Items = items;
foreach (var item in items)
item.Filtered.BindValueChanged(_ => Scheduler.AddOnce(updateFilteredDisplay));
AddInternal(new OsuSpriteText
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Padding = new MarginPadding { Left = Size.X },
Margin = new MarginPadding { Left = 2, Right = 5 },
Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold),
Text = items.Count.ToString(),
Colour = Color4.White,
});
updateFilteredDisplay();
}

View File

@ -93,7 +93,7 @@ namespace osu.Game.Screens.Select.Carousel
return beatmaps.Count > maximum_difficulty_icons
? beatmaps.GroupBy(b => b.BeatmapInfo.Ruleset)
.Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Last().BeatmapInfo.Ruleset))
.Select(group => new GroupedDifficultyIcon(group.ToList(), group.Last().BeatmapInfo.Ruleset))
: beatmaps.Select(b => new FilterableDifficultyIcon(b));
}
}

View File

@ -24,7 +24,7 @@ namespace osu.Game.Screens.Select
{
foreach (Match match in query_syntax_regex.Matches(query))
{
string key = match.Groups["key"].Value.ToLower();
string key = match.Groups["key"].Value.ToLowerInvariant();
var op = parseOperator(match.Groups["op"].Value);
string value = match.Groups["value"].Value;