1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 19:42:55 +08:00

Merge pull request #450 from huoyaoyuan/modselect

Modselect refactor
This commit is contained in:
Dean Herbert 2017-03-09 18:16:16 +09:00 committed by GitHub
commit a266add670
13 changed files with 161 additions and 218 deletions

View File

@ -60,6 +60,8 @@ namespace osu.Game.Modes.Catch
return new Mod[] return new Mod[]
{ {
new CatchModRelax(), new CatchModRelax(),
null,
null,
new MultiMod new MultiMod
{ {
Mods = new Mod[] Mods = new Mod[]

View File

@ -52,7 +52,14 @@ namespace osu.Game.Modes.Mania
new ManiaModNightcore(), new ManiaModNightcore(),
}, },
}, },
new ManiaModHidden(), new MultiMod
{
Mods = new Mod[]
{
new ManiaModFadeIn(),
new ManiaModHidden(),
}
},
new ManiaModFlashlight(), new ManiaModFlashlight(),
}; };
@ -74,8 +81,8 @@ namespace osu.Game.Modes.Mania
new ManiaModKey3(), new ManiaModKey3(),
}, },
}, },
new ManiaModKeyCoop(),
new ManiaModRandom(), new ManiaModRandom(),
new ManiaModKeyCoop(),
new MultiMod new MultiMod
{ {
Mods = new Mod[] Mods = new Mod[]

View File

@ -72,7 +72,7 @@ namespace osu.Game.Modes.Osu
public override string Description => @"Spinners will be automatically completed"; public override string Description => @"Spinners will be automatically completed";
public override double ScoreMultiplier => 0.9; public override double ScoreMultiplier => 0.9;
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModCinema), typeof(OsuModAutopilot) }; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) };
} }
public class OsuModAutopilot : Mod public class OsuModAutopilot : Mod
@ -82,7 +82,7 @@ namespace osu.Game.Modes.Osu
public override string Description => @"Automatic cursor movement - just follow the rhythm."; public override string Description => @"Automatic cursor movement - just follow the rhythm.";
public override double ScoreMultiplier => 0; public override double ScoreMultiplier => 0;
public override bool Ranked => false; public override bool Ranked => false;
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModPerfect), typeof(ModNoFail), typeof(ModAutoplay), typeof(ModCinema) }; public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) };
} }
public class OsuModAutoplay : ModAutoplay public class OsuModAutoplay : ModAutoplay

View File

@ -78,7 +78,6 @@ namespace osu.Game.Modes.Osu
{ {
new OsuModRelax(), new OsuModRelax(),
new OsuModAutopilot(), new OsuModAutopilot(),
new OsuModTarget(),
new OsuModSpunOut(), new OsuModSpunOut(),
new MultiMod new MultiMod
{ {
@ -88,6 +87,7 @@ namespace osu.Game.Modes.Osu
new ModCinema(), new ModCinema(),
}, },
}, },
new OsuModTarget(),
}; };
default: default:

View File

@ -60,6 +60,8 @@ namespace osu.Game.Modes.Taiko
return new Mod[] return new Mod[]
{ {
new TaikoModRelax(), new TaikoModRelax(),
null,
null,
new MultiMod new MultiMod
{ {
Mods = new Mod[] Mods = new Mod[]

View File

@ -65,7 +65,7 @@ namespace osu.Game.Modes
public override string Description => "You can't fail, no matter what."; public override string Description => "You can't fail, no matter what.";
public override double ScoreMultiplier => 0.5; public override double ScoreMultiplier => 0.5;
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModPerfect) }; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModAutoplay) };
} }
public abstract class ModEasy : Mod public abstract class ModEasy : Mod
@ -100,7 +100,7 @@ namespace osu.Game.Modes
public override string Description => "Miss a note and fail."; public override string Description => "Miss a note and fail.";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay), typeof(ModCinema) }; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) };
} }
public abstract class ModDoubleTime : Mod public abstract class ModDoubleTime : Mod
@ -117,7 +117,7 @@ namespace osu.Game.Modes
public override string Name => "Relax"; public override string Name => "Relax";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_relax; public override FontAwesome Icon => FontAwesome.fa_osu_mod_relax;
public override double ScoreMultiplier => 0; public override double ScoreMultiplier => 0;
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModCinema), typeof(ModNoFail), typeof(ModSuddenDeath), typeof(ModPerfect) }; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModNoFail), typeof(ModSuddenDeath) };
} }
public abstract class ModHalfTime : Mod public abstract class ModHalfTime : Mod
@ -126,7 +126,7 @@ namespace osu.Game.Modes
public override FontAwesome Icon => FontAwesome.fa_osu_mod_halftime; public override FontAwesome Icon => FontAwesome.fa_osu_mod_halftime;
public override string Description => "Less zoom"; public override string Description => "Less zoom";
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModDoubleTime), typeof(ModNightcore) }; public override Type[] IncompatibleMods => new[] { typeof(ModDoubleTime) };
} }
public abstract class ModNightcore : ModDoubleTime public abstract class ModNightcore : ModDoubleTime
@ -150,7 +150,7 @@ namespace osu.Game.Modes
public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto; public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto;
public override string Description => "Watch a perfect automated play through the song"; public override string Description => "Watch a perfect automated play through the song";
public override double ScoreMultiplier => 0; public override double ScoreMultiplier => 0;
public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModPerfect) }; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) };
public override void PlayerLoading(Player player) public override void PlayerLoading(Player player)
{ {

View File

@ -25,31 +25,27 @@ namespace osu.Game.Modes.UI
reapplySize(); reapplySize();
} }
} }
private Color4 backgroundColour;
public new Color4 Colour public new Color4 Colour
{ {
get get
{ {
return backgroundColour; return background.Colour;
} }
set set
{ {
backgroundColour = value;
background.Colour = value; background.Colour = value;
} }
} }
private FontAwesome icon;
public FontAwesome Icon public FontAwesome Icon
{ {
get get
{ {
return icon; return modIcon.Icon;
} }
set set
{ {
icon = value;
modIcon.Icon = value; modIcon.Icon = value;
} }
} }

View File

@ -4,17 +4,19 @@
using OpenTK.Input; using OpenTK.Input;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Modes;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods
{ {
public class AssistedSection : ModSection public class AssistedSection : ModSection
{ {
protected override Key[] ToggleKeys => new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M }; protected override Key[] ToggleKeys => new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M };
public override ModType ModType => ModType.Special;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
Colour = colours.Blue; ButtonColour = colours.Blue;
SelectedColour = colours.BlueLight; SelectedColour = colours.BlueLight;
} }

View File

@ -4,17 +4,19 @@
using OpenTK.Input; using OpenTK.Input;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Modes;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods
{ {
public class DifficultyIncreaseSection : ModSection public class DifficultyIncreaseSection : ModSection
{ {
protected override Key[] ToggleKeys => new[] { Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L }; protected override Key[] ToggleKeys => new[] { Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L };
public override ModType ModType => ModType.DifficultyIncrease;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
Colour = colours.Yellow; ButtonColour = colours.Yellow;
SelectedColour = colours.YellowLight; SelectedColour = colours.YellowLight;
} }

View File

@ -4,17 +4,19 @@
using OpenTK.Input; using OpenTK.Input;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Modes;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods
{ {
public class DifficultyReductionSection : ModSection public class DifficultyReductionSection : ModSection
{ {
protected override Key[] ToggleKeys => new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P }; protected override Key[] ToggleKeys => new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P };
public override ModType ModType => ModType.DifficultyReduction;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
Colour = colours.Green; ButtonColour = colours.Green;
SelectedColour = colours.GreenLight; SelectedColour = colours.GreenLight;
} }

View File

@ -22,61 +22,57 @@ namespace osu.Game.Overlays.Mods
{ {
public class ModButton : FillFlowContainer public class ModButton : FillFlowContainer
{ {
private ModIcon[] icons; private ModIcon foregroundIcon { get; set; }
private ModIcon displayIcon => icons[icons.Length - 1];
private SpriteText text; private SpriteText text;
private Container iconsContainer; private Container<ModIcon> iconsContainer;
private SampleChannel sampleOn, sampleOff; private SampleChannel sampleOn, sampleOff;
public Action<Mod> Action; // Passed the selected mod or null if none public Action<Mod> Action; // Passed the selected mod or null if none
private int _selectedMod = -1; private int _selectedIndex = -1;
private int selectedMod private int selectedIndex
{ {
get get
{ {
return _selectedMod; return _selectedIndex;
} }
set set
{ {
if (value == _selectedMod) return; if (value == _selectedIndex) return;
_selectedMod = value; _selectedIndex = value;
if (value >= Mods.Length) if (value >= Mods.Length)
{ {
_selectedMod = -1; _selectedIndex = -1;
} }
else if (value <= -2) else if (value <= -2)
{ {
_selectedMod = Mods.Length - 1; _selectedIndex = Mods.Length - 1;
} }
iconsContainer.RotateTo(Selected ? 5f : 0f, 300, EasingTypes.OutElastic); iconsContainer.RotateTo(Selected ? 5f : 0f, 300, EasingTypes.OutElastic);
iconsContainer.ScaleTo(Selected ? 1.1f : 1f, 300, EasingTypes.OutElastic); iconsContainer.ScaleTo(Selected ? 1.1f : 1f, 300, EasingTypes.OutElastic);
for (int i = 0; i < icons.Length; i++) foregroundIcon.Colour = Selected ? SelectedColour : ButtonColour;
{
if (Selected && i == icons.Length - 1) icons[i].Colour = SelectedColour;
else icons[i].Colour = Colour;
}
displaySelectedMod(); if (mod != null)
displayMod(SelectedMod ?? Mods[0]);
} }
} }
public bool Selected => selectedMod != -1; public bool Selected => selectedIndex != -1;
private Color4 backgroundColour; private Color4 buttonColour;
public new Color4 Colour public Color4 ButtonColour
{ {
get get
{ {
return backgroundColour; return buttonColour;
} }
set set
{ {
if (value == backgroundColour) return; if (value == buttonColour) return;
backgroundColour = value; buttonColour = value;
foreach (ModIcon icon in icons) foreach (ModIcon icon in iconsContainer.Children)
{ {
icon.Colour = value; icon.Colour = value;
} }
@ -94,7 +90,7 @@ namespace osu.Game.Overlays.Mods
{ {
if (value == selectedColour) return; if (value == selectedColour) return;
selectedColour = value; selectedColour = value;
if (Selected) icons[0].Colour = value; if (Selected) foregroundIcon.Colour = value;
} }
} }
@ -107,10 +103,18 @@ namespace osu.Game.Overlays.Mods
} }
set set
{ {
if (mod == value) return;
mod = value; mod = value;
Mods = (mod as MultiMod)?.Mods ?? new[] { mod }; if (mod == null)
{
Mods = new Mod[0];
Alpha = 0;
}
else
{
Mods = (mod as MultiMod)?.Mods ?? new[] { mod };
Alpha = 1;
}
createIcons(); createIcons();
if (Mods.Length > 0) if (Mods.Length > 0)
@ -124,7 +128,7 @@ namespace osu.Game.Overlays.Mods
// the mods from Mod, only multiple if Mod is a MultiMod // the mods from Mod, only multiple if Mod is a MultiMod
public Mod SelectedMod => Mods.ElementAtOrDefault(selectedMod); public Mod SelectedMod => Mods.ElementAtOrDefault(selectedIndex);
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(AudioManager audio) private void load(AudioManager audio)
@ -135,67 +139,47 @@ namespace osu.Game.Overlays.Mods
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{ {
(args.Button == MouseButton.Right ? (Action)SelectPrevious : SelectNext)(); switch (args.Button)
{
case MouseButton.Left:
SelectNext();
break;
case MouseButton.Right:
SelectPrevious();
break;
}
return true; return true;
} }
public void SelectNext() public void SelectNext()
{ {
selectedMod++; (++selectedIndex == -1 ? sampleOff : sampleOn).Play();
if (selectedMod == -1)
{
sampleOff.Play();
}
else
{
sampleOn.Play();
}
Action?.Invoke(SelectedMod); Action?.Invoke(SelectedMod);
} }
public void SelectPrevious() public void SelectPrevious()
{ {
selectedMod--; (--selectedIndex == -1 ? sampleOff : sampleOn).Play();
if (selectedMod == -1)
{
sampleOff.Play();
}
else
{
sampleOn.Play();
}
Action?.Invoke(SelectedMod); Action?.Invoke(SelectedMod);
} }
public void Deselect() public void Deselect()
{ {
selectedMod = -1; selectedIndex = -1;
} }
private void displayMod(Mod mod) private void displayMod(Mod mod)
{ {
displayIcon.Icon = mod.Icon; foregroundIcon.Icon = mod.Icon;
text.Text = mod.Name; text.Text = mod.Name;
} }
private void displaySelectedMod()
{
var modIndex = selectedMod;
if (modIndex <= -1)
{
modIndex = 0;
}
displayMod(Mods[modIndex]);
}
private void createIcons() private void createIcons()
{ {
iconsContainer.Clear();
if (Mods.Length > 1) if (Mods.Length > 1)
{ {
iconsContainer.Add(icons = new[] iconsContainer.Add(new[]
{ {
new ModIcon new ModIcon
{ {
@ -203,35 +187,43 @@ namespace osu.Game.Overlays.Mods
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Position = new Vector2(1.5f), Position = new Vector2(1.5f),
Colour = ButtonColour
}, },
new ModIcon foregroundIcon = new ModIcon
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Position = new Vector2(-1.5f), Position = new Vector2(-1.5f),
Colour = ButtonColour
}, },
}); });
} }
else else
{ {
iconsContainer.Add(icons = new[] iconsContainer.Add(foregroundIcon = new ModIcon
{ {
new ModIcon Origin = Anchor.Centre,
{ Anchor = Anchor.Centre,
Origin = Anchor.Centre, AutoSizeAxes = Axes.Both,
Anchor = Anchor.Centre, Colour = ButtonColour
AutoSizeAxes = Axes.Both,
},
}); });
} }
} }
protected override void LoadComplete()
{
base.LoadComplete();
foreach (ModIcon icon in iconsContainer.Children)
icon.Colour = ButtonColour;
}
public ModButton(Mod m) public ModButton(Mod m)
{ {
Direction = FillDirection.Vertical; Direction = FillDirection.Vertical;
Spacing = new Vector2(0f, -5f); Spacing = new Vector2(0f, -5f);
Size = new Vector2(100f); Size = new Vector2(100f);
AlwaysPresent = true;
Children = new Drawable[] Children = new Drawable[]
{ {
@ -242,7 +234,7 @@ namespace osu.Game.Overlays.Mods
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Children = new Drawable[] Children = new Drawable[]
{ {
iconsContainer = new Container iconsContainer = new Container<ModIcon>
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Origin = Anchor.Centre, Origin = Anchor.Centre,

View File

@ -2,7 +2,6 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Collections.Generic;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK.Input; using OpenTK.Input;
@ -15,53 +14,29 @@ using osu.Game.Modes;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods
{ {
internal class AlwaysPresentFlowContainer : FillFlowContainer public abstract class ModSection : Container
{
public override bool IsPresent => true;
}
public class ModSection : Container
{ {
private OsuSpriteText headerLabel; private OsuSpriteText headerLabel;
private AlwaysPresentFlowContainer buttonsContainer; public FillFlowContainer<ModButton> ButtonsContainer { get; }
public FillFlowContainer ButtonsContainer => buttonsContainer;
public Action<Mod> Action; public Action<Mod> Action;
protected virtual Key[] ToggleKeys => new Key[] { }; protected abstract Key[] ToggleKeys { get; }
public abstract ModType ModType { get; }
public Mod[] SelectedMods
{
get
{
List<Mod> selectedMods = new List<Mod>();
foreach (ModButton button in Buttons)
{
Mod selectedMod = button.SelectedMod;
if (selectedMod != null)
selectedMods.Add(selectedMod);
}
return selectedMods.ToArray();
}
}
private string header;
public string Header public string Header
{ {
get get
{ {
return header; return headerLabel.Text;
} }
set set
{ {
header = value;
headerLabel.Text = value; headerLabel.Text = value;
} }
} }
private ModButton[] buttons = {}; private ModButton[] buttons = { };
public ModButton[] Buttons public ModButton[] Buttons
{ {
get get
@ -75,30 +50,30 @@ namespace osu.Game.Overlays.Mods
foreach (ModButton button in value) foreach (ModButton button in value)
{ {
button.Colour = Colour; button.ButtonColour = ButtonColour;
button.SelectedColour = selectedColour; button.SelectedColour = selectedColour;
button.Action = buttonPressed; button.Action = Action;
} }
buttonsContainer.Add(value); ButtonsContainer.Children = value;
} }
} }
private Color4 colour = Color4.White; private Color4 buttonsBolour = Color4.White;
public new Color4 Colour public Color4 ButtonColour
{ {
get get
{ {
return colour; return buttonsBolour;
} }
set set
{ {
if (value == colour) return; if (value == buttonsBolour) return;
colour = value; buttonsBolour = value;
foreach (ModButton button in buttons) foreach (ModButton button in buttons)
{ {
button.Colour = value; button.ButtonColour = value;
} }
} }
} }
@ -139,12 +114,7 @@ namespace osu.Game.Overlays.Mods
} }
} }
private void buttonPressed(Mod mod) protected ModSection()
{
Action?.Invoke(mod);
}
public ModSection()
{ {
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
@ -155,10 +125,9 @@ namespace osu.Game.Overlays.Mods
Origin = Anchor.TopLeft, Origin = Anchor.TopLeft,
Anchor = Anchor.TopLeft, Anchor = Anchor.TopLeft,
Position = new Vector2(0f, 0f), Position = new Vector2(0f, 0f),
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold"
Text = Header,
}, },
buttonsContainer = new AlwaysPresentFlowContainer ButtonsContainer = new FillFlowContainer<ModButton>
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
@ -168,6 +137,7 @@ namespace osu.Game.Overlays.Mods
{ {
Top = 6, Top = 6,
}, },
AlwaysPresent = true
}, },
}; };
} }

View File

@ -2,8 +2,8 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Configuration; using osu.Framework.Configuration;
@ -41,37 +41,12 @@ namespace osu.Game.Overlays.Mods
private void modeChanged(object sender, EventArgs eventArgs) private void modeChanged(object sender, EventArgs eventArgs)
{ {
var ruleset = Ruleset.GetRuleset(PlayMode); var ruleset = Ruleset.GetRuleset(PlayMode);
foreach (ModSection section in modSectionsContainer.Children)
modSectionsContainer.Children = new ModSection[] section.Buttons = ruleset.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray();
{ refreshSelectedMods();
new DifficultyReductionSection
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Action = modButtonPressed,
Buttons = ruleset.GetModsFor(ModType.DifficultyReduction).Select(m => new ModButton(m)).ToArray(),
},
new DifficultyIncreaseSection
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Action = modButtonPressed,
Buttons = ruleset.GetModsFor(ModType.DifficultyIncrease).Select(m => new ModButton(m)).ToArray(),
},
new AssistedSection
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Action = modButtonPressed,
Buttons = ruleset.GetModsFor(ModType.Special).Select(m => new ModButton(m)).ToArray(),
},
};
} }
[BackgroundDependencyLoader(permitNulls:true)] [BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuColour colours, OsuGame osu) private void load(OsuColour colours, OsuGame osu)
{ {
lowMultiplierColour = colours.Red; lowMultiplierColour = colours.Red;
@ -80,7 +55,7 @@ namespace osu.Game.Overlays.Mods
if (osu != null) if (osu != null)
PlayMode.BindTo(osu.PlayMode); PlayMode.BindTo(osu.PlayMode);
PlayMode.ValueChanged += modeChanged; PlayMode.ValueChanged += modeChanged;
PlayMode.TriggerChange(); modeChanged(null, null);
} }
protected override void PopOut() protected override void PopOut()
@ -116,41 +91,33 @@ namespace osu.Game.Overlays.Mods
public void DeselectAll() public void DeselectAll()
{ {
foreach (ModSection section in modSectionsContainer.Children) foreach (ModSection section in modSectionsContainer.Children)
{ section.DeselectAll();
foreach (ModButton button in section.Buttons)
{
button.Deselect();
}
}
} }
public void DeselectType(Type modType) public void DeselectTypes(Type[] modTypes)
{ {
if (modTypes.Length == 0) return;
foreach (ModSection section in modSectionsContainer.Children) foreach (ModSection section in modSectionsContainer.Children)
{
foreach (ModButton button in section.Buttons) foreach (ModButton button in section.Buttons)
{ {
foreach (Mod mod in button.Mods) Mod selected = button.SelectedMod;
{ if (selected == null) continue;
if (modType.IsInstanceOfType(mod)) foreach (Type type in modTypes)
{ if (type.IsInstanceOfType(selected))
button.Deselect(); button.Deselect();
return;
}
}
} }
}
} }
private void modButtonPressed(Mod selectedMod) private void modButtonPressed(Mod selectedMod)
{ {
if (selectedMod != null) if (selectedMod != null)
{ DeselectTypes(selectedMod.IncompatibleMods);
foreach (Type t in selectedMod.IncompatibleMods)
DeselectType(t);
}
refreshSelectedMods(); refreshSelectedMods();
}
private void refreshSelectedMods()
{
SelectedMods.Value = modSectionsContainer.Children.SelectMany(s => s.Buttons.Select(x => x.SelectedMod).Where(x => x != null)).ToArray();
double multiplier = 1.0; double multiplier = 1.0;
bool ranked = true; bool ranked = true;
@ -158,9 +125,7 @@ namespace osu.Game.Overlays.Mods
foreach (Mod mod in SelectedMods.Value) foreach (Mod mod in SelectedMods.Value)
{ {
multiplier *= mod.ScoreMultiplier; multiplier *= mod.ScoreMultiplier;
ranked &= mod.Ranked;
if (ranked)
ranked = mod.Ranked;
} }
// 1.00x // 1.00x
@ -172,32 +137,11 @@ namespace osu.Game.Overlays.Mods
rankedLabel.Text = $@"{rankedString}, Score Multiplier: "; rankedLabel.Text = $@"{rankedString}, Score Multiplier: ";
if (multiplier > 1.0) if (multiplier > 1.0)
{
multiplierLabel.FadeColour(highMultiplierColour, 200); multiplierLabel.FadeColour(highMultiplierColour, 200);
}
else if (multiplier < 1.0) else if (multiplier < 1.0)
{
multiplierLabel.FadeColour(lowMultiplierColour, 200); multiplierLabel.FadeColour(lowMultiplierColour, 200);
}
else else
{
multiplierLabel.FadeColour(Color4.White, 200); multiplierLabel.FadeColour(Color4.White, 200);
}
}
private void refreshSelectedMods()
{
List<Mod> selectedMods = new List<Mod>();
foreach (ModSection section in modSectionsContainer.Children)
{
foreach (Mod mod in section.SelectedMods)
{
selectedMods.Add(mod);
}
}
SelectedMods.Value = selectedMods.ToArray();
} }
public ModSelectOverlay() public ModSelectOverlay()
@ -308,6 +252,30 @@ namespace osu.Game.Overlays.Mods
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0f, 10f), Spacing = new Vector2(0f, 10f),
Width = content_width, Width = content_width,
Children = new ModSection[]
{
new DifficultyReductionSection
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Action = modButtonPressed,
},
new DifficultyIncreaseSection
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Action = modButtonPressed,
},
new AssistedSection
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Action = modButtonPressed,
},
}
}, },
// Footer // Footer
new Container new Container