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

Merge branch 'master' into beatmap-info

This commit is contained in:
C0D3 M4513R 2022-11-03 07:09:02 +00:00 committed by GitHub
commit 2ec29c0f26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 337 additions and 333 deletions

View File

@ -30,23 +30,24 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
Origin = Anchor.Centre, Origin = Anchor.Centre,
})); }));
AddStep("Rim hit", () => SetContents(_ => new DrawableHit(createHitAtCurrentTime()) AddStep("Rim hit", () => SetContents(_ => new DrawableHit(createHitAtCurrentTime(rim: true))
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
})); }));
AddStep("Rim hit (strong)", () => SetContents(_ => new DrawableHit(createHitAtCurrentTime(true)) AddStep("Rim hit (strong)", () => SetContents(_ => new DrawableHit(createHitAtCurrentTime(true, true))
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
})); }));
} }
private Hit createHitAtCurrentTime(bool strong = false) private Hit createHitAtCurrentTime(bool strong = false, bool rim = false)
{ {
var hit = new Hit var hit = new Hit
{ {
Type = rim ? HitType.Rim : HitType.Centre,
IsStrong = strong, IsStrong = strong,
StartTime = Time.Current + 3000, StartTime = Time.Current + 3000,
}; };

View File

@ -13,6 +13,7 @@ using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.UI; using osu.Game.Rulesets.Taiko.UI;
using osu.Game.Screens.Ranking;
namespace osu.Game.Rulesets.Taiko.Tests.Skinning namespace osu.Game.Rulesets.Taiko.Tests.Skinning
{ {
@ -49,12 +50,20 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
// the hit needs to be added to hierarchy in order for nested objects to be created correctly. // the hit needs to be added to hierarchy in order for nested objects to be created correctly.
// setting zero alpha is supposed to prevent the test from looking broken. // setting zero alpha is supposed to prevent the test from looking broken.
hit.With(h => h.Alpha = 0), hit.With(h => h.Alpha = 0),
new AspectContainer
{
RelativeSizeAxes = Axes.X,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Child =
new HitExplosion(hit.Type) new HitExplosion(hit.Type)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
}.With(explosion => explosion.Apply(hit)) }.With(explosion => explosion.Apply(hit))
} }
}
}; };
} }

View File

@ -41,12 +41,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default
Children = new[] Children = new[]
{ {
new CircularContainer new Circle { RelativeSizeAxes = Axes.Both }
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Children = new[] { new Box { RelativeSizeAxes = Axes.Both } }
}
}; };
} }
} }

View File

@ -1,9 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -12,19 +9,19 @@ using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.UI;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.Skinning.Default
{ {
internal class DefaultHitExplosion : CircularContainer, IAnimatableHitExplosion internal class DefaultHitExplosion : CircularContainer, IAnimatableHitExplosion
{ {
private readonly HitResult result; private readonly HitResult result;
[CanBeNull] private Box? body;
private Box body;
[Resolved] [Resolved]
private OsuColour colours { get; set; } private OsuColour colours { get; set; } = null!;
public DefaultHitExplosion(HitResult result) public DefaultHitExplosion(HitResult result)
{ {
@ -58,7 +55,7 @@ namespace osu.Game.Rulesets.Taiko.UI
updateColour(); updateColour();
} }
private void updateColour([CanBeNull] DrawableHitObject judgedObject = null) private void updateColour(DrawableHitObject? judgedObject = null)
{ {
if (body == null) if (body == null)
return; return;

View File

@ -0,0 +1,181 @@
// 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.
#nullable disable
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.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Screens.Ranking;
using osuTK;
namespace osu.Game.Rulesets.Taiko.Skinning.Default
{
public class DefaultInputDrum : AspectContainer
{
public DefaultInputDrum()
{
RelativeSizeAxes = Axes.Y;
}
[BackgroundDependencyLoader]
private void load()
{
const float middle_split = 0.025f;
InternalChild = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Scale = new Vector2(0.9f),
Children = new[]
{
new TaikoHalfDrum(false)
{
Name = "Left Half",
Anchor = Anchor.Centre,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.X,
X = -middle_split / 2,
RimAction = TaikoAction.LeftRim,
CentreAction = TaikoAction.LeftCentre
},
new TaikoHalfDrum(true)
{
Name = "Right Half",
Anchor = Anchor.Centre,
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.X,
X = middle_split / 2,
RimAction = TaikoAction.RightRim,
CentreAction = TaikoAction.RightCentre
}
}
};
}
/// <summary>
/// A half-drum. Contains one centre and one rim hit.
/// </summary>
private class TaikoHalfDrum : Container, IKeyBindingHandler<TaikoAction>
{
/// <summary>
/// The key to be used for the rim of the half-drum.
/// </summary>
public TaikoAction RimAction;
/// <summary>
/// The key to be used for the centre of the half-drum.
/// </summary>
public TaikoAction CentreAction;
private readonly Sprite rim;
private readonly Sprite rimHit;
private readonly Sprite centre;
private readonly Sprite centreHit;
public TaikoHalfDrum(bool flipped)
{
Masking = true;
Children = new Drawable[]
{
rim = new Sprite
{
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both
},
rimHit = new Sprite
{
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Alpha = 0,
Blending = BlendingParameters.Additive,
},
centre = new Sprite
{
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.7f)
},
centreHit = new Sprite
{
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.7f),
Alpha = 0,
Blending = BlendingParameters.Additive
}
};
}
[BackgroundDependencyLoader]
private void load(TextureStore textures, OsuColour colours)
{
rim.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer");
rimHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer-hit");
centre.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner");
centreHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner-hit");
rimHit.Colour = colours.Blue;
centreHit.Colour = colours.Pink;
}
public bool OnPressed(KeyBindingPressEvent<TaikoAction> e)
{
Drawable target = null;
Drawable back = null;
if (e.Action == CentreAction)
{
target = centreHit;
back = centre;
}
else if (e.Action == RimAction)
{
target = rimHit;
back = rim;
}
if (target != null)
{
const float scale_amount = 0.05f;
const float alpha_amount = 0.5f;
const float down_time = 40;
const float up_time = 1000;
back.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint)
.Then()
.ScaleTo(1, up_time, Easing.OutQuint);
target.Animate(
t => t.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint),
t => t.FadeTo(Math.Min(target.Alpha + alpha_amount, 1), down_time, Easing.OutQuint)
).Then(
t => t.ScaleTo(1, up_time, Easing.OutQuint),
t => t.FadeOut(up_time, Easing.OutQuint)
);
}
return false;
}
public void OnReleased(KeyBindingReleaseEvent<TaikoAction> e)
{
}
}
}
}

View File

@ -1,9 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osuTK;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -11,8 +8,9 @@ using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osuTK;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.Skinning.Default
{ {
public class DefaultKiaiHitExplosion : CircularContainer public class DefaultKiaiHitExplosion : CircularContainer
{ {

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics; using osu.Game.Graphics;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Animations;
@ -19,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
{ {
public class LegacyCirclePiece : CompositeDrawable, IHasAccentColour public class LegacyCirclePiece : CompositeDrawable, IHasAccentColour
{ {
private Drawable backgroundLayer; private Drawable backgroundLayer = null!;
// required for editor blueprints (not sure why these circle pieces are zero size). // required for editor blueprints (not sure why these circle pieces are zero size).
public override Quad ScreenSpaceDrawQuad => backgroundLayer.ScreenSpaceDrawQuad; public override Quad ScreenSpaceDrawQuad => backgroundLayer.ScreenSpaceDrawQuad;
@ -32,7 +30,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(ISkinSource skin, DrawableHitObject drawableHitObject) private void load(ISkinSource skin, DrawableHitObject drawableHitObject)
{ {
Drawable getDrawableFor(string lookup) Drawable? getDrawableFor(string lookup)
{ {
const string normal_hit = "taikohit"; const string normal_hit = "taikohit";
const string big_hit = "taikobig"; const string big_hit = "taikobig";

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -28,11 +26,11 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
} }
} }
private LegacyCirclePiece headCircle; private LegacyCirclePiece headCircle = null!;
private Sprite body; private Sprite body = null!;
private Sprite tailCircle; private Sprite tailCircle = null!;
public LegacyDrumRoll() public LegacyDrumRoll()
{ {

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK.Graphics; using osuTK.Graphics;

View File

@ -1,9 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Animations;
@ -17,8 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
{ {
private readonly Drawable sprite; private readonly Drawable sprite;
[CanBeNull] private readonly Drawable? strongSprite;
private readonly Drawable strongSprite;
/// <summary> /// <summary>
/// Creates a new legacy hit explosion. /// Creates a new legacy hit explosion.
@ -29,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
/// </remarks> /// </remarks>
/// <param name="sprite">The normal legacy explosion sprite.</param> /// <param name="sprite">The normal legacy explosion sprite.</param>
/// <param name="strongSprite">The strong legacy explosion sprite.</param> /// <param name="strongSprite">The strong legacy explosion sprite.</param>
public LegacyHitExplosion(Drawable sprite, [CanBeNull] Drawable strongSprite = null) public LegacyHitExplosion(Drawable sprite, Drawable? strongSprite = null)
{ {
this.sprite = sprite; this.sprite = sprite;
this.strongSprite = strongSprite; this.strongSprite = strongSprite;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -20,9 +18,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
/// </summary> /// </summary>
internal class LegacyInputDrum : Container internal class LegacyInputDrum : Container
{ {
private Container content; private Container content = null!;
private LegacyHalfDrum left; private LegacyHalfDrum left = null!;
private LegacyHalfDrum right; private LegacyHalfDrum right = null!;
public LegacyInputDrum() public LegacyInputDrum()
{ {
@ -142,7 +140,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
public bool OnPressed(KeyBindingPressEvent<TaikoAction> e) public bool OnPressed(KeyBindingPressEvent<TaikoAction> e)
{ {
Drawable target = null; Drawable? target = null;
if (e.Action == CentreAction) if (e.Action == CentreAction)
{ {

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
@ -27,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
} }
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(GameplayState gameplayState) private void load(GameplayState? gameplayState)
{ {
if (gameplayState != null) if (gameplayState != null)
((IBindable<JudgementResult>)LastResult).BindTo(gameplayState.LastJudgementResult); ((IBindable<JudgementResult>)LastResult).BindTo(gameplayState.LastJudgementResult);
@ -91,8 +89,8 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
private class ScrollerSprite : CompositeDrawable private class ScrollerSprite : CompositeDrawable
{ {
private Sprite passingSprite; private Sprite passingSprite = null!;
private Sprite failingSprite; private Sprite failingSprite = null!;
private bool passing = true; private bool passing = true;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -15,7 +13,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
{ {
public class TaikoLegacyHitTarget : CompositeDrawable public class TaikoLegacyHitTarget : CompositeDrawable
{ {
private Container content; private Container content = null!;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(ISkinSource skin) private void load(ISkinSource skin)

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -16,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
{ {
public class TaikoLegacyPlayfieldBackgroundRight : BeatSyncedContainer public class TaikoLegacyPlayfieldBackgroundRight : BeatSyncedContainer
{ {
private Sprite kiai; private Sprite kiai = null!;
private bool kiaiDisplayed; private bool kiaiDisplayed;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Game.Skinning; using osu.Game.Skinning;
namespace osu.Game.Rulesets.Taiko namespace osu.Game.Rulesets.Taiko

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
namespace osu.Game.Rulesets.Taiko namespace osu.Game.Rulesets.Taiko
{ {
public enum TaikoSkinComponents public enum TaikoSkinComponents

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
@ -24,7 +22,8 @@ namespace osu.Game.Rulesets.Taiko.UI
public readonly Bindable<JudgementResult> LastResult; public readonly Bindable<JudgementResult> LastResult;
private readonly Dictionary<TaikoMascotAnimationState, TaikoMascotAnimation> animations; private readonly Dictionary<TaikoMascotAnimationState, TaikoMascotAnimation> animations;
private TaikoMascotAnimation currentAnimation;
private TaikoMascotAnimation? currentAnimation;
private bool lastObjectHit = true; private bool lastObjectHit = true;
private bool kiaiMode; private bool kiaiMode;
@ -40,7 +39,7 @@ namespace osu.Game.Rulesets.Taiko.UI
} }
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(GameplayState gameplayState) private void load(GameplayState? gameplayState)
{ {
InternalChildren = new[] InternalChildren = new[]
{ {

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;

View File

@ -1,10 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using JetBrains.Annotations;
using osuTK; using osuTK;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -13,6 +10,7 @@ using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Skinning.Default;
using osu.Game.Skinning; using osu.Game.Skinning;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
@ -29,10 +27,9 @@ namespace osu.Game.Rulesets.Taiko.UI
private double? secondHitTime; private double? secondHitTime;
[CanBeNull] public DrawableHitObject? JudgedObject;
public DrawableHitObject JudgedObject;
private SkinnableDrawable skinnable; private SkinnableDrawable skinnable = null!;
/// <summary> /// <summary>
/// This constructor only exists to meet the <c>new()</c> type constraint of <see cref="DrawablePool{T}"/>. /// This constructor only exists to meet the <c>new()</c> type constraint of <see cref="DrawablePool{T}"/>.
@ -62,7 +59,7 @@ namespace osu.Game.Rulesets.Taiko.UI
skinnable.OnSkinChanged += runAnimation; skinnable.OnSkinChanged += runAnimation;
} }
public void Apply([CanBeNull] DrawableHitObject drawableHitObject) public void Apply(DrawableHitObject? drawableHitObject)
{ {
JudgedObject = drawableHitObject; JudgedObject = drawableHitObject;
secondHitTime = null; secondHitTime = null;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Pooling;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI

View File

@ -1,20 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using osu.Framework.Allocation; 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.Graphics.Sprites; using osu.Game.Rulesets.Taiko.Skinning.Default;
using osu.Framework.Graphics.Textures;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Screens.Ranking;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
{ {
@ -23,8 +14,6 @@ namespace osu.Game.Rulesets.Taiko.UI
/// </summary> /// </summary>
internal class InputDrum : Container internal class InputDrum : Container
{ {
private const float middle_split = 0.025f;
public InputDrum() public InputDrum()
{ {
AutoSizeAxes = Axes.X; AutoSizeAxes = Axes.X;
@ -43,166 +32,5 @@ namespace osu.Game.Rulesets.Taiko.UI
}, },
}; };
} }
private class DefaultInputDrum : AspectContainer
{
public DefaultInputDrum()
{
RelativeSizeAxes = Axes.Y;
}
[BackgroundDependencyLoader]
private void load()
{
InternalChild = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Scale = new Vector2(0.9f),
Children = new[]
{
new TaikoHalfDrum(false)
{
Name = "Left Half",
Anchor = Anchor.Centre,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.X,
X = -middle_split / 2,
RimAction = TaikoAction.LeftRim,
CentreAction = TaikoAction.LeftCentre
},
new TaikoHalfDrum(true)
{
Name = "Right Half",
Anchor = Anchor.Centre,
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.X,
X = middle_split / 2,
RimAction = TaikoAction.RightRim,
CentreAction = TaikoAction.RightCentre
}
}
};
}
/// <summary>
/// A half-drum. Contains one centre and one rim hit.
/// </summary>
private class TaikoHalfDrum : Container, IKeyBindingHandler<TaikoAction>
{
/// <summary>
/// The key to be used for the rim of the half-drum.
/// </summary>
public TaikoAction RimAction;
/// <summary>
/// The key to be used for the centre of the half-drum.
/// </summary>
public TaikoAction CentreAction;
private readonly Sprite rim;
private readonly Sprite rimHit;
private readonly Sprite centre;
private readonly Sprite centreHit;
public TaikoHalfDrum(bool flipped)
{
Masking = true;
Children = new Drawable[]
{
rim = new Sprite
{
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both
},
rimHit = new Sprite
{
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Alpha = 0,
Blending = BlendingParameters.Additive,
},
centre = new Sprite
{
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.7f)
},
centreHit = new Sprite
{
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.7f),
Alpha = 0,
Blending = BlendingParameters.Additive
}
};
}
[BackgroundDependencyLoader]
private void load(TextureStore textures, OsuColour colours)
{
rim.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer");
rimHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer-hit");
centre.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner");
centreHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner-hit");
rimHit.Colour = colours.Blue;
centreHit.Colour = colours.Pink;
}
public bool OnPressed(KeyBindingPressEvent<TaikoAction> e)
{
Drawable target = null;
Drawable back = null;
if (e.Action == CentreAction)
{
target = centreHit;
back = centre;
}
else if (e.Action == RimAction)
{
target = rimHit;
back = rim;
}
if (target != null)
{
const float scale_amount = 0.05f;
const float alpha_amount = 0.5f;
const float down_time = 40;
const float up_time = 1000;
back.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint)
.Then()
.ScaleTo(1, up_time, Easing.OutQuint);
target.Animate(
t => t.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint),
t => t.FadeTo(Math.Min(target.Alpha + alpha_amount, 1), down_time, Easing.OutQuint)
).Then(
t => t.ScaleTo(1, up_time, Easing.OutQuint),
t => t.FadeOut(up_time, Easing.OutQuint)
);
}
return false;
}
public void OnReleased(KeyBindingReleaseEvent<TaikoAction> e)
{
}
}
}
} }
} }

View File

@ -1,13 +1,12 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Skinning.Default;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK; using osuTK;
@ -22,7 +21,7 @@ namespace osu.Game.Rulesets.Taiko.UI
private readonly HitType hitType; private readonly HitType hitType;
private SkinnableDrawable skinnable; private SkinnableDrawable skinnable = null!;
public override double LifetimeStart => skinnable.Drawable.LifetimeStart; public override double LifetimeStart => skinnable.Drawable.LifetimeStart;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Graphics; using osu.Framework.Graphics;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
@ -89,7 +87,7 @@ namespace osu.Game.Rulesets.Taiko.UI
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(ISkinSource source) private void load(ISkinSource source)
{ {
ISkin skin = source.FindProvider(s => getAnimationFrame(s, state, 0) != null); ISkin? skin = source.FindProvider(s => getAnimationFrame(s, state, 0) != null);
if (skin == null) return; if (skin == null) return;
@ -120,7 +118,7 @@ namespace osu.Game.Rulesets.Taiko.UI
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(ISkinSource source) private void load(ISkinSource source)
{ {
ISkin skin = source.FindProvider(s => getAnimationFrame(s, TaikoMascotAnimationState.Clear, 0) != null); ISkin? skin = source.FindProvider(s => getAnimationFrame(s, TaikoMascotAnimationState.Clear, 0) != null);
if (skin == null) return; if (skin == null) return;
@ -137,7 +135,7 @@ namespace osu.Game.Rulesets.Taiko.UI
} }
} }
private static Texture getAnimationFrame(ISkin skin, TaikoMascotAnimationState state, int frameIndex) private static Texture? getAnimationFrame(ISkin skin, TaikoMascotAnimationState state, int frameIndex)
{ {
var texture = skin.GetTexture($"pippidon{state.ToString().ToLowerInvariant()}{frameIndex}"); var texture = skin.GetTexture($"pippidon{state.ToString().ToLowerInvariant()}{frameIndex}");

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
{ {
public enum TaikoMascotAnimationState public enum TaikoMascotAnimationState

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Rulesets.Taiko.Replays;

View File

@ -59,8 +59,9 @@ namespace osu.Game.Tests.Visual.Beatmaps
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(25f, 50f),
Scale = new Vector2(2f),
State = { Value = DownloadState.NotDownloaded }, State = { Value = DownloadState.NotDownloaded },
Scale = new Vector2(2)
}; };
}); });
} }

View File

@ -37,7 +37,11 @@ namespace osu.Game.Tests.Visual.Beatmaps
beatmapSetInfo = CreateAPIBeatmapSet(Ruleset.Value); beatmapSetInfo = CreateAPIBeatmapSet(Ruleset.Value);
beatmapSetInfo.HasFavourited = favourited; beatmapSetInfo.HasFavourited = favourited;
}); });
AddStep("create button", () => Child = button = new FavouriteButton(beatmapSetInfo) { Scale = new Vector2(2) }); AddStep("create button", () => Child = button = new FavouriteButton(beatmapSetInfo)
{
Size = new Vector2(25f, 50f),
Scale = new Vector2(2f),
});
assertCorrectIcon(favourited); assertCorrectIcon(favourited);
AddAssert("correct tooltip text", () => button.TooltipText == (favourited ? BeatmapsetsStrings.ShowDetailsUnfavourite : BeatmapsetsStrings.ShowDetailsFavourite)); AddAssert("correct tooltip text", () => button.TooltipText == (favourited ? BeatmapsetsStrings.ShowDetailsUnfavourite : BeatmapsetsStrings.ShowDetailsFavourite));
@ -51,7 +55,11 @@ namespace osu.Game.Tests.Visual.Beatmaps
BeatmapFavouriteAction? lastRequestAction = null; BeatmapFavouriteAction? lastRequestAction = null;
AddStep("create beatmap set", () => beatmapSetInfo = CreateAPIBeatmapSet(Ruleset.Value)); AddStep("create beatmap set", () => beatmapSetInfo = CreateAPIBeatmapSet(Ruleset.Value));
AddStep("create button", () => Child = button = new FavouriteButton(beatmapSetInfo) { Scale = new Vector2(2) }); AddStep("create button", () => Child = button = new FavouriteButton(beatmapSetInfo)
{
Size = new Vector2(25f, 50f),
Scale = new Vector2(2f),
});
assertCorrectIcon(false); assertCorrectIcon(false);

View File

@ -93,6 +93,15 @@ namespace osu.Game.Tests.Visual.Gameplay
checkRequestCount(1); checkRequestCount(1);
} }
[Test]
public void TestAutomaticSkipActuatesOnce()
{
createTest();
AddStep("start automated skip", () => skip.SkipWhenReady());
AddUntilStep("wait for button disabled", () => !skip.IsButtonVisible);
checkRequestCount(1);
}
[Test] [Test]
public void TestClickOnlyActuatesOnce() public void TestClickOnlyActuatesOnce()
{ {
@ -110,6 +119,16 @@ namespace osu.Game.Tests.Visual.Gameplay
checkRequestCount(1); checkRequestCount(1);
} }
[Test]
public void TestAutomaticSkipActuatesMultipleTimes()
{
createTest();
AddStep("set increment lower", () => increment = 3000);
AddStep("start automated skip", () => skip.SkipWhenReady());
AddUntilStep("wait for button disabled", () => !skip.IsButtonVisible);
checkRequestCount(2);
}
[Test] [Test]
public void TestClickOnlyActuatesMultipleTimes() public void TestClickOnlyActuatesMultipleTimes()
{ {
@ -137,8 +156,11 @@ namespace osu.Game.Tests.Visual.Gameplay
checkRequestCount(0); checkRequestCount(0);
} }
private void checkRequestCount(int expected) => private void checkRequestCount(int expected)
AddAssert($"request count is {expected}", () => requestCount == expected); {
AddAssert($"skip count is {expected}", () => skip.SkipCount, () => Is.EqualTo(expected));
AddAssert($"request count is {expected}", () => requestCount, () => Is.EqualTo(expected));
}
private class TestSkipOverlay : SkipOverlay private class TestSkipOverlay : SkipOverlay
{ {

View File

@ -18,7 +18,7 @@ namespace osu.Game.Tournament.Models
public Bindable<int> Seed = new BindableInt public Bindable<int> Seed = new BindableInt
{ {
MinValue = 1, MinValue = 1,
MaxValue = 64 MaxValue = 256
}; };
} }
} }

View File

@ -17,7 +17,7 @@ namespace osu.Game.Tournament.Models
public Bindable<int> Seed = new BindableInt public Bindable<int> Seed = new BindableInt
{ {
MinValue = 1, MinValue = 1,
MaxValue = 64 MaxValue = 256
}; };
} }
} }

View File

@ -54,7 +54,7 @@ namespace osu.Game.Tournament.Models
public Bindable<int> LastYearPlacing = new BindableInt public Bindable<int> LastYearPlacing = new BindableInt
{ {
MinValue = 1, MinValue = 1,
MaxValue = 64 MaxValue = 256
}; };
[JsonProperty] [JsonProperty]

View File

@ -81,7 +81,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards
FavouriteState = { BindTarget = FavouriteState }, FavouriteState = { BindTarget = FavouriteState },
ButtonsCollapsedWidth = CORNER_RADIUS, ButtonsCollapsedWidth = CORNER_RADIUS,
ButtonsExpandedWidth = 30, ButtonsExpandedWidth = 30,
ButtonsPadding = new MarginPadding { Vertical = 35 },
Children = new Drawable[] Children = new Drawable[]
{ {
new FillFlowContainer new FillFlowContainer

View File

@ -82,7 +82,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards
FavouriteState = { BindTarget = FavouriteState }, FavouriteState = { BindTarget = FavouriteState },
ButtonsCollapsedWidth = CORNER_RADIUS, ButtonsCollapsedWidth = CORNER_RADIUS,
ButtonsExpandedWidth = 30, ButtonsExpandedWidth = 30,
ButtonsPadding = new MarginPadding { Vertical = 17.5f },
Children = new Drawable[] Children = new Drawable[]
{ {
new FillFlowContainer new FillFlowContainer

View File

@ -4,13 +4,16 @@
#nullable disable #nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Overlays; using osu.Game.Overlays;
using osuTK; using osuTK;
using osuTK.Graphics;
namespace osu.Game.Beatmaps.Drawables.Cards.Buttons namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
{ {
@ -59,6 +62,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private readonly Container content; private readonly Container content;
private readonly Box hover;
protected BeatmapCardIconButton() protected BeatmapCardIconButton()
{ {
@ -69,19 +73,27 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Masking = true, Masking = true,
CornerRadius = BeatmapCard.CORNER_RADIUS,
Scale = new Vector2(0.8f),
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Children = new Drawable[] Children = new Drawable[]
{ {
hover = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.White.Opacity(0.1f),
Blending = BlendingParameters.Additive,
},
Icon = new SpriteIcon Icon = new SpriteIcon
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre Anchor = Anchor.Centre,
} Scale = new Vector2(1.2f),
},
} }
}); });
Size = new Vector2(24);
IconSize = 12; IconSize = 12;
} }
@ -116,8 +128,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
{ {
bool isHovered = IsHovered && Enabled.Value; bool isHovered = IsHovered && Enabled.Value;
content.ScaleTo(isHovered ? 1.2f : 1, 500, Easing.OutQuint); hover.FadeTo(isHovered ? 1f : 0f, 500, Easing.OutQuint);
content.FadeColour(isHovered ? HoverColour : IdleColour, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); content.ScaleTo(isHovered ? 1 : 0.8f, 500, Easing.OutQuint);
Icon.FadeColour(isHovered ? HoverColour : IdleColour, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
} }
} }
} }

View File

@ -48,12 +48,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards
} }
} }
public MarginPadding ButtonsPadding
{
get => buttons.Padding;
set => buttons.Padding = value;
}
protected override Container<Drawable> Content => mainContent; protected override Container<Drawable> Content => mainContent;
private readonly Container background; private readonly Container background;
@ -86,9 +80,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
// workaround for masking artifacts at the top & bottom of card,
// which become especially visible on downloaded beatmaps (when the icon area has a lime background).
Padding = new MarginPadding { Vertical = 1 },
Child = new Box Child = new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -104,25 +95,34 @@ namespace osu.Game.Beatmaps.Drawables.Cards
Child = buttons = new Container<BeatmapCardIconButton> Child = buttons = new Container<BeatmapCardIconButton>
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
// Padding of 4 avoids touching the card borders when in the expanded (ie. showing difficulties) state.
// Left override allows the buttons to visually be wider and look better.
Padding = new MarginPadding(4) { Left = 2 },
Children = new BeatmapCardIconButton[] Children = new BeatmapCardIconButton[]
{ {
new FavouriteButton(beatmapSet) new FavouriteButton(beatmapSet)
{ {
Current = FavouriteState, Current = FavouriteState,
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.Both,
Height = 0.48f,
}, },
new DownloadButton(beatmapSet) new DownloadButton(beatmapSet)
{ {
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
State = { BindTarget = downloadTracker.State } State = { BindTarget = downloadTracker.State },
RelativeSizeAxes = Axes.Both,
Height = 0.48f,
}, },
new GoToBeatmapButton(beatmapSet) new GoToBeatmapButton(beatmapSet)
{ {
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
State = { BindTarget = downloadTracker.State } State = { BindTarget = downloadTracker.State },
RelativeSizeAxes = Axes.Both,
Height = 0.48f,
} }
} }
} }

View File

@ -57,15 +57,13 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
private void updateRelativeChildSize() private void updateRelativeChildSize()
{ {
// the track may not be loaded completely (only has a length once it is). // If the track is not loaded, assign a default sane length otherwise relative positioning becomes meaningless.
if (!beatmap.Value.Track.IsLoaded) double trackLength = beatmap.Value.Track.IsLoaded ? beatmap.Value.Track.Length : 60000;
{ content.RelativeChildSize = new Vector2((float)Math.Max(1, trackLength), 1);
content.RelativeChildSize = Vector2.One;
Schedule(updateRelativeChildSize);
return;
}
content.RelativeChildSize = new Vector2((float)Math.Max(1, beatmap.Value.Track.Length), 1); // The track may not be loaded completely (only has a length once it is).
if (!beatmap.Value.Track.IsLoaded)
Schedule(updateRelativeChildSize);
} }
protected virtual void LoadBeatmap(EditorBeatmap beatmap) protected virtual void LoadBeatmap(EditorBeatmap beatmap)

View File

@ -27,7 +27,7 @@ namespace osu.Game.Screens.Edit
private readonly Bindable<Track> track = new Bindable<Track>(); private readonly Bindable<Track> track = new Bindable<Track>();
public double TrackLength => track.Value?.Length ?? 60000; public double TrackLength => track.Value?.IsLoaded == true ? track.Value.Length : 60000;
public ControlPointInfo ControlPointInfo => Beatmap.ControlPointInfo; public ControlPointInfo ControlPointInfo => Beatmap.ControlPointInfo;

View File

@ -27,6 +27,11 @@ namespace osu.Game.Screens.Play
{ {
public class SkipOverlay : CompositeDrawable, IKeyBindingHandler<GlobalAction> public class SkipOverlay : CompositeDrawable, IKeyBindingHandler<GlobalAction>
{ {
/// <summary>
/// The total number of successful skips performed by this overlay.
/// </summary>
public int SkipCount { get; private set; }
private readonly double startTime; private readonly double startTime;
public Action RequestSkip; public Action RequestSkip;
@ -124,23 +129,36 @@ namespace osu.Game.Screens.Play
return; return;
} }
button.Action = () => RequestSkip?.Invoke(); button.Action = () =>
{
SkipCount++;
RequestSkip?.Invoke();
};
fadeContainer.TriggerShow(); fadeContainer.TriggerShow();
if (skipQueued)
{
Scheduler.AddDelayed(() => button.TriggerClick(), 200);
skipQueued = false;
}
} }
/// <summary>
/// Triggers an "automated" skip to happen as soon as available.
/// </summary>
public void SkipWhenReady() public void SkipWhenReady()
{ {
if (IsLoaded) if (skipQueued) return;
button.TriggerClick();
else
skipQueued = true; skipQueued = true;
attemptNextSkip();
void attemptNextSkip() => Scheduler.AddDelayed(() =>
{
if (!button.Enabled.Value)
{
skipQueued = false;
return;
}
button.TriggerClick();
attemptNextSkip();
}, 200);
} }
protected override void Update() protected override void Update()