diff --git a/osu-framework b/osu-framework
index 209021fb49..2610a31337 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit 209021fb491e21625127be5dbf5efb4c409e6f06
+Subproject commit 2610a3133721b0bc4af852342aa2a179d0e66497
diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
index 5f08048bf9..cdce598ce8 100644
--- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
+++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
@@ -32,6 +32,10 @@
false
+
+ $(SolutionDir)\packages\JetBrains.Annotations.11.1.0\lib\net20\JetBrains.Annotations.dll
+ True
+
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
diff --git a/osu.Game.Rulesets.Catch/packages.config b/osu.Game.Rulesets.Catch/packages.config
index b39a85a382..e67d3e9b34 100644
--- a/osu.Game.Rulesets.Catch/packages.config
+++ b/osu.Game.Rulesets.Catch/packages.config
@@ -1,5 +1,6 @@
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
index 9b6b546b5f..b9e7f8e60f 100644
--- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
+++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
@@ -32,6 +32,10 @@
false
+
+ $(SolutionDir)\packages\JetBrains.Annotations.11.1.0\lib\net20\JetBrains.Annotations.dll
+ True
+
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
diff --git a/osu.Game.Rulesets.Mania/packages.config b/osu.Game.Rulesets.Mania/packages.config
index b39a85a382..e67d3e9b34 100644
--- a/osu.Game.Rulesets.Mania/packages.config
+++ b/osu.Game.Rulesets.Mania/packages.config
@@ -1,5 +1,6 @@
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
index a59d4607df..74a3883f0a 100644
--- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
+++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
@@ -33,6 +33,10 @@
false
+
+ $(SolutionDir)\packages\JetBrains.Annotations.11.1.0\lib\net20\JetBrains.Annotations.dll
+ True
+
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
diff --git a/osu.Game.Rulesets.Osu/packages.config b/osu.Game.Rulesets.Osu/packages.config
index b39a85a382..e67d3e9b34 100644
--- a/osu.Game.Rulesets.Osu/packages.config
+++ b/osu.Game.Rulesets.Osu/packages.config
@@ -1,5 +1,6 @@
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
index 36ac9384cf..90256c7d63 100644
--- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
+++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
@@ -32,6 +32,10 @@
false
+
+ $(SolutionDir)\packages\JetBrains.Annotations.11.1.0\lib\net20\JetBrains.Annotations.dll
+ True
+
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
diff --git a/osu.Game.Rulesets.Taiko/packages.config b/osu.Game.Rulesets.Taiko/packages.config
index b39a85a382..e67d3e9b34 100644
--- a/osu.Game.Rulesets.Taiko/packages.config
+++ b/osu.Game.Rulesets.Taiko/packages.config
@@ -1,5 +1,6 @@
+
\ No newline at end of file
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index 8f5fd3587a..8301f1f734 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -33,6 +33,10 @@
$(SolutionDir)\packages\DeepEqual.1.6.0.0\lib\net40\DeepEqual.dll
+
+ $(SolutionDir)\packages\JetBrains.Annotations.11.1.0\lib\net20\JetBrains.Annotations.dll
+ True
+
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
diff --git a/osu.Game.Tests/packages.config b/osu.Game.Tests/packages.config
index 62ddb99609..c16d10bf45 100644
--- a/osu.Game.Tests/packages.config
+++ b/osu.Game.Tests/packages.config
@@ -1,11 +1,12 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs
similarity index 87%
rename from osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs
rename to osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs
index 4632c6c5f0..b6bc348a52 100644
--- a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs
+++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs
@@ -14,7 +14,7 @@ namespace osu.Game.Input.Bindings
/// A KeyBindingInputManager with a database backing for custom overrides.
///
/// The type of the custom action.
- public class DatabasedKeyBindingInputManager : KeyBindingContainer
+ public class DatabasedKeyBindingContainer : KeyBindingContainer
where T : struct
{
private readonly RulesetInfo ruleset;
@@ -31,7 +31,7 @@ namespace osu.Game.Input.Bindings
/// A reference to identify the current . Used to lookup mappings. Null for global mappings.
/// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts.
/// Specify how to deal with multiple matches of s and s.
- public DatabasedKeyBindingInputManager(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None)
+ public DatabasedKeyBindingContainer(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None)
: base(simultaneousMode)
{
this.ruleset = ruleset;
diff --git a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs
similarity index 91%
rename from osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs
rename to osu.Game/Input/Bindings/GlobalActionContainer.cs
index dcebe939d4..46cda845aa 100644
--- a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs
+++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs
@@ -10,11 +10,11 @@ using osu.Framework.Input.Bindings;
namespace osu.Game.Input.Bindings
{
- public class GlobalKeyBindingInputManager : DatabasedKeyBindingInputManager, IHandleGlobalInput
+ public class GlobalActionContainer : DatabasedKeyBindingContainer, IHandleGlobalInput
{
private readonly Drawable handler;
- public GlobalKeyBindingInputManager(OsuGameBase game)
+ public GlobalActionContainer(OsuGameBase game)
{
if (game is IKeyBindingHandler)
handler = game;
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 9032cb46ce..2cdbe61059 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
+using System.Collections.Generic;
using osu.Framework.Configuration;
using osu.Framework.Screens;
using osu.Game.Configuration;
@@ -27,6 +28,7 @@ using osu.Game.Overlays.Notifications;
using osu.Game.Rulesets;
using osu.Game.Screens.Play;
using osu.Game.Input.Bindings;
+using osu.Game.Rulesets.Mods;
using OpenTK.Graphics;
namespace osu.Game
@@ -80,6 +82,9 @@ namespace osu.Game
private SettingsOverlay settings;
+ // todo: move this to SongSelect once Screen has the ability to unsuspend.
+ public readonly Bindable> SelectedMods = new Bindable>(new List());
+
public OsuGame(string[] args = null)
{
this.args = args;
@@ -111,7 +116,7 @@ namespace osu.Game
Task.Run(() => BeatmapManager.Import(paths.ToArray()));
}
- dependencies.CacheAs(this);
+ dependencies.CacheAs(this);
configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset);
Ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First();
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index d0b9634696..937b204c81 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -95,7 +95,7 @@ namespace osu.Game
dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures"))));
- dependencies.CacheAs(this);
+ dependencies.CacheAs(this);
dependencies.Cache(LocalConfig);
runMigrations();
@@ -212,10 +212,10 @@ namespace osu.Game
{
base.LoadComplete();
- GlobalKeyBindingInputManager globalBinding;
+ GlobalActionContainer globalBinding;
CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both };
- CursorOverrideContainer.Child = globalBinding = new GlobalKeyBindingInputManager(this)
+ CursorOverrideContainer.Child = globalBinding = new GlobalActionContainer(this)
{
RelativeSizeAxes = Axes.Both,
Child = content = new OsuTooltipContainer(CursorOverrideContainer.Cursor) { RelativeSizeAxes = Axes.Both }
diff --git a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs
index f5b3096404..a4c1621266 100644
--- a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs
+++ b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs
@@ -12,7 +12,7 @@ namespace osu.Game.Overlays.KeyBinding
public override FontAwesome Icon => FontAwesome.fa_osu_hot;
public override string Header => "Global";
- public GlobalKeyBindingsSection(GlobalKeyBindingInputManager manager)
+ public GlobalKeyBindingsSection(GlobalActionContainer manager)
{
Add(new DefaultBindingsSubsection(manager));
Add(new InGameKeyBindingsSubsection(manager));
@@ -23,7 +23,7 @@ namespace osu.Game.Overlays.KeyBinding
{
protected override string Header => string.Empty;
- public DefaultBindingsSubsection(GlobalKeyBindingInputManager manager)
+ public DefaultBindingsSubsection(GlobalActionContainer manager)
: base(null)
{
Defaults = manager.GlobalKeyBindings;
@@ -34,7 +34,7 @@ namespace osu.Game.Overlays.KeyBinding
{
protected override string Header => "In Game";
- public InGameKeyBindingsSubsection(GlobalKeyBindingInputManager manager) : base(null)
+ public InGameKeyBindingsSubsection(GlobalActionContainer manager) : base(null)
{
Defaults = manager.InGameKeyBindings;
}
diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs
index 18e43ad39b..b311ee68c0 100644
--- a/osu.Game/Overlays/KeyBindingOverlay.cs
+++ b/osu.Game/Overlays/KeyBindingOverlay.cs
@@ -15,7 +15,7 @@ namespace osu.Game.Overlays
protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!");
[BackgroundDependencyLoader(permitNulls: true)]
- private void load(RulesetStore rulesets, GlobalKeyBindingInputManager global)
+ private void load(RulesetStore rulesets, GlobalActionContainer global)
{
AddSection(new GlobalKeyBindingsSection(global));
diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs
index 80823c56bf..91063bfa38 100644
--- a/osu.Game/Overlays/Mods/ModButton.cs
+++ b/osu.Game/Overlays/Mods/ModButton.cs
@@ -188,17 +188,19 @@ namespace osu.Game.Overlays.Mods
start = Mods.Length - 1;
for (int i = start; i < Mods.Length && i >= 0; i += direction)
- {
- if (Mods[i].HasImplementation)
- {
- changeSelectedIndex(i);
- return;
- }
- }
+ if (SelectAt(i)) return;
Deselect();
}
+ public bool SelectAt(int index)
+ {
+ if (!Mods[index].HasImplementation) return false;
+
+ changeSelectedIndex(index);
+ return true;
+ }
+
public void Deselect() => changeSelectedIndex(-1);
private void displayMod(Mod mod)
diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs
index a43c54f994..03c1f0468c 100644
--- a/osu.Game/Overlays/Mods/ModSection.cs
+++ b/osu.Game/Overlays/Mods/ModSection.cs
@@ -113,6 +113,23 @@ namespace osu.Game.Overlays.Mods
}
}
+ ///
+ /// Select one or more mods in this section.
+ ///
+ /// The types of s which should be deselected.
+ public void SelectTypes(IEnumerable mods)
+ {
+ foreach (var button in buttons)
+ {
+ for (int i = 0; i < button.Mods.Length; i++)
+ {
+ foreach (var mod in mods)
+ if (mod.GetType().IsInstanceOfType(button.Mods[i]))
+ button.SelectAt(i);
+ }
+ }
+ }
+
protected ModSection()
{
AutoSizeAxes = Axes.Y;
diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs
index 96faa376ba..d7268fb186 100644
--- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs
+++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs
@@ -51,6 +51,8 @@ namespace osu.Game.Overlays.Mods
[BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuColour colours, OsuGame osu, RulesetStore rulesets)
{
+ SelectedMods.ValueChanged += selectedModsChanged;
+
LowMultiplierColour = colours.Red;
HighMultiplierColour = colours.Green;
@@ -63,6 +65,37 @@ namespace osu.Game.Overlays.Mods
Ruleset.TriggerChange();
}
+ private void selectedModsChanged(IEnumerable obj)
+ {
+ foreach (ModSection section in ModSectionsContainer.Children)
+ section.SelectTypes(obj);
+
+ 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 (!ranked)
+ MultiplierLabel.Text += " (Unranked)";
+
+ if (multiplier > 1.0)
+ MultiplierLabel.FadeColour(HighMultiplierColour, 200);
+ else if (multiplier < 1.0)
+ MultiplierLabel.FadeColour(LowMultiplierColour, 200);
+ else
+ MultiplierLabel.FadeColour(Color4.White, 200);
+ }
+
protected override void PopOut()
{
base.PopOut();
@@ -97,6 +130,7 @@ namespace osu.Game.Overlays.Mods
{
foreach (ModSection section in ModSectionsContainer.Children)
section.DeselectAll();
+
refreshSelectedMods();
}
@@ -119,30 +153,7 @@ namespace osu.Game.Overlays.Mods
refreshSelectedMods();
}
- private void refreshSelectedMods()
- {
- SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
-
- 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 (!ranked)
- MultiplierLabel.Text += " (Unranked)";
-
- if (multiplier > 1.0)
- MultiplierLabel.FadeColour(HighMultiplierColour, 200);
- else if (multiplier < 1.0)
- MultiplierLabel.FadeColour(LowMultiplierColour, 200);
- else
- MultiplierLabel.FadeColour(Color4.White, 200);
- }
+ private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
public ModSelectOverlay()
{
diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs
index 223586a959..6e06ca6903 100644
--- a/osu.Game/Rulesets/UI/RulesetInputManager.cs
+++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs
@@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.UI
public abstract class RulesetInputManager : PassThroughInputManager, ICanAttachKeyCounter, IHasReplayHandler
where T : struct
{
- public class RulesetKeyBindingContainer : DatabasedKeyBindingInputManager
+ public class RulesetKeyBindingContainer : DatabasedKeyBindingContainer
{
public RulesetKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique)
: base(ruleset, variant, unique)
diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs
index 6fdd38ce30..739bc39269 100644
--- a/osu.Game/Screens/Select/PlaySongSelect.cs
+++ b/osu.Game/Screens/Select/PlaySongSelect.cs
@@ -13,6 +13,7 @@ using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Overlays;
using osu.Game.Overlays.Mods;
+using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Play;
using osu.Game.Screens.Ranking;
@@ -47,10 +48,13 @@ namespace osu.Game.Screens.Select
private SampleChannel sampleConfirm;
[BackgroundDependencyLoader(true)]
- private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay)
+ private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, OsuGame game)
{
sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection");
+ if (game != null)
+ modSelect.SelectedMods.BindTo(game.SelectedMods);
+
Footer.AddButton(@"mods", colours.Yellow, modSelect, Key.F1, float.MaxValue);
BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, colours.Purple, null, Key.Number1);
@@ -121,6 +125,9 @@ namespace osu.Game.Screens.Select
if (Beatmap.Value.Track != null)
Beatmap.Value.Track.Looping = false;
+ Beatmap.Value.Mods.UnbindBindings();
+ Beatmap.Value.Mods.Value = new Mod[] { };
+
return false;
}
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index 79f00cc988..2421a4fdfe 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -181,7 +181,7 @@ namespace osu.Game.Screens.Select
[BackgroundDependencyLoader(permitNulls: true)]
private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuGame osu, OsuColour colours)
{
- dependencies.CacheAs(this);
+ dependencies.CacheAs(this);
if (Footer != null)
{
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 0686d68968..594667ec20 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -91,6 +91,10 @@
$(SolutionDir)\packages\Humanizer.Core.2.2.0\lib\netstandard1.0\Humanizer.dll
+
+ $(SolutionDir)\packages\JetBrains.Annotations.11.1.0\lib\net20\JetBrains.Annotations.dll
+ True
+
$(SolutionDir)\packages\Microsoft.Data.Sqlite.Core.2.0.0\lib\netstandard2.0\Microsoft.Data.Sqlite.dll
@@ -446,8 +450,8 @@
-
-
+
+
diff --git a/osu.Game/packages.config b/osu.Game/packages.config
index 2938739eef..0216c8ae67 100644
--- a/osu.Game/packages.config
+++ b/osu.Game/packages.config
@@ -47,6 +47,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
+