mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 16:32:54 +08:00
Merge branch 'master' into spectator
This commit is contained in:
commit
b86347dc81
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -38,20 +39,25 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
|
|
||||||
protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state)
|
protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state)
|
||||||
{
|
{
|
||||||
if (!(drawable is DrawableOsuHitObject drawableOsu))
|
if (!(drawable is DrawableOsuHitObject))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var h = drawableOsu.HitObject;
|
|
||||||
|
|
||||||
//todo: expose and hide spinner background somehow
|
//todo: expose and hide spinner background somehow
|
||||||
|
|
||||||
switch (drawable)
|
switch (drawable)
|
||||||
{
|
{
|
||||||
case DrawableHitCircle circle:
|
case DrawableHitCircle circle:
|
||||||
// we only want to see the approach circle
|
// we only want to see the approach circle
|
||||||
using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true))
|
applyCirclePieceState(circle, circle.CirclePiece);
|
||||||
circle.CirclePiece.Hide();
|
break;
|
||||||
|
|
||||||
|
case DrawableSliderTail sliderTail:
|
||||||
|
applyCirclePieceState(sliderTail);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DrawableSliderRepeat sliderRepeat:
|
||||||
|
// show only the repeat arrow
|
||||||
|
applyCirclePieceState(sliderRepeat, sliderRepeat.CirclePiece);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DrawableSlider slider:
|
case DrawableSlider slider:
|
||||||
@ -61,6 +67,13 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyCirclePieceState(DrawableOsuHitObject hitObject, IDrawable hitCircle = null)
|
||||||
|
{
|
||||||
|
var h = hitObject.HitObject;
|
||||||
|
using (hitObject.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true))
|
||||||
|
(hitCircle ?? hitObject).Hide();
|
||||||
|
}
|
||||||
|
|
||||||
private void applySliderState(DrawableSlider slider)
|
private void applySliderState(DrawableSlider slider)
|
||||||
{
|
{
|
||||||
((PlaySliderBody)slider.Body.Drawable).AccentColour = slider.AccentColour.Value.Opacity(0);
|
((PlaySliderBody)slider.Body.Drawable).AccentColour = slider.AccentColour.Value.Opacity(0);
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Storyboards;
|
||||||
|
using osu.Game.Storyboards.Drawables;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
|
{
|
||||||
|
public class TestSceneDrawableStoryboardSprite : SkinnableTestScene
|
||||||
|
{
|
||||||
|
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private Storyboard storyboard { get; set; } = new Storyboard();
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSkinSpriteDisallowedByDefault()
|
||||||
|
{
|
||||||
|
const string lookup_name = "hitcircleoverlay";
|
||||||
|
|
||||||
|
AddStep("allow skin lookup", () => storyboard.UseSkinSprites = false);
|
||||||
|
|
||||||
|
AddStep("create sprites", () => SetContents(
|
||||||
|
() => createSprite(lookup_name, Anchor.TopLeft, Vector2.Zero)));
|
||||||
|
|
||||||
|
assertSpritesFromSkin(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestAllowLookupFromSkin()
|
||||||
|
{
|
||||||
|
const string lookup_name = "hitcircleoverlay";
|
||||||
|
|
||||||
|
AddStep("allow skin lookup", () => storyboard.UseSkinSprites = true);
|
||||||
|
|
||||||
|
AddStep("create sprites", () => SetContents(
|
||||||
|
() => createSprite(lookup_name, Anchor.Centre, Vector2.Zero)));
|
||||||
|
|
||||||
|
assertSpritesFromSkin(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DrawableStoryboardSprite createSprite(string lookupName, Anchor origin, Vector2 initialPosition)
|
||||||
|
=> new DrawableStoryboardSprite(
|
||||||
|
new StoryboardSprite(lookupName, origin, initialPosition)
|
||||||
|
).With(s =>
|
||||||
|
{
|
||||||
|
s.LifetimeStart = double.MinValue;
|
||||||
|
s.LifetimeEnd = double.MaxValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
private void assertSpritesFromSkin(bool fromSkin) =>
|
||||||
|
AddAssert($"sprites are {(fromSkin ? "from skin" : "from storyboard")}",
|
||||||
|
() => this.ChildrenOfType<DrawableStoryboardSprite>()
|
||||||
|
.All(sprite => sprite.ChildrenOfType<SkinnableSprite>().Any() == fromSkin));
|
||||||
|
}
|
||||||
|
}
|
@ -265,6 +265,26 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddUntilStep("wait for current", () => loader.IsCurrentScreen());
|
AddUntilStep("wait for current", () => loader.IsCurrentScreen());
|
||||||
|
|
||||||
AddAssert($"epilepsy warning {(warning ? "present" : "absent")}", () => this.ChildrenOfType<EpilepsyWarning>().Any() == warning);
|
AddAssert($"epilepsy warning {(warning ? "present" : "absent")}", () => this.ChildrenOfType<EpilepsyWarning>().Any() == warning);
|
||||||
|
|
||||||
|
if (warning)
|
||||||
|
{
|
||||||
|
AddUntilStep("sound volume decreased", () => Beatmap.Value.Track.AggregateVolume.Value == 0.25);
|
||||||
|
AddUntilStep("sound volume restored", () => Beatmap.Value.Track.AggregateVolume.Value == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEpilepsyWarningEarlyExit()
|
||||||
|
{
|
||||||
|
AddStep("set epilepsy warning", () => epilepsyWarning = true);
|
||||||
|
AddStep("load dummy beatmap", () => ResetPlayer(false));
|
||||||
|
|
||||||
|
AddUntilStep("wait for current", () => loader.IsCurrentScreen());
|
||||||
|
|
||||||
|
AddUntilStep("wait for epilepsy warning", () => loader.ChildrenOfType<EpilepsyWarning>().Single().Alpha > 0);
|
||||||
|
AddStep("exit early", () => loader.Exit());
|
||||||
|
|
||||||
|
AddUntilStep("sound volume restored", () => Beatmap.Value.Track.AggregateVolume.Value == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestPlayerLoaderContainer : Container
|
private class TestPlayerLoaderContainer : Container
|
||||||
|
@ -18,13 +18,13 @@ namespace osu.Game.Tests.Visual.Ranking
|
|||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 1.23 }),
|
new StarRatingDisplay(new StarDifficulty(1.23, 0)),
|
||||||
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 2.34 }),
|
new StarRatingDisplay(new StarDifficulty(2.34, 0)),
|
||||||
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 3.45 }),
|
new StarRatingDisplay(new StarDifficulty(3.45, 0)),
|
||||||
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 4.56 }),
|
new StarRatingDisplay(new StarDifficulty(4.56, 0)),
|
||||||
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 5.67 }),
|
new StarRatingDisplay(new StarDifficulty(5.67, 0)),
|
||||||
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 6.78 }),
|
new StarRatingDisplay(new StarDifficulty(6.78, 0)),
|
||||||
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 10.11 }),
|
new StarRatingDisplay(new StarDifficulty(10.11, 0)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,10 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
|
case Section.General:
|
||||||
|
handleGeneral(storyboard, line);
|
||||||
|
return;
|
||||||
|
|
||||||
case Section.Events:
|
case Section.Events:
|
||||||
handleEvents(line);
|
handleEvents(line);
|
||||||
return;
|
return;
|
||||||
@ -60,6 +64,18 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
base.ParseLine(storyboard, section, line);
|
base.ParseLine(storyboard, section, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleGeneral(Storyboard storyboard, string line)
|
||||||
|
{
|
||||||
|
var pair = SplitKeyVal(line);
|
||||||
|
|
||||||
|
switch (pair.Key)
|
||||||
|
{
|
||||||
|
case "UseSkinSprites":
|
||||||
|
storyboard.UseSkinSprites = pair.Value == "1";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleEvents(string line)
|
private void handleEvents(string line)
|
||||||
{
|
{
|
||||||
var depth = 0;
|
var depth = 0;
|
||||||
|
@ -11,11 +11,13 @@ namespace osu.Game.Online.API
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The local user.
|
/// The local user.
|
||||||
|
/// This is not thread-safe and should be scheduled locally if consumed from a drawable component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Bindable<User> LocalUser { get; }
|
Bindable<User> LocalUser { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current user's activity.
|
/// The current user's activity.
|
||||||
|
/// This is not thread-safe and should be scheduled locally if consumed from a drawable component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Bindable<UserActivity> Activity { get; }
|
Bindable<UserActivity> Activity { get; }
|
||||||
|
|
||||||
@ -40,6 +42,10 @@ namespace osu.Game.Online.API
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
string Endpoint { get; }
|
string Endpoint { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current connection state of the API.
|
||||||
|
/// This is not thread-safe and should be scheduled locally if consumed from a drawable component.
|
||||||
|
/// </summary>
|
||||||
IBindable<APIState> State { get; }
|
IBindable<APIState> State { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
StateContainer = login;
|
StateContainer = login;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onlineStateChanged(ValueChangedEvent<APIState> state)
|
private void onlineStateChanged(ValueChangedEvent<APIState> state) => Schedule(() =>
|
||||||
{
|
{
|
||||||
switch (state.NewValue)
|
switch (state.NewValue)
|
||||||
{
|
{
|
||||||
@ -72,6 +72,6 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
avatar.User = api.LocalUser.Value;
|
avatar.User = api.LocalUser.Value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
|
||||||
using osu.Framework.Audio.Track;
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -18,11 +16,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
public class EpilepsyWarning : VisibilityContainer
|
public class EpilepsyWarning : VisibilityContainer
|
||||||
{
|
{
|
||||||
public const double FADE_DURATION = 500;
|
public const double FADE_DURATION = 250;
|
||||||
|
|
||||||
private readonly BindableDouble trackVolumeOnEpilepsyWarning = new BindableDouble(1f);
|
|
||||||
|
|
||||||
private Track track;
|
|
||||||
|
|
||||||
public EpilepsyWarning()
|
public EpilepsyWarning()
|
||||||
{
|
{
|
||||||
@ -77,26 +71,15 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
track = beatmap.Value.Track;
|
|
||||||
track.AddAdjustment(AdjustableProperty.Volume, trackVolumeOnEpilepsyWarning);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
{
|
{
|
||||||
this.TransformBindableTo(trackVolumeOnEpilepsyWarning, 0.25, FADE_DURATION);
|
|
||||||
|
|
||||||
DimmableBackground?.FadeColour(OsuColour.Gray(0.5f), FADE_DURATION, Easing.OutQuint);
|
DimmableBackground?.FadeColour(OsuColour.Gray(0.5f), FADE_DURATION, Easing.OutQuint);
|
||||||
|
|
||||||
this.FadeIn(FADE_DURATION, Easing.OutQuint);
|
this.FadeIn(FADE_DURATION, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopOut() => this.FadeOut(FADE_DURATION);
|
protected override void PopOut() => this.FadeOut(FADE_DURATION);
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
|
||||||
{
|
|
||||||
base.Dispose(isDisposing);
|
|
||||||
track?.RemoveAdjustment(AdjustableProperty.Volume, trackVolumeOnEpilepsyWarning);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,8 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private bool backgroundBrightnessReduction;
|
private bool backgroundBrightnessReduction;
|
||||||
|
|
||||||
|
private readonly BindableDouble volumeAdjustment = new BindableDouble(1);
|
||||||
|
|
||||||
protected bool BackgroundBrightnessReduction
|
protected bool BackgroundBrightnessReduction
|
||||||
{
|
{
|
||||||
set
|
set
|
||||||
@ -169,6 +171,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
if (epilepsyWarning != null)
|
if (epilepsyWarning != null)
|
||||||
epilepsyWarning.DimmableBackground = Background;
|
epilepsyWarning.DimmableBackground = Background;
|
||||||
|
Beatmap.Value.Track.AddAdjustment(AdjustableProperty.Volume, volumeAdjustment);
|
||||||
|
|
||||||
content.ScaleTo(0.7f);
|
content.ScaleTo(0.7f);
|
||||||
Background?.FadeColour(Color4.White, 800, Easing.OutQuint);
|
Background?.FadeColour(Color4.White, 800, Easing.OutQuint);
|
||||||
@ -197,6 +200,11 @@ namespace osu.Game.Screens.Play
|
|||||||
cancelLoad();
|
cancelLoad();
|
||||||
|
|
||||||
BackgroundBrightnessReduction = false;
|
BackgroundBrightnessReduction = false;
|
||||||
|
|
||||||
|
// we're moving to player, so a period of silence is upcoming.
|
||||||
|
// stop the track before removing adjustment to avoid a volume spike.
|
||||||
|
Beatmap.Value.Track.Stop();
|
||||||
|
Beatmap.Value.Track.RemoveAdjustment(AdjustableProperty.Volume, volumeAdjustment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool OnExiting(IScreen next)
|
public override bool OnExiting(IScreen next)
|
||||||
@ -208,6 +216,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
Background.EnableUserDim.Value = false;
|
Background.EnableUserDim.Value = false;
|
||||||
BackgroundBrightnessReduction = false;
|
BackgroundBrightnessReduction = false;
|
||||||
|
Beatmap.Value.Track.RemoveAdjustment(AdjustableProperty.Volume, volumeAdjustment);
|
||||||
|
|
||||||
return base.OnExiting(next);
|
return base.OnExiting(next);
|
||||||
}
|
}
|
||||||
@ -331,18 +340,16 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
const double epilepsy_display_length = 3000;
|
const double epilepsy_display_length = 3000;
|
||||||
|
|
||||||
pushSequence.Schedule(() =>
|
pushSequence
|
||||||
{
|
.Schedule(() => epilepsyWarning.State.Value = Visibility.Visible)
|
||||||
epilepsyWarning.State.Value = Visibility.Visible;
|
.TransformBindableTo(volumeAdjustment, 0.25, EpilepsyWarning.FADE_DURATION, Easing.OutQuint)
|
||||||
|
.Delay(epilepsy_display_length)
|
||||||
this.Delay(epilepsy_display_length).Schedule(() =>
|
.Schedule(() =>
|
||||||
{
|
{
|
||||||
epilepsyWarning.Hide();
|
epilepsyWarning.Hide();
|
||||||
epilepsyWarning.Expire();
|
epilepsyWarning.Expire();
|
||||||
});
|
})
|
||||||
});
|
.Delay(EpilepsyWarning.FADE_DURATION);
|
||||||
|
|
||||||
pushSequence.Delay(epilepsy_display_length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pushSequence.Schedule(() =>
|
pushSequence.Schedule(() =>
|
||||||
|
@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
@ -51,7 +52,7 @@ namespace osu.Game.Screens.Ranking.Expanded
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load(BeatmapDifficultyManager beatmapDifficultyManager)
|
||||||
{
|
{
|
||||||
var beatmap = score.Beatmap;
|
var beatmap = score.Beatmap;
|
||||||
var metadata = beatmap.BeatmapSet?.Metadata ?? beatmap.Metadata;
|
var metadata = beatmap.BeatmapSet?.Metadata ?? beatmap.Metadata;
|
||||||
@ -138,7 +139,7 @@ namespace osu.Game.Screens.Ranking.Expanded
|
|||||||
Spacing = new Vector2(5, 0),
|
Spacing = new Vector2(5, 0),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new StarRatingDisplay(beatmap)
|
new StarRatingDisplay(beatmapDifficultyManager.GetDifficulty(beatmap, score.Ruleset, score.Mods))
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft
|
Origin = Anchor.CentreLeft
|
||||||
|
@ -22,29 +22,30 @@ namespace osu.Game.Screens.Ranking.Expanded
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class StarRatingDisplay : CompositeDrawable
|
public class StarRatingDisplay : CompositeDrawable
|
||||||
{
|
{
|
||||||
private readonly BeatmapInfo beatmap;
|
private readonly StarDifficulty difficulty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="StarRatingDisplay"/>.
|
/// Creates a new <see cref="StarRatingDisplay"/> using an already computed <see cref="StarDifficulty"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="beatmap">The <see cref="BeatmapInfo"/> to display the star difficulty of.</param>
|
/// <param name="starDifficulty">The already computed <see cref="StarDifficulty"/> to display the star difficulty of.</param>
|
||||||
public StarRatingDisplay(BeatmapInfo beatmap)
|
public StarRatingDisplay(StarDifficulty starDifficulty)
|
||||||
{
|
{
|
||||||
this.beatmap = beatmap;
|
difficulty = starDifficulty;
|
||||||
AutoSizeAxes = Axes.Both;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours, BeatmapDifficultyManager difficultyManager)
|
||||||
{
|
{
|
||||||
var starRatingParts = beatmap.StarDifficulty.ToString("0.00", CultureInfo.InvariantCulture).Split('.');
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.');
|
||||||
string wholePart = starRatingParts[0];
|
string wholePart = starRatingParts[0];
|
||||||
string fractionPart = starRatingParts[1];
|
string fractionPart = starRatingParts[1];
|
||||||
string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
|
string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
|
||||||
|
|
||||||
ColourInfo backgroundColour = beatmap.DifficultyRating == DifficultyRating.ExpertPlus
|
ColourInfo backgroundColour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus
|
||||||
? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959"))
|
? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959"))
|
||||||
: (ColourInfo)colours.ForDifficultyRating(beatmap.DifficultyRating);
|
: (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating);
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
|
@ -39,6 +39,11 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
private readonly IBindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
|
private readonly IBindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapDifficultyManager difficultyManager { get; set; }
|
||||||
|
|
||||||
|
private IBindable<StarDifficulty> beatmapDifficulty;
|
||||||
|
|
||||||
protected BufferedWedgeInfo Info;
|
protected BufferedWedgeInfo Info;
|
||||||
|
|
||||||
public BeatmapInfoWedge()
|
public BeatmapInfoWedge()
|
||||||
@ -88,6 +93,11 @@ namespace osu.Game.Screens.Select
|
|||||||
if (beatmap == value) return;
|
if (beatmap == value) return;
|
||||||
|
|
||||||
beatmap = value;
|
beatmap = value;
|
||||||
|
|
||||||
|
beatmapDifficulty?.UnbindAll();
|
||||||
|
beatmapDifficulty = difficultyManager.GetBindableDifficulty(beatmap.BeatmapInfo);
|
||||||
|
beatmapDifficulty.BindValueChanged(_ => updateDisplay());
|
||||||
|
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +123,7 @@ namespace osu.Game.Screens.Select
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadComponentAsync(loadingInfo = new BufferedWedgeInfo(beatmap, ruleset.Value)
|
LoadComponentAsync(loadingInfo = new BufferedWedgeInfo(beatmap, ruleset.Value, beatmapDifficulty.Value)
|
||||||
{
|
{
|
||||||
Shear = -Shear,
|
Shear = -Shear,
|
||||||
Depth = Info?.Depth + 1 ?? 0
|
Depth = Info?.Depth + 1 ?? 0
|
||||||
@ -141,12 +151,14 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
private readonly WorkingBeatmap beatmap;
|
private readonly WorkingBeatmap beatmap;
|
||||||
private readonly RulesetInfo ruleset;
|
private readonly RulesetInfo ruleset;
|
||||||
|
private readonly StarDifficulty starDifficulty;
|
||||||
|
|
||||||
public BufferedWedgeInfo(WorkingBeatmap beatmap, RulesetInfo userRuleset)
|
public BufferedWedgeInfo(WorkingBeatmap beatmap, RulesetInfo userRuleset, StarDifficulty difficulty)
|
||||||
: base(pixelSnapping: true)
|
: base(pixelSnapping: true)
|
||||||
{
|
{
|
||||||
this.beatmap = beatmap;
|
this.beatmap = beatmap;
|
||||||
ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset;
|
ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset;
|
||||||
|
starDifficulty = difficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -190,7 +202,7 @@ namespace osu.Game.Screens.Select
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
new DifficultyColourBar(beatmapInfo)
|
new DifficultyColourBar(starDifficulty)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Width = 20,
|
Width = 20,
|
||||||
@ -226,7 +238,7 @@ namespace osu.Game.Screens.Select
|
|||||||
Shear = wedged_container_shear,
|
Shear = wedged_container_shear,
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
createStarRatingDisplay(beatmapInfo).With(display =>
|
createStarRatingDisplay(starDifficulty).With(display =>
|
||||||
{
|
{
|
||||||
display.Anchor = Anchor.TopRight;
|
display.Anchor = Anchor.TopRight;
|
||||||
display.Origin = Anchor.TopRight;
|
display.Origin = Anchor.TopRight;
|
||||||
@ -293,8 +305,8 @@ namespace osu.Game.Screens.Select
|
|||||||
StatusPill.Hide();
|
StatusPill.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Drawable createStarRatingDisplay(BeatmapInfo beatmapInfo) => beatmapInfo.StarDifficulty > 0
|
private static Drawable createStarRatingDisplay(StarDifficulty difficulty) => difficulty.Stars > 0
|
||||||
? new StarRatingDisplay(beatmapInfo)
|
? new StarRatingDisplay(difficulty)
|
||||||
{
|
{
|
||||||
Margin = new MarginPadding { Bottom = 5 }
|
Margin = new MarginPadding { Bottom = 5 }
|
||||||
}
|
}
|
||||||
@ -447,11 +459,11 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
private class DifficultyColourBar : Container
|
private class DifficultyColourBar : Container
|
||||||
{
|
{
|
||||||
private readonly BeatmapInfo beatmap;
|
private readonly StarDifficulty difficulty;
|
||||||
|
|
||||||
public DifficultyColourBar(BeatmapInfo beatmap)
|
public DifficultyColourBar(StarDifficulty difficulty)
|
||||||
{
|
{
|
||||||
this.beatmap = beatmap;
|
this.difficulty = difficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -459,7 +471,7 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
const float full_opacity_ratio = 0.7f;
|
const float full_opacity_ratio = 0.7f;
|
||||||
|
|
||||||
var difficultyColour = colours.ForDifficultyRating(beatmap.DifficultyRating);
|
var difficultyColour = colours.ForDifficultyRating(difficulty.DifficultyRating);
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
|
@ -140,7 +140,7 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
LoadComponentAsync(beatmapContainer, loaded =>
|
LoadComponentAsync(beatmapContainer, loaded =>
|
||||||
{
|
{
|
||||||
// make sure the pooled target hasn't changed.
|
// make sure the pooled target hasn't changed.
|
||||||
if (carouselBeatmapSet != Item)
|
if (beatmapContainer != loaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Content.Child = loaded;
|
Content.Child = loaded;
|
||||||
|
@ -15,6 +15,7 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
{
|
{
|
||||||
public class DrawableStoryboard : Container<DrawableStoryboardLayer>
|
public class DrawableStoryboard : Container<DrawableStoryboardLayer>
|
||||||
{
|
{
|
||||||
|
[Cached]
|
||||||
public Storyboard Storyboard { get; }
|
public Storyboard Storyboard { get; }
|
||||||
|
|
||||||
protected override Container<DrawableStoryboardLayer> Content { get; }
|
protected override Container<DrawableStoryboardLayer> Content { get; }
|
||||||
|
@ -2,18 +2,16 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osuTK;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
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.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Storyboards.Drawables
|
namespace osu.Game.Storyboards.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableStoryboardAnimation : TextureAnimation, IFlippable, IVectorScalable
|
public class DrawableStoryboardAnimation : DrawableAnimation, IFlippable, IVectorScalable
|
||||||
{
|
{
|
||||||
public StoryboardAnimation Animation { get; }
|
public StoryboardAnimation Animation { get; }
|
||||||
|
|
||||||
@ -115,18 +113,13 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IBindable<WorkingBeatmap> beatmap, TextureStore textureStore)
|
private void load(TextureStore textureStore, Storyboard storyboard)
|
||||||
{
|
{
|
||||||
for (var frame = 0; frame < Animation.FrameCount; frame++)
|
for (int frame = 0; frame < Animation.FrameCount; frame++)
|
||||||
{
|
{
|
||||||
var framePath = Animation.Path.Replace(".", frame + ".");
|
string framePath = Animation.Path.Replace(".", frame + ".");
|
||||||
|
|
||||||
var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.Equals(framePath, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
|
AddFrame(storyboard.CreateSpriteFromResourcePath(framePath, textureStore), Animation.FrameDelay);
|
||||||
if (path == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var texture = textureStore.Get(path);
|
|
||||||
AddFrame(texture, Animation.FrameDelay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation.ApplyTransforms(this);
|
Animation.ApplyTransforms(this);
|
||||||
|
@ -2,18 +2,16 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osuTK;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Storyboards.Drawables
|
namespace osu.Game.Storyboards.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableStoryboardSprite : Sprite, IFlippable, IVectorScalable
|
public class DrawableStoryboardSprite : CompositeDrawable, IFlippable, IVectorScalable
|
||||||
{
|
{
|
||||||
public StoryboardSprite Sprite { get; }
|
public StoryboardSprite Sprite { get; }
|
||||||
|
|
||||||
@ -111,16 +109,18 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
|
|
||||||
LifetimeStart = sprite.StartTime;
|
LifetimeStart = sprite.StartTime;
|
||||||
LifetimeEnd = sprite.EndTime;
|
LifetimeEnd = sprite.EndTime;
|
||||||
|
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IBindable<WorkingBeatmap> beatmap, TextureStore textureStore)
|
private void load(TextureStore textureStore, Storyboard storyboard)
|
||||||
{
|
{
|
||||||
var path = beatmap.Value.BeatmapSetInfo?.Files?.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
|
var drawable = storyboard.CreateSpriteFromResourcePath(Sprite.Path, textureStore);
|
||||||
if (path == null)
|
|
||||||
return;
|
if (drawable != null)
|
||||||
|
InternalChild = drawable;
|
||||||
|
|
||||||
Texture = textureStore.Get(path);
|
|
||||||
Sprite.ApplyTransforms(this);
|
Sprite.ApplyTransforms(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Storyboards.Drawables;
|
using osu.Game.Storyboards.Drawables;
|
||||||
|
|
||||||
namespace osu.Game.Storyboards
|
namespace osu.Game.Storyboards
|
||||||
@ -15,6 +20,11 @@ namespace osu.Game.Storyboards
|
|||||||
|
|
||||||
public BeatmapInfo BeatmapInfo = new BeatmapInfo();
|
public BeatmapInfo BeatmapInfo = new BeatmapInfo();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the storyboard can fall back to skin sprites in case no matching storyboard sprites are found.
|
||||||
|
/// </summary>
|
||||||
|
public bool UseSkinSprites { get; set; }
|
||||||
|
|
||||||
public bool HasDrawable => Layers.Any(l => l.Elements.Any(e => e.IsDrawable));
|
public bool HasDrawable => Layers.Any(l => l.Elements.Any(e => e.IsDrawable));
|
||||||
|
|
||||||
public double FirstEventTime => Layers.Min(l => l.Elements.FirstOrDefault()?.StartTime ?? 0);
|
public double FirstEventTime => Layers.Min(l => l.Elements.FirstOrDefault()?.StartTime ?? 0);
|
||||||
@ -64,5 +74,19 @@ namespace osu.Game.Storyboards
|
|||||||
drawable.Width = drawable.Height * (BeatmapInfo.WidescreenStoryboard ? 16 / 9f : 4 / 3f);
|
drawable.Width = drawable.Height * (BeatmapInfo.WidescreenStoryboard ? 16 / 9f : 4 / 3f);
|
||||||
return drawable;
|
return drawable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Drawable CreateSpriteFromResourcePath(string path, TextureStore textureStore)
|
||||||
|
{
|
||||||
|
Drawable drawable = null;
|
||||||
|
var storyboardPath = BeatmapInfo.BeatmapSet?.Files?.Find(f => f.Filename.Equals(path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
|
||||||
|
|
||||||
|
if (storyboardPath != null)
|
||||||
|
drawable = new Sprite { Texture = textureStore.Get(storyboardPath) };
|
||||||
|
// if the texture isn't available locally in the beatmap, some storyboards choose to source from the underlying skin lookup hierarchy.
|
||||||
|
else if (UseSkinSprites)
|
||||||
|
drawable = new SkinnableSprite(path);
|
||||||
|
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user