1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 12:23:22 +08:00

Merge branch 'master' into skin-scaling

This commit is contained in:
Dean Herbert 2018-03-22 19:30:17 +09:00 committed by GitHub
commit ee12d75b30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 189 additions and 130 deletions

@ -1 +1 @@
Subproject commit 41e2a0a4304544fb67779c21cad1435c105982d5 Subproject commit 241133f0a65326a563ba23b7166167a882d1d5cb

View File

@ -16,11 +16,9 @@
<language>en-AU</language> <language>en-AU</language>
</metadata> </metadata>
<files> <files>
<file src="*.exe" target="lib\net45\" exclude="**vshost**"/> <file src="**.exe" target="lib\net45\" exclude="**vshost**"/>
<file src="*.dll" target="lib\net45\"/> <file src="**.dll" target="lib\net45\"/>
<file src="*.config" target="lib\net45\"/> <file src="**.config" target="lib\net45\"/>
<file src="x86\*.dll" target="lib\net45\x86\"/>
<file src="x64\*.dll" target="lib\net45\x64\"/>
</files> </files>
</package> </package>

View File

@ -8,7 +8,7 @@ using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Catch.Objects 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; public const double OBJECT_RADIUS = 44;

View File

@ -8,6 +8,8 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects.Drawable 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 }); 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<SkinConfiguration, Color4>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
}
private const float preempt = 1000; private const float preempt = 1000;
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)

View File

@ -64,52 +64,57 @@ namespace osu.Game.Rulesets.Catch.Objects
X = X 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 spanStartTime = StartTime + span * spanDuration;
var reversed = span % 2 == 1; 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 timeProgress = d / length;
var distanceProgress = reversed ? 1 - timeProgress : timeProgress; var distanceProgress = reversed ? 1 - timeProgress : timeProgress;
var lastTickTime = spanStartTime + timeProgress * spanDuration; double time = spanStartTime + timeProgress * spanDuration;
AddNested(new Droplet
double tinyTickInterval = time - lastDropletTime;
while (tinyTickInterval > 100)
tinyTickInterval /= 2;
for (double t = lastDropletTime + tinyTickInterval; t < time; t += tinyTickInterval)
{ {
StartTime = lastTickTime, double progress = reversed ? 1 - (t - spanStartTime) / spanDuration : (t - spanStartTime) / spanDuration;
X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo AddNested(new TinyDroplet
{ {
Bank = s.Bank, StartTime = t,
Name = @"slidertick", X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
Volume = s.Volume Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
})) {
}); Bank = s.Bank,
} Name = @"slidertick",
Volume = s.Volume
}))
});
}
double tinyTickInterval = tickDistance / length * spanDuration; if (d > minDistanceFromEnd && Math.Abs(d - length) > minDistanceFromEnd)
while (tinyTickInterval > 100)
tinyTickInterval /= 2;
for (double t = 0; t < spanDuration; t += tinyTickInterval)
{
double progress = reversed ? 1 - t / spanDuration : t / spanDuration;
AddNested(new TinyDroplet
{ {
StartTime = spanStartTime + t, AddNested(new Droplet
X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
{ {
Bank = s.Bank, StartTime = time,
Name = @"slidertick", X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
Volume = s.Volume Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
})) {
}); Bank = s.Bank,
Name = @"slidertick",
Volume = s.Volume
}))
});
}
lastDropletTime = time;
} }
AddNested(new Fruit AddNested(new Fruit

View File

@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Tests
{ {
protected override string ResourceAssembly => "osu.Game.Rulesets.Catch"; 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) public new void Test(string name)
{ {
base.Test(name); base.Test(name);

View File

@ -5,6 +5,9 @@ using System.ComponentModel;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using System.Linq; using System.Linq;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Skinning;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Osu.Objects.Drawables 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<SkinConfiguration, Color4>(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 UpdatePreemptState() => this.FadeIn(HitObject.TimeFadein);
protected virtual void UpdateCurrentState(ArmedState state) protected virtual void UpdateCurrentState(ArmedState state)

View File

@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
public double? SnakedStart { get; private set; } public double? SnakedStart { get; private set; }
public double? SnakedEnd { get; private set; } public double? SnakedEnd { get; private set; }
private Color4 accentColour; private Color4 accentColour = Color4.White;
/// <summary> /// <summary>
/// Used to colour the path. /// Used to colour the path.
/// </summary> /// </summary>

View File

@ -10,7 +10,7 @@ using osu.Game.Beatmaps.ControlPoints;
namespace osu.Game.Rulesets.Osu.Objects 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; public const double OBJECT_RADIUS = 64;

View File

@ -110,7 +110,7 @@ namespace osu.Game.Beatmaps
Skin skin; Skin skin;
try try
{ {
skin = new BeatmapSkin(BeatmapInfo, store, audioManager); skin = new LegacyBeatmapSkin(BeatmapInfo, store, audioManager);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -23,9 +23,9 @@ namespace osu.Game.Beatmaps
/// <param name="beatmap">The Beatmap to process.</param> /// <param name="beatmap">The Beatmap to process.</param>
public virtual void PostProcess(Beatmap<TObject> beatmap) public virtual void PostProcess(Beatmap<TObject> beatmap)
{ {
IHasComboIndex lastObj = null; IHasComboInformation lastObj = null;
foreach (var obj in beatmap.HitObjects.OfType<IHasComboIndex>()) foreach (var obj in beatmap.HitObjects.OfType<IHasComboInformation>())
{ {
if (obj.NewCombo) if (obj.NewCombo)
{ {

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using osu.Framework.Logging;
using OpenTK.Graphics; using OpenTK.Graphics;
namespace osu.Game.Beatmaps.Formats namespace osu.Game.Beatmaps.Formats
@ -31,7 +32,11 @@ namespace osu.Game.Beatmaps.Formats
if (line.StartsWith(@"[") && line.EndsWith(@"]")) if (line.StartsWith(@"[") && line.EndsWith(@"]"))
{ {
if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section)) 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; continue;
} }

View File

@ -13,6 +13,7 @@ using osu.Game.IO;
using osu.Game.IO.Archives; using osu.Game.IO.Archives;
using osu.Game.IPC; using osu.Game.IPC;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
using SharpCompress.Common;
using FileInfo = osu.Game.IO.FileInfo; using FileInfo = osu.Game.IO.FileInfo;
namespace osu.Game.Database namespace osu.Game.Database
@ -79,7 +80,6 @@ namespace osu.Game.Database
var notification = new ProgressNotification var notification = new ProgressNotification
{ {
Text = "Import is initialising...", Text = "Import is initialising...",
CompletionText = "Import successful!",
Progress = 0, Progress = 0,
State = ProgressNotificationState.Active, State = ProgressNotificationState.Active,
}; };
@ -88,7 +88,8 @@ namespace osu.Game.Database
List<TModel> imported = new List<TModel>(); List<TModel> imported = new List<TModel>();
int i = 0; int current = 0;
int errors = 0;
foreach (string path in paths) foreach (string path in paths)
{ {
if (notification.State == ProgressNotificationState.Cancelled) if (notification.State == ProgressNotificationState.Cancelled)
@ -97,11 +98,11 @@ namespace osu.Game.Database
try 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)) using (ArchiveReader reader = getReaderFrom(path))
imported.Add(Import(reader)); 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. // 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. // e.g. reconstructing/repairing database with items from default storage.
@ -121,9 +122,11 @@ namespace osu.Game.Database
{ {
e = e.InnerException ?? e; e = e.InnerException ?? e;
Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); 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; notification.State = ProgressNotificationState.Completed;
} }
@ -218,9 +221,11 @@ namespace osu.Game.Database
// user requested abort // user requested abort
return; return;
notification.Text = $"Deleting ({i} of {items.Count})"; notification.Text = $"Deleting ({++i} of {items.Count})";
notification.Progress = (float)++i / items.Count;
Delete(b); Delete(b);
notification.Progress = (float)i / items.Count;
} }
} }
@ -254,9 +259,11 @@ namespace osu.Game.Database
// user requested abort // user requested abort
return; return;
notification.Text = $"Restoring ({i} of {items.Count})"; notification.Text = $"Restoring ({++i} of {items.Count})";
notification.Progress = (float)++i / items.Count;
Undelete(item); Undelete(item);
notification.Progress = (float)i / items.Count;
} }
} }
@ -331,7 +338,9 @@ namespace osu.Game.Database
{ {
if (ZipFile.IsZipFile(path)) if (ZipFile.IsZipFile(path))
return new ZipArchiveReader(Files.Storage.GetStream(path), Path.GetFileName(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");
} }
} }
} }

View File

@ -242,7 +242,7 @@ namespace osu.Game.Graphics.Backgrounds
triangle, triangle,
colourInfo, colourInfo,
null, null,
Shared.VertexBatch.Add, Shared.VertexBatch.AddAction,
Vector2.Divide(localInflationAmount, size)); Vector2.Divide(localInflationAmount, size));
} }

View File

@ -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) protected override void OnFocus(InputState state)
{ {
base.OnFocus(state); base.OnFocus(state);

View File

@ -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() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();

View File

@ -0,0 +1,26 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A HitObject that is part of a combo and has extended information about its position relative to other combo objects.
/// </summary>
public interface IHasComboInformation : IHasCombo
{
/// <summary>
/// The offset of this hitobject in the current combo.
/// </summary>
int IndexInCurrentCombo { get; set; }
/// <summary>
/// The offset of this combo in relation to the beatmap.
/// </summary>
int ComboIndex { get; set; }
/// <summary>
/// Whether this is the last object in the current combo.
/// </summary>
bool LastInCombo { get; set; }
}
}

View File

@ -211,7 +211,7 @@ namespace osu.Game.Screens.Menu
rectangle, rectangle,
colourInfo, colourInfo,
null, 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. //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)); Vector2.Divide(inflation, barSize.Yx));
} }

View File

@ -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) protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{ {
if (!interactive) return false;
logoBounceContainer.ScaleTo(0.9f, 1000, Easing.Out); logoBounceContainer.ScaleTo(0.9f, 1000, Easing.Out);
return true; return true;
} }
@ -355,8 +353,6 @@ namespace osu.Game.Screens.Menu
protected override bool OnClick(InputState state) protected override bool OnClick(InputState state)
{ {
if (!interactive) return false;
if (Action?.Invoke() ?? true) if (Action?.Invoke() ?? true)
sampleClick.Play(); sampleClick.Play();
@ -368,8 +364,6 @@ namespace osu.Game.Screens.Menu
protected override bool OnHover(InputState state) protected override bool OnHover(InputState state)
{ {
if (!interactive) return false;
logoHoverContainer.ScaleTo(1.1f, 500, Easing.OutElastic); logoHoverContainer.ScaleTo(1.1f, 500, Easing.OutElastic);
return true; return true;
} }

View File

@ -259,6 +259,8 @@ namespace osu.Game.Screens.Select
private void workingBeatmapChanged(WorkingBeatmap beatmap) private void workingBeatmapChanged(WorkingBeatmap beatmap)
{ {
if (beatmap is DummyWorkingBeatmap) return;
if (IsCurrentScreen && !Carousel.SelectBeatmap(beatmap?.BeatmapInfo, false)) if (IsCurrentScreen && !Carousel.SelectBeatmap(beatmap?.BeatmapInfo, false))
// If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch
if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != Ruleset.Value) if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != Ruleset.Value)

View File

@ -1,31 +0,0 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// 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<byte[]> storage, AudioManager audioManager)
: base(new SkinInfo { Name = beatmap.ToString(), Creator = beatmap.Metadata.Author.ToString() })
{
storage = new LegacySkinResourceStore<BeatmapSetFileInfo>(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);
}
}
}
}

View File

@ -5,8 +5,6 @@ using System;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
namespace osu.Game.Skinning namespace osu.Game.Skinning
{ {
@ -23,6 +21,8 @@ namespace osu.Game.Skinning
SampleChannel GetSample(string sampleName); SampleChannel GetSample(string sampleName);
Color4? GetComboColour(IHasComboIndex comboObject); TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration where TValue : class;
TValue? GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue?> query) where TConfiguration : SkinConfiguration where TValue : struct;
} }
} }

View File

@ -0,0 +1,20 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// 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<byte[]> storage, AudioManager audioManager)
: base(createSkinInfo(beatmap), new LegacySkinResourceStore<BeatmapSetFileInfo>(beatmap.BeatmapSet, storage), audioManager, beatmap.Path)
{
}
private static SkinInfo createSkinInfo(BeatmapInfo beatmap) =>
new SkinInfo { Name = beatmap.ToString(), Creator = beatmap.Metadata.Author.ToString() };
}
}

View File

@ -22,23 +22,21 @@ namespace osu.Game.Skinning
protected SampleManager Samples; protected SampleManager Samples;
public LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager) public LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager)
: this(skin) : this(skin, new LegacySkinResourceStore<SkinFileInfo>(skin, storage), audioManager, "skin.ini")
{ {
storage = new LegacySkinResourceStore<SkinFileInfo>(skin, storage); }
Samples = audioManager.GetSampleManager(storage);
Textures = new TextureStore(new RawTextureLoaderStore(storage));
Stream stream = storage.GetStream("skin.ini"); protected LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager, string filename) : base(skin)
{
Stream stream = storage.GetStream(filename);
if (stream != null) if (stream != null)
using (StreamReader reader = new StreamReader(stream)) using (StreamReader reader = new StreamReader(stream))
Configuration = new LegacySkinDecoder().Decode(reader); Configuration = new LegacySkinDecoder().Decode(reader);
else else
Configuration = new SkinConfiguration(); Configuration = new SkinConfiguration();
}
protected LegacySkin(SkinInfo skin) Samples = audioManager.GetSampleManager(storage);
: base(skin) Textures = new TextureStore(new RawTextureLoaderStore(storage));
{
} }
public override Drawable GetDrawableComponent(string componentName) public override Drawable GetDrawableComponent(string componentName)

View File

@ -29,7 +29,7 @@ namespace osu.Game.Skinning
break; break;
} }
return; break;
} }
base.ParseLine(output, section, line); base.ParseLine(output, section, line);

View File

@ -7,8 +7,6 @@ using osu.Framework.Audio.Sample;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
namespace osu.Game.Skinning namespace osu.Game.Skinning
{ {
@ -22,7 +20,25 @@ namespace osu.Game.Skinning
public SampleChannel GetSample(string sampleName) => source.GetSample(sampleName) ?? fallbackSource?.GetSample(sampleName); 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<TConfiguration, TValue>(Func<TConfiguration, TValue?> 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<TConfiguration, TValue>(Func<TConfiguration, TValue> 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 readonly ISkinSource source;
private ISkinSource fallbackSource; private ISkinSource fallbackSource;

View File

@ -5,8 +5,6 @@ using System;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
namespace osu.Game.Skinning namespace osu.Game.Skinning
{ {
@ -24,8 +22,11 @@ namespace osu.Game.Skinning
public abstract Texture GetTexture(string componentName); public abstract Texture GetTexture(string componentName);
public virtual Color4? GetComboColour(IHasComboIndex comboObject) => public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration where TValue : class
Configuration.ComboColours.Count == 0 ? (Color4?)null : Configuration.ComboColours[comboObject.ComboIndex % Configuration.ComboColours.Count]; => Configuration is TConfiguration conf ? query?.Invoke(conf) : null;
public TValue? GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue?> query) where TConfiguration : SkinConfiguration where TValue : struct
=> Configuration is TConfiguration conf ? query?.Invoke(conf) : null;
protected Skin(SkinInfo skin) protected Skin(SkinInfo skin)
{ {

View File

@ -14,8 +14,6 @@ using osu.Framework.Graphics.Textures;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.IO.Archives; using osu.Game.IO.Archives;
using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
namespace osu.Game.Skinning namespace osu.Game.Skinning
{ {
@ -120,10 +118,12 @@ namespace osu.Game.Skinning
public Drawable GetDrawableComponent(string componentName) => CurrentSkin.Value.GetDrawableComponent(componentName); 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 SampleChannel GetSample(string sampleName) => CurrentSkin.Value.GetSample(sampleName);
public Color4? GetComboColour(IHasComboIndex comboObject) => CurrentSkin.Value.GetComboColour(comboObject); public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration where TValue : class => CurrentSkin.Value.GetValue(query);
public TValue? GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue?> query) where TConfiguration : SkinConfiguration where TValue : struct => CurrentSkin.Value.GetValue(query);
} }
} }

View File

@ -374,7 +374,7 @@
<Compile Include="Overlays\Social\SocialPanel.cs" /> <Compile Include="Overlays\Social\SocialPanel.cs" />
<Compile Include="Rulesets\Mods\IApplicableToDrawableHitObject.cs" /> <Compile Include="Rulesets\Mods\IApplicableToDrawableHitObject.cs" />
<Compile Include="Rulesets\Objects\HitWindows.cs" /> <Compile Include="Rulesets\Objects\HitWindows.cs" />
<Compile Include="Rulesets\Objects\Types\IHasComboIndex.cs" /> <Compile Include="Rulesets\Objects\Types\IHasComboInformation.cs" />
<Compile Include="Rulesets\Replays\Legacy\LegacyReplayFrame.cs" /> <Compile Include="Rulesets\Replays\Legacy\LegacyReplayFrame.cs" />
<Compile Include="Rulesets\Replays\Legacy\ReplayButtonState.cs" /> <Compile Include="Rulesets\Replays\Legacy\ReplayButtonState.cs" />
<Compile Include="Rulesets\Replays\ReplayFrame.cs" /> <Compile Include="Rulesets\Replays\ReplayFrame.cs" />
@ -872,7 +872,7 @@
<Compile Include="Screens\Tournament\Teams\DrawingsTeam.cs" /> <Compile Include="Screens\Tournament\Teams\DrawingsTeam.cs" />
<Compile Include="Screens\Tournament\Teams\ITeamList.cs" /> <Compile Include="Screens\Tournament\Teams\ITeamList.cs" />
<Compile Include="Screens\Tournament\Teams\StorageBackedTeamList.cs" /> <Compile Include="Screens\Tournament\Teams\StorageBackedTeamList.cs" />
<Compile Include="Skinning\BeatmapSkin.cs" /> <Compile Include="Skinning\LegacyBeatmapSkin.cs" />
<Compile Include="Skinning\DefaultSkin.cs" /> <Compile Include="Skinning\DefaultSkin.cs" />
<Compile Include="Skinning\ISkinSource.cs" /> <Compile Include="Skinning\ISkinSource.cs" />
<Compile Include="Skinning\LegacySkin.cs" /> <Compile Include="Skinning\LegacySkin.cs" />