mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 18:53:21 +08:00
Merge branch 'editor-waveform' into editor-waveform-timeline
# Conflicts: # osu.Game/osu.Game.csproj
This commit is contained in:
commit
cb58a1371e
@ -1 +1 @@
|
|||||||
Subproject commit 9d142a8e009794dfee828392e36025d08577131d
|
Subproject commit 65416c914b34590699cf09f6b7d298fa26806f3b
|
@ -10,6 +10,10 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestCaseCatchPlayer : Game.Tests.Visual.TestCasePlayer
|
public class TestCaseCatchPlayer : Game.Tests.Visual.TestCasePlayer
|
||||||
{
|
{
|
||||||
|
public TestCaseCatchPlayer() : base(typeof(CatchRuleset))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected override Beatmap CreateBeatmap()
|
protected override Beatmap CreateBeatmap()
|
||||||
{
|
{
|
||||||
var beatmap = new Beatmap();
|
var beatmap = new Beatmap();
|
||||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(CatcherArea),
|
typeof(Catcher),
|
||||||
};
|
};
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
new CatchInputManager(rulesets.GetRuleset(2))
|
new CatchInputManager(rulesets.GetRuleset(2))
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = new CatcherArea
|
Child = new Catcher
|
||||||
{
|
{
|
||||||
RelativePositionAxes = Axes.Both,
|
RelativePositionAxes = Axes.Both,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
// 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.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -15,11 +17,15 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
private readonly Container<Drawable> content;
|
private readonly Container<Drawable> content;
|
||||||
private readonly CatcherArea catcherArea;
|
|
||||||
|
private readonly Container catcherContainer;
|
||||||
|
private readonly Catcher catcher;
|
||||||
|
|
||||||
public CatchPlayfield()
|
public CatchPlayfield()
|
||||||
: base(Axes.Y)
|
: base(Axes.Y)
|
||||||
{
|
{
|
||||||
|
Container explodingFruitContainer;
|
||||||
|
|
||||||
Reversed.Value = true;
|
Reversed.Value = true;
|
||||||
|
|
||||||
Size = new Vector2(1);
|
Size = new Vector2(1);
|
||||||
@ -33,16 +39,35 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
catcherArea = new CatcherArea
|
explodingFruitContainer = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
catcherContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.TopLeft,
|
Origin = Anchor.TopLeft,
|
||||||
Height = 0.3f
|
Height = 180,
|
||||||
|
Child = catcher = new Catcher
|
||||||
|
{
|
||||||
|
ExplodingFruitTarget = explodingFruitContainer,
|
||||||
|
RelativePositionAxes = Axes.Both,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
X = 0.5f,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
catcher.Size = new Vector2(catcherContainer.DrawSize.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckIfWeCanCatch(CatchBaseHit obj) => Math.Abs(catcher.Position.X - obj.X) < catcher.DrawSize.X / DrawSize.X / 2;
|
||||||
|
|
||||||
public override void Add(DrawableHitObject h)
|
public override void Add(DrawableHitObject h)
|
||||||
{
|
{
|
||||||
h.Depth = (float)h.HitObject.StartTime;
|
h.Depth = (float)h.HitObject.StartTime;
|
||||||
@ -50,7 +75,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
base.Add(h);
|
base.Add(h);
|
||||||
|
|
||||||
var fruit = (DrawableFruit)h;
|
var fruit = (DrawableFruit)h;
|
||||||
fruit.CheckPosition = catcherArea.CheckIfWeCanCatch;
|
fruit.CheckPosition = CheckIfWeCanCatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||||
@ -59,7 +84,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre;
|
Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre;
|
||||||
Remove(judgedObject);
|
Remove(judgedObject);
|
||||||
catcherArea.Add(judgedObject, screenPosition);
|
catcher.Add(judgedObject, screenPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
193
osu.Game.Rulesets.Catch/UI/Catcher.cs
Normal file
193
osu.Game.Rulesets.Catch/UI/Catcher.cs
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
// 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 System.Linq;
|
||||||
|
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.MathUtils;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.UI
|
||||||
|
{
|
||||||
|
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
||||||
|
{
|
||||||
|
private Texture texture;
|
||||||
|
|
||||||
|
private Container<DrawableHitObject> caughtFruit;
|
||||||
|
|
||||||
|
public Container ExplodingFruitTarget;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(TextureStore textures)
|
||||||
|
{
|
||||||
|
texture = textures.Get(@"Play/Catch/fruit-catcher-idle");
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
createCatcherSprite(),
|
||||||
|
caughtFruit = new Container<DrawableHitObject>
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private int currentDirection;
|
||||||
|
|
||||||
|
private bool dashing;
|
||||||
|
|
||||||
|
protected bool Dashing
|
||||||
|
{
|
||||||
|
get { return dashing; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == dashing) return;
|
||||||
|
|
||||||
|
dashing = value;
|
||||||
|
|
||||||
|
if (dashing)
|
||||||
|
Schedule(addAdditiveSprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAdditiveSprite()
|
||||||
|
{
|
||||||
|
if (!dashing) return;
|
||||||
|
|
||||||
|
var additive = createCatcherSprite();
|
||||||
|
|
||||||
|
additive.RelativePositionAxes = Axes.Both;
|
||||||
|
additive.Blending = BlendingMode.Additive;
|
||||||
|
additive.Position = Position;
|
||||||
|
additive.Scale = Scale;
|
||||||
|
|
||||||
|
((Container)Parent).Add(additive);
|
||||||
|
|
||||||
|
additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire();
|
||||||
|
|
||||||
|
Scheduler.AddDelayed(addAdditiveSprite, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sprite createCatcherSprite() => new Sprite
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
Texture = texture,
|
||||||
|
OriginPosition = new Vector2(DrawWidth / 2, 10) //temporary until the sprite is aligned correctly.
|
||||||
|
};
|
||||||
|
|
||||||
|
public bool OnPressed(CatchAction action)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case CatchAction.MoveLeft:
|
||||||
|
currentDirection--;
|
||||||
|
return true;
|
||||||
|
case CatchAction.MoveRight:
|
||||||
|
currentDirection++;
|
||||||
|
return true;
|
||||||
|
case CatchAction.Dash:
|
||||||
|
Dashing = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnReleased(CatchAction action)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case CatchAction.MoveLeft:
|
||||||
|
currentDirection++;
|
||||||
|
return true;
|
||||||
|
case CatchAction.MoveRight:
|
||||||
|
currentDirection--;
|
||||||
|
return true;
|
||||||
|
case CatchAction.Dash:
|
||||||
|
Dashing = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable.
|
||||||
|
/// </summary>
|
||||||
|
private const double base_speed = 1.0 / 512;
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (currentDirection == 0) return;
|
||||||
|
|
||||||
|
double dashModifier = Dashing ? 1 : 0.5;
|
||||||
|
|
||||||
|
Scale = new Vector2(Math.Sign(currentDirection), 1);
|
||||||
|
X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime * base_speed * dashModifier, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(DrawableHitObject fruit, Vector2 absolutePosition)
|
||||||
|
{
|
||||||
|
fruit.RelativePositionAxes = Axes.None;
|
||||||
|
fruit.Position = new Vector2(ToLocalSpace(absolutePosition).X - DrawSize.X / 2, 0);
|
||||||
|
|
||||||
|
fruit.Anchor = Anchor.TopCentre;
|
||||||
|
fruit.Origin = Anchor.BottomCentre;
|
||||||
|
fruit.Scale *= 0.7f;
|
||||||
|
fruit.LifetimeEnd = double.MaxValue;
|
||||||
|
|
||||||
|
float distance = fruit.DrawSize.X / 2 * fruit.Scale.X;
|
||||||
|
|
||||||
|
while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance))
|
||||||
|
{
|
||||||
|
fruit.X += RNG.Next(-5, 5);
|
||||||
|
fruit.Y -= RNG.Next(0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
caughtFruit.Add(fruit);
|
||||||
|
|
||||||
|
if (((CatchBaseHit)fruit.HitObject).LastInCombo)
|
||||||
|
explode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void explode()
|
||||||
|
{
|
||||||
|
var fruit = caughtFruit.ToArray();
|
||||||
|
|
||||||
|
foreach (var f in fruit)
|
||||||
|
{
|
||||||
|
var originalX = f.X * Scale.X;
|
||||||
|
|
||||||
|
if (ExplodingFruitTarget != null)
|
||||||
|
{
|
||||||
|
f.Anchor = Anchor.TopLeft;
|
||||||
|
f.Position = caughtFruit.ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget);
|
||||||
|
|
||||||
|
caughtFruit.Remove(f);
|
||||||
|
|
||||||
|
ExplodingFruitTarget.Add(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
f.MoveToY(f.Y - 50, 250, Easing.OutSine)
|
||||||
|
.Then()
|
||||||
|
.MoveToY(f.Y + 50, 500, Easing.InSine);
|
||||||
|
|
||||||
|
f.MoveToX(f.X + originalX * 6, 1000);
|
||||||
|
f.FadeOut(750);
|
||||||
|
|
||||||
|
f.Expire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,229 +0,0 @@
|
|||||||
// 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 System.Linq;
|
|
||||||
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.MathUtils;
|
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
|
||||||
using OpenTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.UI
|
|
||||||
{
|
|
||||||
public class CatcherArea : Container
|
|
||||||
{
|
|
||||||
private Catcher catcher;
|
|
||||||
private Container explodingFruitContainer;
|
|
||||||
|
|
||||||
public void Add(DrawableHitObject fruit, Vector2 screenPosition) => catcher.AddToStack(fruit, screenPosition);
|
|
||||||
|
|
||||||
public bool CheckIfWeCanCatch(CatchBaseHit obj) => Math.Abs(catcher.Position.X - obj.X) < catcher.DrawSize.X / DrawSize.X / 2;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
explodingFruitContainer = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
catcher = new Catcher
|
|
||||||
{
|
|
||||||
RelativePositionAxes = Axes.Both,
|
|
||||||
ExplodingFruitTarget = explodingFruitContainer,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
X = 0.5f,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
catcher.Size = new Vector2(DrawSize.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Catcher : Container, IKeyBindingHandler<CatchAction>
|
|
||||||
{
|
|
||||||
private Texture texture;
|
|
||||||
|
|
||||||
private Container<DrawableHitObject> caughtFruit;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(TextureStore textures)
|
|
||||||
{
|
|
||||||
texture = textures.Get(@"Play/Catch/fruit-catcher-idle");
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
createCatcherSprite(),
|
|
||||||
caughtFruit = new Container<DrawableHitObject>
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private int currentDirection;
|
|
||||||
|
|
||||||
private bool dashing;
|
|
||||||
|
|
||||||
public Container ExplodingFruitTarget;
|
|
||||||
|
|
||||||
protected bool Dashing
|
|
||||||
{
|
|
||||||
get { return dashing; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == dashing) return;
|
|
||||||
|
|
||||||
dashing = value;
|
|
||||||
|
|
||||||
if (dashing)
|
|
||||||
Schedule(addAdditiveSprite);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addAdditiveSprite()
|
|
||||||
{
|
|
||||||
if (!dashing) return;
|
|
||||||
|
|
||||||
var additive = createCatcherSprite();
|
|
||||||
|
|
||||||
additive.RelativePositionAxes = Axes.Both;
|
|
||||||
additive.Blending = BlendingMode.Additive;
|
|
||||||
additive.Position = Position;
|
|
||||||
additive.Scale = Scale;
|
|
||||||
|
|
||||||
((CatcherArea)Parent).Add(additive);
|
|
||||||
|
|
||||||
additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire();
|
|
||||||
|
|
||||||
Scheduler.AddDelayed(addAdditiveSprite, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Sprite createCatcherSprite() => new Sprite
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
FillMode = FillMode.Fit,
|
|
||||||
Texture = texture,
|
|
||||||
OriginPosition = new Vector2(DrawWidth / 2, 10) //temporary until the sprite is aligned correctly.
|
|
||||||
};
|
|
||||||
|
|
||||||
public bool OnPressed(CatchAction action)
|
|
||||||
{
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case CatchAction.MoveLeft:
|
|
||||||
currentDirection--;
|
|
||||||
return true;
|
|
||||||
case CatchAction.MoveRight:
|
|
||||||
currentDirection++;
|
|
||||||
return true;
|
|
||||||
case CatchAction.Dash:
|
|
||||||
Dashing = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool OnReleased(CatchAction action)
|
|
||||||
{
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case CatchAction.MoveLeft:
|
|
||||||
currentDirection++;
|
|
||||||
return true;
|
|
||||||
case CatchAction.MoveRight:
|
|
||||||
currentDirection--;
|
|
||||||
return true;
|
|
||||||
case CatchAction.Dash:
|
|
||||||
Dashing = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable.
|
|
||||||
/// </summary>
|
|
||||||
private const double base_speed = 1.0 / 512;
|
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
if (currentDirection == 0) return;
|
|
||||||
|
|
||||||
double dashModifier = Dashing ? 1 : 0.5;
|
|
||||||
|
|
||||||
Scale = new Vector2(Math.Sign(currentDirection), 1);
|
|
||||||
X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime * base_speed * dashModifier, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddToStack(DrawableHitObject fruit, Vector2 absolutePosition)
|
|
||||||
{
|
|
||||||
fruit.RelativePositionAxes = Axes.None;
|
|
||||||
fruit.Position = new Vector2(ToLocalSpace(absolutePosition).X - DrawSize.X / 2, 0);
|
|
||||||
|
|
||||||
fruit.Anchor = Anchor.TopCentre;
|
|
||||||
fruit.Origin = Anchor.BottomCentre;
|
|
||||||
fruit.Scale *= 0.7f;
|
|
||||||
fruit.LifetimeEnd = double.MaxValue;
|
|
||||||
|
|
||||||
float distance = fruit.DrawSize.X / 2 * fruit.Scale.X;
|
|
||||||
|
|
||||||
while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance))
|
|
||||||
{
|
|
||||||
fruit.X += RNG.Next(-5, 5);
|
|
||||||
fruit.Y -= RNG.Next(0, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
caughtFruit.Add(fruit);
|
|
||||||
|
|
||||||
if (((CatchBaseHit)fruit.HitObject).LastInCombo)
|
|
||||||
explode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void explode()
|
|
||||||
{
|
|
||||||
var fruit = caughtFruit.ToArray();
|
|
||||||
|
|
||||||
foreach (var f in fruit)
|
|
||||||
{
|
|
||||||
var originalX = f.X * Scale.X;
|
|
||||||
|
|
||||||
if (ExplodingFruitTarget != null)
|
|
||||||
{
|
|
||||||
f.Anchor = Anchor.TopLeft;
|
|
||||||
f.Position = caughtFruit.ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget);
|
|
||||||
|
|
||||||
caughtFruit.Remove(f);
|
|
||||||
|
|
||||||
ExplodingFruitTarget.Add(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
f.MoveToY(f.Y - 50, 250, Easing.OutSine)
|
|
||||||
.Then()
|
|
||||||
.MoveToY(f.Y + 50, 500, Easing.InSine);
|
|
||||||
|
|
||||||
f.MoveToX(f.X + originalX * 6, 1000);
|
|
||||||
f.FadeOut(750);
|
|
||||||
|
|
||||||
f.Expire();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -59,7 +59,7 @@
|
|||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Tests\TestCaseCatcher.cs" />
|
<Compile Include="Tests\TestCaseCatcher.cs" />
|
||||||
<Compile Include="Tests\TestCaseCatchPlayer.cs" />
|
<Compile Include="Tests\TestCaseCatchPlayer.cs" />
|
||||||
<Compile Include="UI\CatcherArea.cs" />
|
<Compile Include="UI\Catcher.cs" />
|
||||||
<Compile Include="UI\CatchRulesetContainer.cs" />
|
<Compile Include="UI\CatchRulesetContainer.cs" />
|
||||||
<Compile Include="UI\CatchPlayfield.cs" />
|
<Compile Include="UI\CatchPlayfield.cs" />
|
||||||
<Compile Include="CatchRuleset.cs" />
|
<Compile Include="CatchRuleset.cs" />
|
||||||
|
@ -58,6 +58,23 @@ namespace osu.Game.Beatmaps
|
|||||||
ComboColors = original?.ComboColors ?? ComboColors;
|
ComboColors = original?.ComboColors ?? ComboColors;
|
||||||
HitObjects = original?.HitObjects ?? HitObjects;
|
HitObjects = original?.HitObjects ?? HitObjects;
|
||||||
Storyboard = original?.Storyboard ?? Storyboard;
|
Storyboard = original?.Storyboard ?? Storyboard;
|
||||||
|
|
||||||
|
if (original == null && Metadata == null)
|
||||||
|
{
|
||||||
|
// we may have no metadata in cases we weren't sourced from the database.
|
||||||
|
// let's fill it (and other related fields) so we don't need to null-check it in future usages.
|
||||||
|
BeatmapInfo = new BeatmapInfo
|
||||||
|
{
|
||||||
|
Metadata = new BeatmapMetadata
|
||||||
|
{
|
||||||
|
Artist = @"Unknown",
|
||||||
|
Title = @"Unknown",
|
||||||
|
Author = @"Unknown Creator",
|
||||||
|
},
|
||||||
|
Version = @"Normal",
|
||||||
|
Difficulty = new BeatmapDifficulty()
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,6 +573,16 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
catch { return new TrackVirtual(); }
|
catch { return new TrackVirtual(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override Waveform GetWaveform()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var trackData = store.GetStream(getPathForFile(Metadata.AudioFile));
|
||||||
|
return trackData == null ? new Waveform() : new Waveform(trackData);
|
||||||
|
}
|
||||||
|
catch { return new Waveform(); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -31,6 +31,8 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
|
|
||||||
public Action<BeatmapInfo> HideDifficultyRequested;
|
public Action<BeatmapInfo> HideDifficultyRequested;
|
||||||
|
|
||||||
|
public Action<BeatmapInfo> EditRequested;
|
||||||
|
|
||||||
public BeatmapSetHeader Header;
|
public BeatmapSetHeader Header;
|
||||||
|
|
||||||
public List<BeatmapPanel> BeatmapPanels;
|
public List<BeatmapPanel> BeatmapPanels;
|
||||||
@ -87,7 +89,8 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
GainedSelection = panelGainedSelection,
|
GainedSelection = panelGainedSelection,
|
||||||
HideRequested = p => HideDifficultyRequested?.Invoke(p),
|
HideRequested = p => HideDifficultyRequested?.Invoke(p),
|
||||||
StartRequested = p => { StartRequested?.Invoke(p.Beatmap); },
|
StartRequested = p => StartRequested?.Invoke(p.Beatmap),
|
||||||
|
EditRequested = p => EditRequested?.Invoke(p.Beatmap),
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
|
@ -611,7 +611,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
CommandTimelineGroup timelineGroup = null;
|
CommandTimelineGroup timelineGroup = null;
|
||||||
|
|
||||||
string line;
|
string line;
|
||||||
while ((line = stream.ReadLine()) != null)
|
while ((line = stream.ReadLine()?.Trim()) != null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(line))
|
if (string.IsNullOrEmpty(line))
|
||||||
continue;
|
continue;
|
||||||
|
@ -8,7 +8,7 @@ namespace osu.Game.Beatmaps.Timing
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The minimum duration required for a break to have any effect.
|
/// The minimum duration required for a break to have any effect.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const double min_break_duration = 650;
|
public const double MIN_BREAK_DURATION = 650;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The break start time.
|
/// The break start time.
|
||||||
@ -28,6 +28,6 @@ namespace osu.Game.Beatmaps.Timing
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the break has any effect. Breaks that are too short are culled before they are added to the beatmap.
|
/// Whether the break has any effect. Breaks that are too short are culled before they are added to the beatmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasEffect => Duration >= min_break_duration;
|
public bool HasEffect => Duration >= MIN_BREAK_DURATION;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -43,6 +43,7 @@ namespace osu.Game.Beatmaps
|
|||||||
protected abstract Beatmap GetBeatmap();
|
protected abstract Beatmap GetBeatmap();
|
||||||
protected abstract Texture GetBackground();
|
protected abstract Texture GetBackground();
|
||||||
protected abstract Track GetTrack();
|
protected abstract Track GetTrack();
|
||||||
|
protected virtual Waveform GetWaveform() => new Waveform();
|
||||||
|
|
||||||
private Beatmap beatmap;
|
private Beatmap beatmap;
|
||||||
private readonly object beatmapLock = new object();
|
private readonly object beatmapLock = new object();
|
||||||
@ -96,6 +97,17 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Waveform waveform;
|
||||||
|
private readonly object waveformLock = new object();
|
||||||
|
public Waveform Waveform
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (waveformLock)
|
||||||
|
return waveform ?? (waveform = GetWaveform());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool TrackLoaded => track != null;
|
public bool TrackLoaded => track != null;
|
||||||
|
|
||||||
public void TransferTo(WorkingBeatmap other)
|
public void TransferTo(WorkingBeatmap other)
|
||||||
@ -114,6 +126,8 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
background?.Dispose();
|
background?.Dispose();
|
||||||
background = null;
|
background = null;
|
||||||
|
|
||||||
|
waveform?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeTrack()
|
public void DisposeTrack()
|
||||||
|
@ -188,11 +188,11 @@ namespace osu.Game
|
|||||||
GetToolbarHeight = () => ToolbarOffset,
|
GetToolbarHeight = () => ToolbarOffset,
|
||||||
Depth = -1
|
Depth = -1
|
||||||
}, overlayContent.Add);
|
}, overlayContent.Add);
|
||||||
LoadComponentAsync(userProfile = new UserProfileOverlay { Depth = -2 }, mainContent.Add);
|
|
||||||
LoadComponentAsync(beatmapSetOverlay = new BeatmapSetOverlay { Depth = -2 }, mainContent.Add);
|
LoadComponentAsync(beatmapSetOverlay = new BeatmapSetOverlay { Depth = -2 }, mainContent.Add);
|
||||||
|
LoadComponentAsync(userProfile = new UserProfileOverlay { Depth = -3 }, mainContent.Add);
|
||||||
LoadComponentAsync(musicController = new MusicController
|
LoadComponentAsync(musicController = new MusicController
|
||||||
{
|
{
|
||||||
Depth = -3,
|
Depth = -4,
|
||||||
Position = new Vector2(0, Toolbar.HEIGHT),
|
Position = new Vector2(0, Toolbar.HEIGHT),
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
@ -200,7 +200,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
LoadComponentAsync(notificationOverlay = new NotificationOverlay
|
LoadComponentAsync(notificationOverlay = new NotificationOverlay
|
||||||
{
|
{
|
||||||
Depth = -3,
|
Depth = -4,
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
}, overlayContent.Add);
|
}, overlayContent.Add);
|
||||||
|
@ -9,6 +9,9 @@ using osu.Game.Graphics.Sprites;
|
|||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.BeatmapSet
|
namespace osu.Game.Overlays.BeatmapSet
|
||||||
{
|
{
|
||||||
@ -17,8 +20,11 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
private const float height = 50;
|
private const float height = 50;
|
||||||
|
|
||||||
private readonly UpdateableAvatar avatar;
|
private readonly UpdateableAvatar avatar;
|
||||||
|
private readonly ClickableArea clickableArea;
|
||||||
private readonly FillFlowContainer fields;
|
private readonly FillFlowContainer fields;
|
||||||
|
|
||||||
|
private UserProfileOverlay profile;
|
||||||
|
|
||||||
private BeatmapSetInfo beatmapSet;
|
private BeatmapSetInfo beatmapSet;
|
||||||
public BeatmapSetInfo BeatmapSet
|
public BeatmapSetInfo BeatmapSet
|
||||||
{
|
{
|
||||||
@ -31,6 +37,8 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
var i = BeatmapSet.OnlineInfo;
|
var i = BeatmapSet.OnlineInfo;
|
||||||
|
|
||||||
avatar.User = i.Author;
|
avatar.User = i.Author;
|
||||||
|
clickableArea.Action = () => profile?.ShowUser(avatar.User);
|
||||||
|
|
||||||
fields.Children = new Drawable[]
|
fields.Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Field("made by", i.Author.Username, @"Exo2.0-RegularItalic"),
|
new Field("made by", i.Author.Username, @"Exo2.0-RegularItalic"),
|
||||||
@ -58,11 +66,15 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
avatar = new UpdateableAvatar
|
clickableArea = new ClickableArea
|
||||||
{
|
{
|
||||||
Size = new Vector2(height),
|
AutoSizeAxes = Axes.Both,
|
||||||
CornerRadius = 3,
|
CornerRadius = 3,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
|
Child = avatar = new UpdateableAvatar
|
||||||
|
{
|
||||||
|
Size = new Vector2(height),
|
||||||
|
},
|
||||||
EdgeEffect = new EdgeEffectParameters
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Colour = Color4.Black.Opacity(0.25f),
|
Colour = Color4.Black.Opacity(0.25f),
|
||||||
@ -80,6 +92,13 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(UserProfileOverlay profile)
|
||||||
|
{
|
||||||
|
this.profile = profile;
|
||||||
|
clickableArea.Action = () => profile?.ShowUser(avatar.User);
|
||||||
|
}
|
||||||
|
|
||||||
private class Field : FillFlowContainer
|
private class Field : FillFlowContainer
|
||||||
{
|
{
|
||||||
public Field(string first, string second, string secondFont)
|
public Field(string first, string second, string secondFont)
|
||||||
@ -103,5 +122,10 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ClickableArea : OsuClickableContainer, IHasTooltip
|
||||||
|
{
|
||||||
|
public string TooltipText => @"View Profile";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ namespace osu.Game.Rulesets
|
|||||||
|
|
||||||
protected override void Prepare(bool reset = false)
|
protected override void Prepare(bool reset = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
Connection.CreateTable<RulesetInfo>();
|
Connection.CreateTable<RulesetInfo>();
|
||||||
|
|
||||||
if (reset)
|
if (reset)
|
||||||
|
@ -51,6 +51,11 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly BindableInt Combo = new BindableInt();
|
public readonly BindableInt Combo = new BindableInt();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current rank.
|
||||||
|
/// </summary>
|
||||||
|
public readonly Bindable<ScoreRank> Rank = new Bindable<ScoreRank>(ScoreRank.X);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// THe highest combo achieved by this score.
|
/// THe highest combo achieved by this score.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -74,6 +79,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
protected ScoreProcessor()
|
protected ScoreProcessor()
|
||||||
{
|
{
|
||||||
Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); };
|
Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); };
|
||||||
|
Accuracy.ValueChanged += delegate { Rank.Value = rankFrom(Accuracy.Value); };
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScoreRank rankFrom(double acc)
|
private ScoreRank rankFrom(double acc)
|
||||||
@ -101,6 +107,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
Accuracy.Value = 1;
|
Accuracy.Value = 1;
|
||||||
Health.Value = 1;
|
Health.Value = 1;
|
||||||
Combo.Value = 0;
|
Combo.Value = 0;
|
||||||
|
Rank.Value = ScoreRank.X;
|
||||||
HighestCombo.Value = 0;
|
HighestCombo.Value = 0;
|
||||||
|
|
||||||
alreadyFailed = false;
|
alreadyFailed = false;
|
||||||
@ -142,7 +149,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
score.Combo = Combo;
|
score.Combo = Combo;
|
||||||
score.MaxCombo = HighestCombo;
|
score.MaxCombo = HighestCombo;
|
||||||
score.Accuracy = Accuracy;
|
score.Accuracy = Accuracy;
|
||||||
score.Rank = rankFrom(Accuracy);
|
score.Rank = Rank;
|
||||||
score.Date = DateTimeOffset.Now;
|
score.Date = DateTimeOffset.Now;
|
||||||
score.Health = Health;
|
score.Health = Health;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ using osu.Game.Screens.Edit.Menus;
|
|||||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Screens.Edit.Screens;
|
using osu.Game.Screens.Edit.Screens;
|
||||||
using osu.Game.Screens.Edit.Screens.Compose;
|
using osu.Game.Screens.Edit.Screens.Compose;
|
||||||
using osu.Game.Screens.Edit.Screens.Design;
|
using osu.Game.Screens.Edit.Screens.Design;
|
||||||
@ -36,6 +38,17 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Name = "Screen container",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Top = 40, Bottom = 60 },
|
||||||
|
Child = screenContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true
|
||||||
|
}
|
||||||
|
},
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
Name = "Top bar",
|
Name = "Top bar",
|
||||||
@ -45,7 +58,17 @@ namespace osu.Game.Screens.Edit
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Items = new[]
|
||||||
|
{
|
||||||
|
new MenuItem("File")
|
||||||
|
{
|
||||||
|
Items = new[]
|
||||||
|
{
|
||||||
|
new EditorMenuItem("Exit", MenuItemType.Standard, Exit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
@ -82,17 +105,6 @@ namespace osu.Game.Screens.Edit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Container
|
|
||||||
{
|
|
||||||
Name = "Screen container",
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Padding = new MarginPadding { Top = 40, Bottom = 60 },
|
|
||||||
Child = screenContainer = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
timeline.Beatmap.BindTo(Beatmap);
|
timeline.Beatmap.BindTo(Beatmap);
|
||||||
|
@ -20,16 +20,16 @@ namespace osu.Game.Screens.Edit.Menus
|
|||||||
{
|
{
|
||||||
public readonly Bindable<EditorScreenMode> Mode = new Bindable<EditorScreenMode>();
|
public readonly Bindable<EditorScreenMode> Mode = new Bindable<EditorScreenMode>();
|
||||||
|
|
||||||
private readonly ScreenSelectionTabControl tabControl;
|
|
||||||
|
|
||||||
public EditorMenuBar()
|
public EditorMenuBar()
|
||||||
: base(Direction.Horizontal, true)
|
: base(Direction.Horizontal, true)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
|
|
||||||
|
MaskingContainer.CornerRadius = 0;
|
||||||
ItemsContainer.Padding = new MarginPadding { Left = 100 };
|
ItemsContainer.Padding = new MarginPadding { Left = 100 };
|
||||||
BackgroundColour = OsuColour.FromHex("111");
|
BackgroundColour = OsuColour.FromHex("111");
|
||||||
|
|
||||||
|
ScreenSelectionTabControl tabControl;
|
||||||
AddRangeInternal(new Drawable[]
|
AddRangeInternal(new Drawable[]
|
||||||
{
|
{
|
||||||
tabControl = new ScreenSelectionTabControl
|
tabControl = new ScreenSelectionTabControl
|
||||||
@ -40,13 +40,13 @@ namespace osu.Game.Screens.Edit.Menus
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
tabControl.Current.BindTo(Mode);
|
Mode.BindTo(tabControl.Current);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
tabControl.Current.TriggerChange();
|
Mode.TriggerChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Framework.Graphics.UserInterface.Menu CreateSubMenu() => new SubMenu();
|
protected override Framework.Graphics.UserInterface.Menu CreateSubMenu() => new SubMenu();
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using osu.Framework.Graphics.UserInterface;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Menus
|
|
||||||
{
|
|
||||||
public class EditorMenuBarItem : MenuItem
|
|
||||||
{
|
|
||||||
public EditorMenuBarItem(string text)
|
|
||||||
: base(text)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -33,6 +33,8 @@ namespace osu.Game.Screens.Edit.Menus
|
|||||||
Height = 1,
|
Height = 1,
|
||||||
Colour = Color4.White.Opacity(0.2f),
|
Colour = Color4.White.Opacity(0.2f),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Current.Value = EditorScreenMode.Compose;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Audio;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Screens.Compose
|
||||||
|
{
|
||||||
|
public class BeatmapWaveformGraph : CompositeDrawable
|
||||||
|
{
|
||||||
|
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
|
private readonly WaveformGraph graph;
|
||||||
|
|
||||||
|
public BeatmapWaveformGraph()
|
||||||
|
{
|
||||||
|
InternalChild = graph = new WaveformGraph { RelativeSizeAxes = Axes.Both };
|
||||||
|
Beatmap.ValueChanged += b => graph.Waveform = b.Waveform;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="WaveformGraph.Resolution"/>.
|
||||||
|
/// </summary>
|
||||||
|
public float Resolution
|
||||||
|
{
|
||||||
|
get { return graph.Resolution; }
|
||||||
|
set { graph.Resolution = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
|||||||
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
private readonly Container timelineContainer;
|
private readonly Container timelineContainer;
|
||||||
private readonly WaveformDisplay waveform;
|
private readonly BeatmapWaveformGraph waveform;
|
||||||
|
|
||||||
public ScrollableTimeline()
|
public ScrollableTimeline()
|
||||||
{
|
{
|
||||||
@ -109,7 +109,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
|||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
waveform = new WaveformDisplay
|
waveform = new BeatmapWaveformGraph
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = OsuColour.FromHex("081a84")
|
Colour = OsuColour.FromHex("081a84")
|
||||||
|
@ -1,166 +0,0 @@
|
|||||||
// 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 System.Collections.Generic;
|
|
||||||
using OpenTK;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Audio.Track;
|
|
||||||
using osu.Framework.Configuration;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Batches;
|
|
||||||
using osu.Framework.Graphics.Colour;
|
|
||||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
|
||||||
using osu.Framework.Graphics.Primitives;
|
|
||||||
using osu.Framework.Graphics.Shaders;
|
|
||||||
using osu.Framework.Graphics.Textures;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Screens.Compose
|
|
||||||
{
|
|
||||||
public class WaveformDisplay : Drawable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The beatmap which the audio waveform should be displayed for.
|
|
||||||
/// </summary>
|
|
||||||
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
|
||||||
|
|
||||||
private Shader shader;
|
|
||||||
private readonly Texture texture;
|
|
||||||
|
|
||||||
public WaveformDisplay()
|
|
||||||
{
|
|
||||||
texture = Texture.WhitePixel;
|
|
||||||
Beatmap.ValueChanged += generateWaveform;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(ShaderManager shaders)
|
|
||||||
{
|
|
||||||
shader = shaders?.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private float resolution = 1;
|
|
||||||
/// <summary>
|
|
||||||
/// Controls the amount of interpolation of the waveform into the width of this <see cref="WaveformDisplay"/>.
|
|
||||||
/// Points in the waveform are interpolated between 1 / <see cref="Resolution"/> pixels of this <see cref="WaveformDisplay"/>.
|
|
||||||
/// </summary>
|
|
||||||
public float Resolution
|
|
||||||
{
|
|
||||||
get { return resolution; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value < 0)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(value));
|
|
||||||
|
|
||||||
if (resolution == value)
|
|
||||||
return;
|
|
||||||
resolution = value;
|
|
||||||
|
|
||||||
Invalidate(Invalidation.DrawNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Waveform waveform;
|
|
||||||
private Track lastQueriedTrack;
|
|
||||||
private void generateWaveform(WorkingBeatmap beatmap)
|
|
||||||
{
|
|
||||||
// Cancel the old query so we don't saturate the audio thread
|
|
||||||
lastQueriedTrack?.CancelWaveformQuery();
|
|
||||||
|
|
||||||
beatmap.Track.QueryWaveform(w =>
|
|
||||||
{
|
|
||||||
if (Beatmap.Value == beatmap)
|
|
||||||
{
|
|
||||||
waveform = w;
|
|
||||||
Invalidate(Invalidation.DrawNode);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
lastQueriedTrack = beatmap.Track;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly WaveformDrawNodeSharedData sharedData = new WaveformDrawNodeSharedData();
|
|
||||||
protected override DrawNode CreateDrawNode() => new WaveformDrawNode();
|
|
||||||
protected override void ApplyDrawNode(DrawNode node)
|
|
||||||
{
|
|
||||||
var n = (WaveformDrawNode)node;
|
|
||||||
|
|
||||||
n.Shader = shader;
|
|
||||||
n.Texture = texture;
|
|
||||||
n.Size = DrawSize;
|
|
||||||
n.Shared = sharedData;
|
|
||||||
n.Points = waveform?.Generate((int)(MathHelper.Clamp(Math.Ceiling(DrawWidth) * Resolution, 0, waveform.MaximumPoints)));
|
|
||||||
n.Channels = waveform?.Channels ?? 0;
|
|
||||||
|
|
||||||
base.ApplyDrawNode(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class WaveformDrawNodeSharedData
|
|
||||||
{
|
|
||||||
public readonly QuadBatch<TexturedVertex2D> VertexBatch = new QuadBatch<TexturedVertex2D>(1000, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class WaveformDrawNode : DrawNode
|
|
||||||
{
|
|
||||||
public Shader Shader;
|
|
||||||
public Texture Texture;
|
|
||||||
|
|
||||||
public WaveformDrawNodeSharedData Shared;
|
|
||||||
|
|
||||||
public List<WaveformPoint> Points;
|
|
||||||
public Vector2 Size;
|
|
||||||
public int Channels;
|
|
||||||
|
|
||||||
public override void Draw(Action<TexturedVertex2D> vertexAction)
|
|
||||||
{
|
|
||||||
base.Draw(vertexAction);
|
|
||||||
|
|
||||||
if (Points == null || Points.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Shader.Bind();
|
|
||||||
Texture.TextureGL.Bind();
|
|
||||||
|
|
||||||
float separation = Size.X / (Points.Count - 1);
|
|
||||||
Vector2 localInflationAmount = new Vector2(0, 1) * DrawInfo.MatrixInverse.ExtractScale().Xy;
|
|
||||||
|
|
||||||
for (int i = 0; i < Points.Count - 1; i++)
|
|
||||||
{
|
|
||||||
ColourInfo colour = DrawInfo.Colour;
|
|
||||||
Quad quadToDraw;
|
|
||||||
|
|
||||||
switch (Channels)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
float height = Size.Y / 2;
|
|
||||||
quadToDraw = new Quad(
|
|
||||||
new Vector2(i * separation, height - Points[i].Amplitude[0] * height),
|
|
||||||
new Vector2((i + 1) * separation, height - Points[i + 1].Amplitude[0] * height),
|
|
||||||
new Vector2(i * separation, height + Points[i].Amplitude[1] * height),
|
|
||||||
new Vector2((i + 1) * separation, height + Points[i + 1].Amplitude[1] * height)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
quadToDraw = new Quad(
|
|
||||||
new Vector2(i * separation, Size.Y - Points[i].Amplitude[0] * Size.Y),
|
|
||||||
new Vector2((i + 1) * separation, Size.Y - Points[i + 1].Amplitude[0] * Size.Y),
|
|
||||||
new Vector2(i * separation, Size.Y),
|
|
||||||
new Vector2((i + 1) * separation, Size.Y)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Texture.DrawQuad(quadToDraw * DrawInfo.Matrix, colour, null, Shared.VertexBatch.Add, Vector2.Divide(localInflationAmount, quadToDraw.Size));
|
|
||||||
}
|
|
||||||
|
|
||||||
Shader.Unbind();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,14 +28,14 @@ namespace osu.Game.Screens.Edit.Screens
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
this.ScaleTo(0.75f).FadeTo(0)
|
this.FadeTo(0)
|
||||||
.Then()
|
.Then()
|
||||||
.ScaleTo(1f, 500, Easing.OutQuint).FadeTo(1f, 250, Easing.OutQuint);
|
.FadeTo(1f, 250, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Exit()
|
public void Exit()
|
||||||
{
|
{
|
||||||
this.ScaleTo(1.25f, 500).FadeOut(250).Expire();
|
this.FadeOut(250).Expire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,13 @@ namespace osu.Game.Screens.Edit.Screens
|
|||||||
{
|
{
|
||||||
public enum EditorScreenMode
|
public enum EditorScreenMode
|
||||||
{
|
{
|
||||||
|
[Description("setup")]
|
||||||
|
SongSetup,
|
||||||
[Description("compose")]
|
[Description("compose")]
|
||||||
Compose,
|
Compose,
|
||||||
[Description("design")]
|
[Description("design")]
|
||||||
Design,
|
Design,
|
||||||
[Description("timing")]
|
[Description("timing")]
|
||||||
Timing,
|
Timing,
|
||||||
[Description("song")]
|
|
||||||
SongSetup
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
103
osu.Game/Screens/Play/BreaksOverlay/ArrowsOverlay.cs
Normal file
103
osu.Game/Screens/Play/BreaksOverlay/ArrowsOverlay.cs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Beatmaps.Timing;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||||
|
{
|
||||||
|
public class ArrowsOverlay : VisibilityContainer
|
||||||
|
{
|
||||||
|
private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2;
|
||||||
|
|
||||||
|
private const int glow_icon_size = 60;
|
||||||
|
private const int glow_icon_blur_sigma = 10;
|
||||||
|
private const float glow_icon_final_offset = 0.22f;
|
||||||
|
private const float glow_icon_offscreen_offset = 0.6f;
|
||||||
|
|
||||||
|
private const int blurred_icon_blur_sigma = 20;
|
||||||
|
private const int blurred_icon_size = 130;
|
||||||
|
private const float blurred_icon_final_offset = 0.35f;
|
||||||
|
private const float blurred_icon_offscreen_offset = 0.7f;
|
||||||
|
|
||||||
|
private readonly GlowIcon leftGlowIcon;
|
||||||
|
private readonly GlowIcon rightGlowIcon;
|
||||||
|
|
||||||
|
private readonly BlurredIcon leftBlurredIcon;
|
||||||
|
private readonly BlurredIcon rightBlurredIcon;
|
||||||
|
|
||||||
|
public ArrowsOverlay()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
leftGlowIcon = new GlowIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
X = -glow_icon_offscreen_offset,
|
||||||
|
Icon = Graphics.FontAwesome.fa_chevron_right,
|
||||||
|
BlurSigma = new Vector2(glow_icon_blur_sigma),
|
||||||
|
Size = new Vector2(glow_icon_size),
|
||||||
|
},
|
||||||
|
rightGlowIcon = new GlowIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
X = glow_icon_offscreen_offset,
|
||||||
|
Icon = Graphics.FontAwesome.fa_chevron_left,
|
||||||
|
BlurSigma = new Vector2(glow_icon_blur_sigma),
|
||||||
|
Size = new Vector2(glow_icon_size),
|
||||||
|
},
|
||||||
|
new ParallaxContainer
|
||||||
|
{
|
||||||
|
ParallaxAmount = -0.02f,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
leftBlurredIcon = new BlurredIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Alpha = 0.7f,
|
||||||
|
X = -blurred_icon_offscreen_offset,
|
||||||
|
Icon = Graphics.FontAwesome.fa_chevron_right,
|
||||||
|
BlurSigma = new Vector2(blurred_icon_blur_sigma),
|
||||||
|
Size = new Vector2(blurred_icon_size),
|
||||||
|
},
|
||||||
|
rightBlurredIcon = new BlurredIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Alpha = 0.7f,
|
||||||
|
X = blurred_icon_offscreen_offset,
|
||||||
|
Icon = Graphics.FontAwesome.fa_chevron_left,
|
||||||
|
BlurSigma = new Vector2(blurred_icon_blur_sigma),
|
||||||
|
Size = new Vector2(blurred_icon_size),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopIn()
|
||||||
|
{
|
||||||
|
leftGlowIcon.MoveToX(-glow_icon_final_offset, fade_duration, Easing.OutQuint);
|
||||||
|
rightGlowIcon.MoveToX(glow_icon_final_offset, fade_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
leftBlurredIcon.MoveToX(-blurred_icon_final_offset, fade_duration, Easing.OutQuint);
|
||||||
|
rightBlurredIcon.MoveToX(blurred_icon_final_offset, fade_duration, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopOut()
|
||||||
|
{
|
||||||
|
leftGlowIcon.MoveToX(-glow_icon_offscreen_offset, fade_duration, Easing.OutQuint);
|
||||||
|
rightGlowIcon.MoveToX(glow_icon_offscreen_offset, fade_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
leftBlurredIcon.MoveToX(-blurred_icon_offscreen_offset, fade_duration, Easing.OutQuint);
|
||||||
|
rightBlurredIcon.MoveToX(blurred_icon_offscreen_offset, fade_duration, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
osu.Game/Screens/Play/BreaksOverlay/BlurredIcon.cs
Normal file
51
osu.Game/Screens/Play/BreaksOverlay/BlurredIcon.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||||
|
{
|
||||||
|
public class BlurredIcon : BufferedContainer
|
||||||
|
{
|
||||||
|
private readonly SpriteIcon icon;
|
||||||
|
|
||||||
|
public FontAwesome Icon
|
||||||
|
{
|
||||||
|
set { icon.Icon = value; }
|
||||||
|
get { return icon.Icon; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector2 Size
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
icon.Size = value;
|
||||||
|
base.Size = value + BlurSigma * 2.5f;
|
||||||
|
ForceRedraw();
|
||||||
|
}
|
||||||
|
get { return base.Size; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlurredIcon()
|
||||||
|
{
|
||||||
|
RelativePositionAxes = Axes.X;
|
||||||
|
CacheDrawnFrameBuffer = true;
|
||||||
|
Child = icon = new SpriteIcon
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Shadow = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
Colour = colours.BlueLighter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
151
osu.Game/Screens/Play/BreaksOverlay/BreakOverlay.cs
Normal file
151
osu.Game/Screens/Play/BreaksOverlay/BreakOverlay.cs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Beatmaps.Timing;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||||
|
{
|
||||||
|
public class BreakOverlay : Container
|
||||||
|
{
|
||||||
|
private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2;
|
||||||
|
private const float remaining_time_container_max_size = 0.3f;
|
||||||
|
private const int vertical_margin = 25;
|
||||||
|
|
||||||
|
private List<BreakPeriod> breaks;
|
||||||
|
public List<BreakPeriod> Breaks
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
breaks = value;
|
||||||
|
initializeBreaks();
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return breaks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly bool letterboxing;
|
||||||
|
private readonly LetterboxOverlay letterboxOverlay;
|
||||||
|
private readonly Container remainingTimeAdjustmentBox;
|
||||||
|
private readonly Container remainingTimeBox;
|
||||||
|
private readonly RemainingTimeCounter remainingTimeCounter;
|
||||||
|
private readonly InfoContainer info;
|
||||||
|
private readonly ArrowsOverlay arrowsOverlay;
|
||||||
|
|
||||||
|
public BreakOverlay(bool letterboxing)
|
||||||
|
{
|
||||||
|
this.letterboxing = letterboxing;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
letterboxOverlay = new LetterboxOverlay
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
remainingTimeAdjustmentBox = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Width = 0,
|
||||||
|
Child = remainingTimeBox = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 8,
|
||||||
|
CornerRadius = 4,
|
||||||
|
Masking = true,
|
||||||
|
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
remainingTimeCounter = new RemainingTimeCounter
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
Margin = new MarginPadding { Bottom = vertical_margin },
|
||||||
|
},
|
||||||
|
info = new InfoContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Margin = new MarginPadding { Top = vertical_margin },
|
||||||
|
},
|
||||||
|
arrowsOverlay = new ArrowsOverlay
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeBreaks()
|
||||||
|
{
|
||||||
|
FinishTransforms(true);
|
||||||
|
Scheduler.CancelDelayedTasks();
|
||||||
|
|
||||||
|
if (breaks == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var b in breaks)
|
||||||
|
{
|
||||||
|
if (!b.HasEffect)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
using (BeginAbsoluteSequence(b.StartTime))
|
||||||
|
{
|
||||||
|
Schedule(() => onBreakIn(b));
|
||||||
|
using (BeginDelayedSequence(b.Duration - fade_duration))
|
||||||
|
Schedule(onBreakOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onBreakIn(BreakPeriod b)
|
||||||
|
{
|
||||||
|
if (letterboxing)
|
||||||
|
letterboxOverlay.Show();
|
||||||
|
|
||||||
|
remainingTimeAdjustmentBox
|
||||||
|
.ResizeWidthTo(remaining_time_container_max_size, fade_duration, Easing.OutQuint)
|
||||||
|
.Delay(b.Duration - fade_duration)
|
||||||
|
.ResizeWidthTo(0);
|
||||||
|
|
||||||
|
remainingTimeBox
|
||||||
|
.ResizeWidthTo(0, b.Duration - fade_duration)
|
||||||
|
.Then()
|
||||||
|
.ResizeWidthTo(1);
|
||||||
|
|
||||||
|
remainingTimeCounter.StartCounting(b.EndTime);
|
||||||
|
|
||||||
|
remainingTimeCounter.Show();
|
||||||
|
info.Show();
|
||||||
|
arrowsOverlay.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onBreakOut()
|
||||||
|
{
|
||||||
|
if (letterboxing)
|
||||||
|
letterboxOverlay.Hide();
|
||||||
|
|
||||||
|
remainingTimeCounter.Hide();
|
||||||
|
info.Hide();
|
||||||
|
arrowsOverlay.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BindProcessor(ScoreProcessor processor)
|
||||||
|
{
|
||||||
|
info.AccuracyDisplay.Current.BindTo(processor.Accuracy);
|
||||||
|
info.GradeDisplay.Current.BindTo(processor.Rank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
65
osu.Game/Screens/Play/BreaksOverlay/GlowIcon.cs
Normal file
65
osu.Game/Screens/Play/BreaksOverlay/GlowIcon.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||||
|
{
|
||||||
|
public class GlowIcon : Container
|
||||||
|
{
|
||||||
|
private readonly SpriteIcon spriteIcon;
|
||||||
|
private readonly BlurredIcon blurredIcon;
|
||||||
|
|
||||||
|
public override Vector2 Size
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
blurredIcon.Size = spriteIcon.Size = value;
|
||||||
|
blurredIcon.ForceRedraw();
|
||||||
|
}
|
||||||
|
get { return base.Size; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 BlurSigma
|
||||||
|
{
|
||||||
|
set { blurredIcon.BlurSigma = value; }
|
||||||
|
get { return blurredIcon.BlurSigma; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public FontAwesome Icon
|
||||||
|
{
|
||||||
|
set { spriteIcon.Icon = blurredIcon.Icon = value; }
|
||||||
|
get { return spriteIcon.Icon; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlowIcon()
|
||||||
|
{
|
||||||
|
RelativePositionAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
blurredIcon = new BlurredIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
spriteIcon = new SpriteIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Shadow = false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
blurredIcon.Colour = colours.Blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
osu.Game/Screens/Play/BreaksOverlay/InfoContainer.cs
Normal file
58
osu.Game/Screens/Play/BreaksOverlay/InfoContainer.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Beatmaps.Timing;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||||
|
{
|
||||||
|
public class InfoContainer : VisibilityContainer
|
||||||
|
{
|
||||||
|
private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2;
|
||||||
|
|
||||||
|
public PercentageInfoLine AccuracyDisplay;
|
||||||
|
public InfoLine<int> RankDisplay;
|
||||||
|
public InfoLine<ScoreRank> GradeDisplay;
|
||||||
|
|
||||||
|
public InfoContainer()
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(5),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = "current progress".ToUpper(),
|
||||||
|
TextSize = 15,
|
||||||
|
Font = "Exo2.0-Black",
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
AccuracyDisplay = new PercentageInfoLine("Accuracy"),
|
||||||
|
RankDisplay = new InfoLine<int>("Rank"),
|
||||||
|
GradeDisplay = new InfoLine<ScoreRank>("Grade"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopIn() => this.FadeIn(fade_duration);
|
||||||
|
protected override void PopOut() => this.FadeOut(fade_duration);
|
||||||
|
}
|
||||||
|
}
|
82
osu.Game/Screens/Play/BreaksOverlay/InfoLine.cs
Normal file
82
osu.Game/Screens/Play/BreaksOverlay/InfoLine.cs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||||
|
{
|
||||||
|
public class InfoLine<T> : Container
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
private const int margin = 2;
|
||||||
|
|
||||||
|
public Bindable<T> Current = new Bindable<T>();
|
||||||
|
|
||||||
|
private readonly OsuSpriteText text;
|
||||||
|
private readonly OsuSpriteText valueText;
|
||||||
|
|
||||||
|
private readonly string prefix;
|
||||||
|
|
||||||
|
public InfoLine(string name, string prefix = @"")
|
||||||
|
{
|
||||||
|
this.prefix = prefix;
|
||||||
|
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
text = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Text = name,
|
||||||
|
TextSize = 17,
|
||||||
|
Margin = new MarginPadding { Right = margin }
|
||||||
|
},
|
||||||
|
valueText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Text = prefix + @"-",
|
||||||
|
TextSize = 17,
|
||||||
|
Font = "Exo2.0-Bold",
|
||||||
|
Margin = new MarginPadding { Left = margin }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Current.ValueChanged += currentValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void currentValueChanged(T newValue)
|
||||||
|
{
|
||||||
|
var newText = prefix + Format(newValue);
|
||||||
|
|
||||||
|
if (valueText.Text == newText)
|
||||||
|
return;
|
||||||
|
|
||||||
|
valueText.Text = newText;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual string Format(T count) => count.ToString();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
text.Colour = colours.Yellow;
|
||||||
|
valueText.Colour = colours.YellowLight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PercentageInfoLine : InfoLine<double>
|
||||||
|
{
|
||||||
|
public PercentageInfoLine(string name, string prefix = "") : base(name, prefix)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string Format(double count) => $@"{count:P2}";
|
||||||
|
}
|
||||||
|
}
|
67
osu.Game/Screens/Play/BreaksOverlay/LetterboxOverlay.cs
Normal file
67
osu.Game/Screens/Play/BreaksOverlay/LetterboxOverlay.cs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Beatmaps.Timing;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||||
|
{
|
||||||
|
public class LetterboxOverlay : VisibilityContainer
|
||||||
|
{
|
||||||
|
private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2;
|
||||||
|
private const int height = 350;
|
||||||
|
|
||||||
|
private static readonly Color4 transparent_black = new Color4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
public LetterboxOverlay()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Origin = Anchor.TopLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = height,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = new ColourInfo
|
||||||
|
{
|
||||||
|
TopLeft = Color4.Black,
|
||||||
|
TopRight = Color4.Black,
|
||||||
|
BottomLeft = transparent_black,
|
||||||
|
BottomRight = transparent_black,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = height,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = new ColourInfo
|
||||||
|
{
|
||||||
|
TopLeft = transparent_black,
|
||||||
|
TopRight = transparent_black,
|
||||||
|
BottomLeft = Color4.Black,
|
||||||
|
BottomRight = Color4.Black,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopIn() => this.FadeIn(fade_duration);
|
||||||
|
protected override void PopOut() => this.FadeOut(fade_duration);
|
||||||
|
}
|
||||||
|
}
|
65
osu.Game/Screens/Play/BreaksOverlay/RemainingTimeCounter.cs
Normal file
65
osu.Game/Screens/Play/BreaksOverlay/RemainingTimeCounter.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
using osu.Game.Beatmaps.Timing;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||||
|
{
|
||||||
|
public class RemainingTimeCounter : VisibilityContainer
|
||||||
|
{
|
||||||
|
private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2;
|
||||||
|
|
||||||
|
private readonly OsuSpriteText counter;
|
||||||
|
|
||||||
|
private int? previousSecond;
|
||||||
|
|
||||||
|
private double endTime;
|
||||||
|
|
||||||
|
private bool isCounting;
|
||||||
|
|
||||||
|
public RemainingTimeCounter()
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
Child = counter = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
TextSize = 33,
|
||||||
|
Font = "Venera",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartCounting(double endTime)
|
||||||
|
{
|
||||||
|
this.endTime = endTime;
|
||||||
|
isCounting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (isCounting)
|
||||||
|
{
|
||||||
|
var currentTime = Clock.CurrentTime;
|
||||||
|
if (currentTime < endTime)
|
||||||
|
{
|
||||||
|
int currentSecond = (int)Math.Ceiling((endTime - Clock.CurrentTime) / 1000.0);
|
||||||
|
if (currentSecond != previousSecond)
|
||||||
|
{
|
||||||
|
counter.Text = currentSecond.ToString();
|
||||||
|
previousSecond = currentSecond;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else isCounting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopIn() => this.FadeIn(fade_duration);
|
||||||
|
protected override void PopOut() => this.FadeOut(fade_duration);
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,7 @@ using osu.Game.Screens.Ranking;
|
|||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Screens.Play.BreaksOverlay;
|
||||||
using osu.Game.Storyboards.Drawables;
|
using osu.Game.Storyboards.Drawables;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
@ -69,6 +70,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private BreakOverlay breakOverlay;
|
||||||
private Container storyboardContainer;
|
private Container storyboardContainer;
|
||||||
private DrawableStoryboard storyboard;
|
private DrawableStoryboard storyboard;
|
||||||
|
|
||||||
@ -179,16 +181,20 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Clock = offsetClock,
|
Clock = offsetClock,
|
||||||
Children = new Drawable[]
|
Child = RulesetContainer,
|
||||||
{
|
|
||||||
RulesetContainer,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
hudOverlay = new HUDOverlay
|
hudOverlay = new HUDOverlay
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre
|
Origin = Anchor.Centre
|
||||||
},
|
},
|
||||||
|
breakOverlay = new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Clock = decoupledClock,
|
||||||
|
Breaks = beatmap.Breaks
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
failOverlay = new FailOverlay
|
failOverlay = new FailOverlay
|
||||||
@ -222,6 +228,8 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
hudOverlay.ModDisplay.Current.BindTo(working.Mods);
|
hudOverlay.ModDisplay.Current.BindTo(working.Mods);
|
||||||
|
|
||||||
|
breakOverlay.BindProcessor(scoreProcessor);
|
||||||
|
|
||||||
// Bind ScoreProcessor to ourselves
|
// Bind ScoreProcessor to ourselves
|
||||||
scoreProcessor.AllJudged += onCompletion;
|
scoreProcessor.AllJudged += onCompletion;
|
||||||
scoreProcessor.Failed += onFail;
|
scoreProcessor.Failed += onFail;
|
||||||
|
@ -177,6 +177,8 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
public Action<BeatmapSetInfo> RestoreRequested;
|
public Action<BeatmapSetInfo> RestoreRequested;
|
||||||
|
|
||||||
|
public Action<BeatmapInfo> EditRequested;
|
||||||
|
|
||||||
public Action<BeatmapInfo> HideDifficultyRequested;
|
public Action<BeatmapInfo> HideDifficultyRequested;
|
||||||
|
|
||||||
public void SelectNext(int direction = 1, bool skipDifficulties = true)
|
public void SelectNext(int direction = 1, bool skipDifficulties = true)
|
||||||
@ -347,6 +349,7 @@ namespace osu.Game.Screens.Select
|
|||||||
StartRequested = b => StartRequested?.Invoke(),
|
StartRequested = b => StartRequested?.Invoke(),
|
||||||
DeleteRequested = b => DeleteRequested?.Invoke(b),
|
DeleteRequested = b => DeleteRequested?.Invoke(b),
|
||||||
RestoreHiddenRequested = s => RestoreRequested?.Invoke(s),
|
RestoreHiddenRequested = s => RestoreRequested?.Invoke(s),
|
||||||
|
EditRequested = b => EditRequested?.Invoke(b),
|
||||||
HideDifficultyRequested = b => HideDifficultyRequested?.Invoke(b),
|
HideDifficultyRequested = b => HideDifficultyRequested?.Invoke(b),
|
||||||
State = BeatmapGroupState.Collapsed
|
State = BeatmapGroupState.Collapsed
|
||||||
};
|
};
|
||||||
|
@ -19,6 +19,7 @@ using osu.Game.Graphics;
|
|||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Screens.Backgrounds;
|
using osu.Game.Screens.Backgrounds;
|
||||||
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Select.Options;
|
using osu.Game.Screens.Select.Options;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Select
|
namespace osu.Game.Screens.Select
|
||||||
@ -108,6 +109,7 @@ namespace osu.Game.Screens.Select
|
|||||||
BeatmapsChanged = carouselBeatmapsLoaded,
|
BeatmapsChanged = carouselBeatmapsLoaded,
|
||||||
DeleteRequested = promptDelete,
|
DeleteRequested = promptDelete,
|
||||||
RestoreRequested = s => { foreach (var b in s.Beatmaps) manager.Restore(b); },
|
RestoreRequested = s => { foreach (var b in s.Beatmaps) manager.Restore(b); },
|
||||||
|
EditRequested = editRequested,
|
||||||
HideDifficultyRequested = b => manager.Hide(b),
|
HideDifficultyRequested = b => manager.Hide(b),
|
||||||
StartRequested = () => carouselRaisedStart(),
|
StartRequested = () => carouselRaisedStart(),
|
||||||
});
|
});
|
||||||
@ -195,6 +197,12 @@ namespace osu.Game.Screens.Select
|
|||||||
carousel.AllowSelection = !Beatmap.Disabled;
|
carousel.AllowSelection = !Beatmap.Disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void editRequested(BeatmapInfo beatmap)
|
||||||
|
{
|
||||||
|
Beatmap.Value = manager.GetWorkingBeatmap(beatmap, Beatmap);
|
||||||
|
Push(new Editor());
|
||||||
|
}
|
||||||
|
|
||||||
private void onBeatmapRestored(BeatmapInfo b) => carousel.UpdateBeatmap(b);
|
private void onBeatmapRestored(BeatmapInfo b) => carousel.UpdateBeatmap(b);
|
||||||
private void onBeatmapHidden(BeatmapInfo b) => carousel.UpdateBeatmap(b);
|
private void onBeatmapHidden(BeatmapInfo b) => carousel.UpdateBeatmap(b);
|
||||||
|
|
||||||
|
91
osu.Game/Tests/Visual/TestCaseBreakOverlay.cs
Normal file
91
osu.Game/Tests/Visual/TestCaseBreakOverlay.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Timing;
|
||||||
|
using osu.Game.Beatmaps.Timing;
|
||||||
|
using osu.Game.Screens.Play.BreaksOverlay;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
internal class TestCaseBreakOverlay : OsuTestCase
|
||||||
|
{
|
||||||
|
public override string Description => @"Tests breaks behavior";
|
||||||
|
|
||||||
|
private readonly BreakOverlay breakOverlay;
|
||||||
|
|
||||||
|
public TestCaseBreakOverlay()
|
||||||
|
{
|
||||||
|
Clock = new FramedClock();
|
||||||
|
|
||||||
|
Child = breakOverlay = new BreakOverlay(true);
|
||||||
|
|
||||||
|
AddStep("2s break", () => startBreak(2000));
|
||||||
|
AddStep("5s break", () => startBreak(5000));
|
||||||
|
AddStep("10s break", () => startBreak(10000));
|
||||||
|
AddStep("15s break", () => startBreak(15000));
|
||||||
|
AddStep("2s, 2s", startMultipleBreaks);
|
||||||
|
AddStep("0.5s, 0.7s, 1s, 2s", startAnotherMultipleBreaks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startBreak(double duration)
|
||||||
|
{
|
||||||
|
breakOverlay.Breaks = new List<BreakPeriod>
|
||||||
|
{
|
||||||
|
new BreakPeriod
|
||||||
|
{
|
||||||
|
StartTime = Clock.CurrentTime,
|
||||||
|
EndTime = Clock.CurrentTime + duration,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startMultipleBreaks()
|
||||||
|
{
|
||||||
|
double currentTime = Clock.CurrentTime;
|
||||||
|
|
||||||
|
breakOverlay.Breaks = new List<BreakPeriod>
|
||||||
|
{
|
||||||
|
new BreakPeriod
|
||||||
|
{
|
||||||
|
StartTime = currentTime,
|
||||||
|
EndTime = currentTime + 2000,
|
||||||
|
},
|
||||||
|
new BreakPeriod
|
||||||
|
{
|
||||||
|
StartTime = currentTime + 4000,
|
||||||
|
EndTime = currentTime + 6000,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startAnotherMultipleBreaks()
|
||||||
|
{
|
||||||
|
double currentTime = Clock.CurrentTime;
|
||||||
|
|
||||||
|
breakOverlay.Breaks = new List<BreakPeriod>
|
||||||
|
{
|
||||||
|
new BreakPeriod // Duration is less than 650 - too short to appear
|
||||||
|
{
|
||||||
|
StartTime = currentTime,
|
||||||
|
EndTime = currentTime + 500,
|
||||||
|
},
|
||||||
|
new BreakPeriod
|
||||||
|
{
|
||||||
|
StartTime = currentTime + 1500,
|
||||||
|
EndTime = currentTime + 2200,
|
||||||
|
},
|
||||||
|
new BreakPeriod
|
||||||
|
{
|
||||||
|
StartTime = currentTime + 3200,
|
||||||
|
EndTime = currentTime + 4200,
|
||||||
|
},
|
||||||
|
new BreakPeriod
|
||||||
|
{
|
||||||
|
StartTime = currentTime + 5200,
|
||||||
|
EndTime = currentTime + 7200,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
public class TestCaseEditorComposeTimeline : OsuTestCase
|
public class TestCaseEditorComposeTimeline : OsuTestCase
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(ScrollableTimeline), typeof(WaveformDisplay) };
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(ScrollableTimeline), typeof(BeatmapWaveformGraph) };
|
||||||
|
|
||||||
private readonly ScrollableTimeline timeline;
|
private readonly ScrollableTimeline timeline;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Screens.Edit.Menus;
|
using osu.Game.Screens.Edit.Menus;
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Items = new[]
|
Items = new[]
|
||||||
{
|
{
|
||||||
new EditorMenuBarItem("File")
|
new MenuItem("File")
|
||||||
{
|
{
|
||||||
Items = new[]
|
Items = new[]
|
||||||
{
|
{
|
||||||
@ -55,7 +56,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
new EditorMenuItem("Exit"),
|
new EditorMenuItem("Exit"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new EditorMenuBarItem("Timing")
|
new MenuItem("Timing")
|
||||||
{
|
{
|
||||||
Items = new[]
|
Items = new[]
|
||||||
{
|
{
|
||||||
@ -78,7 +79,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
new EditorMenuItem("Set Current Position as Preview Point"),
|
new EditorMenuItem("Set Current Position as Preview Point"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new EditorMenuBarItem("Testing")
|
new MenuItem("Testing")
|
||||||
{
|
{
|
||||||
Items = new[]
|
Items = new[]
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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 System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -18,31 +19,39 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
public class TestCasePlayer : OsuTestCase
|
public class TestCasePlayer : OsuTestCase
|
||||||
{
|
{
|
||||||
|
private readonly Type ruleset;
|
||||||
|
|
||||||
protected Player Player;
|
protected Player Player;
|
||||||
private RulesetStore rulesets;
|
|
||||||
|
|
||||||
public override string Description => @"Showing everything to play the game.";
|
public override string Description => @"Showing everything to play the game.";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a TestCase which runs through the Player screen.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ruleset">An optional ruleset type which we want to target. If not provided we'll allow all rulesets to be tested.</param>
|
||||||
|
protected TestCasePlayer(Type ruleset)
|
||||||
|
{
|
||||||
|
this.ruleset = ruleset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestCasePlayer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(RulesetStore rulesets)
|
private void load(RulesetStore rulesets)
|
||||||
{
|
{
|
||||||
this.rulesets = rulesets;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
Add(new Box
|
Add(new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Framework.Graphics.Axes.Both,
|
RelativeSizeAxes = Framework.Graphics.Axes.Both,
|
||||||
Colour = Color4.Black,
|
Colour = Color4.Black,
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (var r in rulesets.Query<RulesetInfo>())
|
string instantiation = ruleset?.AssemblyQualifiedName;
|
||||||
AddStep(r.Name, () => loadPlayerFor(r));
|
|
||||||
|
|
||||||
loadPlayerFor(rulesets.Query<RulesetInfo>().First());
|
foreach (var r in rulesets.Query<RulesetInfo>(rs => rs.Available && (instantiation == null || rs.InstantiationInfo == instantiation)))
|
||||||
|
AddStep(r.Name, () => loadPlayerFor(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual Beatmap CreateBeatmap()
|
protected virtual Beatmap CreateBeatmap()
|
||||||
|
@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
for (int i = 1; i <= 16; i *= 2)
|
for (int i = 1; i <= 16; i *= 2)
|
||||||
{
|
{
|
||||||
var newDisplay = new WaveformDisplay
|
var newDisplay = new BeatmapWaveformGraph
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Resolution = 1f / i
|
Resolution = 1f / i
|
||||||
@ -73,7 +73,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Text = $"Resolution: {(1f / i):0.00}"
|
Text = $"Resolution: {1f / i:0.00}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,6 +266,7 @@
|
|||||||
<Compile Include="Beatmaps\Drawables\BeatmapPanel.cs" />
|
<Compile Include="Beatmaps\Drawables\BeatmapPanel.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\BeatmapSetCover.cs" />
|
<Compile Include="Beatmaps\Drawables\BeatmapSetCover.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\BeatmapSetHeader.cs" />
|
<Compile Include="Beatmaps\Drawables\BeatmapSetHeader.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Screens\Compose\BeatmapWaveformGraph.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\DifficultyColouredContainer.cs" />
|
<Compile Include="Beatmaps\Drawables\DifficultyColouredContainer.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\DifficultyIcon.cs" />
|
<Compile Include="Beatmaps\Drawables\DifficultyIcon.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\Panel.cs" />
|
<Compile Include="Beatmaps\Drawables\Panel.cs" />
|
||||||
@ -274,6 +275,14 @@
|
|||||||
<Compile Include="Beatmaps\Formats\OsuLegacyDecoder.cs" />
|
<Compile Include="Beatmaps\Formats\OsuLegacyDecoder.cs" />
|
||||||
<Compile Include="Beatmaps\IO\ArchiveReader.cs" />
|
<Compile Include="Beatmaps\IO\ArchiveReader.cs" />
|
||||||
<Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" />
|
<Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" />
|
||||||
|
<Compile Include="Screens\Play\BreaksOverlay\ArrowsOverlay.cs" />
|
||||||
|
<Compile Include="Screens\Play\BreaksOverlay\BlurredIcon.cs" />
|
||||||
|
<Compile Include="Screens\Play\BreaksOverlay\BreakOverlay.cs" />
|
||||||
|
<Compile Include="Screens\Play\BreaksOverlay\GlowIcon.cs" />
|
||||||
|
<Compile Include="Screens\Play\BreaksOverlay\InfoContainer.cs" />
|
||||||
|
<Compile Include="Screens\Play\BreaksOverlay\InfoLine.cs" />
|
||||||
|
<Compile Include="Screens\Play\BreaksOverlay\LetterboxOverlay.cs" />
|
||||||
|
<Compile Include="Screens\Play\BreaksOverlay\RemainingTimeCounter.cs" />
|
||||||
<Compile Include="Beatmaps\IO\OszArchiveReader.cs" />
|
<Compile Include="Beatmaps\IO\OszArchiveReader.cs" />
|
||||||
<Compile Include="Beatmaps\Legacy\LegacyBeatmap.cs" />
|
<Compile Include="Beatmaps\Legacy\LegacyBeatmap.cs" />
|
||||||
<Compile Include="Beatmaps\RankStatus.cs" />
|
<Compile Include="Beatmaps\RankStatus.cs" />
|
||||||
@ -615,7 +624,6 @@
|
|||||||
<Compile Include="Screens\Edit\Components\Timelines\Summary\SummaryTimeline.cs" />
|
<Compile Include="Screens\Edit\Components\Timelines\Summary\SummaryTimeline.cs" />
|
||||||
<Compile Include="Screens\Edit\Screens\EditorScreenMode.cs" />
|
<Compile Include="Screens\Edit\Screens\EditorScreenMode.cs" />
|
||||||
<Compile Include="Screens\Edit\Menus\EditorMenuBar.cs" />
|
<Compile Include="Screens\Edit\Menus\EditorMenuBar.cs" />
|
||||||
<Compile Include="Screens\Edit\Menus\EditorMenuBarItem.cs" />
|
|
||||||
<Compile Include="Screens\Edit\Menus\EditorMenuItem.cs" />
|
<Compile Include="Screens\Edit\Menus\EditorMenuItem.cs" />
|
||||||
<Compile Include="Screens\Edit\Menus\EditorMenuItemSpacer.cs" />
|
<Compile Include="Screens\Edit\Menus\EditorMenuItemSpacer.cs" />
|
||||||
<Compile Include="Screens\Edit\Menus\ScreenSelectionTabControl.cs" />
|
<Compile Include="Screens\Edit\Menus\ScreenSelectionTabControl.cs" />
|
||||||
@ -623,7 +631,6 @@
|
|||||||
<Compile Include="Screens\Edit\Screens\EditorScreen.cs" />
|
<Compile Include="Screens\Edit\Screens\EditorScreen.cs" />
|
||||||
<Compile Include="Screens\Edit\Screens\Compose\Compose.cs" />
|
<Compile Include="Screens\Edit\Screens\Compose\Compose.cs" />
|
||||||
<Compile Include="Screens\Edit\Screens\Compose\ScrollableTimeline.cs" />
|
<Compile Include="Screens\Edit\Screens\Compose\ScrollableTimeline.cs" />
|
||||||
<Compile Include="Screens\Edit\Screens\Compose\WaveformDisplay.cs" />
|
|
||||||
<Compile Include="Screens\Loader.cs" />
|
<Compile Include="Screens\Loader.cs" />
|
||||||
<Compile Include="Screens\Menu\Button.cs" />
|
<Compile Include="Screens\Menu\Button.cs" />
|
||||||
<Compile Include="Screens\Menu\ButtonSystem.cs" />
|
<Compile Include="Screens\Menu\ButtonSystem.cs" />
|
||||||
@ -742,6 +749,7 @@
|
|||||||
<Compile Include="Tests\Visual\TestCaseBeatmapOptionsOverlay.cs" />
|
<Compile Include="Tests\Visual\TestCaseBeatmapOptionsOverlay.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseBeatSyncedContainer.cs" />
|
<Compile Include="Tests\Visual\TestCaseBeatSyncedContainer.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseBreadcrumbs.cs" />
|
<Compile Include="Tests\Visual\TestCaseBreadcrumbs.cs" />
|
||||||
|
<Compile Include="Tests\Visual\TestCaseBreakOverlay.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseChatDisplay.cs" />
|
<Compile Include="Tests\Visual\TestCaseChatDisplay.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseContextMenu.cs" />
|
<Compile Include="Tests\Visual\TestCaseContextMenu.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseDialogOverlay.cs" />
|
<Compile Include="Tests\Visual\TestCaseDialogOverlay.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user