1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 02:32:55 +08:00

Merge branch 'master' into open-profile-hotkey

This commit is contained in:
Andrew Hong 2022-08-10 13:34:53 -04:00 committed by GitHub
commit 11d480997a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 389 additions and 88 deletions

View File

@ -52,7 +52,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.810.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2022.810.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.810.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2022.810.2" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Transitive Dependencies"> <ItemGroup Label="Transitive Dependencies">
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. --> <!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->

View File

@ -36,6 +36,23 @@ namespace osu.Game.Tests.NonVisual
Assert.IsTrue(beatmapSetA.Beatmaps.Single().AudioEquals(beatmapSetB.Beatmaps.Single())); Assert.IsTrue(beatmapSetA.Beatmaps.Single().AudioEquals(beatmapSetB.Beatmaps.Single()));
} }
[Test]
public void TestAudioEqualityCaseSensitivity()
{
var beatmapSetA = TestResources.CreateTestBeatmapSetInfo(1);
var beatmapSetB = TestResources.CreateTestBeatmapSetInfo(1);
// empty by default so let's set it..
beatmapSetA.Beatmaps.First().Metadata.AudioFile = "audio.mp3";
beatmapSetB.Beatmaps.First().Metadata.AudioFile = "audio.mp3";
addAudioFile(beatmapSetA, "abc", "AuDiO.mP3");
addAudioFile(beatmapSetB, "abc", "audio.mp3");
Assert.AreNotEqual(beatmapSetA, beatmapSetB);
Assert.IsTrue(beatmapSetA.Beatmaps.Single().AudioEquals(beatmapSetB.Beatmaps.Single()));
}
[Test] [Test]
public void TestAudioEqualitySameHash() public void TestAudioEqualitySameHash()
{ {

View File

@ -199,8 +199,8 @@ namespace osu.Game.Beatmaps
Debug.Assert(x.BeatmapSet != null); Debug.Assert(x.BeatmapSet != null);
Debug.Assert(y.BeatmapSet != null); Debug.Assert(y.BeatmapSet != null);
string? fileHashX = x.BeatmapSet.Files.FirstOrDefault(f => f.Filename == getFilename(x.Metadata))?.File.Hash; string? fileHashX = x.BeatmapSet.GetFile(getFilename(x.Metadata))?.File.Hash;
string? fileHashY = y.BeatmapSet.Files.FirstOrDefault(f => f.Filename == getFilename(y.Metadata))?.File.Hash; string? fileHashY = y.BeatmapSet.GetFile(getFilename(y.Metadata))?.File.Hash;
return fileHashX == fileHashY; return fileHashX == fileHashY;
} }

View File

@ -1,8 +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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Linq; using System.Linq;
using osu.Framework.Localisation; using osu.Framework.Localisation;

View File

@ -300,7 +300,7 @@ namespace osu.Game.Beatmaps
stream.Seek(0, SeekOrigin.Begin); stream.Seek(0, SeekOrigin.Begin);
// AddFile generally handles updating/replacing files, but this is a case where the filename may have also changed so let's delete for simplicity. // AddFile generally handles updating/replacing files, but this is a case where the filename may have also changed so let's delete for simplicity.
var existingFileInfo = setInfo.Files.SingleOrDefault(f => string.Equals(f.Filename, beatmapInfo.Path, StringComparison.OrdinalIgnoreCase)); var existingFileInfo = beatmapInfo.Path != null ? setInfo.GetFile(beatmapInfo.Path) : null;
string targetFilename = createBeatmapFilenameFromMetadata(beatmapInfo); string targetFilename = createBeatmapFilenameFromMetadata(beatmapInfo);
// ensure that two difficulties from the set don't point at the same beatmap file. // ensure that two difficulties from the set don't point at the same beatmap file.

View File

@ -84,13 +84,6 @@ namespace osu.Game.Beatmaps
{ {
} }
/// <summary>
/// Returns the storage path for the file in this beatmapset with the given filename, if any exists, otherwise null.
/// The path returned is relative to the user file storage.
/// </summary>
/// <param name="filename">The name of the file to get the storage path of.</param>
public string? GetPathForFile(string filename) => Files.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.File.GetStoragePath();
public bool Equals(BeatmapSetInfo? other) public bool Equals(BeatmapSetInfo? other)
{ {
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;

View File

@ -0,0 +1,33 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.Models;
namespace osu.Game.Beatmaps
{
public static class BeatmapSetInfoExtensions
{
/// <summary>
/// Returns the storage path for the file in this beatmapset with the given filename, if any exists, otherwise null.
/// The path returned is relative to the user file storage.
/// The lookup is case insensitive.
/// </summary>
/// <param name="model">The model to operate on.</param>
/// <param name="filename">The name of the file to get the storage path of.</param>
public static string? GetPathForFile(this IHasRealmFiles model, string filename) => model.GetFile(filename)?.File.GetStoragePath();
/// <summary>
/// Returns the file usage for the file in this beatmapset with the given filename, if any exists, otherwise null.
/// The path returned is relative to the user file storage.
/// The lookup is case insensitive.
/// </summary>
/// <param name="model">The model to operate on.</param>
/// <param name="filename">The name of the file to get the storage path of.</param>
public static RealmNamedFileUsage? GetFile(this IHasRealmFiles model, string filename) =>
model.Files.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase));
}
}

View File

@ -3,16 +3,20 @@
#nullable disable #nullable disable
using System.ComponentModel; using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
public enum BackgroundSource public enum BackgroundSource
{ {
[LocalisableDescription(typeof(SkinSettingsStrings), nameof(SkinSettingsStrings.SkinSectionHeader))]
Skin, Skin,
[LocalisableDescription(typeof(GameplaySettingsStrings), nameof(GameplaySettingsStrings.BeatmapHeader))]
Beatmap, Beatmap,
[Description("Beatmap (with storyboard / video)")] [LocalisableDescription(typeof(UserInterfaceStrings), nameof(UserInterfaceStrings.BeatmapWithStoryboard))]
BeatmapWithStoryboard, BeatmapWithStoryboard,
} }
} }

View File

@ -3,17 +3,20 @@
#nullable disable #nullable disable
using System.ComponentModel; using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
public enum DiscordRichPresenceMode public enum DiscordRichPresenceMode
{ {
[LocalisableDescription(typeof(OnlineSettingsStrings), nameof(OnlineSettingsStrings.DiscordPresenceOff))]
Off, Off,
[Description("Hide identifiable information")] [LocalisableDescription(typeof(OnlineSettingsStrings), nameof(OnlineSettingsStrings.HideIdentifiableInformation))]
Limited, Limited,
[LocalisableDescription(typeof(OnlineSettingsStrings), nameof(OnlineSettingsStrings.DiscordPresenceFull))]
Full Full
} }
} }

View File

@ -3,17 +3,20 @@
#nullable disable #nullable disable
using System.ComponentModel; using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
public enum HUDVisibilityMode public enum HUDVisibilityMode
{ {
[LocalisableDescription(typeof(GameplaySettingsStrings), nameof(GameplaySettingsStrings.NeverShowHUD))]
Never, Never,
[Description("Hide during gameplay")] [LocalisableDescription(typeof(GameplaySettingsStrings), nameof(GameplaySettingsStrings.HideDuringGameplay))]
HideDuringGameplay, HideDuringGameplay,
[LocalisableDescription(typeof(GameplaySettingsStrings), nameof(GameplaySettingsStrings.AlwaysShowHUD))]
Always Always
} }
} }

View File

@ -3,16 +3,17 @@
#nullable disable #nullable disable
using System.ComponentModel; using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
public enum RandomSelectAlgorithm public enum RandomSelectAlgorithm
{ {
[Description("Never repeat")] [LocalisableDescription(typeof(UserInterfaceStrings), nameof(UserInterfaceStrings.NeverRepeat))]
RandomPermutation, RandomPermutation,
[Description("True Random")] [LocalisableDescription(typeof(UserInterfaceStrings), nameof(UserInterfaceStrings.TrueRandom))]
Random Random
} }
} }

View File

@ -3,17 +3,23 @@
#nullable disable #nullable disable
using System.ComponentModel; using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
public enum ScalingMode public enum ScalingMode
{ {
[LocalisableDescription(typeof(LayoutSettingsStrings), nameof(LayoutSettingsStrings.ScalingOff))]
Off, Off,
[LocalisableDescription(typeof(LayoutSettingsStrings), nameof(LayoutSettingsStrings.ScaleEverything))]
Everything, Everything,
[Description("Excluding overlays")] [LocalisableDescription(typeof(LayoutSettingsStrings), nameof(LayoutSettingsStrings.ScaleEverythingExcludingOverlays))]
ExcludeOverlays, ExcludeOverlays,
[LocalisableDescription(typeof(LayoutSettingsStrings), nameof(LayoutSettingsStrings.ScaleGameplay))]
Gameplay, Gameplay,
} }
} }

View File

@ -3,16 +3,17 @@
#nullable disable #nullable disable
using System.ComponentModel; using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
public enum ScreenshotFormat public enum ScreenshotFormat
{ {
[Description("JPG (web-friendly)")] [LocalisableDescription(typeof(GraphicsSettingsStrings), nameof(GraphicsSettingsStrings.Jpg))]
Jpg = 1, Jpg = 1,
[Description("PNG (lossless)")] [LocalisableDescription(typeof(GraphicsSettingsStrings), nameof(GraphicsSettingsStrings.Png))]
Png = 2 Png = 2
} }
} }

View File

@ -3,6 +3,9 @@
#nullable disable #nullable disable
using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
public enum SeasonalBackgroundMode public enum SeasonalBackgroundMode
@ -10,16 +13,19 @@ namespace osu.Game.Configuration
/// <summary> /// <summary>
/// Seasonal backgrounds are shown regardless of season, if at all available. /// Seasonal backgrounds are shown regardless of season, if at all available.
/// </summary> /// </summary>
[LocalisableDescription(typeof(UserInterfaceStrings), nameof(UserInterfaceStrings.AlwaysSeasonalBackground))]
Always, Always,
/// <summary> /// <summary>
/// Seasonal backgrounds are shown only during their corresponding season. /// Seasonal backgrounds are shown only during their corresponding season.
/// </summary> /// </summary>
[LocalisableDescription(typeof(UserInterfaceStrings), nameof(UserInterfaceStrings.SometimesSeasonalBackground))]
Sometimes, Sometimes,
/// <summary> /// <summary>
/// Seasonal backgrounds are never shown. /// Seasonal backgrounds are never shown.
/// </summary> /// </summary>
[LocalisableDescription(typeof(UserInterfaceStrings), nameof(UserInterfaceStrings.NeverSeasonalBackground))]
Never Never
} }
} }

View File

@ -2,6 +2,7 @@
// 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.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Models; using osu.Game.Models;
namespace osu.Game.Database namespace osu.Game.Database
@ -11,8 +12,16 @@ namespace osu.Game.Database
/// </summary> /// </summary>
public interface IHasRealmFiles public interface IHasRealmFiles
{ {
/// <summary>
/// Available files in this model, with locally filenames.
/// When performing lookups, consider using <see cref="BeatmapSetInfoExtensions.GetFile"/> or <see cref="BeatmapSetInfoExtensions.GetPathForFile"/> to do case-insensitive lookups.
/// </summary>
IList<RealmNamedFileUsage> Files { get; } IList<RealmNamedFileUsage> Files { get; }
/// <summary>
/// A combined hash representing the model, based on the files it contains.
/// Implementation specific.
/// </summary>
string Hash { get; set; } string Hash { get; set; }
} }
} }

View File

@ -42,7 +42,7 @@ namespace osu.Game.Database
[Resolved] [Resolved]
private RealmAccess realmAccess { get; set; } = null!; private RealmAccess realmAccess { get; set; } = null!;
[Resolved] [Resolved(canBeNull: true)] // canBeNull required while we remain on mono for mobile platforms.
private DesktopGameHost? desktopGameHost { get; set; } private DesktopGameHost? desktopGameHost { get; set; }
[Resolved] [Resolved]

View File

@ -7,6 +7,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Extensions; using osu.Game.Extensions;
using osu.Game.Models; using osu.Game.Models;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
@ -79,7 +80,7 @@ namespace osu.Game.Database
/// </summary> /// </summary>
public void AddFile(TModel item, Stream contents, string filename, Realm realm) public void AddFile(TModel item, Stream contents, string filename, Realm realm)
{ {
var existing = item.Files.FirstOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase)); var existing = item.GetFile(filename);
if (existing != null) if (existing != null)
{ {

View File

@ -173,6 +173,11 @@ namespace osu.Game.Database
if (!Filename.EndsWith(realm_extension, StringComparison.Ordinal)) if (!Filename.EndsWith(realm_extension, StringComparison.Ordinal))
Filename += realm_extension; Filename += realm_extension;
#if DEBUG
if (!DebugUtils.IsNUnitRunning)
applyFilenameSchemaSuffix(ref Filename);
#endif
string newerVersionFilename = $"{Filename.Replace(realm_extension, string.Empty)}_newer_version{realm_extension}"; string newerVersionFilename = $"{Filename.Replace(realm_extension, string.Empty)}_newer_version{realm_extension}";
// Attempt to recover a newer database version if available. // Attempt to recover a newer database version if available.
@ -212,6 +217,51 @@ namespace osu.Game.Database
} }
} }
/// <summary>
/// Some developers may be annoyed if a newer version migration (ie. caused by testing a pull request)
/// cause their test database to be unusable with previous versions.
/// To get around this, store development databases against their realm version.
/// Note that this means changes made on newer realm versions will disappear.
/// </summary>
private void applyFilenameSchemaSuffix(ref string filename)
{
string originalFilename = filename;
filename = getVersionedFilename(schema_version);
// First check if the current realm version already exists...
if (storage.Exists(filename))
return;
// Check for a previous version we can use as a base database to migrate from...
for (int i = schema_version - 1; i >= 0; i--)
{
string previousFilename = getVersionedFilename(i);
if (storage.Exists(previousFilename))
{
copyPreviousVersion(previousFilename, filename);
return;
}
}
// Finally, check for a non-versioned file exists (aka before this method was added)...
if (storage.Exists(originalFilename))
copyPreviousVersion(originalFilename, filename);
void copyPreviousVersion(string previousFilename, string newFilename)
{
using (var previous = storage.GetStream(previousFilename))
using (var current = storage.CreateFileSafely(newFilename))
{
Logger.Log(@$"Copying previous realm database {previousFilename} to {newFilename} for migration to schema version {schema_version}");
previous.CopyTo(current);
}
}
string getVersionedFilename(int version) => originalFilename.Replace(realm_extension, $"_{version}{realm_extension}");
}
private void attemptRecoverFromFile(string recoveryFilename) private void attemptRecoverFromFile(string recoveryFilename)
{ {
Logger.Log($@"Performing recovery from {recoveryFilename}", LoggingTarget.Database); Logger.Log($@"Performing recovery from {recoveryFilename}", LoggingTarget.Database);

View File

@ -1,8 +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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -15,8 +13,9 @@ namespace osu.Game.Input.Bindings
{ {
public class GlobalActionContainer : DatabasedKeyBindingContainer<GlobalAction>, IHandleGlobalKeyboardInput public class GlobalActionContainer : DatabasedKeyBindingContainer<GlobalAction>, IHandleGlobalKeyboardInput
{ {
private readonly Drawable handler; private readonly Drawable? handler;
private InputManager parentInputManager;
private InputManager? parentInputManager;
public GlobalActionContainer(OsuGameBase game) public GlobalActionContainer(OsuGameBase game)
: base(matchingMode: KeyCombinationMatchingMode.Modifiers) : base(matchingMode: KeyCombinationMatchingMode.Modifiers)
@ -32,7 +31,10 @@ namespace osu.Game.Input.Bindings
parentInputManager = GetContainingInputManager(); parentInputManager = GetContainingInputManager();
} }
// IMPORTANT: Do not change the order of key bindings in this list.
// It is used to decide the order of precedence (see note in DatabasedKeyBindingContainer).
public override IEnumerable<IKeyBinding> DefaultKeyBindings => GlobalKeyBindings public override IEnumerable<IKeyBinding> DefaultKeyBindings => GlobalKeyBindings
.Concat(OverlayKeyBindings)
.Concat(EditorKeyBindings) .Concat(EditorKeyBindings)
.Concat(InGameKeyBindings) .Concat(InGameKeyBindings)
.Concat(SongSelectKeyBindings) .Concat(SongSelectKeyBindings)
@ -40,26 +42,6 @@ namespace osu.Game.Input.Bindings
public IEnumerable<KeyBinding> GlobalKeyBindings => new[] public IEnumerable<KeyBinding> GlobalKeyBindings => new[]
{ {
new KeyBinding(InputKey.F6, GlobalAction.ToggleNowPlaying),
new KeyBinding(InputKey.F8, GlobalAction.ToggleChat),
new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial),
new KeyBinding(InputKey.F10, GlobalAction.ToggleGameplayMouseButtons),
new KeyBinding(InputKey.F12, GlobalAction.TakeScreenshot),
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.F }, GlobalAction.ToggleFPSDisplay),
new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings),
new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar),
new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings),
new KeyBinding(new[] { InputKey.Control, InputKey.D }, GlobalAction.ToggleBeatmapListing),
new KeyBinding(new[] { InputKey.Control, InputKey.N }, GlobalAction.ToggleNotifications),
new KeyBinding(new[] { InputKey.Control, InputKey.P }, GlobalAction.ToggleProfile),
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.S }, GlobalAction.ToggleSkinEditor),
new KeyBinding(InputKey.Escape, GlobalAction.Back),
new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back),
new KeyBinding(new[] { InputKey.Alt, InputKey.Home }, GlobalAction.Home),
new KeyBinding(InputKey.Up, GlobalAction.SelectPrevious), new KeyBinding(InputKey.Up, GlobalAction.SelectPrevious),
new KeyBinding(InputKey.Down, GlobalAction.SelectNext), new KeyBinding(InputKey.Down, GlobalAction.SelectNext),
@ -70,7 +52,32 @@ namespace osu.Game.Input.Bindings
new KeyBinding(InputKey.Enter, GlobalAction.Select), new KeyBinding(InputKey.Enter, GlobalAction.Select),
new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select), new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select),
new KeyBinding(InputKey.Escape, GlobalAction.Back),
new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back),
new KeyBinding(new[] { InputKey.Alt, InputKey.Home }, GlobalAction.Home),
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.F }, GlobalAction.ToggleFPSDisplay),
new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar),
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.S }, GlobalAction.ToggleSkinEditor),
new KeyBinding(new[] { InputKey.Control, InputKey.P }, GlobalAction.ToggleProfile),
new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings),
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.R }, GlobalAction.RandomSkin), new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.R }, GlobalAction.RandomSkin),
new KeyBinding(InputKey.F10, GlobalAction.ToggleGameplayMouseButtons),
new KeyBinding(InputKey.F12, GlobalAction.TakeScreenshot),
};
public IEnumerable<KeyBinding> OverlayKeyBindings => new[]
{
new KeyBinding(InputKey.F8, GlobalAction.ToggleChat),
new KeyBinding(InputKey.F6, GlobalAction.ToggleNowPlaying),
new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial),
new KeyBinding(new[] { InputKey.Control, InputKey.D }, GlobalAction.ToggleBeatmapListing),
new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings),
new KeyBinding(new[] { InputKey.Control, InputKey.N }, GlobalAction.ToggleNotifications),
}; };
public IEnumerable<KeyBinding> EditorKeyBindings => new[] public IEnumerable<KeyBinding> EditorKeyBindings => new[]

View File

@ -3,8 +3,9 @@
#nullable disable #nullable disable
using System.ComponentModel;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Input namespace osu.Game.Input
{ {
@ -17,18 +18,20 @@ namespace osu.Game.Input
/// <summary> /// <summary>
/// The mouse cursor will be free to move outside the game window. /// The mouse cursor will be free to move outside the game window.
/// </summary> /// </summary>
[LocalisableDescription(typeof(MouseSettingsStrings), nameof(MouseSettingsStrings.NeverConfine))]
Never, Never,
/// <summary> /// <summary>
/// The mouse cursor will be locked to the window bounds during gameplay, /// The mouse cursor will be locked to the window bounds during gameplay,
/// but may otherwise move freely. /// but may otherwise move freely.
/// </summary> /// </summary>
[Description("During Gameplay")] [LocalisableDescription(typeof(MouseSettingsStrings), nameof(MouseSettingsStrings.ConfineDuringGameplay))]
DuringGameplay, DuringGameplay,
/// <summary> /// <summary>
/// The mouse cursor will always be locked to the window bounds while the game has focus. /// The mouse cursor will always be locked to the window bounds while the game has focus.
/// </summary> /// </summary>
[LocalisableDescription(typeof(MouseSettingsStrings), nameof(MouseSettingsStrings.AlwaysConfine))]
Always Always
} }
} }

View File

@ -104,6 +104,31 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase visibility of first object when visual impairment mods are enabled"); public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase visibility of first object when visual impairment mods are enabled");
/// <summary>
/// "Hide during gameplay"
/// </summary>
public static LocalisableString HideDuringGameplay => new TranslatableString(getKey(@"hide_during_gameplay"), @"Hide during gameplay");
/// <summary>
/// "Always"
/// </summary>
public static LocalisableString AlwaysShowHUD => new TranslatableString(getKey(@"always_show_hud"), @"Always");
/// <summary>
/// "Never"
/// </summary>
public static LocalisableString NeverShowHUD => new TranslatableString(getKey(@"never_show_hud"), @"Never");
/// <summary>
/// "Standardised"
/// </summary>
public static LocalisableString StandardisedScoreDisplay => new TranslatableString(getKey(@"standardised_score_display"), @"Standardised");
/// <summary>
/// "Classic"
/// </summary>
public static LocalisableString ClassicScoreDisplay => new TranslatableString(getKey(@"classic_score_display"), @"Classic");
private static string getKey(string key) => $"{prefix}:{key}"; private static string getKey(string key) => $"{prefix}:{key}";
} }
} }

View File

@ -129,6 +129,16 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString UseHardwareAcceleration => new TranslatableString(getKey(@"use_hardware_acceleration"), @"Use hardware acceleration"); public static LocalisableString UseHardwareAcceleration => new TranslatableString(getKey(@"use_hardware_acceleration"), @"Use hardware acceleration");
/// <summary>
/// "JPG (web-friendly)"
/// </summary>
public static LocalisableString Jpg => new TranslatableString(getKey(@"jpg_web_friendly"), @"JPG (web-friendly)");
/// <summary>
/// "PNG (lossless)"
/// </summary>
public static LocalisableString Png => new TranslatableString(getKey(@"png_lossless"), @"PNG (lossless)");
private static string getKey(string key) => $"{prefix}:{key}"; private static string getKey(string key) => $"{prefix}:{key}";
} }
} }

View File

@ -19,6 +19,11 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString GlobalKeyBindingHeader => new TranslatableString(getKey(@"global_key_binding_header"), @"Global"); public static LocalisableString GlobalKeyBindingHeader => new TranslatableString(getKey(@"global_key_binding_header"), @"Global");
/// <summary>
/// "Overlays"
/// </summary>
public static LocalisableString OverlaysSection => new TranslatableString(getKey(@"overlays_section"), @"Overlays");
/// <summary> /// <summary>
/// "Song Select" /// "Song Select"
/// </summary> /// </summary>

View File

@ -29,6 +29,26 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString FullscreenMacOSNote => new TranslatableString(getKey(@"fullscreen_macos_note"), @"Using fullscreen on macOS makes interacting with the menu bar and spaces no longer work, and may lead to freezes if a system dialog is presented. Using borderless is recommended."); public static LocalisableString FullscreenMacOSNote => new TranslatableString(getKey(@"fullscreen_macos_note"), @"Using fullscreen on macOS makes interacting with the menu bar and spaces no longer work, and may lead to freezes if a system dialog is presented. Using borderless is recommended.");
/// <summary>
/// "Excluding overlays"
/// </summary>
public static LocalisableString ScaleEverythingExcludingOverlays => new TranslatableString(getKey(@"scale_everything_excluding_overlays"), @"Excluding overlays");
/// <summary>
/// "Everything"
/// </summary>
public static LocalisableString ScaleEverything => new TranslatableString(getKey(@"scale_everything"), @"Everything");
/// <summary>
/// "Gameplay"
/// </summary>
public static LocalisableString ScaleGameplay => new TranslatableString(getKey(@"scale_gameplay"), @"Gameplay");
/// <summary>
/// "Off"
/// </summary>
public static LocalisableString ScalingOff => new TranslatableString(getKey(@"scaling_off"), @"Off");
private static string getKey(string key) => $@"{prefix}:{key}"; private static string getKey(string key) => $@"{prefix}:{key}";
} }
} }

View File

@ -64,6 +64,21 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString HighPrecisionPlatformWarning => new TranslatableString(getKey(@"high_precision_platform_warning"), @"This setting has known issues on your platform. If you encounter problems, it is recommended to adjust sensitivity externally and keep this disabled for now."); public static LocalisableString HighPrecisionPlatformWarning => new TranslatableString(getKey(@"high_precision_platform_warning"), @"This setting has known issues on your platform. If you encounter problems, it is recommended to adjust sensitivity externally and keep this disabled for now.");
/// <summary>
/// "Always"
/// </summary>
public static LocalisableString AlwaysConfine => new TranslatableString(getKey(@"always_confine"), @"Always");
/// <summary>
/// "During Gameplay"
/// </summary>
public static LocalisableString ConfineDuringGameplay => new TranslatableString(getKey(@"confine_during_gameplay"), @"During Gameplay");
/// <summary>
/// "Never"
/// </summary>
public static LocalisableString NeverConfine => new TranslatableString(getKey(@"never_confine"), @"Never");
private static string getKey(string key) => $@"{prefix}:{key}"; private static string getKey(string key) => $@"{prefix}:{key}";
} }
} }

View File

@ -64,6 +64,21 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString ShowExplicitContent => new TranslatableString(getKey(@"show_explicit_content"), @"Show explicit content in search results"); public static LocalisableString ShowExplicitContent => new TranslatableString(getKey(@"show_explicit_content"), @"Show explicit content in search results");
/// <summary>
/// "Hide identifiable information"
/// </summary>
public static LocalisableString HideIdentifiableInformation => new TranslatableString(getKey(@"hide_identifiable_information"), @"Hide identifiable information");
/// <summary>
/// "Full"
/// </summary>
public static LocalisableString DiscordPresenceFull => new TranslatableString(getKey(@"discord_presence_full"), @"Full");
/// <summary>
/// "Off"
/// </summary>
public static LocalisableString DiscordPresenceOff => new TranslatableString(getKey(@"discord_presence_off"), @"Off");
private static string getKey(string key) => $"{prefix}:{key}"; private static string getKey(string key) => $"{prefix}:{key}";
} }
} }

View File

@ -14,6 +14,21 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString Rulesets => new TranslatableString(getKey(@"rulesets"), @"Rulesets"); public static LocalisableString Rulesets => new TranslatableString(getKey(@"rulesets"), @"Rulesets");
/// <summary>
/// "None"
/// </summary>
public static LocalisableString BorderNone => new TranslatableString(getKey(@"no_borders"), @"None");
/// <summary>
/// "Corners"
/// </summary>
public static LocalisableString BorderCorners => new TranslatableString(getKey(@"corner_borders"), @"Corners");
/// <summary>
/// "Full"
/// </summary>
public static LocalisableString BorderFull => new TranslatableString(getKey(@"full_borders"), @"Full");
private static string getKey(string key) => $@"{prefix}:{key}"; private static string getKey(string key) => $@"{prefix}:{key}";
} }
} }

View File

@ -114,6 +114,46 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString NoLimit => new TranslatableString(getKey(@"no_limit"), @"no limit"); public static LocalisableString NoLimit => new TranslatableString(getKey(@"no_limit"), @"no limit");
/// <summary>
/// "Beatmap (with storyboard / video)"
/// </summary>
public static LocalisableString BeatmapWithStoryboard => new TranslatableString(getKey(@"beatmap_with_storyboard"), @"Beatmap (with storyboard / video)");
/// <summary>
/// "Always"
/// </summary>
public static LocalisableString AlwaysSeasonalBackground => new TranslatableString(getKey(@"always_seasonal_backgrounds"), @"Always");
/// <summary>
/// "Never"
/// </summary>
public static LocalisableString NeverSeasonalBackground => new TranslatableString(getKey(@"never_seasonal_backgrounds"), @"Never");
/// <summary>
/// "Sometimes"
/// </summary>
public static LocalisableString SometimesSeasonalBackground => new TranslatableString(getKey(@"sometimes_seasonal_backgrounds"), @"Sometimes");
/// <summary>
/// "Sequential"
/// </summary>
public static LocalisableString SequentialHotkeyStyle => new TranslatableString(getKey(@"mods_sequential_hotkeys"), @"Sequential");
/// <summary>
/// "Classic"
/// </summary>
public static LocalisableString ClassicHotkeyStyle => new TranslatableString(getKey(@"mods_classic_hotkeys"), @"Classic");
/// <summary>
/// "Never repeat"
/// </summary>
public static LocalisableString NeverRepeat => new TranslatableString(getKey(@"never_repeat_random"), @"Never repeat");
/// <summary>
/// "True Random"
/// </summary>
public static LocalisableString TrueRandom => new TranslatableString(getKey(@"true_random"), @"True Random");
private static string getKey(string key) => $"{prefix}:{key}"; private static string getKey(string key) => $"{prefix}:{key}";
} }
} }

View File

@ -1,7 +1,9 @@
// 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 osu.Framework.Localisation;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Mods.Input namespace osu.Game.Overlays.Mods.Input
{ {
@ -15,6 +17,7 @@ namespace osu.Game.Overlays.Mods.Input
/// Individual letters in a row trigger the mods in a sequential fashion. /// Individual letters in a row trigger the mods in a sequential fashion.
/// Uses <see cref="SequentialModHotkeyHandler"/>. /// Uses <see cref="SequentialModHotkeyHandler"/>.
/// </summary> /// </summary>
[LocalisableDescription(typeof(UserInterfaceStrings), nameof(UserInterfaceStrings.SequentialHotkeyStyle))]
Sequential, Sequential,
/// <summary> /// <summary>
@ -22,6 +25,7 @@ namespace osu.Game.Overlays.Mods.Input
/// One keybinding can toggle between what used to be <see cref="MultiMod"/>s on stable, /// One keybinding can toggle between what used to be <see cref="MultiMod"/>s on stable,
/// and some mods in a column may not have any hotkeys at all. /// and some mods in a column may not have any hotkeys at all.
/// </summary> /// </summary>
[LocalisableDescription(typeof(UserInterfaceStrings), nameof(UserInterfaceStrings.ClassicHotkeyStyle))]
Classic Classic
} }
} }

View File

@ -1,8 +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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation; using osu.Framework.Localisation;
@ -23,6 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
public GlobalKeyBindingsSection(GlobalActionContainer manager) public GlobalKeyBindingsSection(GlobalActionContainer manager)
{ {
Add(new DefaultBindingsSubsection(manager)); Add(new DefaultBindingsSubsection(manager));
Add(new OverlayBindingsSubsection(manager));
Add(new AudioControlKeyBindingsSubsection(manager)); Add(new AudioControlKeyBindingsSubsection(manager));
Add(new SongSelectKeyBindingSubsection(manager)); Add(new SongSelectKeyBindingSubsection(manager));
Add(new InGameKeyBindingsSubsection(manager)); Add(new InGameKeyBindingsSubsection(manager));
@ -40,6 +39,17 @@ namespace osu.Game.Overlays.Settings.Sections.Input
} }
} }
private class OverlayBindingsSubsection : KeyBindingsSubsection
{
protected override LocalisableString Header => InputSettingsStrings.OverlaysSection;
public OverlayBindingsSubsection(GlobalActionContainer manager)
: base(null)
{
Defaults = manager.OverlayKeyBindings;
}
}
private class SongSelectKeyBindingSubsection : KeyBindingsSubsection private class SongSelectKeyBindingSubsection : KeyBindingsSubsection
{ {
protected override LocalisableString Header => InputSettingsStrings.SongSelectSection; protected override LocalisableString Header => InputSettingsStrings.SongSelectSection;

View File

@ -5,6 +5,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using osu.Game.Beatmaps;
using osu.Game.IO.FileAbstraction; using osu.Game.IO.FileAbstraction;
using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Edit.Checks.Components;
using osu.Game.Storyboards; using osu.Game.Storyboards;

View File

@ -5,6 +5,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Edit.Checks.Components;
namespace osu.Game.Rulesets.Edit.Checks namespace osu.Game.Rulesets.Edit.Checks

View File

@ -16,6 +16,8 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Rulesets.Scoring namespace osu.Game.Rulesets.Scoring
{ {
@ -636,7 +638,10 @@ namespace osu.Game.Rulesets.Scoring
public enum ScoringMode public enum ScoringMode
{ {
[LocalisableDescription(typeof(GameplaySettingsStrings), nameof(GameplaySettingsStrings.StandardisedScoreDisplay))]
Standardised, Standardised,
[LocalisableDescription(typeof(GameplaySettingsStrings), nameof(GameplaySettingsStrings.ClassicScoreDisplay))]
Classic Classic
} }
} }

View File

@ -3,12 +3,20 @@
#nullable disable #nullable disable
using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Rulesets.UI namespace osu.Game.Rulesets.UI
{ {
public enum PlayfieldBorderStyle public enum PlayfieldBorderStyle
{ {
[LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.BorderNone))]
None, None,
[LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.BorderCorners))]
Corners, Corners,
[LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.BorderFull))]
Full Full
} }
} }

View File

@ -4,7 +4,6 @@
#nullable disable #nullable disable
using System.IO; using System.IO;
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;
@ -78,7 +77,7 @@ namespace osu.Game.Screens.Edit.Setup
// remove the previous background for now. // remove the previous background for now.
// in the future we probably want to check if this is being used elsewhere (other difficulties?) // in the future we probably want to check if this is being used elsewhere (other difficulties?)
var oldFile = set.Files.FirstOrDefault(f => f.Filename == working.Value.Metadata.BackgroundFile); var oldFile = set.GetFile(working.Value.Metadata.BackgroundFile);
using (var stream = source.OpenRead()) using (var stream = source.OpenRead())
{ {
@ -107,7 +106,7 @@ namespace osu.Game.Screens.Edit.Setup
// remove the previous audio track for now. // remove the previous audio track for now.
// in the future we probably want to check if this is being used elsewhere (other difficulties?) // in the future we probably want to check if this is being used elsewhere (other difficulties?)
var oldFile = set.Files.FirstOrDefault(f => f.Filename == working.Value.Metadata.AudioFile); var oldFile = set.GetFile(working.Value.Metadata.AudioFile);
using (var stream = source.OpenRead()) using (var stream = source.OpenRead())
{ {

View File

@ -10,6 +10,7 @@ using System.Threading;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Extensions; using osu.Game.Extensions;
using osu.Game.IO; using osu.Game.IO;
@ -49,7 +50,7 @@ namespace osu.Game.Skinning
protected override void Populate(SkinInfo model, ArchiveReader? archive, Realm realm, CancellationToken cancellationToken = default) protected override void Populate(SkinInfo model, ArchiveReader? archive, Realm realm, CancellationToken cancellationToken = default)
{ {
var skinInfoFile = model.Files.SingleOrDefault(f => f.Filename == skin_info_file); var skinInfoFile = model.GetFile(skin_info_file);
if (skinInfoFile != null) if (skinInfoFile != null)
{ {
@ -129,7 +130,7 @@ namespace osu.Game.Skinning
authorLine, authorLine,
}; };
var existingFile = item.Files.SingleOrDefault(f => f.Filename.Equals(@"skin.ini", StringComparison.OrdinalIgnoreCase)); var existingFile = item.GetFile(@"skin.ini");
if (existingFile == null) if (existingFile == null)
{ {
@ -163,7 +164,7 @@ namespace osu.Game.Skinning
{ {
Logger.Log($"Skin {item}'s skin.ini had issues and has been removed. Please report this and provide the problematic skin.", LoggingTarget.Database, LogLevel.Important); Logger.Log($"Skin {item}'s skin.ini had issues and has been removed. Please report this and provide the problematic skin.", LoggingTarget.Database, LogLevel.Important);
var existingIni = item.Files.SingleOrDefault(f => f.Filename.Equals(@"skin.ini", StringComparison.OrdinalIgnoreCase)); var existingIni = item.GetFile(@"skin.ini");
if (existingIni != null) if (existingIni != null)
item.Files.Remove(existingIni); item.Files.Remove(existingIni);
@ -248,7 +249,7 @@ namespace osu.Game.Skinning
{ {
string filename = @$"{drawableInfo.Key}.json"; string filename = @$"{drawableInfo.Key}.json";
var oldFile = s.Files.FirstOrDefault(f => f.Filename == filename); var oldFile = s.GetFile(filename);
if (oldFile != null) if (oldFile != null)
modelManager.ReplaceFile(oldFile, streamContent, s.Realm); modelManager.ReplaceFile(oldFile, streamContent, s.Realm);

View File

@ -1,10 +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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
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;
@ -12,14 +8,14 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.Video; using osu.Framework.Graphics.Video;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Extensions;
namespace osu.Game.Storyboards.Drawables namespace osu.Game.Storyboards.Drawables
{ {
public class DrawableStoryboardVideo : CompositeDrawable public class DrawableStoryboardVideo : CompositeDrawable
{ {
public readonly StoryboardVideo Video; public readonly StoryboardVideo Video;
private Video video;
private Video? drawableVideo;
public override bool RemoveWhenNotAlive => false; public override bool RemoveWhenNotAlive => false;
@ -33,7 +29,7 @@ namespace osu.Game.Storyboards.Drawables
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(IBindable<WorkingBeatmap> beatmap, TextureStore textureStore) private void load(IBindable<WorkingBeatmap> beatmap, TextureStore textureStore)
{ {
string path = beatmap.Value.BeatmapSetInfo?.Files.FirstOrDefault(f => f.Filename.Equals(Video.Path, StringComparison.OrdinalIgnoreCase))?.File.GetStoragePath(); string? path = beatmap.Value.BeatmapSetInfo?.GetPathForFile(Video.Path);
if (path == null) if (path == null)
return; return;
@ -43,7 +39,7 @@ namespace osu.Game.Storyboards.Drawables
if (stream == null) if (stream == null)
return; return;
InternalChild = video = new Video(stream, false) InternalChild = drawableVideo = new Video(stream, false)
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fill, FillMode = FillMode.Fill,
@ -57,12 +53,12 @@ namespace osu.Game.Storyboards.Drawables
{ {
base.LoadComplete(); base.LoadComplete();
if (video == null) return; if (drawableVideo == null) return;
using (video.BeginAbsoluteSequence(Video.StartTime)) using (drawableVideo.BeginAbsoluteSequence(Video.StartTime))
{ {
Schedule(() => video.PlaybackPosition = Time.Current - Video.StartTime); Schedule(() => drawableVideo.PlaybackPosition = Time.Current - Video.StartTime);
video.FadeIn(500); drawableVideo.FadeIn(500);
} }
} }
} }

View File

@ -1,14 +1,10 @@
// 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.
#nullable disable
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Extensions;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Storyboards.Drawables; using osu.Game.Storyboards.Drawables;
@ -90,12 +86,12 @@ namespace osu.Game.Storyboards
} }
} }
public DrawableStoryboard CreateDrawable(IReadOnlyList<Mod> mods = null) => public DrawableStoryboard CreateDrawable(IReadOnlyList<Mod>? mods = null) =>
new DrawableStoryboard(this, mods); new DrawableStoryboard(this, mods);
public Texture GetTextureFromPath(string path, TextureStore textureStore) public Texture? GetTextureFromPath(string path, TextureStore textureStore)
{ {
string storyboardPath = BeatmapInfo.BeatmapSet?.Files.FirstOrDefault(f => f.Filename.Equals(path, StringComparison.OrdinalIgnoreCase))?.File.GetStoragePath(); string? storyboardPath = BeatmapInfo.BeatmapSet?.GetPathForFile(path);
if (!string.IsNullOrEmpty(storyboardPath)) if (!string.IsNullOrEmpty(storyboardPath))
return textureStore.Get(storyboardPath); return textureStore.Get(storyboardPath);

View File

@ -110,7 +110,7 @@ namespace osu.Game.Tests.Visual
// Specific to tests, the player can be disposed without OnExiting() ever being called. // Specific to tests, the player can be disposed without OnExiting() ever being called.
// We should make sure that the gameplay session has finished even in this case. // We should make sure that the gameplay session has finished even in this case.
if (LoadedBeatmapSuccessfully) if (LoadedBeatmapSuccessfully)
spectatorClient.EndPlaying(GameplayState); spectatorClient?.EndPlaying(GameplayState);
} }
} }
} }

View File

@ -36,7 +36,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Realm" Version="10.14.0" /> <PackageReference Include="Realm" Version="10.14.0" />
<PackageReference Include="ppy.osu.Framework" Version="2022.810.0" /> <PackageReference Include="ppy.osu.Framework" Version="2022.810.2" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.810.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2022.810.0" />
<PackageReference Include="Sentry" Version="3.19.0" /> <PackageReference Include="Sentry" Version="3.19.0" />
<PackageReference Include="SharpCompress" Version="0.32.1" /> <PackageReference Include="SharpCompress" Version="0.32.1" />

View File

@ -61,7 +61,7 @@
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.810.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2022.810.2" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.810.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2022.810.0" />
</ItemGroup> </ItemGroup>
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) --> <!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) -->
@ -84,7 +84,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.14" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="5.0.14" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="5.0.14" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="ppy.osu.Framework" Version="2022.810.0" /> <PackageReference Include="ppy.osu.Framework" Version="2022.810.2" />
<PackageReference Include="SharpCompress" Version="0.32.1" /> <PackageReference Include="SharpCompress" Version="0.32.1" />
<PackageReference Include="NUnit" Version="3.13.3" /> <PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />