mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 11:37:28 +08:00
Merge branch 'master' into taiko_legacy_rep
This commit is contained in:
commit
b9f8ed3123
@ -1 +1 @@
|
||||
Subproject commit 16a4bef775a49166f38faa6e952d83d8823fe3e0
|
||||
Subproject commit 9a773e62eb246206b918ba4fccf9f2507aaa4595
|
@ -154,6 +154,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
this.FadeOut(fade_out_time, Easing.OutQuint).Expire();
|
||||
}
|
||||
|
||||
Expire(true);
|
||||
}
|
||||
|
||||
public Drawable ProxiedLayer => HeadCircle.ApproachCircle;
|
||||
|
@ -6,30 +6,24 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public class ApproachCircle : Container
|
||||
{
|
||||
private readonly Sprite approachCircle;
|
||||
|
||||
public ApproachCircle()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
approachCircle = new Sprite()
|
||||
};
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
approachCircle.Texture = textures.Get(@"Play/osu/approachcircle");
|
||||
Child = new SkinnableDrawable("Play/osu/approachcircle", name => new Sprite { Texture = textures.Get(name) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,20 +2,16 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public class CirclePiece : Container, IKeyBindingHandler<OsuAction>
|
||||
{
|
||||
private readonly Sprite disc;
|
||||
|
||||
public Func<bool> Hit;
|
||||
|
||||
public CirclePiece()
|
||||
@ -27,26 +23,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
disc = new Sprite
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
},
|
||||
new TrianglesPiece
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0.5f,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
disc.Texture = textures.Get(@"Play/osu/disc");
|
||||
InternalChild = new SkinnableDrawable("Play/osu/hitcircle", _ => new DefaultCirclePiece());
|
||||
}
|
||||
|
||||
public bool OnPressed(OsuAction action)
|
||||
|
@ -0,0 +1,35 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public class DefaultCirclePiece : Container
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Sprite
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = textures.Get(@"Play/osu/disc"),
|
||||
},
|
||||
new TrianglesPiece
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0.5f,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -6,34 +6,30 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public class GlowPiece : Container
|
||||
{
|
||||
private readonly Sprite layer;
|
||||
|
||||
public GlowPiece()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
layer = new Sprite
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0.5f
|
||||
}
|
||||
};
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
layer.Texture = textures.Get(@"Play/osu/ring-glow");
|
||||
Child = new SkinnableDrawable("Play/osu/ring-glow", name => new Sprite
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = textures.Get(name),
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0.5f
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
@ -28,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new CircularContainer
|
||||
new SkinnableDrawable("Play/osu/number-glow", name => new CircularContainer
|
||||
{
|
||||
Masking = true,
|
||||
Origin = Anchor.Centre,
|
||||
@ -38,11 +39,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
Radius = 60,
|
||||
Colour = Color4.White.Opacity(0.5f),
|
||||
},
|
||||
Children = new[]
|
||||
{
|
||||
new Box()
|
||||
}
|
||||
},
|
||||
Child = new Box()
|
||||
}, false),
|
||||
number = new OsuSpriteText
|
||||
{
|
||||
Text = @"1",
|
||||
|
@ -6,6 +6,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
@ -15,24 +16,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
Size = new Vector2(128);
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = Size.X / 2;
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
BorderThickness = 10;
|
||||
BorderColour = Color4.White;
|
||||
|
||||
Children = new Drawable[]
|
||||
InternalChild = new SkinnableDrawable("Play/osu/hitcircleoverlay", _ => new Container
|
||||
{
|
||||
new Box
|
||||
Masking = true,
|
||||
CornerRadius = Size.X / 2,
|
||||
BorderThickness = 10,
|
||||
BorderColour = Color4.White,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +92,7 @@
|
||||
<Compile Include="Objects\Drawables\IRequireTracking.cs" />
|
||||
<Compile Include="Objects\Drawables\ITrackSnaking.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\ApproachCircle.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\DefaultCirclePiece.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\SpinnerBackground.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\CirclePiece.cs" />
|
||||
<Compile Include="Objects\Drawables\DrawableSlider.cs" />
|
||||
|
@ -2,10 +2,9 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Audio
|
||||
{
|
||||
@ -14,7 +13,9 @@ namespace osu.Game.Rulesets.Taiko.Audio
|
||||
private readonly ControlPointInfo controlPoints;
|
||||
private readonly Dictionary<double, DrumSample> mappings = new Dictionary<double, DrumSample>();
|
||||
|
||||
public DrumSampleMapping(ControlPointInfo controlPoints, AudioManager audio)
|
||||
public readonly List<SkinnableSound> Sounds = new List<SkinnableSound>();
|
||||
|
||||
public DrumSampleMapping(ControlPointInfo controlPoints)
|
||||
{
|
||||
this.controlPoints = controlPoints;
|
||||
|
||||
@ -27,20 +28,34 @@ namespace osu.Game.Rulesets.Taiko.Audio
|
||||
|
||||
foreach (var s in samplePoints)
|
||||
{
|
||||
var centre = s.GetSampleInfo();
|
||||
var rim = s.GetSampleInfo(SampleInfo.HIT_CLAP);
|
||||
|
||||
// todo: this is ugly
|
||||
centre.Namespace = "taiko";
|
||||
rim.Namespace = "taiko";
|
||||
|
||||
mappings[s.Time] = new DrumSample
|
||||
{
|
||||
Centre = s.GetSampleInfo().GetChannel(audio.Sample, "Taiko"),
|
||||
Rim = s.GetSampleInfo(SampleInfo.HIT_CLAP).GetChannel(audio.Sample, "Taiko")
|
||||
Centre = addSound(centre),
|
||||
Rim = addSound(rim)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private SkinnableSound addSound(SampleInfo sampleInfo)
|
||||
{
|
||||
var drawable = new SkinnableSound(sampleInfo);
|
||||
Sounds.Add(drawable);
|
||||
return drawable;
|
||||
}
|
||||
|
||||
public DrumSample SampleAt(double time) => mappings[controlPoints.SamplePointAt(time).Time];
|
||||
|
||||
public class DrumSample
|
||||
{
|
||||
public SampleChannel Centre;
|
||||
public SampleChannel Rim;
|
||||
public SkinnableSound Centre;
|
||||
public SkinnableSound Rim;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using OpenTK;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
@ -34,9 +33,9 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
private void load()
|
||||
{
|
||||
var sampleMappings = new DrumSampleMapping(controlPoints, audio);
|
||||
var sampleMappings = new DrumSampleMapping(controlPoints);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@ -63,6 +62,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
CentreAction = TaikoAction.RightCentre
|
||||
}
|
||||
};
|
||||
|
||||
AddRangeInternal(sampleMappings.Sounds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Audio.Sample;
|
||||
|
||||
namespace osu.Game.Audio
|
||||
{
|
||||
@ -14,22 +13,10 @@ namespace osu.Game.Audio
|
||||
public const string HIT_NORMAL = @"hitnormal";
|
||||
public const string HIT_CLAP = @"hitclap";
|
||||
|
||||
public SampleChannel GetChannel(SampleManager manager, string resourceNamespace = null)
|
||||
{
|
||||
SampleChannel channel = null;
|
||||
|
||||
if (resourceNamespace != null)
|
||||
channel = manager.Get($"Gameplay/{resourceNamespace}/{Bank}-{Name}");
|
||||
|
||||
// try without namespace as a fallback.
|
||||
if (channel == null)
|
||||
channel = manager.Get($"Gameplay/{Bank}-{Name}");
|
||||
|
||||
if (channel != null)
|
||||
channel.Volume.Value = Volume / 100.0;
|
||||
|
||||
return channel;
|
||||
}
|
||||
/// <summary>
|
||||
/// An optional ruleset namespace.
|
||||
/// </summary>
|
||||
public string Namespace;
|
||||
|
||||
/// <summary>
|
||||
/// The bank to load the sample from.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// 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;
|
||||
@ -106,7 +106,7 @@ namespace osu.Game
|
||||
|
||||
runMigrations();
|
||||
|
||||
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host));
|
||||
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
|
||||
|
||||
dependencies.Cache(API = new APIAccess
|
||||
{
|
||||
|
@ -3,20 +3,19 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using Container = osu.Framework.Graphics.Containers.Container;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Audio;
|
||||
using System.Linq;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Objects.Drawables
|
||||
{
|
||||
@ -32,7 +31,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
// Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first
|
||||
protected virtual string SampleNamespace => null;
|
||||
|
||||
protected List<SampleChannel> Samples = new List<SampleChannel>();
|
||||
protected SkinnableSound Samples;
|
||||
|
||||
protected virtual IEnumerable<SampleInfo> GetSamples() => HitObject.Samples;
|
||||
|
||||
private List<DrawableHitObject> nestedHitObjects;
|
||||
@ -83,31 +83,22 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
private void load()
|
||||
{
|
||||
var samples = GetSamples();
|
||||
var samples = GetSamples().ToArray();
|
||||
|
||||
if (samples.Any())
|
||||
{
|
||||
if (HitObject.SampleControlPoint == null)
|
||||
throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}."
|
||||
+ $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}.");
|
||||
|
||||
foreach (SampleInfo s in samples)
|
||||
AddInternal(Samples = new SkinnableSound(samples.Select(s => new SampleInfo
|
||||
{
|
||||
SampleInfo localSampleInfo = new SampleInfo
|
||||
{
|
||||
Bank = s.Bank ?? HitObject.SampleControlPoint.SampleBank,
|
||||
Name = s.Name,
|
||||
Volume = s.Volume > 0 ? s.Volume : HitObject.SampleControlPoint.SampleVolume
|
||||
};
|
||||
|
||||
SampleChannel channel = localSampleInfo.GetChannel(audio.Sample, SampleNamespace);
|
||||
|
||||
if (channel == null)
|
||||
continue;
|
||||
|
||||
Samples.Add(channel);
|
||||
}
|
||||
Bank = s.Bank ?? HitObject.SampleControlPoint.SampleBank,
|
||||
Name = s.Name,
|
||||
Volume = s.Volume > 0 ? s.Volume : HitObject.SampleControlPoint.SampleVolume,
|
||||
Namespace = SampleNamespace
|
||||
}).ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,7 +130,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
/// <summary>
|
||||
/// Plays all the hitsounds for this <see cref="DrawableHitObject"/>.
|
||||
/// </summary>
|
||||
public void PlaySamples() => Samples.ForEach(s => s?.Play());
|
||||
public void PlaySamples() => Samples?.Play();
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
@ -221,10 +212,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
return false;
|
||||
|
||||
if (NestedHitObjects != null)
|
||||
{
|
||||
foreach (var d in NestedHitObjects)
|
||||
judgementOccurred |= d.UpdateJudgement(userTriggered);
|
||||
}
|
||||
|
||||
if (!ProvidesJudgement || judgementFinalized || judgementOccurred)
|
||||
return judgementOccurred;
|
||||
|
26
osu.Game/Skinning/DefaultSkin.cs
Normal file
26
osu.Game/Skinning/DefaultSkin.cs
Normal 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
|
||||
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class DefaultSkin : Skin
|
||||
{
|
||||
public DefaultSkin()
|
||||
: base(SkinInfo.Default)
|
||||
{
|
||||
}
|
||||
|
||||
public override Drawable GetDrawableComponent(string componentName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SampleChannel GetSample(string sampleName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
47
osu.Game/Skinning/LegacySkin.cs
Normal file
47
osu.Game/Skinning/LegacySkin.cs
Normal file
@ -0,0 +1,47 @@
|
||||
// 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;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class LegacySkin : Skin
|
||||
{
|
||||
private readonly TextureStore textures;
|
||||
|
||||
private readonly SampleManager samples;
|
||||
|
||||
public LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager)
|
||||
: base(skin)
|
||||
{
|
||||
samples = audioManager.GetSampleManager(storage);
|
||||
textures = new TextureStore(new RawTextureLoaderStore(storage));
|
||||
}
|
||||
|
||||
private string getPathForFile(string filename) =>
|
||||
SkinInfo.Files.FirstOrDefault(f => string.Equals(Path.GetFileNameWithoutExtension(f.Filename), filename, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath;
|
||||
|
||||
public override Drawable GetDrawableComponent(string componentName)
|
||||
{
|
||||
var texture = textures.Get(getPathForFile(componentName.Split('/').Last()));
|
||||
if (texture == null) return null;
|
||||
|
||||
return new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
Texture = texture,
|
||||
};
|
||||
}
|
||||
|
||||
public override SampleChannel GetSample(string sampleName) => samples.Get(getPathForFile(sampleName.Split('/').Last()));
|
||||
}
|
||||
}
|
22
osu.Game/Skinning/Skin.cs
Normal file
22
osu.Game/Skinning/Skin.cs
Normal file
@ -0,0 +1,22 @@
|
||||
// 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.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public abstract class Skin
|
||||
{
|
||||
public readonly SkinInfo SkinInfo;
|
||||
|
||||
public abstract Drawable GetDrawableComponent(string componentName);
|
||||
|
||||
public abstract SampleChannel GetSample(string sampleName);
|
||||
|
||||
protected Skin(SkinInfo skin)
|
||||
{
|
||||
SkinInfo = skin;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
@ -15,6 +16,9 @@ namespace osu.Game.Skinning
|
||||
{
|
||||
public class SkinManager : ArchiveModelManager<SkinInfo, SkinFileInfo>
|
||||
{
|
||||
private readonly AudioManager audio;
|
||||
|
||||
public readonly Bindable<Skin> CurrentSkin = new Bindable<Skin>(new DefaultSkin());
|
||||
public readonly Bindable<SkinInfo> CurrentSkinInfo = new Bindable<SkinInfo>(SkinInfo.Default) { Default = SkinInfo.Default };
|
||||
|
||||
public override string[] HandledExtensions => new[] { ".osk" };
|
||||
@ -30,13 +34,37 @@ namespace osu.Game.Skinning
|
||||
return userSkins;
|
||||
}
|
||||
|
||||
protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name };
|
||||
protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo
|
||||
{
|
||||
Name = archive.Name
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a <see cref="Skin"/> instance for the provided <see cref="SkinInfo"/>
|
||||
/// </summary>
|
||||
/// <param name="skinInfo">The skin to lookup.</param>
|
||||
/// <returns>A <see cref="Skin"/> instance correlating to the provided <see cref="SkinInfo"/>.</returns>
|
||||
public Skin GetSkin(SkinInfo skinInfo)
|
||||
{
|
||||
if (skinInfo == SkinInfo.Default)
|
||||
return new DefaultSkin();
|
||||
|
||||
return new LegacySkin(skinInfo, Files.Store, audio);
|
||||
}
|
||||
|
||||
private SkinStore store;
|
||||
|
||||
public SkinManager(Storage storage, DatabaseContextFactory contextFactory, IIpcHost importHost)
|
||||
public SkinManager(Storage storage, DatabaseContextFactory contextFactory, IIpcHost importHost, AudioManager audio)
|
||||
: base(storage, contextFactory, new SkinStore(contextFactory, storage), importHost)
|
||||
{
|
||||
this.audio = audio;
|
||||
|
||||
CurrentSkinInfo.ValueChanged += info => CurrentSkin.Value = GetSkin(info);
|
||||
CurrentSkin.ValueChanged += skin =>
|
||||
{
|
||||
if (skin.SkinInfo != CurrentSkinInfo.Value)
|
||||
throw new InvalidOperationException($"Setting {nameof(CurrentSkin)}'s value directly is not supported. Use {nameof(CurrentSkinInfo)} instead.");
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
53
osu.Game/Skinning/SkinReloadableDrawable.cs
Normal file
53
osu.Game/Skinning/SkinReloadableDrawable.cs
Normal file
@ -0,0 +1,53 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
/// <summary>
|
||||
/// A drawable which has a callback when the skin changes.
|
||||
/// </summary>
|
||||
public abstract class SkinReloadableDrawable : CompositeDrawable
|
||||
{
|
||||
private Bindable<Skin> skin;
|
||||
|
||||
/// <summary>
|
||||
/// Whether fallback to default skin should be allowed if the custom skin is missing this resource.
|
||||
/// </summary>
|
||||
private readonly bool allowDefaultFallback;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SkinReloadableDrawable"/>
|
||||
/// </summary>
|
||||
/// <param name="fallback">Whether fallback to default skin should be allowed if the custom skin is missing this resource.</param>
|
||||
protected SkinReloadableDrawable(bool fallback = true)
|
||||
{
|
||||
allowDefaultFallback = fallback;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(SkinManager skinManager)
|
||||
{
|
||||
skin = skinManager.CurrentSkin.GetBoundCopy();
|
||||
skin.ValueChanged += skin => SkinChanged(skin, allowDefaultFallback || skin.SkinInfo == SkinInfo.Default);
|
||||
}
|
||||
|
||||
protected override void LoadAsyncComplete()
|
||||
{
|
||||
base.LoadAsyncComplete();
|
||||
skin.TriggerChange();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a change is made to the skin.
|
||||
/// </summary>
|
||||
/// <param name="skin">The new skin.</param>
|
||||
/// <param name="allowFallback">Whether fallback to default skin should be allowed if the custom skin is missing this resource.</param>
|
||||
protected virtual void SkinChanged(Skin skin, bool allowFallback)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
44
osu.Game/Skinning/SkinnableDrawable.cs
Normal file
44
osu.Game/Skinning/SkinnableDrawable.cs
Normal file
@ -0,0 +1,44 @@
|
||||
// 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;
|
||||
using osu.Framework.Graphics;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class SkinnableDrawable : SkinnableDrawable<Drawable>
|
||||
{
|
||||
public SkinnableDrawable(string name, Func<string, Drawable> defaultImplementation, bool fallback = true)
|
||||
: base(name, defaultImplementation, fallback)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class SkinnableDrawable<T> : SkinReloadableDrawable
|
||||
where T : Drawable
|
||||
{
|
||||
private readonly Func<string, T> createDefault;
|
||||
|
||||
private readonly string componentName;
|
||||
|
||||
public SkinnableDrawable(string name, Func<string, T> defaultImplementation, bool fallback = true) : base(fallback)
|
||||
{
|
||||
componentName = name;
|
||||
createDefault = defaultImplementation;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
protected override void SkinChanged(Skin skin, bool allowFallback)
|
||||
{
|
||||
var drawable = skin.GetDrawableComponent(componentName);
|
||||
if (drawable == null && allowFallback)
|
||||
drawable = createDefault(componentName);
|
||||
|
||||
if (drawable != null)
|
||||
InternalChild = drawable;
|
||||
else
|
||||
ClearInternal();
|
||||
}
|
||||
}
|
||||
}
|
62
osu.Game/Skinning/SkinnableSound.cs
Normal file
62
osu.Game/Skinning/SkinnableSound.cs
Normal file
@ -0,0 +1,62 @@
|
||||
// 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;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Game.Audio;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class SkinnableSound : SkinReloadableDrawable
|
||||
{
|
||||
private readonly SampleInfo[] samples;
|
||||
private SampleChannel[] channels;
|
||||
|
||||
private AudioManager audio;
|
||||
|
||||
public SkinnableSound(params SampleInfo[] samples)
|
||||
{
|
||||
this.samples = samples;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
this.audio = audio;
|
||||
}
|
||||
|
||||
public void Play() => channels?.ForEach(c => c.Play());
|
||||
|
||||
protected override void SkinChanged(Skin skin, bool allowFallback)
|
||||
{
|
||||
channels = samples.Select(s =>
|
||||
{
|
||||
var ch = loadChannel(s, skin.GetSample);
|
||||
if (ch == null && allowFallback)
|
||||
ch = loadChannel(s, audio.Sample.Get);
|
||||
return ch;
|
||||
}).Where(c => c != null).ToArray();
|
||||
}
|
||||
|
||||
private SampleChannel loadChannel(SampleInfo info, Func<string, SampleChannel> getSampleFunction)
|
||||
{
|
||||
SampleChannel ch = null;
|
||||
|
||||
if (info.Namespace != null)
|
||||
ch = getSampleFunction($"Gameplay/{info.Namespace}/{info.Bank}-{info.Name}");
|
||||
|
||||
// try without namespace as a fallback.
|
||||
if (ch == null)
|
||||
ch = getSampleFunction($"Gameplay/{info.Bank}-{info.Name}");
|
||||
|
||||
if (ch != null)
|
||||
ch.Volume.Value = info.Volume / 100.0;
|
||||
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
}
|
@ -323,7 +323,7 @@
|
||||
<DependentUpon>20171209034410_AddRulesetInfoShortName.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\20180219060912_AddSkins.cs" />
|
||||
<Compile Include="Migrations\20180219060912_AddSkins.designer.cs">
|
||||
<Compile Include="Migrations\20180219060912_AddSkins.Designer.cs">
|
||||
<DependentUpon>20180219060912_AddSkins.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\OsuDbContextModelSnapshot.cs" />
|
||||
@ -854,9 +854,15 @@
|
||||
<Compile Include="Screens\Tournament\Teams\DrawingsTeam.cs" />
|
||||
<Compile Include="Screens\Tournament\Teams\ITeamList.cs" />
|
||||
<Compile Include="Screens\Tournament\Teams\StorageBackedTeamList.cs" />
|
||||
<Compile Include="Skinning\DefaultSkin.cs" />
|
||||
<Compile Include="Skinning\LegacySkin.cs" />
|
||||
<Compile Include="Skinning\Skin.cs" />
|
||||
<Compile Include="Skinning\SkinFileInfo.cs" />
|
||||
<Compile Include="Skinning\SkinInfo.cs" />
|
||||
<Compile Include="Skinning\SkinManager.cs" />
|
||||
<Compile Include="Skinning\SkinnableDrawable.cs" />
|
||||
<Compile Include="Skinning\SkinnableSound.cs" />
|
||||
<Compile Include="Skinning\SkinReloadableDrawable.cs" />
|
||||
<Compile Include="Skinning\SkinStore.cs" />
|
||||
<Compile Include="Storyboards\CommandLoop.cs" />
|
||||
<Compile Include="Storyboards\CommandTimeline.cs" />
|
||||
@ -930,4 +936,4 @@
|
||||
<Import Project="$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.osx.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.osx.targets" Condition="Exists('$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.osx.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.osx.targets')" />
|
||||
<Import Project="$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.linux.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.linux.targets" Condition="Exists('$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.linux.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.linux.targets')" />
|
||||
<Import Project="$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.v110_xp.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.v110_xp.targets" Condition="Exists('$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.v110_xp.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.v110_xp.targets')" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
Loading…
Reference in New Issue
Block a user