mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 20:22:55 +08:00
Merge pull request #11725 from smoogipoo/freemods-user-settings
Add local user customisation for freemod mod settings
This commit is contained in:
commit
98c5b0220c
52
osu.Game/Configuration/ModSettingChangeTracker.cs
Normal file
52
osu.Game/Configuration/ModSettingChangeTracker.cs
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// A helper class for tracking changes to the settings of a set of <see cref="Mod"/>s.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ensure to dispose when usage is finished.
|
||||
/// </remarks>
|
||||
public class ModSettingChangeTracker : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Notifies that the setting of a <see cref="Mod"/> has changed.
|
||||
/// </summary>
|
||||
public Action<Mod> SettingChanged;
|
||||
|
||||
private readonly List<ISettingsItem> settings = new List<ISettingsItem>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ModSettingChangeTracker"/> for a set of <see cref="Mod"/>s.
|
||||
/// </summary>
|
||||
/// <param name="mods">The set of <see cref="Mod"/>s whose settings need to be tracked.</param>
|
||||
public ModSettingChangeTracker(IEnumerable<Mod> mods)
|
||||
{
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
foreach (var setting in mod.CreateSettingsControls().OfType<ISettingsItem>())
|
||||
{
|
||||
setting.SettingChanged += () => SettingChanged?.Invoke(mod);
|
||||
settings.Add(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
SettingChanged = null;
|
||||
|
||||
foreach (var r in settings)
|
||||
r.Dispose();
|
||||
settings.Clear();
|
||||
}
|
||||
}
|
||||
}
|
@ -51,6 +51,11 @@ namespace osu.Game.Overlays.Mods
|
||||
/// </summary>
|
||||
protected virtual bool Stacked => true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether configurable <see cref="Mod"/>s can be configured by the local user.
|
||||
/// </summary>
|
||||
protected virtual bool AllowConfiguration => true;
|
||||
|
||||
[NotNull]
|
||||
private Func<Mod, bool> isValidMod = m => true;
|
||||
|
||||
@ -300,6 +305,7 @@ namespace osu.Game.Overlays.Mods
|
||||
Text = "Customisation",
|
||||
Action = () => ModSettingsContainer.ToggleVisibility(),
|
||||
Enabled = { Value = false },
|
||||
Alpha = AllowConfiguration ? 1 : 0,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
},
|
||||
@ -512,7 +518,8 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
OnModSelected(selectedMod);
|
||||
|
||||
if (selectedMod.RequiresConfiguration) ModSettingsContainer.Show();
|
||||
if (selectedMod.RequiresConfiguration && AllowConfiguration)
|
||||
ModSettingsContainer.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -20,17 +20,18 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
{
|
||||
protected override bool Stacked => false;
|
||||
|
||||
protected override bool AllowConfiguration => false;
|
||||
|
||||
public new Func<Mod, bool> IsValidMod
|
||||
{
|
||||
get => base.IsValidMod;
|
||||
set => base.IsValidMod = m => m.HasImplementation && !m.RequiresConfiguration && !(m is ModAutoplay) && value(m);
|
||||
set => base.IsValidMod = m => m.HasImplementation && !(m is ModAutoplay) && value(m);
|
||||
}
|
||||
|
||||
public FreeModSelectOverlay()
|
||||
{
|
||||
IsValidMod = m => true;
|
||||
|
||||
CustomiseButton.Alpha = 0;
|
||||
MultiplierSection.Alpha = 0;
|
||||
DeselectAllButton.Alpha = 0;
|
||||
|
||||
|
@ -59,6 +59,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea();
|
||||
|
||||
protected override bool IsValidFreeMod(Mod mod) => base.IsValidFreeMod(mod) && !(mod is ModTimeRamp) && !(mod is ModRateAdjust) && !mod.RequiresConfiguration;
|
||||
protected override bool IsValidFreeMod(Mod mod) => base.IsValidFreeMod(mod) && !(mod is ModTimeRamp) && !(mod is ModRateAdjust);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays.Mods;
|
||||
@ -314,12 +316,33 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
private ModSettingChangeTracker modSettingChangeTracker;
|
||||
private ScheduledDelegate debouncedModSettingsUpdate;
|
||||
|
||||
private void onUserModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
||||
{
|
||||
modSettingChangeTracker?.Dispose();
|
||||
|
||||
if (client.Room == null)
|
||||
return;
|
||||
|
||||
client.ChangeUserMods(mods.NewValue);
|
||||
|
||||
modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue);
|
||||
modSettingChangeTracker.SettingChanged += onModSettingsChanged;
|
||||
}
|
||||
|
||||
private void onModSettingsChanged(Mod mod)
|
||||
{
|
||||
// Debounce changes to mod settings so as to not thrash the network.
|
||||
debouncedModSettingsUpdate?.Cancel();
|
||||
debouncedModSettingsUpdate = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
if (client.Room == null)
|
||||
return;
|
||||
|
||||
client.ChangeUserMods(UserMods.Value);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
private void updateBeatmapAvailability(ValueChangedEvent<BeatmapAvailability> availability)
|
||||
@ -385,14 +408,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
if (client != null)
|
||||
client.LoadRequested -= onLoadRequested;
|
||||
|
||||
modSettingChangeTracker?.Dispose();
|
||||
}
|
||||
|
||||
private class UserModSelectOverlay : LocalPlayerModSelectOverlay
|
||||
{
|
||||
public UserModSelectOverlay()
|
||||
{
|
||||
CustomiseButton.Alpha = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ using System.Threading;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets;
|
||||
|
||||
namespace osu.Game.Screens.Select.Details
|
||||
@ -83,32 +82,22 @@ namespace osu.Game.Screens.Select.Details
|
||||
mods.BindValueChanged(modsChanged, true);
|
||||
}
|
||||
|
||||
private readonly List<ISettingsItem> references = new List<ISettingsItem>();
|
||||
private ModSettingChangeTracker modSettingChangeTracker;
|
||||
private ScheduledDelegate debouncedStatisticsUpdate;
|
||||
|
||||
private void modsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
||||
{
|
||||
// TODO: find a more permanent solution for this if/when it is needed in other components.
|
||||
// this is generating drawables for the only purpose of storing bindable references.
|
||||
foreach (var r in references)
|
||||
r.Dispose();
|
||||
modSettingChangeTracker?.Dispose();
|
||||
|
||||
references.Clear();
|
||||
|
||||
ScheduledDelegate debounce = null;
|
||||
|
||||
foreach (var mod in mods.NewValue.OfType<IApplicableToDifficulty>())
|
||||
modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue);
|
||||
modSettingChangeTracker.SettingChanged += m =>
|
||||
{
|
||||
foreach (var setting in mod.CreateSettingsControls().OfType<ISettingsItem>())
|
||||
{
|
||||
setting.SettingChanged += () =>
|
||||
{
|
||||
debounce?.Cancel();
|
||||
debounce = Scheduler.AddDelayed(updateStatistics, 100);
|
||||
};
|
||||
if (!(m is IApplicableToDifficulty))
|
||||
return;
|
||||
|
||||
references.Add(setting);
|
||||
}
|
||||
}
|
||||
debouncedStatisticsUpdate?.Cancel();
|
||||
debouncedStatisticsUpdate = Scheduler.AddDelayed(updateStatistics, 100);
|
||||
};
|
||||
|
||||
updateStatistics();
|
||||
}
|
||||
@ -173,6 +162,7 @@ namespace osu.Game.Screens.Select.Details
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
modSettingChangeTracker?.Dispose();
|
||||
starDifficultyCancellationSource?.Cancel();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user