mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 20:07:29 +08:00
Merge remote-tracking branch 'refs/remotes/ppy/master' into clickable_users
This commit is contained in:
commit
d61e72b5a3
@ -1 +1 @@
|
||||
Subproject commit cdb031c3a8ef693cd71458c5e19c68127ab72938
|
||||
Subproject commit 9d142a8e009794dfee828392e36025d08577131d
|
@ -10,6 +10,10 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
[TestFixture]
|
||||
public class TestCaseCatchPlayer : Game.Tests.Visual.TestCasePlayer
|
||||
{
|
||||
public TestCaseCatchPlayer() : base(typeof(CatchRuleset))
|
||||
{
|
||||
}
|
||||
|
||||
protected override Beatmap CreateBeatmap()
|
||||
{
|
||||
var beatmap = new Beatmap();
|
||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(CatcherArea),
|
||||
typeof(Catcher),
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
new CatchInputManager(rulesets.GetRuleset(2))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new CatcherArea
|
||||
Child = new Catcher
|
||||
{
|
||||
RelativePositionAxes = Axes.Both,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
|
@ -1,10 +1,12 @@
|
||||
// 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.Graphics;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@ -15,11 +17,15 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container<Drawable> content;
|
||||
private readonly CatcherArea catcherArea;
|
||||
|
||||
private readonly Container catcherContainer;
|
||||
private readonly Catcher catcher;
|
||||
|
||||
public CatchPlayfield()
|
||||
: base(Axes.Y)
|
||||
{
|
||||
Container explodingFruitContainer;
|
||||
|
||||
Reversed.Value = true;
|
||||
|
||||
Size = new Vector2(1);
|
||||
@ -33,16 +39,35 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
catcherArea = new CatcherArea
|
||||
explodingFruitContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
catcherContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
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)
|
||||
{
|
||||
h.Depth = (float)h.HitObject.StartTime;
|
||||
@ -50,7 +75,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
base.Add(h);
|
||||
|
||||
var fruit = (DrawableFruit)h;
|
||||
fruit.CheckPosition = catcherArea.CheckIfWeCanCatch;
|
||||
fruit.CheckPosition = CheckIfWeCanCatch;
|
||||
}
|
||||
|
||||
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
@ -59,7 +84,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre;
|
||||
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="Tests\TestCaseCatcher.cs" />
|
||||
<Compile Include="Tests\TestCaseCatchPlayer.cs" />
|
||||
<Compile Include="UI\CatcherArea.cs" />
|
||||
<Compile Include="UI\Catcher.cs" />
|
||||
<Compile Include="UI\CatchRulesetContainer.cs" />
|
||||
<Compile Include="UI\CatchPlayfield.cs" />
|
||||
<Compile Include="CatchRuleset.cs" />
|
||||
|
@ -55,14 +55,17 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
||||
|
||||
Beatmap<TaikoHitObject> converted = base.ConvertBeatmap(original);
|
||||
|
||||
// Post processing step to transform hit objects with the same start time into strong hits
|
||||
converted.HitObjects = converted.HitObjects.GroupBy(t => t.StartTime).Select(x =>
|
||||
if (original.BeatmapInfo.RulesetID == 3)
|
||||
{
|
||||
TaikoHitObject first = x.First();
|
||||
if (x.Skip(1).Any())
|
||||
first.IsStrong = true;
|
||||
return first;
|
||||
}).ToList();
|
||||
// Post processing step to transform mania hit objects with the same start time into strong hits
|
||||
converted.HitObjects = converted.HitObjects.GroupBy(t => t.StartTime).Select(x =>
|
||||
{
|
||||
TaikoHitObject first = x.First();
|
||||
if (x.Skip(1).Any())
|
||||
first.IsStrong = true;
|
||||
return first;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
@ -58,6 +58,23 @@ namespace osu.Game.Beatmaps
|
||||
ComboColors = original?.ComboColors ?? ComboColors;
|
||||
HitObjects = original?.HitObjects ?? HitObjects;
|
||||
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()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
public class OsuTabItem : TabItem<T>, IHasAccentColour
|
||||
{
|
||||
protected readonly SpriteText Text;
|
||||
private readonly Box box;
|
||||
protected readonly Box Bar;
|
||||
|
||||
private Color4 accentColour;
|
||||
public Color4 AccentColour
|
||||
@ -77,13 +77,13 @@ namespace osu.Game.Graphics.UserInterface
|
||||
|
||||
private void fadeActive()
|
||||
{
|
||||
box.FadeIn(transition_length, Easing.OutQuint);
|
||||
Bar.FadeIn(transition_length, Easing.OutQuint);
|
||||
Text.FadeColour(Color4.White, transition_length, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void fadeInactive()
|
||||
{
|
||||
box.FadeOut(transition_length, Easing.OutQuint);
|
||||
Bar.FadeOut(transition_length, Easing.OutQuint);
|
||||
Text.FadeColour(AccentColour, transition_length, Easing.OutQuint);
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold", // Font should only turn bold when active?
|
||||
},
|
||||
box = new Box
|
||||
Bar = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
|
@ -38,7 +38,6 @@ namespace osu.Game.Rulesets
|
||||
|
||||
protected override void Prepare(bool reset = false)
|
||||
{
|
||||
|
||||
Connection.CreateTable<RulesetInfo>();
|
||||
|
||||
if (reset)
|
||||
|
@ -32,16 +32,11 @@ namespace osu.Game.Screens.Edit
|
||||
Height = 40,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex("111")
|
||||
},
|
||||
new EditorMenuBar
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
X = 100,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Items = new[]
|
||||
{
|
||||
new EditorMenuBarItem("File")
|
||||
|
@ -19,8 +19,20 @@ namespace osu.Game.Screens.Edit.Menus
|
||||
public EditorMenuBar()
|
||||
: base(Direction.Horizontal, true)
|
||||
{
|
||||
ItemsContainer.Padding = new MarginPadding(0);
|
||||
BackgroundColour = Color4.Transparent;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
ItemsContainer.Padding = new MarginPadding { Left = 100 };
|
||||
BackgroundColour = OsuColour.FromHex("111");
|
||||
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new ScreenSelectionTabControl
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
X = -15
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override Framework.Graphics.UserInterface.Menu CreateSubMenu() => new SubMenu();
|
||||
@ -29,27 +41,35 @@ namespace osu.Game.Screens.Edit.Menus
|
||||
|
||||
private class DrawableEditorBarMenuItem : DrawableOsuMenuItem
|
||||
{
|
||||
private Color4 openedForegroundColour;
|
||||
private Color4 openedBackgroundColour;
|
||||
private BackgroundBox background;
|
||||
|
||||
public DrawableEditorBarMenuItem(MenuItem item)
|
||||
: base(item)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft;
|
||||
Origin = Anchor.CentreLeft;
|
||||
|
||||
StateChanged += stateChanged;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
ForegroundColour = ForegroundColourHover = colours.BlueLight;
|
||||
BackgroundColour = BackgroundColourHover = Color4.Transparent;
|
||||
openedForegroundColour = Color4.White;
|
||||
openedBackgroundColour = colours.Gray3;
|
||||
ForegroundColour = colours.BlueLight;
|
||||
BackgroundColour = Color4.Transparent;
|
||||
ForegroundColourHover = Color4.White;
|
||||
BackgroundColourHover = colours.Gray3;
|
||||
}
|
||||
|
||||
public override void SetFlowDirection(Direction direction)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
protected override void UpdateBackgroundColour()
|
||||
{
|
||||
if (State == MenuItemState.Selected)
|
||||
Background.FadeColour(openedBackgroundColour);
|
||||
Background.FadeColour(BackgroundColourHover);
|
||||
else
|
||||
base.UpdateBackgroundColour();
|
||||
}
|
||||
@ -57,24 +77,58 @@ namespace osu.Game.Screens.Edit.Menus
|
||||
protected override void UpdateForegroundColour()
|
||||
{
|
||||
if (State == MenuItemState.Selected)
|
||||
Foreground.FadeColour(openedForegroundColour);
|
||||
Foreground.FadeColour(ForegroundColourHover);
|
||||
else
|
||||
base.UpdateForegroundColour();
|
||||
}
|
||||
|
||||
protected override Drawable CreateBackground() => new Container
|
||||
private void stateChanged(MenuItemState newState)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Child = new Container
|
||||
if (newState == MenuItemState.Selected)
|
||||
background.Expand();
|
||||
else
|
||||
background.Contract();
|
||||
}
|
||||
|
||||
protected override Drawable CreateBackground() => background = new BackgroundBox();
|
||||
protected override DrawableOsuMenuItem.TextContainer CreateTextContainer() => new TextContainer();
|
||||
|
||||
private new class TextContainer : DrawableOsuMenuItem.TextContainer
|
||||
{
|
||||
public TextContainer()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 2,
|
||||
Masking = true,
|
||||
CornerRadius = 4,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
NormalText.TextSize = BoldText.TextSize = 14;
|
||||
NormalText.Margin = BoldText.Margin = new MarginPadding { Horizontal = 10, Vertical = MARGIN_VERTICAL };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class BackgroundBox : CompositeDrawable
|
||||
{
|
||||
private readonly Container innerBackground;
|
||||
|
||||
public BackgroundBox()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Masking = true;
|
||||
InternalChild = innerBackground = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
CornerRadius = 4,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expands the background such that it doesn't show the bottom corners.
|
||||
/// </summary>
|
||||
public void Expand() => innerBackground.Height = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Contracts the background such that it shows the bottom corners.
|
||||
/// </summary>
|
||||
public void Contract() => innerBackground.Height = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private class SubMenu : OsuMenu
|
||||
|
85
osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs
Normal file
85
osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs
Normal file
@ -0,0 +1,85 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using OpenTK;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Menus
|
||||
{
|
||||
public class ScreenSelectionTabControl : OsuTabControl<EditorScreenMode>
|
||||
{
|
||||
public ScreenSelectionTabControl()
|
||||
{
|
||||
AutoSizeAxes = Axes.X;
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
|
||||
TabContainer.RelativeSizeAxes &= ~Axes.X;
|
||||
TabContainer.AutoSizeAxes = Axes.X;
|
||||
TabContainer.Padding = new MarginPadding();
|
||||
|
||||
Add(new Box
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
Colour = Color4.White.Opacity(0.2f),
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
AccentColour = colours.Yellow;
|
||||
}
|
||||
|
||||
protected override Dropdown<EditorScreenMode> CreateDropdown() => null;
|
||||
|
||||
protected override TabItem<EditorScreenMode> CreateTabItem(EditorScreenMode value) => new TabItem(value);
|
||||
|
||||
private class TabItem : OsuTabItem
|
||||
{
|
||||
private const float transition_length = 250;
|
||||
|
||||
public TabItem(EditorScreenMode value)
|
||||
: base(value)
|
||||
{
|
||||
Text.Margin = new MarginPadding();
|
||||
Text.Anchor = Anchor.CentreLeft;
|
||||
Text.Origin = Anchor.CentreLeft;
|
||||
}
|
||||
|
||||
protected override void OnActivated()
|
||||
{
|
||||
base.OnActivated();
|
||||
Bar.ScaleTo(new Vector2(1, 5), transition_length, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void OnDeactivated()
|
||||
{
|
||||
base.OnDeactivated();
|
||||
Bar.ScaleTo(Vector2.One, transition_length, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum EditorScreenMode
|
||||
{
|
||||
[Description("compose")]
|
||||
Compose,
|
||||
[Description("design")]
|
||||
Design,
|
||||
[Description("timing")]
|
||||
Timing,
|
||||
[Description("song")]
|
||||
SongSetup
|
||||
}
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
// 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 osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Edit.Menus;
|
||||
|
||||
@ -9,74 +12,82 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseEditorMenuBar : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(EditorMenuBar), typeof(ScreenSelectionTabControl) };
|
||||
|
||||
public TestCaseEditorMenuBar()
|
||||
{
|
||||
Add(new EditorMenuBar
|
||||
Add(new Container
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 50,
|
||||
Y = 50,
|
||||
Items = new[]
|
||||
Child = new EditorMenuBar
|
||||
{
|
||||
new EditorMenuBarItem("File")
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Items = new[]
|
||||
{
|
||||
Items = new[]
|
||||
new EditorMenuBarItem("File")
|
||||
{
|
||||
new EditorMenuItem("Clear All Notes"),
|
||||
new EditorMenuItem("Open Difficulty..."),
|
||||
new EditorMenuItem("Save"),
|
||||
new EditorMenuItem("Create a new Difficulty..."),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Revert to Saved"),
|
||||
new EditorMenuItem("Revert to Saved (Full)"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Test Beatmap"),
|
||||
new EditorMenuItem("Open AiMod"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Upload Beatmap..."),
|
||||
new EditorMenuItem("Export Package"),
|
||||
new EditorMenuItem("Export Map Package"),
|
||||
new EditorMenuItem("Import from..."),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Open Song Folder"),
|
||||
new EditorMenuItem("Open .osu in Notepad"),
|
||||
new EditorMenuItem("Open .osb in Notepad"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Exit"),
|
||||
}
|
||||
},
|
||||
new EditorMenuBarItem("Timing")
|
||||
{
|
||||
Items = new[]
|
||||
Items = new[]
|
||||
{
|
||||
new EditorMenuItem("Clear All Notes"),
|
||||
new EditorMenuItem("Open Difficulty..."),
|
||||
new EditorMenuItem("Save"),
|
||||
new EditorMenuItem("Create a new Difficulty..."),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Revert to Saved"),
|
||||
new EditorMenuItem("Revert to Saved (Full)"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Test Beatmap"),
|
||||
new EditorMenuItem("Open AiMod"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Upload Beatmap..."),
|
||||
new EditorMenuItem("Export Package"),
|
||||
new EditorMenuItem("Export Map Package"),
|
||||
new EditorMenuItem("Import from..."),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Open Song Folder"),
|
||||
new EditorMenuItem("Open .osu in Notepad"),
|
||||
new EditorMenuItem("Open .osb in Notepad"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Exit"),
|
||||
}
|
||||
},
|
||||
new EditorMenuBarItem("Timing")
|
||||
{
|
||||
new EditorMenuItem("Time Signature"),
|
||||
new EditorMenuItem("Metronome Clicks"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Add Timing Section"),
|
||||
new EditorMenuItem("Add Inheriting Section"),
|
||||
new EditorMenuItem("Reset Current Section"),
|
||||
new EditorMenuItem("Delete Timing Section"),
|
||||
new EditorMenuItem("Resnap Current Section"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Timing Setup"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Resnap All Notes", MenuItemType.Destructive),
|
||||
new EditorMenuItem("Move all notes in time...", MenuItemType.Destructive),
|
||||
new EditorMenuItem("Recalculate Slider Lengths", MenuItemType.Destructive),
|
||||
new EditorMenuItem("Delete All Timing Sections", MenuItemType.Destructive),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Set Current Position as Preview Point"),
|
||||
}
|
||||
},
|
||||
new EditorMenuBarItem("Testing")
|
||||
{
|
||||
Items = new[]
|
||||
Items = new[]
|
||||
{
|
||||
new EditorMenuItem("Time Signature"),
|
||||
new EditorMenuItem("Metronome Clicks"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Add Timing Section"),
|
||||
new EditorMenuItem("Add Inheriting Section"),
|
||||
new EditorMenuItem("Reset Current Section"),
|
||||
new EditorMenuItem("Delete Timing Section"),
|
||||
new EditorMenuItem("Resnap Current Section"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Timing Setup"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Resnap All Notes", MenuItemType.Destructive),
|
||||
new EditorMenuItem("Move all notes in time...", MenuItemType.Destructive),
|
||||
new EditorMenuItem("Recalculate Slider Lengths", MenuItemType.Destructive),
|
||||
new EditorMenuItem("Delete All Timing Sections", MenuItemType.Destructive),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Set Current Position as Preview Point"),
|
||||
}
|
||||
},
|
||||
new EditorMenuBarItem("Testing")
|
||||
{
|
||||
new EditorMenuItem("Item 1"),
|
||||
new EditorMenuItem("Item 2"),
|
||||
new EditorMenuItem("Item 3"),
|
||||
}
|
||||
},
|
||||
Items = new[]
|
||||
{
|
||||
new EditorMenuItem("Item 1"),
|
||||
new EditorMenuItem("Item 2"),
|
||||
new EditorMenuItem("Item 3"),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@ -18,31 +19,39 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCasePlayer : OsuTestCase
|
||||
{
|
||||
private readonly Type ruleset;
|
||||
|
||||
protected Player Player;
|
||||
private RulesetStore rulesets;
|
||||
|
||||
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]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
this.rulesets = rulesets;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Add(new Box
|
||||
{
|
||||
RelativeSizeAxes = Framework.Graphics.Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
});
|
||||
|
||||
foreach (var r in rulesets.Query<RulesetInfo>())
|
||||
AddStep(r.Name, () => loadPlayerFor(r));
|
||||
string instantiation = ruleset?.AssemblyQualifiedName;
|
||||
|
||||
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()
|
||||
|
@ -617,6 +617,7 @@
|
||||
<Compile Include="Screens\Edit\Menus\EditorMenuBarItem.cs" />
|
||||
<Compile Include="Screens\Edit\Menus\EditorMenuItem.cs" />
|
||||
<Compile Include="Screens\Edit\Menus\EditorMenuItemSpacer.cs" />
|
||||
<Compile Include="Screens\Edit\Menus\ScreenSelectionTabControl.cs" />
|
||||
<Compile Include="Screens\Loader.cs" />
|
||||
<Compile Include="Screens\Menu\Button.cs" />
|
||||
<Compile Include="Screens\Menu\ButtonSystem.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user