1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 14:47:25 +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
@ -52,16 +52,19 @@ namespace osu.Desktop
// 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))
{ {
// If users running in compatibility mode becomes more of a common thing, we may want to provide better guidance or even consider unsafe
// disabling it ourselves. {
// We could also better detect compatibility mode if required: // If users running in compatibility mode becomes more of a common thing, we may want to provide better guidance or even consider
// https://stackoverflow.com/questions/10744651/how-i-can-detect-if-my-application-is-running-under-compatibility-mode#comment58183249_10744730 // disabling it ourselves.
SDL.SDL_ShowSimpleMessageBox(SDL.SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR, // We could also better detect compatibility mode if required:
"Your operating system is too old to run osu!", // https://stackoverflow.com/questions/10744651/how-i-can-detect-if-my-application-is-running-under-compatibility-mode#comment58183249_10744730
"This version of osu! requires at least Windows 8.1 to run.\n" SDL3.SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR,
+ "Please upgrade your operating system or consider using an older version of osu!.\n\n" "Your operating system is too old to run osu!"u8,
+ "If you are running a newer version of windows, please check you don't have \"Compatibility mode\" turned on for osu!", IntPtr.Zero); "This version of osu! requires at least Windows 8.1 to run.\n"u8
return; + "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!"u8, null);
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>