1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-22 02:17:19 +08:00

Centralise selection animation logic

This commit is contained in:
Dean Herbert 2021-02-04 18:10:55 +09:00
parent 4bfe3aabdc
commit f23ca7c7cf
4 changed files with 48 additions and 31 deletions

View File

@ -33,6 +33,8 @@ namespace osu.Game.Overlays.Mods
private CancellationTokenSource modsLoadCts;
protected bool SelectionAnimationRunning => pendingSelectionOperations.Count > 0;
/// <summary>
/// True when all mod icons have completed loading.
/// </summary>
@ -49,7 +51,11 @@ namespace osu.Game.Overlays.Mods
return new ModButton(m)
{
SelectionChanged = Action,
SelectionChanged = mod =>
{
ModButtonStateChanged(mod);
Action?.Invoke(mod);
},
};
}).ToArray();
@ -78,6 +84,10 @@ namespace osu.Game.Overlays.Mods
}
}
protected virtual void ModButtonStateChanged(Mod mod)
{
}
private ModButton[] buttons = Array.Empty<ModButton>();
protected override bool OnKeyDown(KeyDownEvent e)
@ -94,44 +104,53 @@ namespace osu.Game.Overlays.Mods
return base.OnKeyDown(e);
}
private const double initial_multiple_selection_delay = 100;
private readonly Queue<Action> pendingSelectionOperations = new Queue<Action>();
protected override void LoadComplete()
{
base.LoadComplete();
Scheduler.AddDelayed(() =>
{
if (pendingSelectionOperations.TryDequeue(out var dequeuedAction))
dequeuedAction();
}, initial_multiple_selection_delay, true);
}
/// <summary>
/// Selects all mods.
/// </summary>
public void SelectAll()
{
pendingSelectionOperations.Clear();
foreach (var button in buttons.Where(b => !b.Selected))
button.SelectAt(0);
pendingSelectionOperations.Enqueue(() => button.SelectAt(0));
}
/// <summary>
/// Deselects all mods.
/// </summary>
/// <param name="immediate">Set to true to bypass animations and update selections immediately.</param>
public void DeselectAll(bool immediate = false) => DeselectTypes(buttons.Select(b => b.SelectedMod?.GetType()).Where(t => t != null), immediate);
public void DeselectAll() => DeselectTypes(buttons.Select(b => b.SelectedMod?.GetType()).Where(t => t != null));
/// <summary>
/// Deselect one or more mods in this section.
/// </summary>
/// <param name="modTypes">The types of <see cref="Mod"/>s which should be deselected.</param>
/// <param name="immediate">Set to true to bypass animations and update selections immediately.</param>
public void DeselectTypes(IEnumerable<Type> modTypes, bool immediate = false)
public void DeselectTypes(IEnumerable<Type> modTypes)
{
int delay = 0;
pendingSelectionOperations.Clear();
foreach (var button in buttons)
{
Mod selected = button.SelectedMod;
if (selected == null) continue;
if (button.SelectedMod == null) continue;
foreach (var type in modTypes)
{
if (type.IsInstanceOfType(selected))
{
if (immediate)
button.Deselect();
else
Scheduler.AddDelayed(button.Deselect, delay += 50);
}
if (type.IsInstanceOfType(button.SelectedMod))
pendingSelectionOperations.Enqueue(button.Deselect);
}
}
}

View File

@ -14,7 +14,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Framework.Threading;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Containers;

View File

@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Mods
base.OnModSelected(mod);
foreach (var section in ModSectionsContainer.Children)
section.DeselectTypes(mod.IncompatibleMods, true);
section.DeselectTypes(mod.IncompatibleMods);
}
}
}

View File

@ -3,7 +3,6 @@
using System;
using System.Linq;
using System.Reflection.Emit;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
@ -72,7 +71,7 @@ namespace osu.Game.Screens.OnlinePlay
private void deselectAll()
{
foreach (var section in ModSectionsContainer.Children)
section.DeselectAll(true);
section.DeselectAll();
}
protected override ModSection CreateModSection(ModType type) => new FreeModSection(type);
@ -99,21 +98,21 @@ namespace osu.Game.Screens.OnlinePlay
private void onCheckboxChanged(bool value)
{
foreach (var button in ButtonsContainer.OfType<ModButton>())
{
if (value)
button.SelectAt(0);
else
button.Deselect();
}
if (value)
SelectAll();
else
DeselectAll();
}
protected override void Update()
protected override void ModButtonStateChanged(Mod mod)
{
base.Update();
base.ModButtonStateChanged(mod);
var validButtons = ButtonsContainer.OfType<ModButton>().Where(b => b.Mod.HasImplementation);
checkbox.Current.Value = validButtons.All(b => b.Selected);
if (!SelectionAnimationRunning)
{
var validButtons = ButtonsContainer.OfType<ModButton>().Where(b => b.Mod.HasImplementation);
checkbox.Current.Value = validButtons.All(b => b.Selected);
}
}
}