diff --git a/Directory.Build.props b/Directory.Build.props index 3ab3dc3d13..709545bf1d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -34,7 +34,7 @@ https://github.com/ppy/osu Automated release. ppy Pty Ltd - Copyright (c) 2021 ppy Pty Ltd + Copyright (c) 2022 ppy Pty Ltd osu game diff --git a/LICENCE b/LICENCE index b5962ad3b2..d3e7537cef 100644 --- a/LICENCE +++ b/LICENCE @@ -1,4 +1,4 @@ -Copyright (c) 2021 ppy Pty Ltd . +Copyright (c) 2022 ppy Pty Ltd . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Templates/osu.Game.Templates.csproj b/Templates/osu.Game.Templates.csproj index 4624d3d771..b8c3ad373a 100644 --- a/Templates/osu.Game.Templates.csproj +++ b/Templates/osu.Game.Templates.csproj @@ -8,7 +8,7 @@ https://github.com/ppy/osu/blob/master/Templates https://github.com/ppy/osu Automated release. - Copyright (c) 2021 ppy Pty Ltd + Copyright (c) 2022 ppy Pty Ltd Templates to use when creating a ruleset for consumption in osu!. dotnet-new;templates;osu netstandard2.1 diff --git a/osu.Desktop/osu.nuspec b/osu.Desktop/osu.nuspec index 1757fd7c73..dc1ec17e2c 100644 --- a/osu.Desktop/osu.nuspec +++ b/osu.Desktop/osu.nuspec @@ -11,7 +11,7 @@ false A free-to-win rhythm game. Rhythm is just a *click* away! testing - Copyright (c) 2021 ppy Pty Ltd + Copyright (c) 2022 ppy Pty Ltd en-AU diff --git a/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs b/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs index db7fc0b4a0..76c49edf78 100644 --- a/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs +++ b/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs @@ -83,6 +83,20 @@ namespace osu.Game.Tests.NonVisual.Skinning "followpoint.png", "followpoint@2x.png", 2 }, + new object[] + { + // Looking up a path with extension specified should work. + new[] { "Gameplay/osu/followpoint.png" }, + "Gameplay/osu/followpoint.png", + "Gameplay/osu/followpoint.png", 1 + }, + new object[] + { + // Looking up a path with extension specified should also work with @2x sprites. + new[] { "Gameplay/osu/followpoint@2x.png" }, + "Gameplay/osu/followpoint.png", + "Gameplay/osu/followpoint@2x.png", 2 + }, }; [TestCaseSource(nameof(fallbackTestCases))] diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 2f966ac0a9..9aacb50684 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Globalization; using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; using osu.Framework.Extensions; @@ -102,6 +103,9 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.MenuParallax, true); + // See https://stackoverflow.com/a/63307411 for default sourcing. + SetDefault(OsuSetting.Prefer24HourTime, CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern.Contains(@"tt")); + // Gameplay SetDefault(OsuSetting.PositionalHitsounds, true); // replaced by level setting below, can be removed 20220703. SetDefault(OsuSetting.PositionalHitsoundsLevel, 0.2f, 0, 1); @@ -287,6 +291,7 @@ namespace osu.Game.Configuration MenuVoice, CursorRotation, MenuParallax, + Prefer24HourTime, BeatmapDetailTab, BeatmapDetailModsFilter, Username, diff --git a/osu.Game/Localisation/GeneralSettingsStrings.cs b/osu.Game/Localisation/GeneralSettingsStrings.cs index a60e4891f4..c65e6c77f4 100644 --- a/osu.Game/Localisation/GeneralSettingsStrings.cs +++ b/osu.Game/Localisation/GeneralSettingsStrings.cs @@ -29,6 +29,11 @@ namespace osu.Game.Localisation /// public static LocalisableString PreferOriginalMetadataLanguage => new TranslatableString(getKey(@"prefer_original"), @"Prefer metadata in original language"); + /// + /// "Prefer 24-hour time display" + /// + public static LocalisableString Prefer24HourTimeDisplay => new TranslatableString(getKey(@"prefer_24_hour_time_display"), @"Prefer 24-hour time display"); + /// /// "Updates" /// diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index 200618c469..cdce187a35 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Localisation; +using osu.Game.Configuration; using osu.Game.Extensions; using osu.Game.Localisation; @@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections.General protected override LocalisableString Header => GeneralSettingsStrings.LanguageHeader; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager frameworkConfig) + private void load(FrameworkConfigManager frameworkConfig, OsuConfigManager config) { frameworkLocale = frameworkConfig.GetBindable(FrameworkSetting.Locale); @@ -34,6 +35,11 @@ namespace osu.Game.Overlays.Settings.Sections.General LabelText = GeneralSettingsStrings.PreferOriginalMetadataLanguage, Current = frameworkConfig.GetBindable(FrameworkSetting.ShowUnicode) }, + new SettingsCheckbox + { + LabelText = GeneralSettingsStrings.Prefer24HourTimeDisplay, + Current = config.GetBindable(OsuSetting.Prefer24HourTime) + }, }; if (!LanguageExtensions.TryParseCultureCode(frameworkLocale.Value, out var locale)) diff --git a/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs b/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs index 81a362450c..ac6f563336 100644 --- a/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs +++ b/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs @@ -29,6 +29,23 @@ namespace osu.Game.Overlays.Toolbar } } + private bool use24HourDisplay; + + public bool Use24HourDisplay + { + get => use24HourDisplay; + set + { + if (use24HourDisplay == value) + return; + + use24HourDisplay = value; + + updateMetrics(); + UpdateDisplay(DateTimeOffset.Now); //Update realTime.Text immediately instead of waiting until next second + } + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -50,13 +67,14 @@ namespace osu.Game.Overlays.Toolbar protected override void UpdateDisplay(DateTimeOffset now) { - realTime.Text = $"{now:HH:mm:ss}"; + realTime.Text = use24HourDisplay ? $"{now:HH:mm:ss}" : $"{now:h:mm:ss tt}"; gameTime.Text = $"running {new TimeSpan(TimeSpan.TicksPerSecond * (int)(Clock.CurrentTime / 1000)):c}"; } private void updateMetrics() { - Width = showRuntime ? 66 : 45; // Allows for space for game time up to 99 days (in the padding area since this is quite rare). + Width = showRuntime || !use24HourDisplay ? 66 : 45; // Allows for space for game time up to 99 days (in the padding area since this is quite rare). + gameTime.FadeTo(showRuntime ? 1 : 0); } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index 22a96603dc..308359570f 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -20,6 +20,7 @@ namespace osu.Game.Overlays.Toolbar public class ToolbarClock : OsuClickableContainer { private Bindable clockDisplayMode; + private Bindable prefer24HourTime; private Box hoverBackground; private Box flashBackground; @@ -38,6 +39,7 @@ namespace osu.Game.Overlays.Toolbar private void load(OsuConfigManager config) { clockDisplayMode = config.GetBindable(OsuSetting.ToolbarClockDisplayMode); + prefer24HourTime = config.GetBindable(OsuSetting.Prefer24HourTime); Children = new Drawable[] { @@ -94,6 +96,8 @@ namespace osu.Game.Overlays.Toolbar analog.FadeTo(showAnalog ? 1 : 0); }, true); + + prefer24HourTime.BindValueChanged(prefer24H => digital.Use24HourDisplay = prefer24H.NewValue, true); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs index d67bfb89ab..ebf3c9c319 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs @@ -21,21 +21,20 @@ namespace osu.Game.Skinning.Editor private readonly List> targetComponents = new List>(); + [Resolved] + private SkinEditor editor { get; set; } + public SkinBlueprintContainer(Drawable target) { this.target = target; } - [BackgroundDependencyLoader(true)] - private void load(SkinEditor editor) - { - SelectedItems.BindTo(editor.SelectedComponents); - } - protected override void LoadComplete() { base.LoadComplete(); + SelectedItems.BindTo(editor.SelectedComponents); + // track each target container on the current screen. var targetContainers = target.ChildrenOfType().ToArray(); @@ -56,7 +55,7 @@ namespace osu.Game.Skinning.Editor } } - private void componentsChanged(object sender, NotifyCollectionChangedEventArgs e) + private void componentsChanged(object sender, NotifyCollectionChangedEventArgs e) => Schedule(() => { switch (e.Action) { @@ -79,7 +78,7 @@ namespace osu.Game.Skinning.Editor AddBlueprintFor(item); break; } - } + }); protected override void AddBlueprintFor(ISkinnableDrawable item) { @@ -93,5 +92,13 @@ namespace osu.Game.Skinning.Editor protected override SelectionBlueprint CreateBlueprintFor(ISkinnableDrawable component) => new SkinBlueprint(component); + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + foreach (var list in targetComponents) + list.UnbindAll(); + } } } diff --git a/osu.Game/Skinning/Editor/SkinEditor.cs b/osu.Game/Skinning/Editor/SkinEditor.cs index bcff70c008..e36d5ca3c6 100644 --- a/osu.Game/Skinning/Editor/SkinEditor.cs +++ b/osu.Game/Skinning/Editor/SkinEditor.cs @@ -203,6 +203,9 @@ namespace osu.Game.Skinning.Editor SelectedComponents.Clear(); + // Immediately clear the previous blueprint container to ensure it doesn't try to interact with the old target. + content?.Clear(); + Scheduler.AddOnce(loadBlueprintContainer); Scheduler.AddOnce(populateSettings); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index a97b5d44ce..f7d5581621 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -443,9 +443,7 @@ namespace osu.Game.Skinning string lookupName = name.Replace(@"@2x", string.Empty); float ratio = 2; - string twoTimesFilename = Path.HasExtension(lookupName) - ? @$"{Path.GetFileNameWithoutExtension(lookupName)}@2x{Path.GetExtension(lookupName)}" - : @$"{lookupName}@2x"; + string twoTimesFilename = $"{Path.ChangeExtension(lookupName, null)}@2x{Path.GetExtension(lookupName)}"; var texture = Textures?.Get(twoTimesFilename, wrapModeS, wrapModeT);