1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 16:07:24 +08:00

Revert "Temporary rollback of framework / SDL3"

This reverts commit d7d569cf4e.
This commit is contained in:
Dean Herbert 2024-05-22 16:29:39 +08:00
parent 3a608aa815
commit d0b1ebff5a
No known key found for this signature in database
44 changed files with 226 additions and 304 deletions

View File

@ -10,7 +10,7 @@
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk> <EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Framework.Android" Version="2024.329.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2024.509.0" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>
<!-- Fody does not handle Android build well, and warns when unchanged. <!-- Fody does not handle Android build well, and warns when unchanged.

View File

@ -1,76 +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.
using osu.Framework.Allocation;
using osu.Framework.Android.Input;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings;
namespace osu.Android
{
public partial class AndroidJoystickSettings : SettingsSubsection
{
protected override LocalisableString Header => JoystickSettingsStrings.JoystickGamepad;
private readonly AndroidJoystickHandler joystickHandler;
private readonly Bindable<bool> enabled = new BindableBool(true);
private SettingsSlider<float> deadzoneSlider = null!;
private Bindable<float> handlerDeadzone = null!;
private Bindable<float> localDeadzone = null!;
public AndroidJoystickSettings(AndroidJoystickHandler joystickHandler)
{
this.joystickHandler = joystickHandler;
}
[BackgroundDependencyLoader]
private void load()
{
// use local bindable to avoid changing enabled state of game host's bindable.
handlerDeadzone = joystickHandler.DeadzoneThreshold.GetBoundCopy();
localDeadzone = handlerDeadzone.GetUnboundCopy();
Children = new Drawable[]
{
new SettingsCheckbox
{
LabelText = CommonStrings.Enabled,
Current = enabled
},
deadzoneSlider = new SettingsSlider<float>
{
LabelText = JoystickSettingsStrings.DeadzoneThreshold,
KeyboardStep = 0.01f,
DisplayAsPercentage = true,
Current = localDeadzone,
},
};
}
protected override void LoadComplete()
{
base.LoadComplete();
enabled.BindTo(joystickHandler.Enabled);
enabled.BindValueChanged(e => deadzoneSlider.Current.Disabled = !e.NewValue, true);
handlerDeadzone.BindValueChanged(val =>
{
bool disabled = localDeadzone.Disabled;
localDeadzone.Disabled = false;
localDeadzone.Value = val.NewValue;
localDeadzone.Disabled = disabled;
}, true);
localDeadzone.BindValueChanged(val => handlerDeadzone.Value = val.NewValue);
}
}
}

View File

@ -1,97 +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.
using Android.OS;
using osu.Framework.Allocation;
using osu.Framework.Android.Input;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Localisation;
using osu.Game.Configuration;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings;
using osu.Game.Overlays.Settings.Sections.Input;
namespace osu.Android
{
public partial class AndroidMouseSettings : SettingsSubsection
{
private readonly AndroidMouseHandler mouseHandler;
protected override LocalisableString Header => MouseSettingsStrings.Mouse;
private Bindable<double> handlerSensitivity = null!;
private Bindable<double> localSensitivity = null!;
private Bindable<bool> relativeMode = null!;
public AndroidMouseSettings(AndroidMouseHandler mouseHandler)
{
this.mouseHandler = mouseHandler;
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager osuConfig)
{
// use local bindable to avoid changing enabled state of game host's bindable.
handlerSensitivity = mouseHandler.Sensitivity.GetBoundCopy();
localSensitivity = handlerSensitivity.GetUnboundCopy();
relativeMode = mouseHandler.UseRelativeMode.GetBoundCopy();
// High precision/pointer capture is only available on Android 8.0 and up
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
AddRange(new Drawable[]
{
new SettingsCheckbox
{
LabelText = MouseSettingsStrings.HighPrecisionMouse,
TooltipText = MouseSettingsStrings.HighPrecisionMouseTooltip,
Current = relativeMode,
Keywords = new[] { @"raw", @"input", @"relative", @"cursor", @"captured", @"pointer" },
},
new MouseSettings.SensitivitySetting
{
LabelText = MouseSettingsStrings.CursorSensitivity,
Current = localSensitivity,
},
});
}
AddRange(new Drawable[]
{
new SettingsCheckbox
{
LabelText = MouseSettingsStrings.DisableMouseWheelVolumeAdjust,
TooltipText = MouseSettingsStrings.DisableMouseWheelVolumeAdjustTooltip,
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableWheel),
},
new SettingsCheckbox
{
LabelText = MouseSettingsStrings.DisableClicksDuringGameplay,
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableButtons),
},
});
}
protected override void LoadComplete()
{
base.LoadComplete();
relativeMode.BindValueChanged(relative => localSensitivity.Disabled = !relative.NewValue, true);
handlerSensitivity.BindValueChanged(val =>
{
bool disabled = localSensitivity.Disabled;
localSensitivity.Disabled = false;
localSensitivity.Value = val.NewValue;
localSensitivity.Disabled = disabled;
}, true);
localSensitivity.BindValueChanged(val => handlerSensitivity.Value = val.NewValue);
}
}
}

View File

@ -5,13 +5,9 @@ using System;
using Android.App; using Android.App;
using Microsoft.Maui.Devices; using Microsoft.Maui.Devices;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Android.Input;
using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Input.Handlers;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game; using osu.Game;
using osu.Game.Overlays.Settings;
using osu.Game.Overlays.Settings.Sections.Input;
using osu.Game.Updater; using osu.Game.Updater;
using osu.Game.Utils; using osu.Game.Utils;
@ -88,24 +84,6 @@ namespace osu.Android
protected override BatteryInfo CreateBatteryInfo() => new AndroidBatteryInfo(); protected override BatteryInfo CreateBatteryInfo() => new AndroidBatteryInfo();
public override SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler)
{
switch (handler)
{
case AndroidMouseHandler mh:
return new AndroidMouseSettings(mh);
case AndroidJoystickHandler jh:
return new AndroidJoystickSettings(jh);
case AndroidTouchHandler th:
return new TouchSettings(th);
default:
return base.CreateSettingsSubsectionFor(handler);
}
}
private class AndroidBatteryInfo : BatteryInfo private class AndroidBatteryInfo : BatteryInfo
{ {
public override double? ChargeLevel => Battery.ChargeLevel; public override double? ChargeLevel => Battery.ChargeLevel;

View File

@ -22,7 +22,7 @@ using osu.Game.IPC;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Performance; using osu.Game.Performance;
using osu.Game.Utils; using osu.Game.Utils;
using SDL2; using SDL;
namespace osu.Desktop namespace osu.Desktop
{ {
@ -161,7 +161,7 @@ namespace osu.Desktop
host.Window.Title = Name; host.Window.Title = Name;
} }
protected override BatteryInfo CreateBatteryInfo() => new SDL2BatteryInfo(); protected override BatteryInfo CreateBatteryInfo() => new SDL3BatteryInfo();
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
@ -170,13 +170,14 @@ namespace osu.Desktop
archiveImportIPCChannel?.Dispose(); archiveImportIPCChannel?.Dispose();
} }
private class SDL2BatteryInfo : BatteryInfo private unsafe class SDL3BatteryInfo : BatteryInfo
{ {
public override double? ChargeLevel public override double? ChargeLevel
{ {
get get
{ {
SDL.SDL_GetPowerInfo(out _, out int percentage); int percentage;
SDL3.SDL_GetPowerInfo(null, &percentage);
if (percentage == -1) if (percentage == -1)
return null; return null;
@ -185,7 +186,7 @@ namespace osu.Desktop
} }
} }
public override bool OnBattery => SDL.SDL_GetPowerInfo(out _, out _) == SDL.SDL_PowerState.SDL_POWERSTATE_ON_BATTERY; public override bool OnBattery => SDL3.SDL_GetPowerInfo(null, null) == SDL_PowerState.SDL_POWERSTATE_ON_BATTERY;
} }
} }
} }

View File

@ -13,7 +13,7 @@ using osu.Framework.Platform;
using osu.Game; using osu.Game;
using osu.Game.IPC; using osu.Game.IPC;
using osu.Game.Tournament; using osu.Game.Tournament;
using SDL2; using SDL;
using Squirrel; using Squirrel;
namespace osu.Desktop namespace osu.Desktop
@ -51,18 +51,21 @@ namespace osu.Desktop
// While .NET 8 only supports Windows 10 and above, running on Windows 7/8.1 may still work. We are limited by realm currently, as they choose to only support 8.1 and higher. // While .NET 8 only supports Windows 10 and above, running on Windows 7/8.1 may still work. We are limited by realm currently, as they choose to only support 8.1 and higher.
// See https://www.mongodb.com/docs/realm/sdk/dotnet/compatibility/ // See https://www.mongodb.com/docs/realm/sdk/dotnet/compatibility/
if (windowsVersion.Major < 6 || (windowsVersion.Major == 6 && windowsVersion.Minor <= 2)) if (windowsVersion.Major < 6 || (windowsVersion.Major == 6 && windowsVersion.Minor <= 2))
{
unsafe
{ {
// If users running in compatibility mode becomes more of a common thing, we may want to provide better guidance or even consider // If users running in compatibility mode becomes more of a common thing, we may want to provide better guidance or even consider
// disabling it ourselves. // disabling it ourselves.
// We could also better detect compatibility mode if required: // We could also better detect compatibility mode if required:
// https://stackoverflow.com/questions/10744651/how-i-can-detect-if-my-application-is-running-under-compatibility-mode#comment58183249_10744730 // https://stackoverflow.com/questions/10744651/how-i-can-detect-if-my-application-is-running-under-compatibility-mode#comment58183249_10744730
SDL.SDL_ShowSimpleMessageBox(SDL.SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR, SDL3.SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR,
"Your operating system is too old to run osu!", "Your operating system is too old to run osu!"u8,
"This version of osu! requires at least Windows 8.1 to run.\n" "This version of osu! requires at least Windows 8.1 to run.\n"u8
+ "Please upgrade your operating system or consider using an older version of osu!.\n\n" + "Please upgrade your operating system or consider using an older version of osu!.\n\n"u8
+ "If you are running a newer version of windows, please check you don't have \"Compatibility mode\" turned on for osu!", IntPtr.Zero); + "If you are running a newer version of windows, please check you don't have \"Compatibility mode\" turned on for osu!"u8, null);
return; return;
} }
}
setupSquirrel(); setupSquirrel();
} }
@ -104,7 +107,13 @@ namespace osu.Desktop
} }
} }
using (DesktopGameHost host = Host.GetSuitableDesktopHost(gameName, new HostOptions { IPCPort = !tournamentClient ? OsuGame.IPC_PORT : null })) var hostOptions = new HostOptions
{
IPCPort = !tournamentClient ? OsuGame.IPC_PORT : null,
FriendlyGameName = OsuGameBase.GAME_NAME,
};
using (DesktopGameHost host = Host.GetSuitableDesktopHost(gameName, hostOptions))
{ {
if (!host.IsPrimaryInstance) if (!host.IsPrimaryInstance)
{ {

View File

@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
} }
// Generally all the control points are within the visible area all the time. // Generally all the control points are within the visible area all the time.
public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => true; public override bool UpdateSubTreeMasking() => true;
/// <summary> /// <summary>
/// Handles correction of invalid path types. /// Handles correction of invalid path types.

View File

@ -8,7 +8,6 @@ using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
@ -37,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.UI
// For osu! gameplay, everything is always on screen. // For osu! gameplay, everything is always on screen.
// Skipping masking calculations improves performance in intense beatmaps (ie. https://osu.ppy.sh/beatmapsets/150945#osu/372245) // Skipping masking calculations improves performance in intense beatmaps (ie. https://osu.ppy.sh/beatmapsets/150945#osu/372245)
public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => false; public override bool UpdateSubTreeMasking() => false;
public SmokeContainer Smoke { get; } public SmokeContainer Smoke { get; }
public FollowPointRenderer FollowPoints { get; } public FollowPointRenderer FollowPoints { get; }

View File

@ -7,7 +7,6 @@ using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
@ -345,7 +344,7 @@ namespace osu.Game.Rulesets.Taiko.UI
{ {
public void Add(Drawable proxy) => AddInternal(proxy); public void Add(Drawable proxy) => AddInternal(proxy);
public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) public override bool UpdateSubTreeMasking()
{ {
// DrawableHitObject disables masking. // DrawableHitObject disables masking.
// Hitobject content is proxied and unproxied based on hit status and the IsMaskedAway value could get stuck because of this. // Hitobject content is proxied and unproxied based on hit status and the IsMaskedAway value could get stuck because of this.

View File

@ -22,7 +22,7 @@ namespace osu.Game.Tournament.Screens.Ladder
protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false; protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false;
public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => false; public override bool UpdateSubTreeMasking() => false;
protected override void OnDrag(DragEvent e) protected override void OnDrag(DragEvent e)
{ {

View File

@ -6,6 +6,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using JetBrains.Annotations;
using Realms; using Realms;
using Realms.Schema; using Realms.Schema;
@ -15,8 +16,12 @@ namespace osu.Game.Database
{ {
private IList<T> emptySet => Array.Empty<T>(); private IList<T> emptySet => Array.Empty<T>();
[MustDisposeResource]
public IEnumerator<T> GetEnumerator() => emptySet.GetEnumerator(); public IEnumerator<T> GetEnumerator() => emptySet.GetEnumerator();
[MustDisposeResource]
IEnumerator IEnumerable.GetEnumerator() => emptySet.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => emptySet.GetEnumerator();
public int Count => emptySet.Count; public int Count => emptySet.Count;
public T this[int index] => emptySet[index]; public T this[int index] => emptySet[index];
public int IndexOf(object? item) => item == null ? -1 : emptySet.IndexOf((T)item); public int IndexOf(object? item) => item == null ? -1 : emptySet.IndexOf((T)item);

View File

@ -1,7 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System.Numerics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -10,7 +10,7 @@ using osu.Framework.Graphics.UserInterface;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osuTK; using Vector2 = osuTK.Vector2;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface
/// An <see cref="IExpandable"/> implementation for the UI slider bar control. /// An <see cref="IExpandable"/> implementation for the UI slider bar control.
/// </summary> /// </summary>
public partial class ExpandableSlider<T, TSlider> : CompositeDrawable, IExpandable, IHasCurrentValue<T> public partial class ExpandableSlider<T, TSlider> : CompositeDrawable, IExpandable, IHasCurrentValue<T>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible where T : struct, INumber<T>, IMinMaxValue<T>
where TSlider : RoundedSliderBar<T>, new() where TSlider : RoundedSliderBar<T>, new()
{ {
private readonly OsuSpriteText label; private readonly OsuSpriteText label;
@ -129,7 +129,7 @@ namespace osu.Game.Graphics.UserInterface
/// An <see cref="IExpandable"/> implementation for the UI slider bar control. /// An <see cref="IExpandable"/> implementation for the UI slider bar control.
/// </summary> /// </summary>
public partial class ExpandableSlider<T> : ExpandableSlider<T, RoundedSliderBar<T>> public partial class ExpandableSlider<T> : ExpandableSlider<T, RoundedSliderBar<T>>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible where T : struct, INumber<T>, IMinMaxValue<T>
{ {
} }
} }

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; using System;
using System.Numerics;
using System.Globalization; using System.Globalization;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
@ -15,7 +16,7 @@ using osu.Game.Utils;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
public abstract partial class OsuSliderBar<T> : SliderBar<T>, IHasTooltip public abstract partial class OsuSliderBar<T> : SliderBar<T>, IHasTooltip
where T : struct, IEquatable<T>, IComparable<T>, IConvertible where T : struct, INumber<T>, IMinMaxValue<T>
{ {
public bool PlaySamplesOnAdjust { get; set; } = true; public bool PlaySamplesOnAdjust { get; set; } = true;
@ -85,11 +86,11 @@ namespace osu.Game.Graphics.UserInterface
private LocalisableString getTooltipText(T value) private LocalisableString getTooltipText(T value)
{ {
if (CurrentNumber.IsInteger) if (CurrentNumber.IsInteger)
return value.ToInt32(NumberFormatInfo.InvariantInfo).ToString("N0"); return int.CreateTruncating(value).ToString("N0");
double floatValue = value.ToDouble(NumberFormatInfo.InvariantInfo); double floatValue = double.CreateTruncating(value);
decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits); decimal decimalPrecision = normalise(decimal.CreateTruncating(CurrentNumber.Precision), max_decimal_digits);
// Find the number of significant digits (we could have less than 5 after normalize()) // Find the number of significant digits (we could have less than 5 after normalize())
int significantDigits = FormatUtils.FindPrecision(decimalPrecision); int significantDigits = FormatUtils.FindPrecision(decimalPrecision);

View File

@ -8,6 +8,8 @@ using System.Linq;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
@ -143,13 +145,6 @@ namespace osu.Game.Graphics.UserInterface
FadeUnhovered(); FadeUnhovered();
} }
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
if (accentColour == default)
AccentColour = colours.Blue;
}
public OsuTabItem(T value) public OsuTabItem(T value)
: base(value) : base(value)
{ {
@ -196,10 +191,21 @@ namespace osu.Game.Graphics.UserInterface
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
}, },
new HoverClickSounds(HoverSampleSet.TabSelect) new HoverSounds(HoverSampleSet.TabSelect)
}; };
} }
private Sample selectSample;
[BackgroundDependencyLoader]
private void load(OsuColour colours, AudioManager audio)
{
if (accentColour == default)
AccentColour = colours.Blue;
selectSample = audio.Samples.Get(@"UI/tabselect-select");
}
protected override void OnActivated() protected override void OnActivated()
{ {
Text.Font = Text.Font.With(weight: FontWeight.Bold); Text.Font = Text.Font.With(weight: FontWeight.Bold);
@ -211,6 +217,8 @@ namespace osu.Game.Graphics.UserInterface
Text.Font = Text.Font.With(weight: FontWeight.Medium); Text.Font = Text.Font.With(weight: FontWeight.Medium);
FadeUnhovered(); FadeUnhovered();
} }
protected override void OnActivatedByUser() => selectSample.Play();
} }
} }
} }

View File

@ -7,6 +7,8 @@ using System;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -53,6 +55,8 @@ namespace osu.Game.Graphics.UserInterface
} }
} }
private Sample selectSample = null!;
public PageTabItem(T value) public PageTabItem(T value)
: base(value) : base(value)
{ {
@ -78,12 +82,18 @@ namespace osu.Game.Graphics.UserInterface
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
}, },
new HoverClickSounds(HoverSampleSet.TabSelect) new HoverSounds(HoverSampleSet.TabSelect)
}; };
Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Torus, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Torus, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true);
} }
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
selectSample = audio.Samples.Get(@"UI/tabselect-select");
}
protected virtual LocalisableString CreateText() => (Value as Enum)?.GetLocalisableDescription() ?? Value.ToString(); protected virtual LocalisableString CreateText() => (Value as Enum)?.GetLocalisableDescription() ?? Value.ToString();
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)
@ -112,6 +122,8 @@ namespace osu.Game.Graphics.UserInterface
protected override void OnActivated() => slideActive(); protected override void OnActivated() => slideActive();
protected override void OnDeactivated() => slideInactive(); protected override void OnDeactivated() => slideInactive();
protected override void OnActivatedByUser() => selectSample.Play();
} }
} }
} }

View File

@ -2,7 +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; using System;
using osuTK; using System.Numerics;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
@ -11,11 +11,12 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Overlays; using osu.Game.Overlays;
using Vector2 = osuTK.Vector2;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
public partial class RoundedSliderBar<T> : OsuSliderBar<T> public partial class RoundedSliderBar<T> : OsuSliderBar<T>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible where T : struct, INumber<T>, IMinMaxValue<T>
{ {
protected readonly Nub Nub; protected readonly Nub Nub;
protected readonly Box LeftBox; protected readonly Box LeftBox;

View File

@ -2,7 +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; using System;
using osuTK; using System.Numerics;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
@ -12,11 +12,12 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Overlays; using osu.Game.Overlays;
using static osu.Game.Graphics.UserInterface.ShearedNub; using static osu.Game.Graphics.UserInterface.ShearedNub;
using Vector2 = osuTK.Vector2;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
public partial class ShearedSliderBar<T> : OsuSliderBar<T> public partial class ShearedSliderBar<T> : OsuSliderBar<T>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible where T : struct, INumber<T>, IMinMaxValue<T>
{ {
protected readonly ShearedNub Nub; protected readonly ShearedNub Nub;
protected readonly Box LeftBox; protected readonly Box LeftBox;

View File

@ -1,14 +1,14 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System.Numerics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
namespace osu.Game.Graphics.UserInterfaceV2 namespace osu.Game.Graphics.UserInterfaceV2
{ {
public partial class LabelledSliderBar<TNumber> : LabelledComponent<SettingsSlider<TNumber>, TNumber> public partial class LabelledSliderBar<TNumber> : LabelledComponent<SettingsSlider<TNumber>, TNumber>
where TNumber : struct, IEquatable<TNumber>, IComparable<TNumber>, IConvertible where TNumber : struct, INumber<TNumber>, IMinMaxValue<TNumber>
{ {
public LabelledSliderBar() public LabelledSliderBar()
: base(true) : base(true)

View File

@ -1,7 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System.Numerics;
using System.Globalization; using System.Globalization;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -10,12 +10,12 @@ using osu.Framework.Graphics.UserInterface;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
using osu.Game.Utils; using osu.Game.Utils;
using osuTK; using Vector2 = osuTK.Vector2;
namespace osu.Game.Graphics.UserInterfaceV2 namespace osu.Game.Graphics.UserInterfaceV2
{ {
public partial class SliderWithTextBoxInput<T> : CompositeDrawable, IHasCurrentValue<T> public partial class SliderWithTextBoxInput<T> : CompositeDrawable, IHasCurrentValue<T>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible where T : struct, INumber<T>, IMinMaxValue<T>
{ {
/// <summary> /// <summary>
/// A custom step value for each key press which actuates a change on this control. /// A custom step value for each key press which actuates a change on this control.
@ -138,7 +138,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
{ {
if (updatingFromTextBox) return; if (updatingFromTextBox) return;
decimal decimalValue = slider.Current.Value.ToDecimal(NumberFormatInfo.InvariantInfo); decimal decimalValue = decimal.CreateTruncating(slider.Current.Value);
textBox.Text = decimalValue.ToString($@"N{FormatUtils.FindPrecision(decimalValue)}"); textBox.Text = decimalValue.ToString($@"N{FormatUtils.FindPrecision(decimalValue)}");
} }
} }

View File

@ -75,6 +75,12 @@ namespace osu.Game
{ {
public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv", ".mpg", ".wmv", ".m4v" }; public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv", ".mpg", ".wmv", ".m4v" };
#if DEBUG
public const string GAME_NAME = "osu! (development)";
#else
public const string GAME_NAME = "osu!";
#endif
public const string OSU_PROTOCOL = "osu://"; public const string OSU_PROTOCOL = "osu://";
public const string CLIENT_STREAM_NAME = @"lazer"; public const string CLIENT_STREAM_NAME = @"lazer";
@ -241,11 +247,7 @@ namespace osu.Game
public OsuGameBase() public OsuGameBase()
{ {
Name = @"osu!"; Name = GAME_NAME;
#if DEBUG
Name += " (development)";
#endif
allowableExceptions = UnhandledExceptionsBeforeCrash; allowableExceptions = UnhandledExceptionsBeforeCrash;
} }

View File

@ -5,6 +5,8 @@
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -47,13 +49,15 @@ namespace osu.Game.Overlays.BeatmapListing
[Resolved] [Resolved]
private OverlayColourProvider colourProvider { get; set; } private OverlayColourProvider colourProvider { get; set; }
private Sample selectSample = null!;
public TabItem(BeatmapCardSize value) public TabItem(BeatmapCardSize value)
: base(value) : base(value)
{ {
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load(AudioManager audio)
{ {
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
Masking = true; Masking = true;
@ -79,8 +83,10 @@ namespace osu.Game.Overlays.BeatmapListing
Icon = getIconForCardSize(Value) Icon = getIconForCardSize(Value)
} }
}, },
new HoverClickSounds(HoverSampleSet.TabSelect) new HoverSounds(HoverSampleSet.TabSelect)
}; };
selectSample = audio.Samples.Get(@"UI/tabselect-select");
} }
private static IconUsage getIconForCardSize(BeatmapCardSize cardSize) private static IconUsage getIconForCardSize(BeatmapCardSize cardSize)
@ -111,6 +117,8 @@ namespace osu.Game.Overlays.BeatmapListing
updateState(); updateState();
} }
protected override void OnActivatedByUser() => selectSample.Play();
protected override void OnDeactivated() protected override void OnDeactivated()
{ {
if (IsLoaded) if (IsLoaded)

View File

@ -128,7 +128,11 @@ namespace osu.Game.Overlays.BeatmapListing
protected override bool OnClick(ClickEvent e) protected override bool OnClick(ClickEvent e)
{ {
base.OnClick(e); base.OnClick(e);
// this tab item implementation is not managed by a TabControl,
// therefore we have to manually update Active state and play select sound when this tab item is clicked.
Active.Toggle(); Active.Toggle();
SelectSample.Play();
return true; return true;
} }
} }

View File

@ -5,6 +5,8 @@
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
@ -24,13 +26,15 @@ namespace osu.Game.Overlays.BeatmapListing
private OsuSpriteText text; private OsuSpriteText text;
protected Sample SelectSample { get; private set; } = null!;
public FilterTabItem(T value) public FilterTabItem(T value)
: base(value) : base(value)
{ {
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load(AudioManager audio)
{ {
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
AddRangeInternal(new Drawable[] AddRangeInternal(new Drawable[]
@ -40,10 +44,12 @@ namespace osu.Game.Overlays.BeatmapListing
Font = OsuFont.GetFont(size: 13, weight: FontWeight.Regular), Font = OsuFont.GetFont(size: 13, weight: FontWeight.Regular),
Text = LabelFor(Value) Text = LabelFor(Value)
}, },
new HoverClickSounds(HoverSampleSet.TabSelect) new HoverSounds(HoverSampleSet.TabSelect)
}); });
Enabled.Value = true; Enabled.Value = true;
SelectSample = audio.Samples.Get(@"UI/tabselect-select");
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -71,6 +77,8 @@ namespace osu.Game.Overlays.BeatmapListing
protected override void OnDeactivated() => UpdateState(); protected override void OnDeactivated() => UpdateState();
protected override void OnActivatedByUser() => SelectSample.Play();
/// <summary> /// <summary>
/// Returns the label text to be used for the supplied <paramref name="value"/>. /// Returns the label text to be used for the supplied <paramref name="value"/>.
/// </summary> /// </summary>

View File

@ -21,7 +21,7 @@ namespace osu.Game.Overlays.BeatmapSet
// propagate value to tab items first to enable only available rulesets. // propagate value to tab items first to enable only available rulesets.
beatmapSet.Value = value; beatmapSet.Value = value;
SelectTab(TabContainer.TabItems.FirstOrDefault(t => t.Enabled.Value)); Current.Value = TabContainer.TabItems.FirstOrDefault(t => t.Enabled.Value)?.Value;
} }
} }

View File

@ -11,6 +11,8 @@ using osuTK;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Localisation; using osu.Framework.Localisation;
@ -65,6 +67,8 @@ namespace osu.Game.Overlays
private readonly SpriteIcon icon; private readonly SpriteIcon icon;
private Sample selectSample = null!;
public PanelDisplayTabItem(OverlayPanelDisplayStyle value) public PanelDisplayTabItem(OverlayPanelDisplayStyle value)
: base(value) : base(value)
{ {
@ -78,14 +82,22 @@ namespace osu.Game.Overlays
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit FillMode = FillMode.Fit
}, },
new HoverClickSounds() new HoverSounds(HoverSampleSet.TabSelect)
}); });
} }
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
selectSample = audio.Samples.Get(@"UI/tabselect-select");
}
protected override void OnActivated() => updateState(); protected override void OnActivated() => updateState();
protected override void OnDeactivated() => updateState(); protected override void OnDeactivated() => updateState();
protected override void OnActivatedByUser() => selectSample.Play();
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)
{ {
updateState(); updateState();

View File

@ -10,6 +10,8 @@ using osu.Game.Rulesets;
using osuTK.Graphics; using osuTK.Graphics;
using osuTK; using osuTK;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
@ -39,6 +41,8 @@ namespace osu.Game.Overlays
public LocalisableString TooltipText => Value.Name; public LocalisableString TooltipText => Value.Name;
private Sample selectSample = null!;
public OverlayRulesetTabItem(RulesetInfo value) public OverlayRulesetTabItem(RulesetInfo value)
: base(value) : base(value)
{ {
@ -59,12 +63,18 @@ namespace osu.Game.Overlays
Icon = value.CreateInstance().CreateIcon(), Icon = value.CreateInstance().CreateIcon(),
}, },
}, },
new HoverClickSounds() new HoverSounds(HoverSampleSet.TabSelect)
}); });
Enabled.Value = true; Enabled.Value = true;
} }
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
selectSample = audio.Samples.Get(@"UI/tabselect-select");
}
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
@ -90,6 +100,8 @@ namespace osu.Game.Overlays
protected override void OnDeactivated() => updateState(); protected override void OnDeactivated() => updateState();
protected override void OnActivatedByUser() => selectSample.Play();
private void updateState() private void updateState()
{ {
AccentColour = Enabled.Value ? getActiveColour() : colourProvider.Foreground1; AccentColour = Enabled.Value ? getActiveColour() : colourProvider.Foreground1;

View File

@ -11,6 +11,8 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using osuTK.Graphics; using osuTK.Graphics;
@ -49,8 +51,10 @@ namespace osu.Game.Overlays
Margin = new MarginPadding(PADDING); Margin = new MarginPadding(PADDING);
} }
private Sample selectSample;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider, OsuColour colours) private void load(OverlayColourProvider colourProvider, OsuColour colours, AudioManager audio)
{ {
AddRange(new Drawable[] AddRange(new Drawable[]
{ {
@ -87,9 +91,11 @@ namespace osu.Game.Overlays
CollapsedSize = 2, CollapsedSize = 2,
Expanded = true Expanded = true
}, },
new HoverClickSounds() new HoverSounds(HoverSampleSet.TabSelect)
}); });
selectSample = audio.Samples.Get(@"UI/tabselect-select");
SelectedItem.BindValueChanged(_ => updateState(), true); SelectedItem.BindValueChanged(_ => updateState(), true);
} }
@ -105,6 +111,8 @@ namespace osu.Game.Overlays
protected override void OnDeactivated() => updateState(); protected override void OnDeactivated() => updateState();
protected override void OnActivatedByUser() => selectSample.Play();
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)
{ {
updateState(); updateState();

View File

@ -4,6 +4,8 @@
#nullable disable #nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
@ -80,6 +82,8 @@ namespace osu.Game.Overlays
} }
} }
private Sample selectSample = null!;
public OverlayTabItem(T value) public OverlayTabItem(T value)
: base(value) : base(value)
{ {
@ -101,10 +105,16 @@ namespace osu.Game.Overlays
ExpandedSize = 5f, ExpandedSize = 5f,
CollapsedSize = 0 CollapsedSize = 0
}, },
new HoverClickSounds(HoverSampleSet.TabSelect) new HoverSounds(HoverSampleSet.TabSelect)
}; };
} }
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
selectSample = audio.Samples.Get(@"UI/tabselect-select");
}
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)
{ {
base.OnHover(e); base.OnHover(e);
@ -136,6 +146,8 @@ namespace osu.Game.Overlays
Text.Font = Text.Font.With(weight: FontWeight.Medium); Text.Font = Text.Font.With(weight: FontWeight.Medium);
} }
protected override void OnActivatedByUser() => selectSample.Play();
private void updateState() private void updateState()
{ {
if (Active.Value) if (Active.Value)

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; using System;
using System.Numerics;
using System.Globalization; using System.Globalization;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
@ -12,7 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections
/// A slider intended to show a "size" multiplier number, where 1x is 1.0. /// A slider intended to show a "size" multiplier number, where 1x is 1.0.
/// </summary> /// </summary>
public partial class SizeSlider<T> : RoundedSliderBar<T> public partial class SizeSlider<T> : RoundedSliderBar<T>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible, IFormattable where T : struct, INumber<T>, IMinMaxValue<T>, IFormattable
{ {
public override LocalisableString TooltipText => Current.Value.ToString(@"0.##x", NumberFormatInfo.CurrentInfo); public override LocalisableString TooltipText => Current.Value.ToString(@"0.##x", NumberFormatInfo.CurrentInfo);
} }

View File

@ -1,7 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System.Numerics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Settings
/// Mostly provided for convenience of use with <see cref="SettingSourceAttribute"/>. /// Mostly provided for convenience of use with <see cref="SettingSourceAttribute"/>.
/// </summary> /// </summary>
public partial class SettingsPercentageSlider<TValue> : SettingsSlider<TValue> public partial class SettingsPercentageSlider<TValue> : SettingsSlider<TValue>
where TValue : struct, IEquatable<TValue>, IComparable<TValue>, IConvertible where TValue : struct, INumber<TValue>, IMinMaxValue<TValue>
{ {
protected override Drawable CreateControl() => ((RoundedSliderBar<TValue>)base.CreateControl()).With(sliderBar => sliderBar.DisplayAsPercentage = true); protected override Drawable CreateControl() => ((RoundedSliderBar<TValue>)base.CreateControl()).With(sliderBar => sliderBar.DisplayAsPercentage = true);
} }

View File

@ -1,7 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System.Numerics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
@ -9,12 +9,12 @@ using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.Settings namespace osu.Game.Overlays.Settings
{ {
public partial class SettingsSlider<T> : SettingsSlider<T, RoundedSliderBar<T>> public partial class SettingsSlider<T> : SettingsSlider<T, RoundedSliderBar<T>>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible where T : struct, INumber<T>, IMinMaxValue<T>
{ {
} }
public partial class SettingsSlider<TValue, TSlider> : SettingsItem<TValue> public partial class SettingsSlider<TValue, TSlider> : SettingsItem<TValue>
where TValue : struct, IEquatable<TValue>, IComparable<TValue>, IConvertible where TValue : struct, INumber<TValue>, IMinMaxValue<TValue>
where TSlider : RoundedSliderBar<TValue>, new() where TSlider : RoundedSliderBar<TValue>, new()
{ {
protected override Drawable CreateControl() => new TSlider protected override Drawable CreateControl() => new TSlider

View File

@ -3,11 +3,8 @@
#nullable disable #nullable disable
using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -24,8 +21,6 @@ namespace osu.Game.Overlays.Toolbar
{ {
protected Drawable ModeButtonLine { get; private set; } protected Drawable ModeButtonLine { get; private set; }
private readonly Dictionary<string, Sample> selectionSamples = new Dictionary<string, Sample>();
public ToolbarRulesetSelector() public ToolbarRulesetSelector()
{ {
RelativeSizeAxes = Axes.Y; RelativeSizeAxes = Axes.Y;
@ -33,7 +28,7 @@ namespace osu.Game.Overlays.Toolbar
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(AudioManager audio) private void load()
{ {
AddRangeInternal(new[] AddRangeInternal(new[]
{ {
@ -59,9 +54,6 @@ namespace osu.Game.Overlays.Toolbar
} }
}, },
}); });
foreach (var ruleset in Rulesets.AvailableRulesets)
selectionSamples[ruleset.ShortName] = audio.Samples.Get($"UI/ruleset-select-{ruleset.ShortName}");
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -88,10 +80,6 @@ namespace osu.Game.Overlays.Toolbar
if (SelectedTab != null) if (SelectedTab != null)
{ {
ModeButtonLine.MoveToX(SelectedTab.DrawPosition.X, !hasInitialPosition ? 0 : 500, Easing.OutElasticQuarter); ModeButtonLine.MoveToX(SelectedTab.DrawPosition.X, !hasInitialPosition ? 0 : 500, Easing.OutElasticQuarter);
if (hasInitialPosition)
selectionSamples[SelectedTab.Value.ShortName]?.Play();
hasInitialPosition = true; hasInitialPosition = true;
} }
} }
@ -121,7 +109,7 @@ namespace osu.Game.Overlays.Toolbar
RulesetInfo found = Rulesets.AvailableRulesets.ElementAtOrDefault(requested); RulesetInfo found = Rulesets.AvailableRulesets.ElementAtOrDefault(requested);
if (found != null) if (found != null)
Current.Value = found; SelectItem(found);
return true; return true;
} }

View File

@ -2,6 +2,8 @@
// 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.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
@ -17,6 +19,8 @@ namespace osu.Game.Overlays.Toolbar
{ {
private readonly RulesetButton ruleset; private readonly RulesetButton ruleset;
private Sample? selectSample;
public ToolbarRulesetTabButton(RulesetInfo value) public ToolbarRulesetTabButton(RulesetInfo value)
: base(value) : base(value)
{ {
@ -34,10 +38,18 @@ namespace osu.Game.Overlays.Toolbar
ruleset.SetIcon(rInstance.CreateIcon()); ruleset.SetIcon(rInstance.CreateIcon());
} }
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
selectSample = audio.Samples.Get($@"UI/ruleset-select-{Value.ShortName}");
}
protected override void OnActivated() => ruleset.Active = true; protected override void OnActivated() => ruleset.Active = true;
protected override void OnDeactivated() => ruleset.Active = false; protected override void OnDeactivated() => ruleset.Active = false;
protected override void OnActivatedByUser() => selectSample?.Play();
private partial class RulesetButton : ToolbarButton private partial class RulesetButton : ToolbarButton
{ {
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds(); protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds();

View File

@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Mods
} }
} }
private float maxValue; private float maxValue = 10; // matches default max value of `CurrentNumber`
public float MaxValue public float MaxValue
{ {

View File

@ -15,7 +15,6 @@ using osu.Framework.Extensions.ListExtensions;
using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Extensions.TypeExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Lists; using osu.Framework.Lists;
using osu.Framework.Threading; using osu.Framework.Threading;
using osu.Framework.Utils; using osu.Framework.Utils;
@ -632,7 +631,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
#endregion #endregion
public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => false; public override bool UpdateSubTreeMasking() => false;
protected override void UpdateAfterChildren() protected override void UpdateAfterChildren()
{ {

View File

@ -129,6 +129,13 @@ namespace osu.Game.Rulesets.Scoring
OnIterationFail?.Invoke($"FAILED drop {testDrop}: recovery too low ({recovery} < {hpRecoveryAvailable})"); OnIterationFail?.Invoke($"FAILED drop {testDrop}: recovery too low ({recovery} < {hpRecoveryAvailable})");
} }
if (!fail && double.IsInfinity(HpMultiplierNormal))
{
OnIterationSuccess?.Invoke("Drain computation algorithm diverged to infinity. PASSING with zero drop, resetting HP multiplier to 1.");
HpMultiplierNormal = 1;
return 0;
}
if (!fail) if (!fail)
{ {
OnIterationSuccess?.Invoke($"PASSED drop {testDrop}"); OnIterationSuccess?.Invoke($"PASSED drop {testDrop}");

View File

@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.UI
break; break;
base.UpdateSubTree(); base.UpdateSubTree();
UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); UpdateSubTreeMasking();
} while (state == PlaybackState.RequiresCatchUp && stopwatch.ElapsedMilliseconds < max_catchup_milliseconds); } while (state == PlaybackState.RequiresCatchUp && stopwatch.ElapsedMilliseconds < max_catchup_milliseconds);
return true; return true;

View File

@ -7,7 +7,6 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Caching; using osu.Framework.Caching;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -20,7 +19,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
public partial class TimelineTickDisplay : TimelinePart<PointVisualisation> public partial class TimelineTickDisplay : TimelinePart<PointVisualisation>
{ {
// With current implementation every tick in the sub-tree should be visible, no need to check whether they are masked away. // With current implementation every tick in the sub-tree should be visible, no need to check whether they are masked away.
public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => false; public override bool UpdateSubTreeMasking() => false;
[Resolved] [Resolved]
private EditorBeatmap beatmap { get; set; } = null!; private EditorBeatmap beatmap { get; set; } = null!;

View File

@ -372,7 +372,7 @@ namespace osu.Game.Screens.Edit
} }
} }
}, },
new EditorScreenSwitcherControl screenSwitcher = new EditorScreenSwitcherControl
{ {
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
@ -662,23 +662,23 @@ namespace osu.Game.Screens.Edit
return true; return true;
case GlobalAction.EditorComposeMode: case GlobalAction.EditorComposeMode:
Mode.Value = EditorScreenMode.Compose; screenSwitcher.SelectItem(EditorScreenMode.Compose);
return true; return true;
case GlobalAction.EditorDesignMode: case GlobalAction.EditorDesignMode:
Mode.Value = EditorScreenMode.Design; screenSwitcher.SelectItem(EditorScreenMode.Design);
return true; return true;
case GlobalAction.EditorTimingMode: case GlobalAction.EditorTimingMode:
Mode.Value = EditorScreenMode.Timing; screenSwitcher.SelectItem(EditorScreenMode.Timing);
return true; return true;
case GlobalAction.EditorSetupMode: case GlobalAction.EditorSetupMode:
Mode.Value = EditorScreenMode.SongSetup; screenSwitcher.SelectItem(EditorScreenMode.SongSetup);
return true; return true;
case GlobalAction.EditorVerifyMode: case GlobalAction.EditorVerifyMode:
Mode.Value = EditorScreenMode.Verify; screenSwitcher.SelectItem(EditorScreenMode.Verify);
return true; return true;
case GlobalAction.EditorTestGameplay: case GlobalAction.EditorTestGameplay:
@ -959,6 +959,8 @@ namespace osu.Game.Screens.Edit
[CanBeNull] [CanBeNull]
private ScheduledDelegate playbackDisabledDebounce; private ScheduledDelegate playbackDisabledDebounce;
private EditorScreenSwitcherControl screenSwitcher;
private void updateSampleDisabledState() private void updateSampleDisabledState()
{ {
bool shouldDisableSamples = clock.SeekingOrStopped.Value bool shouldDisableSamples = clock.SeekingOrStopped.Value

View File

@ -1,7 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System.Numerics;
using System.Globalization; using System.Globalization;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -12,7 +12,7 @@ using osu.Framework.Localisation;
using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
using osu.Game.Utils; using osu.Game.Utils;
using osuTK; using Vector2 = osuTK.Vector2;
namespace osu.Game.Screens.Edit.Timing namespace osu.Game.Screens.Edit.Timing
{ {
@ -22,7 +22,7 @@ namespace osu.Game.Screens.Edit.Timing
/// by providing an "indeterminate state". /// by providing an "indeterminate state".
/// </summary> /// </summary>
public partial class IndeterminateSliderWithTextBoxInput<T> : CompositeDrawable, IHasCurrentValue<T?> public partial class IndeterminateSliderWithTextBoxInput<T> : CompositeDrawable, IHasCurrentValue<T?>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible where T : struct, INumber<T>, IMinMaxValue<T>
{ {
/// <summary> /// <summary>
/// A custom step value for each key press which actuates a change on this control. /// A custom step value for each key press which actuates a change on this control.
@ -136,7 +136,7 @@ namespace osu.Game.Screens.Edit.Timing
slider.Current.Value = nonNullValue; slider.Current.Value = nonNullValue;
// use the value from the slider to ensure that any precision/min/max set on it via the initial indeterminate value have been applied correctly. // use the value from the slider to ensure that any precision/min/max set on it via the initial indeterminate value have been applied correctly.
decimal decimalValue = slider.Current.Value.ToDecimal(NumberFormatInfo.InvariantInfo); decimal decimalValue = decimal.CreateTruncating(slider.Current.Value);
textBox.Text = decimalValue.ToString($@"N{FormatUtils.FindPrecision(decimalValue)}"); textBox.Text = decimalValue.ToString($@"N{FormatUtils.FindPrecision(decimalValue)}");
textBox.PlaceholderText = string.Empty; textBox.PlaceholderText = string.Empty;
} }

View File

@ -4,6 +4,8 @@
#nullable disable #nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -78,14 +80,17 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
}, },
}, },
}, },
new HoverClickSounds(), new HoverSounds(HoverSampleSet.TabSelect),
}; };
} }
private Sample selectSample;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours, AudioManager audio)
{ {
selection.Colour = colours.Yellow; selection.Colour = colours.Yellow;
selectSample = audio.Samples.Get(@"UI/tabselect-select");
} }
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)
@ -109,6 +114,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
{ {
selection.FadeOut(transition_duration, Easing.OutQuint); selection.FadeOut(transition_duration, Easing.OutQuint);
} }
protected override void OnActivatedByUser() => selectSample.Play();
} }
} }
} }

View File

@ -1,7 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System.Numerics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings;
namespace osu.Game.Screens.Play.PlayerSettings namespace osu.Game.Screens.Play.PlayerSettings
{ {
public partial class PlayerSliderBar<T> : SettingsSlider<T> public partial class PlayerSliderBar<T> : SettingsSlider<T>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible where T : struct, INumber<T>, IMinMaxValue<T>
{ {
public RoundedSliderBar<T> Bar => (RoundedSliderBar<T>)Control; public RoundedSliderBar<T> Bar => (RoundedSliderBar<T>)Control;

View File

@ -35,8 +35,8 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Realm" Version="11.5.0" /> <PackageReference Include="Realm" Version="11.5.0" />
<PackageReference Include="ppy.osu.Framework" Version="2024.329.0" /> <PackageReference Include="ppy.osu.Framework" Version="2024.509.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2024.517.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2024.510.0" />
<PackageReference Include="Sentry" Version="4.3.0" /> <PackageReference Include="Sentry" Version="4.3.0" />
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. --> <!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
<PackageReference Include="SharpCompress" Version="0.36.0" /> <PackageReference Include="SharpCompress" Version="0.36.0" />

View File

@ -23,6 +23,6 @@
<RuntimeIdentifier>iossimulator-x64</RuntimeIdentifier> <RuntimeIdentifier>iossimulator-x64</RuntimeIdentifier>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Framework.iOS" Version="2024.329.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2024.509.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>