mirror of
https://github.com/ppy/osu.git
synced 2025-02-21 03:02:54 +08:00
Add ruleset-specific legacy skin providers
This moves implementation of osu! skinnables to OsuLegacySkin.
This commit is contained in:
parent
de2c6aa23d
commit
5e362d10b1
228
osu.Game.Rulesets.Osu/OsuLegacySkin.cs
Normal file
228
osu.Game.Rulesets.Osu/OsuLegacySkin.cs
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Animations;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu
|
||||||
|
{
|
||||||
|
public class OsuLegacySkin : ISkin
|
||||||
|
{
|
||||||
|
private readonly ISkin source;
|
||||||
|
|
||||||
|
private Lazy<SkinConfiguration> configuration;
|
||||||
|
|
||||||
|
private Lazy<bool> hasHitCircle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// On osu-stable, hitcircles have 5 pixels of transparent padding on each side to allow for shadows etc.
|
||||||
|
/// Their hittable area is 128px, but the actual circle portion is 118px.
|
||||||
|
/// We must account for some gameplay elements such as slider bodies, where this padding is not present.
|
||||||
|
/// </summary>
|
||||||
|
private const float legacy_circle_radius = 64 - 5;
|
||||||
|
|
||||||
|
public OsuLegacySkin(ISkinSource source)
|
||||||
|
{
|
||||||
|
this.source = source;
|
||||||
|
|
||||||
|
source.SourceChanged += sourceChanged;
|
||||||
|
sourceChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sourceChanged()
|
||||||
|
{
|
||||||
|
configuration = new Lazy<SkinConfiguration>(() =>
|
||||||
|
{
|
||||||
|
var config = new SkinConfiguration();
|
||||||
|
if (hasHitCircle.Value)
|
||||||
|
config.SliderPathRadius = legacy_circle_radius;
|
||||||
|
return config;
|
||||||
|
});
|
||||||
|
|
||||||
|
hasHitCircle = new Lazy<bool>(() => source.GetTexture("hitcircle") != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const double default_frame_time = 1000 / 60d;
|
||||||
|
|
||||||
|
public Drawable GetDrawableComponent(string componentName)
|
||||||
|
{
|
||||||
|
switch (componentName)
|
||||||
|
{
|
||||||
|
case "Play/osu/sliderball":
|
||||||
|
var sliderBallContent = getAnimation("sliderb", true, true, "");
|
||||||
|
|
||||||
|
if (sliderBallContent != null)
|
||||||
|
{
|
||||||
|
var size = sliderBallContent.Size;
|
||||||
|
|
||||||
|
sliderBallContent.RelativeSizeAxes = Axes.Both;
|
||||||
|
sliderBallContent.Size = Vector2.One;
|
||||||
|
|
||||||
|
return new LegacySliderBall(sliderBallContent)
|
||||||
|
{
|
||||||
|
Size = size
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
case "Play/osu/hitcircle":
|
||||||
|
if (hasHitCircle.Value)
|
||||||
|
return new LegacyMainCirclePiece();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable getAnimation(string componentName, bool animatable, bool looping, string animationSeparator = "-")
|
||||||
|
{
|
||||||
|
Texture texture;
|
||||||
|
|
||||||
|
Texture getFrameTexture(int frame) => source.GetTexture($"{componentName}{animationSeparator}{frame}");
|
||||||
|
|
||||||
|
TextureAnimation animation = null;
|
||||||
|
|
||||||
|
if (animatable)
|
||||||
|
{
|
||||||
|
for (int i = 0;; i++)
|
||||||
|
{
|
||||||
|
if ((texture = getFrameTexture(i)) == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (animation == null)
|
||||||
|
animation = new TextureAnimation
|
||||||
|
{
|
||||||
|
DefaultFrameLength = default_frame_time,
|
||||||
|
Repeat = looping
|
||||||
|
};
|
||||||
|
|
||||||
|
animation.AddFrame(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animation != null)
|
||||||
|
return animation;
|
||||||
|
|
||||||
|
if ((texture = source.GetTexture(componentName)) != null)
|
||||||
|
return new Sprite { Texture = texture };
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Texture GetTexture(string componentName) => null;
|
||||||
|
|
||||||
|
public SampleChannel GetSample(string sampleName) => null;
|
||||||
|
|
||||||
|
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration
|
||||||
|
=> configuration.Value is TConfiguration conf ? query.Invoke(conf) : default;
|
||||||
|
|
||||||
|
public class LegacySliderBall : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly Drawable animationContent;
|
||||||
|
|
||||||
|
public LegacySliderBall(Drawable animationContent)
|
||||||
|
{
|
||||||
|
this.animationContent = animationContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin, DrawableHitObject drawableObject)
|
||||||
|
{
|
||||||
|
animationContent.Colour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White;
|
||||||
|
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture("sliderb-nd"),
|
||||||
|
Colour = new Color4(5, 5, 5, 255),
|
||||||
|
},
|
||||||
|
animationContent,
|
||||||
|
new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture("sliderb-spec"),
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LegacyMainCirclePiece : CompositeDrawable
|
||||||
|
{
|
||||||
|
public LegacyMainCirclePiece()
|
||||||
|
{
|
||||||
|
Size = new Vector2(128);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IBindable<ArmedState> state = new Bindable<ArmedState>();
|
||||||
|
|
||||||
|
private readonly Bindable<Color4> accentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(DrawableHitObject drawableObject, ISkinSource skin)
|
||||||
|
{
|
||||||
|
Sprite hitCircleSprite;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
hitCircleSprite = new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture("hitcircle"),
|
||||||
|
Colour = drawableObject.AccentColour.Value,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText
|
||||||
|
{
|
||||||
|
Font = OsuFont.Numeric.With(size: 40),
|
||||||
|
UseFullGlyphHeight = false,
|
||||||
|
}, confineMode: ConfineMode.NoScaling)
|
||||||
|
{
|
||||||
|
Text = (((IHasComboInformation)drawableObject.HitObject).IndexInCurrentCombo + 1).ToString()
|
||||||
|
},
|
||||||
|
new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture("hitcircleoverlay"),
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
state.BindTo(drawableObject.State);
|
||||||
|
state.BindValueChanged(updateState, true);
|
||||||
|
|
||||||
|
accentColour.BindTo(drawableObject.AccentColour);
|
||||||
|
accentColour.BindValueChanged(colour => hitCircleSprite.Colour = colour.NewValue, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateState(ValueChangedEvent<ArmedState> state)
|
||||||
|
{
|
||||||
|
const double legacy_fade_duration = 240;
|
||||||
|
|
||||||
|
switch (state.NewValue)
|
||||||
|
{
|
||||||
|
case ArmedState.Hit:
|
||||||
|
this.FadeOut(legacy_fade_duration, Easing.Out);
|
||||||
|
this.ScaleTo(1.4f, legacy_fade_duration, Easing.Out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,7 @@ using osu.Game.Rulesets.Osu.Beatmaps;
|
|||||||
using osu.Game.Rulesets.Osu.Configuration;
|
using osu.Game.Rulesets.Osu.Configuration;
|
||||||
using osu.Game.Rulesets.Osu.Difficulty;
|
using osu.Game.Rulesets.Osu.Difficulty;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu
|
namespace osu.Game.Rulesets.Osu
|
||||||
{
|
{
|
||||||
@ -163,6 +164,8 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
|
|
||||||
public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this);
|
public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this);
|
||||||
|
|
||||||
|
public override ISkin CreateLegacySkinProvider(ISkinSource source) => new OsuLegacySkin(source);
|
||||||
|
|
||||||
public override int? LegacyID => 0;
|
public override int? LegacyID => 0;
|
||||||
|
|
||||||
public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new OsuReplayFrame();
|
public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new OsuReplayFrame();
|
||||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
},
|
},
|
||||||
// Todo: This should not exist, but currently helps to reduce LOH allocations due to unbinding skin source events on judgement disposal
|
// Todo: This should not exist, but currently helps to reduce LOH allocations due to unbinding skin source events on judgement disposal
|
||||||
// Todo: Remove when hitobjects are properly pooled
|
// Todo: Remove when hitobjects are properly pooled
|
||||||
new LocalSkinOverrideContainer(null)
|
new SkinProvidingContainer(null)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = HitObjectContainer,
|
Child = HitObjectContainer,
|
||||||
|
@ -18,6 +18,7 @@ using osu.Game.Configuration;
|
|||||||
using osu.Game.Rulesets.Configuration;
|
using osu.Game.Rulesets.Configuration;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets
|
namespace osu.Game.Rulesets
|
||||||
{
|
{
|
||||||
@ -44,6 +45,8 @@ namespace osu.Game.Rulesets
|
|||||||
|
|
||||||
public ModAutoplay GetAutoplayMod() => GetAllMods().OfType<ModAutoplay>().First();
|
public ModAutoplay GetAutoplayMod() => GetAllMods().OfType<ModAutoplay>().First();
|
||||||
|
|
||||||
|
public virtual ISkin CreateLegacySkinProvider(ISkinSource source) => null;
|
||||||
|
|
||||||
protected Ruleset(RulesetInfo rulesetInfo = null)
|
protected Ruleset(RulesetInfo rulesetInfo = null)
|
||||||
{
|
{
|
||||||
RulesetInfo = rulesetInfo ?? createRulesetInfo();
|
RulesetInfo = rulesetInfo ?? createRulesetInfo();
|
||||||
|
@ -60,7 +60,9 @@ namespace osu.Game.Screens.Play
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private ScoreManager scoreManager { get; set; }
|
private ScoreManager scoreManager { get; set; }
|
||||||
|
|
||||||
private RulesetInfo ruleset;
|
private RulesetInfo rulesetInfo;
|
||||||
|
|
||||||
|
private Ruleset ruleset;
|
||||||
|
|
||||||
private IAPIProvider api;
|
private IAPIProvider api;
|
||||||
|
|
||||||
@ -121,20 +123,29 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime);
|
InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime);
|
||||||
|
|
||||||
|
SkinProvidingContainer skinProvidingContainer = new BeatmapSkinProvidingContainer(working.Skin)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
};
|
||||||
|
|
||||||
GameplayClockContainer.Children = new[]
|
GameplayClockContainer.Children = new[]
|
||||||
{
|
{
|
||||||
DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both },
|
DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both },
|
||||||
new ScalingContainer(ScalingMode.Gameplay)
|
new ScalingContainer(ScalingMode.Gameplay)
|
||||||
{
|
{
|
||||||
Child = new LocalSkinOverrideContainer(working.Skin)
|
Child = skinProvidingContainer.WithChild(
|
||||||
{
|
// the skinProvidingContainer is used as the fallback source here to allow the ruleset-specific skin implementation
|
||||||
RelativeSizeAxes = Axes.Both,
|
// full access to all skin sources.
|
||||||
Children = new Drawable[]
|
new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(skinProvidingContainer))
|
||||||
{
|
{
|
||||||
DrawableRuleset,
|
RelativeSizeAxes = Axes.Both,
|
||||||
new ComboEffects(ScoreProcessor)
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
DrawableRuleset,
|
||||||
|
new ComboEffects(ScoreProcessor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
},
|
},
|
||||||
breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor)
|
breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor)
|
||||||
{
|
{
|
||||||
@ -222,20 +233,20 @@ namespace osu.Game.Screens.Play
|
|||||||
if (beatmap == null)
|
if (beatmap == null)
|
||||||
throw new InvalidOperationException("Beatmap was not loaded");
|
throw new InvalidOperationException("Beatmap was not loaded");
|
||||||
|
|
||||||
ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset;
|
rulesetInfo = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset;
|
||||||
var rulesetInstance = ruleset.CreateInstance();
|
ruleset = rulesetInfo.CreateInstance();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(working, Mods.Value);
|
DrawableRuleset = ruleset.CreateDrawableRulesetWith(working, Mods.Value);
|
||||||
}
|
}
|
||||||
catch (BeatmapInvalidForRulesetException)
|
catch (BeatmapInvalidForRulesetException)
|
||||||
{
|
{
|
||||||
// we may fail to create a DrawableRuleset if the beatmap cannot be loaded with the user's preferred ruleset
|
// we may fail to create a DrawableRuleset if the beatmap cannot be loaded with the user's preferred ruleset
|
||||||
// let's try again forcing the beatmap's ruleset.
|
// let's try again forcing the beatmap's ruleset.
|
||||||
ruleset = beatmap.BeatmapInfo.Ruleset;
|
rulesetInfo = beatmap.BeatmapInfo.Ruleset;
|
||||||
rulesetInstance = ruleset.CreateInstance();
|
ruleset = rulesetInfo.CreateInstance();
|
||||||
DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(Beatmap.Value, Mods.Value);
|
DrawableRuleset = ruleset.CreateDrawableRulesetWith(Beatmap.Value, Mods.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DrawableRuleset.Objects.Any())
|
if (!DrawableRuleset.Objects.Any())
|
||||||
@ -313,7 +324,7 @@ namespace osu.Game.Screens.Play
|
|||||||
var score = DrawableRuleset.ReplayScore?.ScoreInfo ?? new ScoreInfo
|
var score = DrawableRuleset.ReplayScore?.ScoreInfo ?? new ScoreInfo
|
||||||
{
|
{
|
||||||
Beatmap = Beatmap.Value.BeatmapInfo,
|
Beatmap = Beatmap.Value.BeatmapInfo,
|
||||||
Ruleset = ruleset,
|
Ruleset = rulesetInfo,
|
||||||
Mods = Mods.Value.ToArray(),
|
Mods = Mods.Value.ToArray(),
|
||||||
User = api.LocalUser.Value,
|
User = api.LocalUser.Value,
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,6 @@ using System.Threading.Tasks;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Animations;
|
using osu.Framework.Graphics.Animations;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -20,8 +19,6 @@ using osu.Framework.Text;
|
|||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -34,13 +31,6 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
protected IResourceStore<SampleChannel> Samples;
|
protected IResourceStore<SampleChannel> Samples;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// On osu-stable, hitcircles have 5 pixels of transparent padding on each side to allow for shadows etc.
|
|
||||||
/// Their hittable area is 128px, but the actual circle portion is 118px.
|
|
||||||
/// We must account for some gameplay elements such as slider bodies, where this padding is not present.
|
|
||||||
/// </summary>
|
|
||||||
private const float legacy_circle_radius = 64 - 5;
|
|
||||||
|
|
||||||
public LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager)
|
public LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager)
|
||||||
: this(skin, new LegacySkinResourceStore<SkinFileInfo>(skin, storage), audioManager, "skin.ini")
|
: this(skin, new LegacySkinResourceStore<SkinFileInfo>(skin, storage), audioManager, "skin.ini")
|
||||||
{
|
{
|
||||||
@ -48,8 +38,6 @@ namespace osu.Game.Skinning
|
|||||||
if (!Configuration.CustomColours.ContainsKey("SliderBall")) Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255);
|
if (!Configuration.CustomColours.ContainsKey("SliderBall")) Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly bool hasHitCircle;
|
|
||||||
|
|
||||||
protected LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager, string filename)
|
protected LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager, string filename)
|
||||||
: base(skin)
|
: base(skin)
|
||||||
{
|
{
|
||||||
@ -62,14 +50,6 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
Samples = audioManager.GetSampleStore(storage);
|
Samples = audioManager.GetSampleStore(storage);
|
||||||
Textures = new TextureStore(new TextureLoaderStore(storage));
|
Textures = new TextureStore(new TextureLoaderStore(storage));
|
||||||
|
|
||||||
using (var testStream = storage.GetStream("hitcircle@2x") ?? storage.GetStream("hitcircle"))
|
|
||||||
hasHitCircle |= testStream != null;
|
|
||||||
|
|
||||||
if (hasHitCircle)
|
|
||||||
{
|
|
||||||
Configuration.SliderPathRadius = legacy_circle_radius;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
@ -94,30 +74,6 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
case "Play/osu/sliderball":
|
|
||||||
var sliderBallContent = getAnimation("sliderb", true, true, "");
|
|
||||||
|
|
||||||
if (sliderBallContent != null)
|
|
||||||
{
|
|
||||||
var size = sliderBallContent.Size;
|
|
||||||
|
|
||||||
sliderBallContent.RelativeSizeAxes = Axes.Both;
|
|
||||||
sliderBallContent.Size = Vector2.One;
|
|
||||||
|
|
||||||
return new LegacySliderBall(sliderBallContent)
|
|
||||||
{
|
|
||||||
Size = size
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
|
|
||||||
case "Play/osu/hitcircle":
|
|
||||||
if (hasHitCircle)
|
|
||||||
return new LegacyMainCirclePiece();
|
|
||||||
|
|
||||||
return null;
|
|
||||||
|
|
||||||
case "Play/osu/sliderfollowcircle":
|
case "Play/osu/sliderfollowcircle":
|
||||||
animatable = true;
|
animatable = true;
|
||||||
break;
|
break;
|
||||||
@ -355,99 +311,6 @@ namespace osu.Game.Skinning
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LegacySliderBall : CompositeDrawable
|
|
||||||
{
|
|
||||||
private readonly Drawable animationContent;
|
|
||||||
|
|
||||||
public LegacySliderBall(Drawable animationContent)
|
|
||||||
{
|
|
||||||
this.animationContent = animationContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(ISkinSource skin, DrawableHitObject drawableObject)
|
|
||||||
{
|
|
||||||
animationContent.Colour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White;
|
|
||||||
|
|
||||||
InternalChildren = new[]
|
|
||||||
{
|
|
||||||
new Sprite
|
|
||||||
{
|
|
||||||
Texture = skin.GetTexture("sliderb-nd"),
|
|
||||||
Colour = new Color4(5, 5, 5, 255),
|
|
||||||
},
|
|
||||||
animationContent,
|
|
||||||
new Sprite
|
|
||||||
{
|
|
||||||
Texture = skin.GetTexture("sliderb-spec"),
|
|
||||||
Blending = BlendingParameters.Additive,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LegacyMainCirclePiece : CompositeDrawable
|
|
||||||
{
|
|
||||||
public LegacyMainCirclePiece()
|
|
||||||
{
|
|
||||||
Size = new Vector2(128);
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly IBindable<ArmedState> state = new Bindable<ArmedState>();
|
|
||||||
|
|
||||||
private readonly Bindable<Color4> accentColour = new Bindable<Color4>();
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(DrawableHitObject drawableObject, ISkinSource skin)
|
|
||||||
{
|
|
||||||
Sprite hitCircleSprite;
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
hitCircleSprite = new Sprite
|
|
||||||
{
|
|
||||||
Texture = skin.GetTexture("hitcircle"),
|
|
||||||
Colour = drawableObject.AccentColour.Value,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
},
|
|
||||||
new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText
|
|
||||||
{
|
|
||||||
Font = OsuFont.Numeric.With(size: 40),
|
|
||||||
UseFullGlyphHeight = false,
|
|
||||||
}, confineMode: ConfineMode.NoScaling)
|
|
||||||
{
|
|
||||||
Text = (((IHasComboInformation)drawableObject.HitObject).IndexInCurrentCombo + 1).ToString()
|
|
||||||
},
|
|
||||||
new Sprite
|
|
||||||
{
|
|
||||||
Texture = skin.GetTexture("hitcircleoverlay"),
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
state.BindTo(drawableObject.State);
|
|
||||||
state.BindValueChanged(updateState, true);
|
|
||||||
|
|
||||||
accentColour.BindTo(drawableObject.AccentColour);
|
|
||||||
accentColour.BindValueChanged(colour => hitCircleSprite.Colour = colour.NewValue, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateState(ValueChangedEvent<ArmedState> state)
|
|
||||||
{
|
|
||||||
const double legacy_fade_duration = 240;
|
|
||||||
|
|
||||||
switch (state.NewValue)
|
|
||||||
{
|
|
||||||
case ArmedState.Hit:
|
|
||||||
this.FadeOut(legacy_fade_duration, Easing.Out);
|
|
||||||
this.ScaleTo(1.4f, legacy_fade_duration, Easing.Out);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sprite which is displayed within the playfield, but historically was not considered part of the playfield.
|
/// A sprite which is displayed within the playfield, but historically was not considered part of the playfield.
|
||||||
/// Performs scale adjustment to undo the scale applied by <see cref="PlayfieldAdjustmentContainer"/> (osu! ruleset specifically).
|
/// Performs scale adjustment to undo the scale applied by <see cref="PlayfieldAdjustmentContainer"/> (osu! ruleset specifically).
|
||||||
|
Loading…
Reference in New Issue
Block a user