diff --git a/osu-framework b/osu-framework
index 41e2a0a430..241133f0a6 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit 41e2a0a4304544fb67779c21cad1435c105982d5
+Subproject commit 241133f0a65326a563ba23b7166167a882d1d5cb
diff --git a/osu.Desktop/osu.nuspec b/osu.Desktop/osu.nuspec
index bb7d382cee..316a5443ef 100644
--- a/osu.Desktop/osu.nuspec
+++ b/osu.Desktop/osu.nuspec
@@ -16,11 +16,9 @@
en-AU
-
-
-
-
-
+
+
+
diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs
index a6ab18bbf7..1a0ccc9b1e 100644
--- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs
+++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs
@@ -8,7 +8,7 @@ using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Catch.Objects
{
- public abstract class CatchHitObject : HitObject, IHasXPosition, IHasComboIndex
+ public abstract class CatchHitObject : HitObject, IHasXPosition, IHasComboInformation
{
public const double OBJECT_RADIUS = 44;
diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs
index 8d56fc1081..582946ff00 100644
--- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs
+++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs
@@ -8,6 +8,8 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using OpenTK;
using osu.Game.Rulesets.Scoring;
+using osu.Game.Skinning;
+using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
@@ -57,6 +59,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
AddJudgement(new Judgement { Result = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss });
}
+ protected override void SkinChanged(ISkinSource skin, bool allowFallback)
+ {
+ base.SkinChanged(skin, allowFallback);
+
+ if (HitObject is IHasComboInformation combo)
+ AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
+ }
+
private const float preempt = 1000;
protected override void UpdateState(ArmedState state)
diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
index 1e4051c5aa..29ad3c3956 100644
--- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
+++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
@@ -64,52 +64,57 @@ namespace osu.Game.Rulesets.Catch.Objects
X = X
});
- for (var span = 0; span < this.SpanCount(); span++)
+ double lastDropletTime = StartTime;
+
+ for (int span = 0; span < this.SpanCount(); span++)
{
var spanStartTime = StartTime + span * spanDuration;
var reversed = span % 2 == 1;
- for (var d = tickDistance; d <= length; d += tickDistance)
+ for (double d = 0; d <= length; d += tickDistance)
{
- if (d > length - minDistanceFromEnd)
- break;
-
var timeProgress = d / length;
var distanceProgress = reversed ? 1 - timeProgress : timeProgress;
- var lastTickTime = spanStartTime + timeProgress * spanDuration;
- AddNested(new Droplet
+ double time = spanStartTime + timeProgress * spanDuration;
+
+ double tinyTickInterval = time - lastDropletTime;
+ while (tinyTickInterval > 100)
+ tinyTickInterval /= 2;
+
+ for (double t = lastDropletTime + tinyTickInterval; t < time; t += tinyTickInterval)
{
- StartTime = lastTickTime,
- X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
- Samples = new List(Samples.Select(s => new SampleInfo
+ double progress = reversed ? 1 - (t - spanStartTime) / spanDuration : (t - spanStartTime) / spanDuration;
+
+ AddNested(new TinyDroplet
{
- Bank = s.Bank,
- Name = @"slidertick",
- Volume = s.Volume
- }))
- });
- }
+ StartTime = t,
+ X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
+ Samples = new List(Samples.Select(s => new SampleInfo
+ {
+ Bank = s.Bank,
+ Name = @"slidertick",
+ Volume = s.Volume
+ }))
+ });
+ }
- double tinyTickInterval = tickDistance / length * spanDuration;
- while (tinyTickInterval > 100)
- tinyTickInterval /= 2;
-
- for (double t = 0; t < spanDuration; t += tinyTickInterval)
- {
- double progress = reversed ? 1 - t / spanDuration : t / spanDuration;
-
- AddNested(new TinyDroplet
+ if (d > minDistanceFromEnd && Math.Abs(d - length) > minDistanceFromEnd)
{
- StartTime = spanStartTime + t,
- X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
- Samples = new List(Samples.Select(s => new SampleInfo
+ AddNested(new Droplet
{
- Bank = s.Bank,
- Name = @"slidertick",
- Volume = s.Volume
- }))
- });
+ StartTime = time,
+ X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
+ Samples = new List(Samples.Select(s => new SampleInfo
+ {
+ Bank = s.Bank,
+ Name = @"slidertick",
+ Volume = s.Volume
+ }))
+ });
+ }
+
+ lastDropletTime = time;
}
AddNested(new Fruit
diff --git a/osu.Game.Rulesets.Catch/Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch/Tests/CatchBeatmapConversionTest.cs
index 826c900140..e40510b71b 100644
--- a/osu.Game.Rulesets.Catch/Tests/CatchBeatmapConversionTest.cs
+++ b/osu.Game.Rulesets.Catch/Tests/CatchBeatmapConversionTest.cs
@@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Tests
{
protected override string ResourceAssembly => "osu.Game.Rulesets.Catch";
- [TestCase("basic"), Ignore("See: https://github.com/ppy/osu/issues/2149")]
+ [TestCase("basic"), Ignore("See: https://github.com/ppy/osu/issues/2232")]
public new void Test(string name)
{
base.Test(name);
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
index 2e59e2dc60..d4d89c2aa3 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
@@ -5,6 +5,9 @@ using System.ComponentModel;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Graphics;
using System.Linq;
+using osu.Game.Rulesets.Objects.Types;
+using osu.Game.Skinning;
+using OpenTK.Graphics;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
@@ -34,6 +37,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}
}
+ protected override void SkinChanged(ISkinSource skin, bool allowFallback)
+ {
+ base.SkinChanged(skin, allowFallback);
+
+ if (HitObject is IHasComboInformation combo)
+ AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
+ }
+
protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadein);
protected virtual void UpdateCurrentState(ArmedState state)
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs
index 26186a0049..c59c22c771 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs
@@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
public double? SnakedStart { get; private set; }
public double? SnakedEnd { get; private set; }
- private Color4 accentColour;
+ private Color4 accentColour = Color4.White;
///
/// Used to colour the path.
///
diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
index 5d1908fa6e..c00c30ced9 100644
--- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
@@ -10,7 +10,7 @@ using osu.Game.Beatmaps.ControlPoints;
namespace osu.Game.Rulesets.Osu.Objects
{
- public abstract class OsuHitObject : HitObject, IHasComboIndex, IHasPosition
+ public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition
{
public const double OBJECT_RADIUS = 64;
diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs
index 58b51085a4..5874314f75 100644
--- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs
+++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs
@@ -110,7 +110,7 @@ namespace osu.Game.Beatmaps
Skin skin;
try
{
- skin = new BeatmapSkin(BeatmapInfo, store, audioManager);
+ skin = new LegacyBeatmapSkin(BeatmapInfo, store, audioManager);
}
catch (Exception e)
{
diff --git a/osu.Game/Beatmaps/BeatmapProcessor.cs b/osu.Game/Beatmaps/BeatmapProcessor.cs
index 83b2867df7..f2cc419043 100644
--- a/osu.Game/Beatmaps/BeatmapProcessor.cs
+++ b/osu.Game/Beatmaps/BeatmapProcessor.cs
@@ -23,9 +23,9 @@ namespace osu.Game.Beatmaps
/// The Beatmap to process.
public virtual void PostProcess(Beatmap beatmap)
{
- IHasComboIndex lastObj = null;
+ IHasComboInformation lastObj = null;
- foreach (var obj in beatmap.HitObjects.OfType())
+ foreach (var obj in beatmap.HitObjects.OfType())
{
if (obj.NewCombo)
{
diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs
index 67d497ba83..131c010c5c 100644
--- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs
+++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using osu.Framework.Logging;
using OpenTK.Graphics;
namespace osu.Game.Beatmaps.Formats
@@ -31,7 +32,11 @@ namespace osu.Game.Beatmaps.Formats
if (line.StartsWith(@"[") && line.EndsWith(@"]"))
{
if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section))
- throw new InvalidDataException($@"Unknown osu section {line}");
+ {
+ Logger.Log($"Unknown section \"{line}\" in {beatmap}");
+ section = Section.None;
+ }
+
continue;
}
diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs
index a65593ff82..f0e67a7185 100644
--- a/osu.Game/Database/ArchiveModelManager.cs
+++ b/osu.Game/Database/ArchiveModelManager.cs
@@ -13,6 +13,7 @@ using osu.Game.IO;
using osu.Game.IO.Archives;
using osu.Game.IPC;
using osu.Game.Overlays.Notifications;
+using SharpCompress.Common;
using FileInfo = osu.Game.IO.FileInfo;
namespace osu.Game.Database
@@ -79,7 +80,6 @@ namespace osu.Game.Database
var notification = new ProgressNotification
{
Text = "Import is initialising...",
- CompletionText = "Import successful!",
Progress = 0,
State = ProgressNotificationState.Active,
};
@@ -88,7 +88,8 @@ namespace osu.Game.Database
List imported = new List();
- int i = 0;
+ int current = 0;
+ int errors = 0;
foreach (string path in paths)
{
if (notification.State == ProgressNotificationState.Cancelled)
@@ -97,11 +98,11 @@ namespace osu.Game.Database
try
{
- notification.Text = $"Importing ({i} of {paths.Length})\n{Path.GetFileName(path)}";
+ notification.Text = $"Importing ({++current} of {paths.Length})\n{Path.GetFileName(path)}";
using (ArchiveReader reader = getReaderFrom(path))
imported.Add(Import(reader));
- notification.Progress = (float)++i / paths.Length;
+ notification.Progress = (float)current / paths.Length;
// We may or may not want to delete the file depending on where it is stored.
// e.g. reconstructing/repairing database with items from default storage.
@@ -121,9 +122,11 @@ namespace osu.Game.Database
{
e = e.InnerException ?? e;
Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})");
+ errors++;
}
}
+ notification.Text = errors > 0 ? $"Import complete with {errors} errors" : "Import successful!";
notification.State = ProgressNotificationState.Completed;
}
@@ -218,9 +221,11 @@ namespace osu.Game.Database
// user requested abort
return;
- notification.Text = $"Deleting ({i} of {items.Count})";
- notification.Progress = (float)++i / items.Count;
+ notification.Text = $"Deleting ({++i} of {items.Count})";
+
Delete(b);
+
+ notification.Progress = (float)i / items.Count;
}
}
@@ -254,9 +259,11 @@ namespace osu.Game.Database
// user requested abort
return;
- notification.Text = $"Restoring ({i} of {items.Count})";
- notification.Progress = (float)++i / items.Count;
+ notification.Text = $"Restoring ({++i} of {items.Count})";
+
Undelete(item);
+
+ notification.Progress = (float)i / items.Count;
}
}
@@ -331,7 +338,9 @@ namespace osu.Game.Database
{
if (ZipFile.IsZipFile(path))
return new ZipArchiveReader(Files.Storage.GetStream(path), Path.GetFileName(path));
- return new LegacyFilesystemReader(path);
+ if (Directory.Exists(path))
+ return new LegacyFilesystemReader(path);
+ throw new InvalidFormatException($"{path} is not a valid archive");
}
}
}
diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs
index 6f9d83473f..89ed8044e6 100644
--- a/osu.Game/Graphics/Backgrounds/Triangles.cs
+++ b/osu.Game/Graphics/Backgrounds/Triangles.cs
@@ -242,7 +242,7 @@ namespace osu.Game.Graphics.Backgrounds
triangle,
colourInfo,
null,
- Shared.VertexBatch.Add,
+ Shared.VertexBatch.AddAction,
Vector2.Divide(localInflationAmount, size));
}
diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs
index 6d9bf231c3..33786252ab 100644
--- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs
+++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs
@@ -30,6 +30,9 @@ namespace osu.Game.Graphics.UserInterface
}
}
+ // We may not be focused yet, but we need to handle keyboard input to be able to request focus
+ public override bool HandleKeyboardInput => HoldFocus || base.HandleKeyboardInput;
+
protected override void OnFocus(InputState state)
{
base.OnFocus(state);
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index 945cd928d4..348364a2bf 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -102,14 +102,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
}
}
- protected override void SkinChanged(ISkinSource skin, bool allowFallback)
- {
- base.SkinChanged(skin, allowFallback);
-
- if (HitObject is IHasComboIndex combo)
- AccentColour = skin.GetComboColour(combo) ?? Color4.White;
- }
-
protected override void LoadComplete()
{
base.LoadComplete();
diff --git a/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs b/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs
new file mode 100644
index 0000000000..1d4f4e0f90
--- /dev/null
+++ b/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs
@@ -0,0 +1,26 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+namespace osu.Game.Rulesets.Objects.Types
+{
+ ///
+ /// A HitObject that is part of a combo and has extended information about its position relative to other combo objects.
+ ///
+ public interface IHasComboInformation : IHasCombo
+ {
+ ///
+ /// The offset of this hitobject in the current combo.
+ ///
+ int IndexInCurrentCombo { get; set; }
+
+ ///
+ /// The offset of this combo in relation to the beatmap.
+ ///
+ int ComboIndex { get; set; }
+
+ ///
+ /// Whether this is the last object in the current combo.
+ ///
+ bool LastInCombo { get; set; }
+ }
+}
diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs
index 3a3f3d4650..fc747acbb4 100644
--- a/osu.Game/Screens/Menu/LogoVisualisation.cs
+++ b/osu.Game/Screens/Menu/LogoVisualisation.cs
@@ -211,7 +211,7 @@ namespace osu.Game.Screens.Menu
rectangle,
colourInfo,
null,
- Shared.VertexBatch.Add,
+ Shared.VertexBatch.AddAction,
//barSize by itself will make it smooth more in the X axis than in the Y axis, this reverts that.
Vector2.Divide(inflation, barSize.Yx));
}
diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs
index 3fcb885655..b7d2ed2e1f 100644
--- a/osu.Game/Screens/Menu/OsuLogo.cs
+++ b/osu.Game/Screens/Menu/OsuLogo.cs
@@ -337,12 +337,10 @@ namespace osu.Game.Screens.Menu
}
}
- private bool interactive => Action != null && Alpha > 0.2f;
+ public override bool HandleMouseInput => base.HandleMouseInput && Action != null && Alpha > 0.2f;
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
- if (!interactive) return false;
-
logoBounceContainer.ScaleTo(0.9f, 1000, Easing.Out);
return true;
}
@@ -355,8 +353,6 @@ namespace osu.Game.Screens.Menu
protected override bool OnClick(InputState state)
{
- if (!interactive) return false;
-
if (Action?.Invoke() ?? true)
sampleClick.Play();
@@ -368,8 +364,6 @@ namespace osu.Game.Screens.Menu
protected override bool OnHover(InputState state)
{
- if (!interactive) return false;
-
logoHoverContainer.ScaleTo(1.1f, 500, Easing.OutElastic);
return true;
}
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index ca8a1cae41..f01616ade2 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -259,6 +259,8 @@ namespace osu.Game.Screens.Select
private void workingBeatmapChanged(WorkingBeatmap beatmap)
{
+ if (beatmap is DummyWorkingBeatmap) return;
+
if (IsCurrentScreen && !Carousel.SelectBeatmap(beatmap?.BeatmapInfo, false))
// If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch
if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != Ruleset.Value)
diff --git a/osu.Game/Skinning/BeatmapSkin.cs b/osu.Game/Skinning/BeatmapSkin.cs
deleted file mode 100644
index 815aac2f64..0000000000
--- a/osu.Game/Skinning/BeatmapSkin.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using System.IO;
-using osu.Framework.Audio;
-using osu.Framework.Graphics.Textures;
-using osu.Framework.IO.Stores;
-using osu.Game.Beatmaps;
-
-namespace osu.Game.Skinning
-{
- public class BeatmapSkin : LegacySkin
- {
- public BeatmapSkin(BeatmapInfo beatmap, IResourceStore storage, AudioManager audioManager)
- : base(new SkinInfo { Name = beatmap.ToString(), Creator = beatmap.Metadata.Author.ToString() })
- {
- storage = new LegacySkinResourceStore(beatmap.BeatmapSet, storage);
-
- Samples = audioManager.GetSampleManager(storage);
-
- Textures = new TextureStore(new RawTextureLoaderStore(storage));
-
- var decoder = new LegacySkinDecoder();
-
- using (StreamReader reader = new StreamReader(storage.GetStream(beatmap.Path)))
- {
- Configuration = decoder.Decode(reader);
- }
- }
- }
-}
diff --git a/osu.Game/Skinning/ISkinSource.cs b/osu.Game/Skinning/ISkinSource.cs
index 924fdbd8c1..d8f259b4ea 100644
--- a/osu.Game/Skinning/ISkinSource.cs
+++ b/osu.Game/Skinning/ISkinSource.cs
@@ -5,8 +5,6 @@ using System;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures;
-using osu.Game.Rulesets.Objects.Types;
-using OpenTK.Graphics;
namespace osu.Game.Skinning
{
@@ -23,6 +21,8 @@ namespace osu.Game.Skinning
SampleChannel GetSample(string sampleName);
- Color4? GetComboColour(IHasComboIndex comboObject);
+ TValue GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : class;
+
+ TValue? GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : struct;
}
}
diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs
new file mode 100644
index 0000000000..01beb8db32
--- /dev/null
+++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs
@@ -0,0 +1,20 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Framework.Audio;
+using osu.Framework.IO.Stores;
+using osu.Game.Beatmaps;
+
+namespace osu.Game.Skinning
+{
+ public class LegacyBeatmapSkin : LegacySkin
+ {
+ public LegacyBeatmapSkin(BeatmapInfo beatmap, IResourceStore storage, AudioManager audioManager)
+ : base(createSkinInfo(beatmap), new LegacySkinResourceStore(beatmap.BeatmapSet, storage), audioManager, beatmap.Path)
+ {
+ }
+
+ private static SkinInfo createSkinInfo(BeatmapInfo beatmap) =>
+ new SkinInfo { Name = beatmap.ToString(), Creator = beatmap.Metadata.Author.ToString() };
+ }
+}
diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs
index a361fa2b8a..66e8cb8f9f 100644
--- a/osu.Game/Skinning/LegacySkin.cs
+++ b/osu.Game/Skinning/LegacySkin.cs
@@ -22,23 +22,21 @@ namespace osu.Game.Skinning
protected SampleManager Samples;
public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager)
- : this(skin)
+ : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini")
{
- storage = new LegacySkinResourceStore(skin, storage);
- Samples = audioManager.GetSampleManager(storage);
- Textures = new TextureStore(new RawTextureLoaderStore(storage));
+ }
- Stream stream = storage.GetStream("skin.ini");
+ protected LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, string filename) : base(skin)
+ {
+ Stream stream = storage.GetStream(filename);
if (stream != null)
using (StreamReader reader = new StreamReader(stream))
Configuration = new LegacySkinDecoder().Decode(reader);
else
Configuration = new SkinConfiguration();
- }
- protected LegacySkin(SkinInfo skin)
- : base(skin)
- {
+ Samples = audioManager.GetSampleManager(storage);
+ Textures = new TextureStore(new RawTextureLoaderStore(storage));
}
public override Drawable GetDrawableComponent(string componentName)
diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs
index 9a881f9241..853abceddf 100644
--- a/osu.Game/Skinning/LegacySkinDecoder.cs
+++ b/osu.Game/Skinning/LegacySkinDecoder.cs
@@ -29,7 +29,7 @@ namespace osu.Game.Skinning
break;
}
- return;
+ break;
}
base.ParseLine(output, section, line);
diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs
index a0cc11a324..b7e2bd0daf 100644
--- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs
+++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs
@@ -7,8 +7,6 @@ using osu.Framework.Audio.Sample;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Textures;
-using osu.Game.Rulesets.Objects.Types;
-using OpenTK.Graphics;
namespace osu.Game.Skinning
{
@@ -22,7 +20,25 @@ namespace osu.Game.Skinning
public SampleChannel GetSample(string sampleName) => source.GetSample(sampleName) ?? fallbackSource?.GetSample(sampleName);
- public Color4? GetComboColour(IHasComboIndex comboObject) => source.GetComboColour(comboObject) ?? fallbackSource?.GetComboColour(comboObject);
+ public TValue? GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : struct
+ {
+ TValue? val = null;
+ var conf = (source as Skin)?.Configuration as TConfiguration;
+ if (conf != null)
+ val = query?.Invoke(conf);
+
+ return val ?? fallbackSource?.GetValue(query);
+ }
+
+ public TValue GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : class
+ {
+ TValue val = null;
+ var conf = (source as Skin)?.Configuration as TConfiguration;
+ if (conf != null)
+ val = query?.Invoke(conf);
+
+ return val ?? fallbackSource?.GetValue(query);
+ }
private readonly ISkinSource source;
private ISkinSource fallbackSource;
diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs
index 5d2c640244..02fb84a4a2 100644
--- a/osu.Game/Skinning/Skin.cs
+++ b/osu.Game/Skinning/Skin.cs
@@ -5,8 +5,6 @@ using System;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures;
-using osu.Game.Rulesets.Objects.Types;
-using OpenTK.Graphics;
namespace osu.Game.Skinning
{
@@ -24,8 +22,11 @@ namespace osu.Game.Skinning
public abstract Texture GetTexture(string componentName);
- public virtual Color4? GetComboColour(IHasComboIndex comboObject) =>
- Configuration.ComboColours.Count == 0 ? (Color4?)null : Configuration.ComboColours[comboObject.ComboIndex % Configuration.ComboColours.Count];
+ public TValue GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : class
+ => Configuration is TConfiguration conf ? query?.Invoke(conf) : null;
+
+ public TValue? GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : struct
+ => Configuration is TConfiguration conf ? query?.Invoke(conf) : null;
protected Skin(SkinInfo skin)
{
diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs
index 9ae6eef49f..f965a77cce 100644
--- a/osu.Game/Skinning/SkinManager.cs
+++ b/osu.Game/Skinning/SkinManager.cs
@@ -14,8 +14,6 @@ using osu.Framework.Graphics.Textures;
using osu.Framework.Platform;
using osu.Game.Database;
using osu.Game.IO.Archives;
-using osu.Game.Rulesets.Objects.Types;
-using OpenTK.Graphics;
namespace osu.Game.Skinning
{
@@ -120,10 +118,12 @@ namespace osu.Game.Skinning
public Drawable GetDrawableComponent(string componentName) => CurrentSkin.Value.GetDrawableComponent(componentName);
- public Texture GetTexture(string componentName)=> CurrentSkin.Value.GetTexture(componentName);
+ public Texture GetTexture(string componentName) => CurrentSkin.Value.GetTexture(componentName);
public SampleChannel GetSample(string sampleName) => CurrentSkin.Value.GetSample(sampleName);
- public Color4? GetComboColour(IHasComboIndex comboObject) => CurrentSkin.Value.GetComboColour(comboObject);
+ public TValue GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : class => CurrentSkin.Value.GetValue(query);
+
+ public TValue? GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : struct => CurrentSkin.Value.GetValue(query);
}
}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 1c902a158f..6460de179d 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -374,7 +374,7 @@
-
+
@@ -872,7 +872,7 @@
-
+