mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 14:52:57 +08:00
Merge pull request #4947 from peppy/mod-select-overlay-layout
Fix file layout of ModSelectOverlay
This commit is contained in:
commit
911328b895
@ -1,43 +1,40 @@
|
||||
// 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 osuTK;
|
||||
using osuTK.Input;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays.Mods.Sections;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens;
|
||||
using osu.Framework.Input.Events;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public class ModSelectOverlay : WaveOverlayContainer
|
||||
{
|
||||
private const float content_width = 0.8f;
|
||||
|
||||
protected Color4 LowMultiplierColour, HighMultiplierColour;
|
||||
|
||||
protected readonly TriangleButton DeselectAllButton;
|
||||
protected readonly TriangleButton CloseButton;
|
||||
protected readonly OsuSpriteText MultiplierLabel, UnrankedLabel;
|
||||
private readonly FillFlowContainer footerContainer;
|
||||
|
||||
protected readonly OsuSpriteText MultiplierLabel;
|
||||
protected readonly OsuSpriteText UnrankedLabel;
|
||||
|
||||
protected override bool BlockNonPositionalInput => false;
|
||||
|
||||
@ -49,170 +46,14 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
protected readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio, Bindable<IReadOnlyList<Mod>> mods)
|
||||
{
|
||||
LowMultiplierColour = colours.Red;
|
||||
HighMultiplierColour = colours.Green;
|
||||
UnrankedLabel.Colour = colours.Blue;
|
||||
protected Color4 LowMultiplierColour;
|
||||
protected Color4 HighMultiplierColour;
|
||||
|
||||
Ruleset.BindTo(ruleset);
|
||||
if (mods != null) SelectedMods.BindTo(mods);
|
||||
|
||||
sampleOn = audio.Samples.Get(@"UI/check-on");
|
||||
sampleOff = audio.Samples.Get(@"UI/check-off");
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Ruleset.BindValueChanged(rulesetChanged, true);
|
||||
SelectedMods.BindValueChanged(selectedModsChanged, true);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
Ruleset.UnbindAll();
|
||||
SelectedMods.UnbindAll();
|
||||
}
|
||||
|
||||
private void rulesetChanged(ValueChangedEvent<RulesetInfo> e)
|
||||
{
|
||||
if (e.NewValue == null) return;
|
||||
|
||||
var instance = e.NewValue.CreateInstance();
|
||||
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.Mods = instance.GetModsFor(section.ModType);
|
||||
|
||||
// attempt to re-select any already selected mods.
|
||||
// this may be the first time we are receiving the ruleset, in which case they will still match.
|
||||
selectedModsChanged(new ValueChangedEvent<IReadOnlyList<Mod>>(SelectedMods.Value, SelectedMods.Value));
|
||||
|
||||
// write the mods back to the SelectedMods bindable in the case a change was not applicable.
|
||||
// this generally isn't required as the previous line will perform deselection; just here for safety.
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
private void selectedModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> e)
|
||||
{
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList());
|
||||
|
||||
updateMods();
|
||||
}
|
||||
|
||||
private void updateMods()
|
||||
{
|
||||
double multiplier = 1.0;
|
||||
bool ranked = true;
|
||||
|
||||
foreach (Mod mod in SelectedMods.Value)
|
||||
{
|
||||
multiplier *= mod.ScoreMultiplier;
|
||||
ranked &= mod.Ranked;
|
||||
}
|
||||
|
||||
MultiplierLabel.Text = $"{multiplier:N2}x";
|
||||
if (multiplier > 1.0)
|
||||
MultiplierLabel.FadeColour(HighMultiplierColour, 200);
|
||||
else if (multiplier < 1.0)
|
||||
MultiplierLabel.FadeColour(LowMultiplierColour, 200);
|
||||
else
|
||||
MultiplierLabel.FadeColour(Color4.White, 200);
|
||||
|
||||
UnrankedLabel.FadeTo(ranked ? 0 : 1, 200);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
base.PopOut();
|
||||
|
||||
footerContainer.MoveToX(footerContainer.DrawSize.X, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
footerContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.MoveToX(100f, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
base.PopIn();
|
||||
|
||||
footerContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
footerContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeselectAll()
|
||||
{
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.DeselectAll();
|
||||
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deselect one or more mods.
|
||||
/// </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(Type[] modTypes, bool immediate = false)
|
||||
{
|
||||
if (modTypes.Length == 0) return;
|
||||
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.DeselectTypes(modTypes, immediate);
|
||||
}
|
||||
private const float content_width = 0.8f;
|
||||
private readonly FillFlowContainer footerContainer;
|
||||
|
||||
private SampleChannel sampleOn, sampleOff;
|
||||
|
||||
private void modButtonPressed(Mod selectedMod)
|
||||
{
|
||||
if (selectedMod != null)
|
||||
{
|
||||
if (State == Visibility.Visible) sampleOn?.Play();
|
||||
DeselectTypes(selectedMod.IncompatibleMods, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (State == Visibility.Visible) sampleOff?.Play();
|
||||
}
|
||||
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Number1:
|
||||
DeselectAllButton.Click();
|
||||
return true;
|
||||
|
||||
case Key.Number2:
|
||||
CloseButton.Click();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnKeyDown(e);
|
||||
}
|
||||
|
||||
private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
||||
|
||||
public ModSelectOverlay()
|
||||
{
|
||||
Waves.FirstWaveColour = OsuColour.FromHex(@"19b0e2");
|
||||
@ -430,5 +271,171 @@ namespace osu.Game.Overlays.Mods
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio, Bindable<IReadOnlyList<Mod>> mods)
|
||||
{
|
||||
LowMultiplierColour = colours.Red;
|
||||
HighMultiplierColour = colours.Green;
|
||||
UnrankedLabel.Colour = colours.Blue;
|
||||
|
||||
Ruleset.BindTo(ruleset);
|
||||
if (mods != null) SelectedMods.BindTo(mods);
|
||||
|
||||
sampleOn = audio.Samples.Get(@"UI/check-on");
|
||||
sampleOff = audio.Samples.Get(@"UI/check-off");
|
||||
}
|
||||
|
||||
public void DeselectAll()
|
||||
{
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.DeselectAll();
|
||||
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deselect one or more mods.
|
||||
/// </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(Type[] modTypes, bool immediate = false)
|
||||
{
|
||||
if (modTypes.Length == 0) return;
|
||||
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.DeselectTypes(modTypes, immediate);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Ruleset.BindValueChanged(rulesetChanged, true);
|
||||
SelectedMods.BindValueChanged(selectedModsChanged, true);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
base.PopOut();
|
||||
|
||||
footerContainer.MoveToX(footerContainer.DrawSize.X, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
footerContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.MoveToX(100f, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
base.PopIn();
|
||||
|
||||
footerContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
footerContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Number1:
|
||||
DeselectAllButton.Click();
|
||||
return true;
|
||||
|
||||
case Key.Number2:
|
||||
CloseButton.Click();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnKeyDown(e);
|
||||
}
|
||||
|
||||
private void rulesetChanged(ValueChangedEvent<RulesetInfo> e)
|
||||
{
|
||||
if (e.NewValue == null) return;
|
||||
|
||||
var instance = e.NewValue.CreateInstance();
|
||||
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.Mods = instance.GetModsFor(section.ModType);
|
||||
|
||||
// attempt to re-select any already selected mods.
|
||||
// this may be the first time we are receiving the ruleset, in which case they will still match.
|
||||
selectedModsChanged(new ValueChangedEvent<IReadOnlyList<Mod>>(SelectedMods.Value, SelectedMods.Value));
|
||||
|
||||
// write the mods back to the SelectedMods bindable in the case a change was not applicable.
|
||||
// this generally isn't required as the previous line will perform deselection; just here for safety.
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
private void selectedModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> e)
|
||||
{
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList());
|
||||
|
||||
updateMods();
|
||||
}
|
||||
|
||||
private void updateMods()
|
||||
{
|
||||
var multiplier = 1.0;
|
||||
var ranked = true;
|
||||
|
||||
foreach (var mod in SelectedMods.Value)
|
||||
{
|
||||
multiplier *= mod.ScoreMultiplier;
|
||||
ranked &= mod.Ranked;
|
||||
}
|
||||
|
||||
MultiplierLabel.Text = $"{multiplier:N2}x";
|
||||
if (multiplier > 1.0)
|
||||
MultiplierLabel.FadeColour(HighMultiplierColour, 200);
|
||||
else if (multiplier < 1.0)
|
||||
MultiplierLabel.FadeColour(LowMultiplierColour, 200);
|
||||
else
|
||||
MultiplierLabel.FadeColour(Color4.White, 200);
|
||||
|
||||
UnrankedLabel.FadeTo(ranked ? 0 : 1, 200);
|
||||
}
|
||||
|
||||
private void modButtonPressed(Mod selectedMod)
|
||||
{
|
||||
if (selectedMod != null)
|
||||
{
|
||||
if (State == Visibility.Visible) sampleOn?.Play();
|
||||
DeselectTypes(selectedMod.IncompatibleMods, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (State == Visibility.Visible) sampleOff?.Play();
|
||||
}
|
||||
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
||||
|
||||
#region Disposal
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
Ruleset.UnbindAll();
|
||||
SelectedMods.UnbindAll();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user