1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 05:53:10 +08:00

Merge branch 'master' into mania-beatmap-conversion

This commit is contained in:
Dean Herbert 2017-05-19 18:18:59 +09:00 committed by GitHub
commit da31d129ee
12 changed files with 303 additions and 183 deletions

View File

@ -129,8 +129,6 @@ namespace osu.Desktop.VisualTests.Tests
}; };
Add(clockAdjustContainer); Add(clockAdjustContainer);
load(mode);
} }
private int depth; private int depth;

View File

@ -1,15 +1,16 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.MathUtils;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Game.Rulesets.Osu.UI; using osu.Game.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Allocation;
using osu.Game.Screens.Ranking;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -18,9 +19,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private readonly Spinner spinner; private readonly Spinner spinner;
private readonly SpinnerDisc disc; private readonly SpinnerDisc disc;
private readonly SpinnerTicks ticks;
private readonly Container mainContainer;
private readonly SpinnerBackground background; private readonly SpinnerBackground background;
private readonly Container circleContainer; private readonly Container circleContainer;
private readonly DrawableHitCircle circle; private readonly CirclePiece circle;
private readonly GlowPiece glow;
private readonly TextAwesome symbol;
private Color4 normalColour;
private Color4 completeColour;
public DrawableSpinner(Spinner s) : base(s) public DrawableSpinner(Spinner s) : base(s)
{ {
@ -29,57 +40,91 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Origin = Anchor.Centre; Origin = Anchor.Centre;
Position = s.Position; Position = s.Position;
//take up full playfield. RelativeSizeAxes = Axes.Both;
Size = new Vector2(OsuPlayfield.BASE_SIZE.X);
// we are slightly bigger than our parent, to clip the top and bottom of the circle
Height = 1.3f;
spinner = s; spinner = s;
Children = new Drawable[] Children = new Drawable[]
{ {
background = new SpinnerBackground
{
Alpha = 0,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
DiscColour = Color4.Black
},
disc = new SpinnerDisc
{
Alpha = 0,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
DiscColour = AccentColour
},
circleContainer = new Container circleContainer = new Container
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Children = new [] Children = new Drawable[]
{ {
circle = new DrawableHitCircle(s) glow = new GlowPiece(),
circle = new CirclePiece
{ {
Interactive = false,
Position = Vector2.Zero, Position = Vector2.Zero,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
} },
new RingPiece(),
symbol = new TextAwesome
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
UseFullGlyphHeight = true,
TextSize = 48,
Icon = FontAwesome.fa_asterisk,
Shadow = false,
},
} }
} },
mainContainer = new AspectContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Children = new Drawable[]
{
background = new SpinnerBackground
{
Alpha = 0.6f,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
disc = new SpinnerDisc(spinner)
{
Scale = Vector2.Zero,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
circleContainer.CreateProxy(),
ticks = new SpinnerTicks
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
}
},
}; };
background.Scale = scaleToCircle;
disc.Scale = scaleToCircle;
} }
public float Progress => MathHelper.Clamp(disc.RotationAbsolute / 360 / spinner.SpinsRequired, 0, 1);
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {
if (Time.Current < HitObject.StartTime) return; if (Time.Current < HitObject.StartTime) return;
disc.ScaleTo(Interpolation.ValueAt(Math.Sqrt(Progress), scaleToCircle, Vector2.One, 0, 1), 100); if (Progress >= 1 && !disc.Complete)
{
if (Progress >= 1)
disc.Complete = true; disc.Complete = true;
const float duration = 200;
disc.FadeAccent(completeColour, duration);
background.FadeAccent(completeColour, duration);
background.FadeOut(duration);
circle.FadeColour(completeColour, duration);
glow.FadeColour(completeColour, duration);
}
if (!userTriggered && Time.Current >= spinner.EndTime) if (!userTriggered && Time.Current >= spinner.EndTime)
{ {
if (Progress >= 1) if (Progress >= 1)
@ -106,26 +151,48 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
} }
} }
private Vector2 scaleToCircle => circle.Scale * circle.DrawWidth / DrawWidth * 0.95f; [BackgroundDependencyLoader]
private void load(OsuColour colours)
{
normalColour = colours.SpinnerBase;
public float Progress => MathHelper.Clamp(disc.RotationAbsolute / 360 / spinner.SpinsRequired, 0, 1); background.AccentColour = normalColour;
completeColour = colours.YellowLight.Opacity(0.6f);
disc.AccentColour = colours.SpinnerFill;
circle.Colour = colours.BlueDark;
glow.Colour = colours.BlueDark;
}
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
circle.Rotation = disc.Rotation;
ticks.Rotation = disc.Rotation;
float relativeCircleScale = spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight;
disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, EasingTypes.OutQuint);
symbol.RotateTo(disc.Rotation / 2, 500, EasingTypes.OutQuint);
}
protected override void UpdatePreemptState() protected override void UpdatePreemptState()
{ {
base.UpdatePreemptState(); base.UpdatePreemptState();
circleContainer.ScaleTo(1, 400, EasingTypes.OutElastic); circleContainer.ScaleTo(spinner.Scale * 0.3f);
circleContainer.ScaleTo(spinner.Scale, TIME_PREEMPT / 1.4f, EasingTypes.OutQuint);
background.Delay(TIME_PREEMPT - 500); disc.RotateTo(-720);
symbol.RotateTo(-720);
background.ScaleTo(scaleToCircle * 1.2f, 400, EasingTypes.OutQuint); mainContainer.ScaleTo(0);
background.FadeIn(200); mainContainer.ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, TIME_PREEMPT - 150, EasingTypes.OutQuint);
background.Delay(400); mainContainer.Delay(TIME_PREEMPT - 150);
background.ScaleTo(1, 250, EasingTypes.OutQuint); mainContainer.ScaleTo(1, 500, EasingTypes.OutQuint);
disc.Delay(TIME_PREEMPT - 50);
disc.FadeIn(200);
} }
protected override void UpdateCurrentState(ArmedState state) protected override void UpdateCurrentState(ArmedState state)

View File

@ -16,7 +16,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
private readonly Sprite disc; private readonly Sprite disc;
public Func<bool> Hit; public Func<bool> Hit;
public CirclePiece() public CirclePiece()

View File

@ -1,10 +1,55 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
public class SpinnerBackground : SpinnerDisc public class SpinnerBackground : CircularContainer, IHasAccentColour
{ {
public override bool HandleInput => false; public override bool HandleInput => false;
protected Box Disc;
public Color4 AccentColour
{
get
{
return Disc.Colour;
}
set
{
Disc.Colour = value;
EdgeEffect = new EdgeEffect
{
Type = EdgeEffectType.Glow,
Radius = 14,
Colour = value.Opacity(0.3f),
};
}
}
public SpinnerBackground()
{
RelativeSizeAxes = Axes.Both;
Masking = true;
Children = new Drawable[]
{
Disc = new Box
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Alpha = 1,
},
};
}
} }
} }

View File

@ -2,13 +2,8 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transforms; using osu.Framework.Graphics.Transforms;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -17,104 +12,31 @@ using OpenTK.Graphics;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
public class SpinnerDisc : CircularContainer public class SpinnerDisc : CircularContainer, IHasAccentColour
{ {
protected Sprite Disc; private readonly Spinner spinner;
public SRGBColour DiscColour public Color4 AccentColour
{ {
get { return Disc.Colour; } get { return background.AccentColour; }
set { Disc.Colour = value; } set { background.AccentColour = value; }
} }
private Color4 completeColour; private readonly SpinnerBackground background;
[BackgroundDependencyLoader] private const float idle_alpha = 0.2f;
private void load(OsuColour colours) private const float tracking_alpha = 0.4f;
public SpinnerDisc(Spinner s)
{ {
completeColour = colours.YellowLight.Opacity(0.8f); spinner = s;
Masking = true;
}
private class SpinnerBorder : Container
{
public SpinnerBorder()
{
Origin = Anchor.Centre;
Anchor = Anchor.Centre;
RelativeSizeAxes = Axes.Both;
layout();
}
private int lastLayoutDotCount;
private void layout()
{
int count = (int)(MathHelper.Pi * ScreenSpaceDrawQuad.Width / 9);
if (count == lastLayoutDotCount) return;
lastLayoutDotCount = count;
while (Children.Count() < count)
{
Add(new CircularContainer
{
Colour = Color4.White,
RelativePositionAxes = Axes.Both,
Masking = true,
Origin = Anchor.Centre,
Size = new Vector2(1 / ScreenSpaceDrawQuad.Width * 2000),
Children = new[]
{
new Box
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
}
}
});
}
var size = new Vector2(1 / ScreenSpaceDrawQuad.Width * 2000);
int i = 0;
foreach (var d in Children)
{
d.Size = size;
d.Position = new Vector2(
0.5f + (float)Math.Sin((float)i / count * 2 * MathHelper.Pi) / 2,
0.5f + (float)Math.Cos((float)i / count * 2 * MathHelper.Pi) / 2
);
i++;
}
}
protected override void Update()
{
base.Update();
layout();
}
}
public SpinnerDisc()
{
AlwaysReceiveInput = true; AlwaysReceiveInput = true;
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Children = new Drawable[] Children = new Drawable[]
{ {
Disc = new Box background = new SpinnerBackground { Alpha = idle_alpha },
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Alpha = 0.2f,
},
new SpinnerBorder()
}; };
} }
@ -125,10 +47,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
set set
{ {
if (value == tracking) return; if (value == tracking) return;
tracking = value; tracking = value;
Disc.FadeTo(tracking ? 0.5f : 0.2f, 100); background.FadeTo(tracking ? tracking_alpha : idle_alpha, 100);
} }
} }
@ -139,31 +60,28 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
set set
{ {
if (value == complete) return; if (value == complete) return;
complete = value; complete = value;
Disc.FadeColour(completeColour, 200);
updateCompleteTick(); updateCompleteTick();
} }
} }
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{ {
Tracking = true; Tracking |= state.Mouse.HasMainButtonPressed;
return base.OnMouseDown(state, args); return base.OnMouseDown(state, args);
} }
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
{ {
Tracking = false; Tracking &= state.Mouse.HasMainButtonPressed;
return base.OnMouseUp(state, args); return base.OnMouseUp(state, args);
} }
protected override bool OnMouseMove(InputState state) protected override bool OnMouseMove(InputState state)
{ {
Tracking |= state.Mouse.HasMainButtonPressed; Tracking |= state.Mouse.HasMainButtonPressed;
mousePosition = state.Mouse.Position; mousePosition = Parent.ToLocalSpace(state.Mouse.NativeState.Position);
return base.OnMouseMove(state); return base.OnMouseMove(state);
} }
@ -177,13 +95,24 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360)); private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360));
private bool rotationTransferred;
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
var thisAngle = -(float)MathHelper.RadiansToDegrees(Math.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2)); var thisAngle = -(float)MathHelper.RadiansToDegrees(Math.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2));
if (tracking)
bool validAndTracking = tracking && spinner.StartTime <= Time.Current && spinner.EndTime > Time.Current;
if (validAndTracking)
{ {
if (!rotationTransferred)
{
currentRotation = Rotation * 2;
rotationTransferred = true;
}
if (thisAngle - lastAngle > 180) if (thisAngle - lastAngle > 180)
lastAngle += 360; lastAngle += 360;
else if (lastAngle - thisAngle > 180) else if (lastAngle - thisAngle > 180)
@ -192,17 +121,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
currentRotation += thisAngle - lastAngle; currentRotation += thisAngle - lastAngle;
RotationAbsolute += Math.Abs(thisAngle - lastAngle); RotationAbsolute += Math.Abs(thisAngle - lastAngle);
} }
lastAngle = thisAngle; lastAngle = thisAngle;
if (Complete && updateCompleteTick()) if (Complete && updateCompleteTick())
{ {
Disc.Flush(flushType: typeof(TransformAlpha)); background.Flush(flushType: typeof(TransformAlpha));
Disc.FadeTo(0.75f, 30, EasingTypes.OutExpo); background.FadeTo(tracking_alpha + 0.4f, 60, EasingTypes.OutExpo);
Disc.Delay(30); background.Delay(60);
Disc.FadeTo(0.5f, 250, EasingTypes.OutQuint); background.FadeTo(tracking_alpha, 250, EasingTypes.OutQuint);
} }
RotateTo(currentRotation, 100, EasingTypes.OutExpo); RotateTo(currentRotation / 2, validAndTracking ? 500 : 1500, EasingTypes.OutExpo);
} }
} }
} }

View File

@ -0,0 +1,71 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public class SpinnerTicks : Container
{
private Color4 glowColour;
public SpinnerTicks()
{
Origin = Anchor.Centre;
Anchor = Anchor.Centre;
RelativeSizeAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
glowColour = colours.BlueDarker.Opacity(0.4f);
layout();
}
private void layout()
{
const int count = 18;
for (int i = 0; i < count; i++)
{
Add(new Container
{
Colour = Color4.Black,
Alpha = 0.4f,
EdgeEffect = new EdgeEffect
{
Type = EdgeEffectType.Glow,
Radius = 20,
Colour = glowColour,
},
RelativePositionAxes = Axes.Both,
Masking = true,
CornerRadius = 5,
Size = new Vector2(60, 10),
Origin = Anchor.Centre,
Position = new Vector2(
0.5f + (float)Math.Sin((float)i / count * 2 * MathHelper.Pi) / 2 * 0.86f,
0.5f + (float)Math.Cos((float)i / count * 2 * MathHelper.Pi) / 2 * 0.86f
),
Rotation = -(float)i / count * 360 + 90,
Children = new[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
}
}
});
}
}
}
}

View File

@ -91,25 +91,25 @@ namespace osu.Game.Rulesets.Osu.Replays
// Make the cursor stay at a hitObject as long as possible (mainly for autopilot). // Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50) if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
{ {
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), prev.EndPosition.X, prev.EndPosition.Y, ReplayButtonState.None)); if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.Position.X, h.Position.Y, ReplayButtonState.None)); if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
} }
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50) else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
{ {
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), prev.EndPosition.X, prev.EndPosition.Y, ReplayButtonState.None)); if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.Position.X, h.Position.Y, ReplayButtonState.None)); if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
} }
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > endTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50) else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > endTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50)
{ {
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), prev.EndPosition.X, prev.EndPosition.Y, ReplayButtonState.None)); if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.Position.X, h.Position.Y, ReplayButtonState.None)); if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
} }
} }
private void addHitObjectReplay(OsuHitObject h) private void addHitObjectReplay(OsuHitObject h)
{ {
// Default values for circles/sliders // Default values for circles/sliders
Vector2 startPosition = h.Position; Vector2 startPosition = h.StackedPosition;
EasingTypes easing = preferredEasing; EasingTypes easing = preferredEasing;
float spinnerDirection = -1; float spinnerDirection = -1;
@ -238,7 +238,7 @@ namespace osu.Game.Rulesets.Osu.Replays
// TODO: Why do we delay 1 ms if the object is a spinner? There already is KEY_UP_DELAY from hEndTime. // TODO: Why do we delay 1 ms if the object is a spinner? There already is KEY_UP_DELAY from hEndTime.
double hEndTime = ((h as IHasEndTime)?.EndTime ?? h.StartTime) + KEY_UP_DELAY; double hEndTime = ((h as IHasEndTime)?.EndTime ?? h.StartTime) + KEY_UP_DELAY;
int endDelay = h is Spinner ? 1 : 0; int endDelay = h is Spinner ? 1 : 0;
ReplayFrame endFrame = new ReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, ReplayButtonState.None); ReplayFrame endFrame = new ReplayFrame(hEndTime + endDelay, h.StackedEndPosition.X, h.StackedEndPosition.Y, ReplayButtonState.None);
// Decrement because we want the previous frame, not the next one // Decrement because we want the previous frame, not the next one
int index = FindInsertionIndex(startFrame) - 1; int index = FindInsertionIndex(startFrame) - 1;

View File

@ -64,6 +64,7 @@
<Compile Include="Objects\Drawables\Pieces\RingPiece.cs" /> <Compile Include="Objects\Drawables\Pieces\RingPiece.cs" />
<Compile Include="Objects\Drawables\Pieces\SliderBouncer.cs" /> <Compile Include="Objects\Drawables\Pieces\SliderBouncer.cs" />
<Compile Include="Objects\Drawables\Pieces\SpinnerDisc.cs" /> <Compile Include="Objects\Drawables\Pieces\SpinnerDisc.cs" />
<Compile Include="Objects\Drawables\Pieces\SpinnerTicks.cs" />
<Compile Include="Objects\Drawables\Pieces\TrianglesPiece.cs" /> <Compile Include="Objects\Drawables\Pieces\TrianglesPiece.cs" />
<Compile Include="Objects\Drawables\Pieces\SliderBall.cs" /> <Compile Include="Objects\Drawables\Pieces\SliderBall.cs" />
<Compile Include="Objects\Drawables\Pieces\SliderBody.cs" /> <Compile Include="Objects\Drawables\Pieces\SliderBody.cs" />
@ -103,9 +104,7 @@
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<ItemGroup> <ItemGroup />
<Folder Include="Replays\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -26,6 +26,7 @@ namespace osu.Game.Database
public string[] SearchableTerms => new[] public string[] SearchableTerms => new[]
{ {
Author,
Artist, Artist,
ArtistUnicode, ArtistUnicode,
Title, Title,

View File

@ -87,5 +87,8 @@ namespace osu.Game.Graphics
public readonly Color4 RedDarker = FromHex(@"870000"); public readonly Color4 RedDarker = FromHex(@"870000");
public readonly Color4 ChatBlue = FromHex(@"17292e"); public readonly Color4 ChatBlue = FromHex(@"17292e");
public readonly Color4 SpinnerBase = FromHex(@"002c3c");
public readonly Color4 SpinnerFill = FromHex(@"005b7c");
} }
} }

View File

@ -241,8 +241,8 @@ namespace osu.Game.Screens.Play
skipButton.Action = null; skipButton.Action = null;
}; };
skipButton.Delay(firstHitObject - skip_required_cutoff - fade_time); using (skipButton.BeginDelayedSequence(firstHitObject - skip_required_cutoff - fade_time))
skipButton.FadeOut(fade_time); skipButton.FadeOut(fade_time);
skipButton.Expire(); skipButton.Expire();
} }
@ -263,18 +263,20 @@ namespace osu.Game.Screens.Play
ValidForResume = false; ValidForResume = false;
Delay(1000); using (BeginDelayedSequence(1000))
onCompletionEvent = Schedule(delegate
{ {
var score = new Score onCompletionEvent = Schedule(delegate
{ {
Beatmap = Beatmap.BeatmapInfo, var score = new Score
Ruleset = ruleset {
}; Beatmap = Beatmap.BeatmapInfo,
scoreProcessor.PopulateScore(score); Ruleset = ruleset
score.User = HitRenderer.Replay?.User ?? (Game as OsuGame)?.API?.LocalUser?.Value; };
Push(new Results(score)); scoreProcessor.PopulateScore(score);
}); score.User = HitRenderer.Replay?.User ?? (Game as OsuGame)?.API?.LocalUser?.Value;
Push(new Results(score));
});
}
} }
private void onFail() private void onFail()
@ -299,17 +301,19 @@ namespace osu.Game.Screens.Play
Content.ScaleTo(0.7f); Content.ScaleTo(0.7f);
Content.Delay(250); using (Content.BeginDelayedSequence(250))
Content.FadeIn(250); Content.FadeIn(250);
Content.ScaleTo(1, 750, EasingTypes.OutQuint); Content.ScaleTo(1, 750, EasingTypes.OutQuint);
Delay(750); using (BeginDelayedSequence(750))
Schedule(() => Schedule(() =>
{ {
decoupledClock.Start(); if (!pauseContainer.IsPaused)
initializeSkipButton(); decoupledClock.Start();
});
initializeSkipButton();
});
pauseContainer.Alpha = 0; pauseContainer.Alpha = 0;
pauseContainer.FadeIn(750, EasingTypes.OutQuint); pauseContainer.FadeIn(750, EasingTypes.OutQuint);

View File

@ -198,8 +198,11 @@ namespace osu.Game.Screens.Select
var pendingSelection = selectionChangedDebounce; var pendingSelection = selectionChangedDebounce;
selectionChangedDebounce = null; selectionChangedDebounce = null;
pendingSelection?.RunTask(); if (pendingSelection?.Completed == false)
pendingSelection?.Cancel(); // cancel the already scheduled task. {
pendingSelection?.RunTask();
pendingSelection?.Cancel(); // cancel the already scheduled task.
}
if (Beatmap == null) return; if (Beatmap == null) return;