Merge branch 'master' into fix-catch-clamp

This commit is contained in:
Ondřej Vajďák 2022-09-21 11:35:58 +02:00 committed by GitHub
commit cc21e42e35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 123 additions and 79 deletions

View File

@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Catch.Tests
}); });
} }
private class TestSkin : DefaultSkin private class TestSkin : TrianglesSkin
{ {
public bool FlipCatcherPlate { get; set; } public bool FlipCatcherPlate { get; set; }

View File

@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(SkinManager skins) private void load(SkinManager skins)
{ {
var defaultLegacySkin = skins.DefaultLegacySkin; var defaultLegacySkin = skins.DefaultClassicSkin;
// sprite names intentionally swapped to match stable member naming / ease of cross-referencing // sprite names intentionally swapped to match stable member naming / ease of cross-referencing
explosion1.Texture = defaultLegacySkin.GetTexture("scoreboard-explosion-2"); explosion1.Texture = defaultLegacySkin.GetTexture("scoreboard-explosion-2");

View File

@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
[Test] [Test]
public void TestDefaultSkin() public void TestDefaultSkin()
{ {
AddStep("set default skin", () => skins.CurrentSkinInfo.Value = DefaultSkin.CreateInfo().ToLiveUnmanaged()); AddStep("set default skin", () => skins.CurrentSkinInfo.Value = TrianglesSkin.CreateInfo().ToLiveUnmanaged());
} }
[Test] [Test]

View File

@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Tests
}); });
AddStep("setup default legacy skin", () => AddStep("setup default legacy skin", () =>
{ {
skinManager.CurrentSkinInfo.Value = skinManager.DefaultLegacySkin.SkinInfo; skinManager.CurrentSkinInfo.Value = skinManager.DefaultClassicSkin.SkinInfo;
}); });
}); });
} }

View File

@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Tests
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
Child = new SkinProvidingContainer(new DefaultSkin(null)) Child = new SkinProvidingContainer(new TrianglesSkin(null))
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Child = drawableHitCircle = new DrawableHitCircle(hitCircle) Child = drawableHitCircle = new DrawableHitCircle(hitCircle)

View File

@ -44,6 +44,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1; double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;
if (mods.Any(m => m is OsuModTouchDevice))
{
aimRating = Math.Pow(aimRating, 0.8);
flashlightRating = Math.Pow(flashlightRating, 0.8);
}
if (mods.Any(h => h is OsuModRelax)) if (mods.Any(h => h is OsuModRelax))
{ {
aimRating *= 0.9; aimRating *= 0.9;
@ -127,6 +133,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
protected override Mod[] DifficultyAdjustmentMods => new Mod[] protected override Mod[] DifficultyAdjustmentMods => new Mod[]
{ {
new OsuModTouchDevice(),
new OsuModDoubleTime(), new OsuModDoubleTime(),
new OsuModHalfTime(), new OsuModHalfTime(),
new OsuModEasy(), new OsuModEasy(),

View File

@ -88,12 +88,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
private double computeAimValue(ScoreInfo score, OsuDifficultyAttributes attributes) private double computeAimValue(ScoreInfo score, OsuDifficultyAttributes attributes)
{ {
double rawAim = attributes.AimDifficulty; double aimValue = Math.Pow(5.0 * Math.Max(1.0, attributes.AimDifficulty / 0.0675) - 4.0, 3.0) / 100000.0;
if (score.Mods.Any(m => m is OsuModTouchDevice))
rawAim = Math.Pow(rawAim, 0.8);
double aimValue = Math.Pow(5.0 * Math.Max(1.0, rawAim / 0.0675) - 4.0, 3.0) / 100000.0;
double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) + double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) +
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0); (totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
@ -233,12 +228,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
if (!score.Mods.Any(h => h is OsuModFlashlight)) if (!score.Mods.Any(h => h is OsuModFlashlight))
return 0.0; return 0.0;
double rawFlashlight = attributes.FlashlightDifficulty; double flashlightValue = Math.Pow(attributes.FlashlightDifficulty, 2.0) * 25.0;
if (score.Mods.Any(m => m is OsuModTouchDevice))
rawFlashlight = Math.Pow(rawFlashlight, 0.8);
double flashlightValue = Math.Pow(rawFlashlight, 2.0) * 25.0;
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses. // Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0) if (effectiveMissCount > 0)

View File

@ -306,7 +306,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
new Color4(128, 255, 128, 255), new Color4(128, 255, 128, 255),
new Color4(255, 187, 255, 255), new Color4(255, 187, 255, 255),
new Color4(255, 177, 140, 255), new Color4(255, 177, 140, 255),
new Color4(100, 100, 100, 100), new Color4(100, 100, 100, 255), // alpha is specified as 100, but should be ignored.
}; };
Assert.AreEqual(expectedColors.Length, comboColors.Count); Assert.AreEqual(expectedColors.Length, comboColors.Count);
for (int i = 0; i < expectedColors.Length; i++) for (int i = 0; i < expectedColors.Length; i++)

View File

@ -202,7 +202,7 @@ namespace osu.Game.Tests.Skins.IO
skinManager.CurrentSkinInfo.Value.PerformRead(s => skinManager.CurrentSkinInfo.Value.PerformRead(s =>
{ {
Assert.IsFalse(s.Protected); Assert.IsFalse(s.Protected);
Assert.AreEqual(typeof(DefaultSkin), s.CreateInstance(skinManager).GetType()); Assert.AreEqual(typeof(TrianglesSkin), s.CreateInstance(skinManager).GetType());
new LegacySkinExporter(osu.Dependencies.Get<Storage>()).ExportModelTo(s, exportStream); new LegacySkinExporter(osu.Dependencies.Get<Storage>()).ExportModelTo(s, exportStream);
@ -215,7 +215,7 @@ namespace osu.Game.Tests.Skins.IO
{ {
Assert.IsFalse(s.Protected); Assert.IsFalse(s.Protected);
Assert.AreNotEqual(originalSkinId, s.ID); Assert.AreNotEqual(originalSkinId, s.ID);
Assert.AreEqual(typeof(DefaultSkin), s.CreateInstance(skinManager).GetType()); Assert.AreEqual(typeof(TrianglesSkin), s.CreateInstance(skinManager).GetType());
}); });
return Task.CompletedTask; return Task.CompletedTask;
@ -226,7 +226,7 @@ namespace osu.Game.Tests.Skins.IO
{ {
var skinManager = osu.Dependencies.Get<SkinManager>(); var skinManager = osu.Dependencies.Get<SkinManager>();
skinManager.CurrentSkinInfo.Value = skinManager.DefaultLegacySkin.SkinInfo; skinManager.CurrentSkinInfo.Value = skinManager.DefaultClassicSkin.SkinInfo;
skinManager.EnsureMutableSkin(); skinManager.EnsureMutableSkin();

View File

@ -29,7 +29,7 @@ namespace osu.Game.Tests.Skins
new Color4(142, 199, 255, 255), new Color4(142, 199, 255, 255),
new Color4(255, 128, 128, 255), new Color4(255, 128, 128, 255),
new Color4(128, 255, 255, 255), new Color4(128, 255, 255, 255),
new Color4(100, 100, 100, 100), new Color4(100, 100, 100, 255), // alpha is specified as 100, but should be ignored.
}; };
Assert.AreEqual(expectedColors.Count, comboColors.Count); Assert.AreEqual(expectedColors.Count, comboColors.Count);

View File

@ -1,12 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Skinning;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
{ {
@ -19,7 +18,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
SetContents(skin => SetContents(skin =>
{ {
var implementation = skin != null var implementation = skin is LegacySkin
? CreateLegacyImplementation() ? CreateLegacyImplementation()
: CreateDefaultImplementation(); : CreateDefaultImplementation();

View File

@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test] [Test]
public void TestEmptyLegacyBeatmapSkinFallsBack() public void TestEmptyLegacyBeatmapSkinFallsBack()
{ {
CreateSkinTest(DefaultSkin.CreateInfo(), () => new LegacyBeatmapSkin(new BeatmapInfo(), null)); CreateSkinTest(TrianglesSkin.CreateInfo(), () => new LegacyBeatmapSkin(new BeatmapInfo(), null));
AddUntilStep("wait for hud load", () => Player.ChildrenOfType<SkinnableTargetContainer>().All(c => c.ComponentsLoaded)); AddUntilStep("wait for hud load", () => Player.ChildrenOfType<SkinnableTargetContainer>().All(c => c.ComponentsLoaded));
AddAssert("hud from default skin", () => AssertComponentsFromExpectedSource(SkinnableTarget.MainHUDComponents, skinManager.CurrentSkin.Value)); AddAssert("hud from default skin", () => AssertComponentsFromExpectedSource(SkinnableTarget.MainHUDComponents, skinManager.CurrentSkin.Value));
} }

View File

@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual.Gameplay
} }
private TestParticleSpewer createSpewer() => private TestParticleSpewer createSpewer() =>
new TestParticleSpewer(skinManager.DefaultLegacySkin.GetTexture("star2")) new TestParticleSpewer(skinManager.DefaultClassicSkin.GetTexture("star2"))
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
RelativePositionAxes = Axes.Both, RelativePositionAxes = Axes.Both,

View File

@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Navigation
[Test] [Test]
public void TestEditDefaultSkin() public void TestEditDefaultSkin()
{ {
AddAssert("is default skin", () => skinManager.CurrentSkinInfo.Value.ID == SkinInfo.DEFAULT_SKIN); AddAssert("is default skin", () => skinManager.CurrentSkinInfo.Value.ID == SkinInfo.TRIANGLES_SKIN);
AddStep("open settings", () => { Game.Settings.Show(); }); AddStep("open settings", () => { Game.Settings.Show(); });
@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Navigation
AddStep("open skin editor", () => skinEditor.Show()); AddStep("open skin editor", () => skinEditor.Show());
// Until step required as the skin editor may take time to load (and an extra scheduled frame for the mutable part). // Until step required as the skin editor may take time to load (and an extra scheduled frame for the mutable part).
AddUntilStep("is modified default skin", () => skinManager.CurrentSkinInfo.Value.ID != SkinInfo.DEFAULT_SKIN); AddUntilStep("is modified default skin", () => skinManager.CurrentSkinInfo.Value.ID != SkinInfo.TRIANGLES_SKIN);
AddAssert("is not protected", () => skinManager.CurrentSkinInfo.Value.PerformRead(s => !s.Protected)); AddAssert("is not protected", () => skinManager.CurrentSkinInfo.Value.PerformRead(s => !s.Protected));
AddUntilStep("export button enabled", () => Game.Settings.ChildrenOfType<SkinSection.ExportSkinButton>().SingleOrDefault()?.Enabled.Value == true); AddUntilStep("export button enabled", () => Game.Settings.ChildrenOfType<SkinSection.ExportSkinButton>().SingleOrDefault()?.Enabled.Value == true);

View File

@ -34,6 +34,8 @@ namespace osu.Game.Tests.Visual.UserInterface
[SetUp] [SetUp]
public void SetUp() => Schedule(() => public void SetUp() => Schedule(() =>
{ {
InputManager.MoveMouseTo(Vector2.Zero);
TimeToCompleteProgress = 2000; TimeToCompleteProgress = 2000;
progressingNotifications.Clear(); progressingNotifications.Clear();
@ -230,6 +232,31 @@ namespace osu.Game.Tests.Visual.UserInterface
AddUntilStep("wait overlay not present", () => !notificationOverlay.IsPresent); AddUntilStep("wait overlay not present", () => !notificationOverlay.IsPresent);
} }
[Test]
public void TestProgressClick()
{
ProgressNotification notification = null!;
AddStep("add progress notification", () =>
{
notification = new ProgressNotification
{
Text = @"Uploading to BSS...",
CompletionText = "Uploaded to BSS!",
};
notificationOverlay.Post(notification);
progressingNotifications.Add(notification);
});
AddStep("hover over notification", () => InputManager.MoveMouseTo(notificationOverlay.ChildrenOfType<ProgressNotification>().Single()));
AddStep("left click", () => InputManager.Click(MouseButton.Left));
AddAssert("not cancelled", () => notification.State == ProgressNotificationState.Active);
AddStep("right click", () => InputManager.Click(MouseButton.Right));
AddAssert("cancelled", () => notification.State == ProgressNotificationState.Cancelled);
}
[Test] [Test]
public void TestCompleteProgress() public void TestCompleteProgress()
{ {
@ -301,7 +328,7 @@ namespace osu.Game.Tests.Visual.UserInterface
{ {
SimpleNotification notification = null!; SimpleNotification notification = null!;
AddStep(@"post", () => notificationOverlay.Post(notification = new BackgroundNotification { Text = @"Welcome to osu!. Enjoy your stay!" })); AddStep(@"post", () => notificationOverlay.Post(notification = new BackgroundNotification { Text = @"Welcome to osu!. Enjoy your stay!" }));
AddUntilStep("check is toast", () => !notification.IsInToastTray); AddUntilStep("check is toast", () => notification.IsInToastTray);
AddAssert("light is not visible", () => notification.ChildrenOfType<Notification.NotificationLight>().Single().Alpha == 0); AddAssert("light is not visible", () => notification.ChildrenOfType<Notification.NotificationLight>().Single().Alpha == 0);
AddUntilStep("wait for forward to overlay", () => !notification.IsInToastTray); AddUntilStep("wait for forward to overlay", () => !notification.IsInToastTray);

View File

@ -79,7 +79,7 @@ namespace osu.Game.Beatmaps.Formats
switch (section) switch (section)
{ {
case Section.Colours: case Section.Colours:
HandleColours(output, line); HandleColours(output, line, false);
return; return;
} }
} }
@ -93,7 +93,7 @@ namespace osu.Game.Beatmaps.Formats
return line; return line;
} }
protected void HandleColours<TModel>(TModel output, string line) protected void HandleColours<TModel>(TModel output, string line, bool allowAlpha)
{ {
var pair = SplitKeyVal(line); var pair = SplitKeyVal(line);
@ -108,7 +108,7 @@ namespace osu.Game.Beatmaps.Formats
try try
{ {
byte alpha = split.Length == 4 ? byte.Parse(split[3]) : (byte)255; byte alpha = allowAlpha && split.Length == 4 ? byte.Parse(split[3]) : (byte)255;
colour = new Color4(byte.Parse(split[0]), byte.Parse(split[1]), byte.Parse(split[2]), alpha); colour = new Color4(byte.Parse(split[0]), byte.Parse(split[1]), byte.Parse(split[2]), alpha);
} }
catch catch

View File

@ -39,7 +39,7 @@ namespace osu.Game.Configuration
{ {
// UI/selection defaults // UI/selection defaults
SetDefault(OsuSetting.Ruleset, string.Empty); SetDefault(OsuSetting.Ruleset, string.Empty);
SetDefault(OsuSetting.Skin, SkinInfo.DEFAULT_SKIN.ToString()); SetDefault(OsuSetting.Skin, SkinInfo.TRIANGLES_SKIN.ToString());
SetDefault(OsuSetting.BeatmapDetailTab, PlayBeatmapDetailArea.TabType.Details); SetDefault(OsuSetting.BeatmapDetailTab, PlayBeatmapDetailArea.TabType.Details);
SetDefault(OsuSetting.BeatmapDetailModsFilter, false); SetDefault(OsuSetting.BeatmapDetailModsFilter, false);

View File

@ -69,8 +69,9 @@ namespace osu.Game.Database
/// 22 2022-07-31 Added ModPreset. /// 22 2022-07-31 Added ModPreset.
/// 23 2022-08-01 Added LastLocalUpdate to BeatmapInfo. /// 23 2022-08-01 Added LastLocalUpdate to BeatmapInfo.
/// 24 2022-08-22 Added MaximumStatistics to ScoreInfo. /// 24 2022-08-22 Added MaximumStatistics to ScoreInfo.
/// 25 2022-09-18 Remove skins to add with new naming.
/// </summary> /// </summary>
private const int schema_version = 24; private const int schema_version = 25;
/// <summary> /// <summary>
/// Lock object which is held during <see cref="BlockAllOperations"/> sections, blocking realm retrieval during blocking periods. /// Lock object which is held during <see cref="BlockAllOperations"/> sections, blocking realm retrieval during blocking periods.
@ -870,6 +871,11 @@ namespace osu.Game.Database
} }
break; break;
case 25:
// Remove the default skins so they can be added back by SkinManager with updated naming.
migration.NewRealm.RemoveRange(migration.NewRealm.All<SkinInfo>().Where(s => s.Protected));
break;
} }
} }

View File

@ -229,8 +229,8 @@ namespace osu.Game.Overlays.Notifications
protected override bool OnClick(ClickEvent e) protected override bool OnClick(ClickEvent e)
{ {
// Clicking with anything but left button should dismiss but not perform the activation action. // Clicking with anything but left button should dismiss but not perform the activation action.
if (e.Button == MouseButton.Left) if (e.Button == MouseButton.Left && Activated?.Invoke() == false)
Activated?.Invoke(); return true;
Close(false); Close(false);
return true; return true;

View File

@ -78,8 +78,7 @@ namespace osu.Game.Overlays.Settings.Sections
realmSubscription = realm.RegisterForNotifications(_ => realm.Realm.All<SkinInfo>() realmSubscription = realm.RegisterForNotifications(_ => realm.Realm.All<SkinInfo>()
.Where(s => !s.DeletePending) .Where(s => !s.DeletePending)
.OrderByDescending(s => s.Protected) // protected skins should be at the top. .OrderBy(s => s.Name, StringComparer.OrdinalIgnoreCase), skinsChanged);
.ThenBy(s => s.Name, StringComparer.OrdinalIgnoreCase), skinsChanged);
skinDropdown.Current.BindValueChanged(skin => skinDropdown.Current.BindValueChanged(skin =>
{ {
@ -101,14 +100,17 @@ namespace osu.Game.Overlays.Settings.Sections
if (!sender.Any()) if (!sender.Any())
return; return;
int protectedCount = sender.Count(s => s.Protected);
// For simplicity repopulate the full list. // For simplicity repopulate the full list.
// In the future we should change this to properly handle ChangeSet events. // In the future we should change this to properly handle ChangeSet events.
dropdownItems.Clear(); dropdownItems.Clear();
foreach (var skin in sender)
dropdownItems.Add(sender.Single(s => s.ID == SkinInfo.TRIANGLES_SKIN).ToLive(realm));
dropdownItems.Add(sender.Single(s => s.ID == SkinInfo.CLASSIC_SKIN).ToLive(realm));
dropdownItems.Add(random_skin_info);
foreach (var skin in sender.Where(s => !s.Protected))
dropdownItems.Add(skin.ToLive(realm)); dropdownItems.Add(skin.ToLive(realm));
dropdownItems.Insert(protectedCount, random_skin_info);
Schedule(() => skinDropdown.Items = dropdownItems); Schedule(() => skinDropdown.Items = dropdownItems);
} }

View File

@ -130,7 +130,7 @@ namespace osu.Game.Screens.Backgrounds
case BackgroundSource.Skin: case BackgroundSource.Skin:
// default skins should use the default background rotation, which won't be the case if a SkinBackground is created for them. // default skins should use the default background rotation, which won't be the case if a SkinBackground is created for them.
if (skin.Value is DefaultSkin || skin.Value is DefaultLegacySkin) if (skin.Value is TrianglesSkin || skin.Value is DefaultLegacySkin)
break; break;
newBackground = new SkinBackground(skin.Value, getBackgroundTextureName()); newBackground = new SkinBackground(skin.Value, getBackgroundTextureName());

View File

@ -17,7 +17,7 @@ namespace osu.Game.Skinning
public static SkinInfo CreateInfo() => new SkinInfo public static SkinInfo CreateInfo() => new SkinInfo
{ {
ID = Skinning.SkinInfo.CLASSIC_SKIN, // this is temporary until database storage is decided upon. ID = Skinning.SkinInfo.CLASSIC_SKIN, // this is temporary until database storage is decided upon.
Name = "osu!classic", Name = "osu! \"classic\" (2013)",
Creator = "team osu!", Creator = "team osu!",
Protected = true, Protected = true,
InstantiationInfo = typeof(DefaultLegacySkin).GetInvariantInstantiationInfo() InstantiationInfo = typeof(DefaultLegacySkin).GetInvariantInstantiationInfo()

View File

@ -121,7 +121,7 @@ namespace osu.Game.Skinning
break; break;
case string when pair.Key.StartsWith("Colour", StringComparison.Ordinal): case string when pair.Key.StartsWith("Colour", StringComparison.Ordinal):
HandleColours(currentConfig, line); HandleColours(currentConfig, line, true);
break; break;
// Custom sprite paths // Custom sprite paths

View File

@ -48,7 +48,7 @@ namespace osu.Game.Skinning
// osu!catch section only has colour settings // osu!catch section only has colour settings
// so no harm in handling the entire section // so no harm in handling the entire section
case Section.CatchTheBeat: case Section.CatchTheBeat:
HandleColours(skin, line); HandleColours(skin, line, true);
return; return;
} }

View File

@ -81,7 +81,7 @@ namespace osu.Game.Skinning
} }
} }
int lastDefaultSkinIndex = sources.IndexOf(sources.OfType<DefaultSkin>().LastOrDefault()); int lastDefaultSkinIndex = sources.IndexOf(sources.OfType<TrianglesSkin>().LastOrDefault());
// Ruleset resources should be given the ability to override game-wide defaults // Ruleset resources should be given the ability to override game-wide defaults
// This is achieved by placing them before the last instance of DefaultSkin. // This is achieved by placing them before the last instance of DefaultSkin.

View File

@ -232,6 +232,9 @@ namespace osu.Game.Skinning
{ {
skin.SkinInfo.PerformWrite(s => skin.SkinInfo.PerformWrite(s =>
{ {
// Update for safety
s.InstantiationInfo = skin.GetType().GetInvariantInstantiationInfo();
// Serialise out the SkinInfo itself. // Serialise out the SkinInfo itself.
string skinInfoJson = JsonConvert.SerializeObject(s, new JsonSerializerSettings { Formatting = Formatting.Indented }); string skinInfoJson = JsonConvert.SerializeObject(s, new JsonSerializerSettings { Formatting = Formatting.Indented });

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.IO; using osu.Game.IO;
@ -19,7 +18,7 @@ namespace osu.Game.Skinning
[JsonObject(MemberSerialization.OptIn)] [JsonObject(MemberSerialization.OptIn)]
public class SkinInfo : RealmObject, IHasRealmFiles, IEquatable<SkinInfo>, IHasGuidPrimaryKey, ISoftDelete, IHasNamedFiles public class SkinInfo : RealmObject, IHasRealmFiles, IEquatable<SkinInfo>, IHasGuidPrimaryKey, ISoftDelete, IHasNamedFiles
{ {
internal static readonly Guid DEFAULT_SKIN = new Guid("2991CFD8-2140-469A-BCB9-2EC23FBCE4AD"); internal static readonly Guid TRIANGLES_SKIN = new Guid("2991CFD8-2140-469A-BCB9-2EC23FBCE4AD");
internal static readonly Guid CLASSIC_SKIN = new Guid("81F02CD3-EEC6-4865-AC23-FAE26A386187"); internal static readonly Guid CLASSIC_SKIN = new Guid("81F02CD3-EEC6-4865-AC23-FAE26A386187");
internal static readonly Guid RANDOM_SKIN = new Guid("D39DFEFB-477C-4372-B1EA-2BCEA5FB8908"); internal static readonly Guid RANDOM_SKIN = new Guid("D39DFEFB-477C-4372-B1EA-2BCEA5FB8908");
@ -45,7 +44,16 @@ namespace osu.Game.Skinning
var type = string.IsNullOrEmpty(InstantiationInfo) var type = string.IsNullOrEmpty(InstantiationInfo)
// handle the case of skins imported before InstantiationInfo was added. // handle the case of skins imported before InstantiationInfo was added.
? typeof(LegacySkin) ? typeof(LegacySkin)
: Type.GetType(InstantiationInfo).AsNonNull(); : Type.GetType(InstantiationInfo);
if (type == null)
{
// Since the class was renamed from "DefaultSkin" to "TrianglesSkin", the type retrieval would fail
// for user modified skins. This aims to amicably handle that.
// If we ever add more default skins in the future this will need some kind of proper migration rather than
// a single fallback.
return new TrianglesSkin(this, resources);
}
return (Skin)Activator.CreateInstance(type, this, resources); return (Skin)Activator.CreateInstance(type, this, resources);
} }

View File

@ -49,9 +49,9 @@ namespace osu.Game.Skinning
public readonly Bindable<Skin> CurrentSkin = new Bindable<Skin>(); public readonly Bindable<Skin> CurrentSkin = new Bindable<Skin>();
public readonly Bindable<Live<SkinInfo>> CurrentSkinInfo = new Bindable<Live<SkinInfo>>(Skinning.DefaultSkin.CreateInfo().ToLiveUnmanaged()) public readonly Bindable<Live<SkinInfo>> CurrentSkinInfo = new Bindable<Live<SkinInfo>>(TrianglesSkin.CreateInfo().ToLiveUnmanaged())
{ {
Default = Skinning.DefaultSkin.CreateInfo().ToLiveUnmanaged() Default = TrianglesSkin.CreateInfo().ToLiveUnmanaged()
}; };
private readonly SkinImporter skinImporter; private readonly SkinImporter skinImporter;
@ -59,14 +59,14 @@ namespace osu.Game.Skinning
private readonly IResourceStore<byte[]> userFiles; private readonly IResourceStore<byte[]> userFiles;
/// <summary> /// <summary>
/// The default skin. /// The default "triangles" skin.
/// </summary> /// </summary>
public Skin DefaultSkin { get; } public Skin DefaultSkinTriangles { get; }
/// <summary> /// <summary>
/// The default legacy skin. /// The default "classic" skin.
/// </summary> /// </summary>
public Skin DefaultLegacySkin { get; } public Skin DefaultClassicSkin { get; }
public SkinManager(Storage storage, RealmAccess realm, GameHost host, IResourceStore<byte[]> resources, AudioManager audio, Scheduler scheduler) public SkinManager(Storage storage, RealmAccess realm, GameHost host, IResourceStore<byte[]> resources, AudioManager audio, Scheduler scheduler)
: base(storage, realm) : base(storage, realm)
@ -85,8 +85,8 @@ namespace osu.Game.Skinning
var defaultSkins = new[] var defaultSkins = new[]
{ {
DefaultLegacySkin = new DefaultLegacySkin(this), DefaultClassicSkin = new DefaultLegacySkin(this),
DefaultSkin = new DefaultSkin(this), DefaultSkinTriangles = new TrianglesSkin(this),
}; };
// Ensure the default entries are present. // Ensure the default entries are present.
@ -104,7 +104,7 @@ namespace osu.Game.Skinning
CurrentSkin.Value = skin.NewValue.PerformRead(GetSkin); CurrentSkin.Value = skin.NewValue.PerformRead(GetSkin);
}; };
CurrentSkin.Value = DefaultSkin; CurrentSkin.Value = DefaultSkinTriangles;
CurrentSkin.ValueChanged += skin => CurrentSkin.ValueChanged += skin =>
{ {
if (!skin.NewValue.SkinInfo.Equals(CurrentSkinInfo.Value)) if (!skin.NewValue.SkinInfo.Equals(CurrentSkinInfo.Value))
@ -125,7 +125,7 @@ namespace osu.Game.Skinning
if (randomChoices.Length == 0) if (randomChoices.Length == 0)
{ {
CurrentSkinInfo.Value = Skinning.DefaultSkin.CreateInfo().ToLiveUnmanaged(); CurrentSkinInfo.Value = TrianglesSkin.CreateInfo().ToLiveUnmanaged();
return; return;
} }
@ -229,11 +229,11 @@ namespace osu.Game.Skinning
{ {
yield return CurrentSkin.Value; yield return CurrentSkin.Value;
if (CurrentSkin.Value is LegacySkin && CurrentSkin.Value != DefaultLegacySkin) if (CurrentSkin.Value is LegacySkin && CurrentSkin.Value != DefaultClassicSkin)
yield return DefaultLegacySkin; yield return DefaultClassicSkin;
if (CurrentSkin.Value != DefaultSkin) if (CurrentSkin.Value != DefaultSkinTriangles)
yield return DefaultSkin; yield return DefaultSkinTriangles;
} }
} }
@ -294,7 +294,7 @@ namespace osu.Game.Skinning
Guid currentUserSkin = CurrentSkinInfo.Value.ID; Guid currentUserSkin = CurrentSkinInfo.Value.ID;
if (items.Any(s => s.ID == currentUserSkin)) if (items.Any(s => s.ID == currentUserSkin))
scheduler.Add(() => CurrentSkinInfo.Value = Skinning.DefaultSkin.CreateInfo().ToLiveUnmanaged()); scheduler.Add(() => CurrentSkinInfo.Value = TrianglesSkin.CreateInfo().ToLiveUnmanaged());
Delete(items.ToList(), silent); Delete(items.ToList(), silent);
}); });
@ -310,10 +310,10 @@ namespace osu.Game.Skinning
if (skinInfo == null) if (skinInfo == null)
{ {
if (guid == SkinInfo.CLASSIC_SKIN) if (guid == SkinInfo.CLASSIC_SKIN)
skinInfo = DefaultLegacySkin.SkinInfo; skinInfo = DefaultClassicSkin.SkinInfo;
} }
CurrentSkinInfo.Value = skinInfo ?? DefaultSkin.SkinInfo; CurrentSkinInfo.Value = skinInfo ?? DefaultSkinTriangles.SkinInfo;
} }
} }
} }

View File

@ -112,7 +112,7 @@ namespace osu.Game.Skinning
// Temporarily used to exclude undesirable ISkin implementations // Temporarily used to exclude undesirable ISkin implementations
static bool isUserSkin(ISkin skin) static bool isUserSkin(ISkin skin)
=> skin.GetType() == typeof(DefaultSkin) => skin.GetType() == typeof(TrianglesSkin)
|| skin.GetType() == typeof(DefaultLegacySkin) || skin.GetType() == typeof(DefaultLegacySkin)
|| skin.GetType() == typeof(LegacySkin); || skin.GetType() == typeof(LegacySkin);
} }

View File

@ -22,26 +22,26 @@ using osuTK.Graphics;
namespace osu.Game.Skinning namespace osu.Game.Skinning
{ {
public class DefaultSkin : Skin public class TrianglesSkin : Skin
{ {
public static SkinInfo CreateInfo() => new SkinInfo public static SkinInfo CreateInfo() => new SkinInfo
{ {
ID = osu.Game.Skinning.SkinInfo.DEFAULT_SKIN, ID = osu.Game.Skinning.SkinInfo.TRIANGLES_SKIN,
Name = "osu! (triangles)", Name = "osu! \"triangles\" (2017)",
Creator = "team osu!", Creator = "team osu!",
Protected = true, Protected = true,
InstantiationInfo = typeof(DefaultSkin).GetInvariantInstantiationInfo() InstantiationInfo = typeof(TrianglesSkin).GetInvariantInstantiationInfo()
}; };
private readonly IStorageResourceProvider resources; private readonly IStorageResourceProvider resources;
public DefaultSkin(IStorageResourceProvider resources) public TrianglesSkin(IStorageResourceProvider resources)
: this(CreateInfo(), resources) : this(CreateInfo(), resources)
{ {
} }
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)]
public DefaultSkin(SkinInfo skin, IStorageResourceProvider resources) public TrianglesSkin(SkinInfo skin, IStorageResourceProvider resources)
: base(skin, resources) : base(skin, resources)
{ {
this.resources = resources; this.resources = resources;

View File

@ -29,8 +29,9 @@ namespace osu.Game.Tests.Visual
{ {
public abstract class SkinnableTestScene : OsuGridTestScene, IStorageResourceProvider public abstract class SkinnableTestScene : OsuGridTestScene, IStorageResourceProvider
{ {
private TrianglesSkin trianglesSkin;
private Skin metricsSkin; private Skin metricsSkin;
private Skin defaultSkin; private Skin legacySkin;
private Skin specialSkin; private Skin specialSkin;
private Skin oldSkin; private Skin oldSkin;
@ -47,8 +48,9 @@ namespace osu.Game.Tests.Visual
{ {
var dllStore = new DllResourceStore(GetType().Assembly); var dllStore = new DllResourceStore(GetType().Assembly);
trianglesSkin = new TrianglesSkin(this);
metricsSkin = new TestLegacySkin(new SkinInfo { Name = "metrics-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), this, true); metricsSkin = new TestLegacySkin(new SkinInfo { Name = "metrics-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), this, true);
defaultSkin = new DefaultLegacySkin(this); legacySkin = new DefaultLegacySkin(this);
specialSkin = new TestLegacySkin(new SkinInfo { Name = "special-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/special_skin"), this, true); specialSkin = new TestLegacySkin(new SkinInfo { Name = "special-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/special_skin"), this, true);
oldSkin = new TestLegacySkin(new SkinInfo { Name = "old-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/old_skin"), this, true); oldSkin = new TestLegacySkin(new SkinInfo { Name = "old-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/old_skin"), this, true);
} }
@ -61,9 +63,9 @@ namespace osu.Game.Tests.Visual
var beatmap = CreateBeatmapForSkinProvider(); var beatmap = CreateBeatmapForSkinProvider();
Cell(0).Child = createProvider(null, creationFunction, beatmap); Cell(0).Child = createProvider(trianglesSkin, creationFunction, beatmap);
Cell(1).Child = createProvider(metricsSkin, creationFunction, beatmap); Cell(1).Child = createProvider(metricsSkin, creationFunction, beatmap);
Cell(2).Child = createProvider(defaultSkin, creationFunction, beatmap); Cell(2).Child = createProvider(legacySkin, creationFunction, beatmap);
Cell(3).Child = createProvider(specialSkin, creationFunction, beatmap); Cell(3).Child = createProvider(specialSkin, creationFunction, beatmap);
Cell(4).Child = createProvider(oldSkin, creationFunction, beatmap); Cell(4).Child = createProvider(oldSkin, creationFunction, beatmap);
} }