1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-19 14:42:56 +08:00

Merge remote-tracking branch 'refs/remotes/ppy/master' into comments_api

This commit is contained in:
Andrei Zavatski 2019-10-08 12:42:59 +03:00
commit 70e1d731ad
34 changed files with 331 additions and 259 deletions

View File

@ -6,7 +6,6 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Edit.Blueprints;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables;
@ -39,6 +38,8 @@ namespace osu.Game.Rulesets.Mania.Tests
AccentColour = { Value = OsuColour.Gray(0.3f) } AccentColour = { Value = OsuColour.Gray(0.3f) }
} }
}; };
AddBlueprint(new HoldNoteSelectionBlueprint(drawableObject));
} }
protected override void Update() protected override void Update()
@ -51,7 +52,5 @@ namespace osu.Game.Rulesets.Mania.Tests
nested.Y = (float)(-finalPosition * content.DrawHeight); nested.Y = (float)(-finalPosition * content.DrawHeight);
} }
} }
protected override SelectionBlueprint CreateBlueprint() => new HoldNoteSelectionBlueprint(drawableObject);
} }
} }

View File

@ -5,7 +5,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Edit.Blueprints;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables;
@ -17,8 +16,6 @@ namespace osu.Game.Rulesets.Mania.Tests
{ {
public class TestSceneNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene public class TestSceneNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene
{ {
private readonly DrawableNote drawableObject;
protected override Container<Drawable> Content => content ?? base.Content; protected override Container<Drawable> Content => content ?? base.Content;
private readonly Container content; private readonly Container content;
@ -27,6 +24,8 @@ namespace osu.Game.Rulesets.Mania.Tests
var note = new Note { Column = 0 }; var note = new Note { Column = 0 };
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
DrawableNote drawableObject;
base.Content.Child = content = new ScrollingTestContainer(ScrollingDirection.Down) base.Content.Child = content = new ScrollingTestContainer(ScrollingDirection.Down)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
@ -34,8 +33,8 @@ namespace osu.Game.Rulesets.Mania.Tests
Size = new Vector2(50, 20), Size = new Vector2(50, 20),
Child = drawableObject = new DrawableNote(note) Child = drawableObject = new DrawableNote(note)
}; };
}
protected override SelectionBlueprint CreateBlueprint() => new NoteSelectionBlueprint(drawableObject); AddBlueprint(new NoteSelectionBlueprint(drawableObject));
}
} }
} }

View File

@ -1,10 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
@ -14,16 +15,51 @@ namespace osu.Game.Rulesets.Osu.Tests
{ {
public class TestSceneHitCircleSelectionBlueprint : SelectionBlueprintTestScene public class TestSceneHitCircleSelectionBlueprint : SelectionBlueprintTestScene
{ {
private readonly DrawableHitCircle drawableObject; private HitCircle hitCircle;
private DrawableHitCircle drawableObject;
private TestBlueprint blueprint;
public TestSceneHitCircleSelectionBlueprint() [SetUp]
public void Setup() => Schedule(() =>
{ {
var hitCircle = new HitCircle { Position = new Vector2(256, 192) }; Clear();
hitCircle = new HitCircle { Position = new Vector2(256, 192) };
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }); hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 });
Add(drawableObject = new DrawableHitCircle(hitCircle)); Add(drawableObject = new DrawableHitCircle(hitCircle));
AddBlueprint(blueprint = new TestBlueprint(drawableObject));
});
[Test]
public void TestInitialState()
{
AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position);
} }
protected override SelectionBlueprint CreateBlueprint() => new HitCircleSelectionBlueprint(drawableObject); [Test]
public void TestMoveHitObject()
{
AddStep("move hitobject", () => hitCircle.Position = new Vector2(300, 225));
AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position);
}
[Test]
public void TestMoveAfterApplyingDefaults()
{
AddStep("apply defaults", () => hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }));
AddStep("move hitobject", () => hitCircle.Position = new Vector2(300, 225));
AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position);
}
private class TestBlueprint : HitCircleSelectionBlueprint
{
public new HitCirclePiece CirclePiece => base.CirclePiece;
public TestBlueprint(DrawableHitCircle hitCircle)
: base(hitCircle)
{
}
}
} }
} }

View File

@ -3,11 +3,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
@ -29,11 +31,16 @@ namespace osu.Game.Rulesets.Osu.Tests
typeof(PathControlPointPiece) typeof(PathControlPointPiece)
}; };
private readonly DrawableSlider drawableObject; private Slider slider;
private DrawableSlider drawableObject;
private TestSliderBlueprint blueprint;
public TestSceneSliderSelectionBlueprint() [SetUp]
public void Setup() => Schedule(() =>
{ {
var slider = new Slider Clear();
slider = new Slider
{ {
Position = new Vector2(256, 192), Position = new Vector2(256, 192),
Path = new SliderPath(PathType.Bezier, new[] Path = new SliderPath(PathType.Bezier, new[]
@ -47,8 +54,71 @@ namespace osu.Game.Rulesets.Osu.Tests
slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }); slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 });
Add(drawableObject = new DrawableSlider(slider)); Add(drawableObject = new DrawableSlider(slider));
AddBlueprint(blueprint = new TestSliderBlueprint(drawableObject));
});
[Test]
public void TestInitialState()
{
checkPositions();
} }
protected override SelectionBlueprint CreateBlueprint() => new SliderSelectionBlueprint(drawableObject); [Test]
public void TestMoveHitObject()
{
moveHitObject();
checkPositions();
}
[Test]
public void TestMoveAfterApplyingDefaults()
{
AddStep("apply defaults", () => slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }));
moveHitObject();
checkPositions();
}
private void moveHitObject()
{
AddStep("move hitobject", () =>
{
slider.Position = new Vector2(300, 225);
});
}
private void checkPositions()
{
AddAssert("body positioned correctly", () => blueprint.BodyPiece.Position == slider.Position);
AddAssert("head positioned correctly",
() => Precision.AlmostEquals(blueprint.HeadBlueprint.CirclePiece.ScreenSpaceDrawQuad.Centre, drawableObject.HeadCircle.ScreenSpaceDrawQuad.Centre));
AddAssert("tail positioned correctly",
() => Precision.AlmostEquals(blueprint.TailBlueprint.CirclePiece.ScreenSpaceDrawQuad.Centre, drawableObject.TailCircle.ScreenSpaceDrawQuad.Centre));
}
private class TestSliderBlueprint : SliderSelectionBlueprint
{
public new SliderBodyPiece BodyPiece => base.BodyPiece;
public new TestSliderCircleBlueprint HeadBlueprint => (TestSliderCircleBlueprint)base.HeadBlueprint;
public new TestSliderCircleBlueprint TailBlueprint => (TestSliderCircleBlueprint)base.TailBlueprint;
public TestSliderBlueprint(DrawableSlider slider)
: base(slider)
{
}
protected override SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new TestSliderCircleBlueprint(slider, position);
}
private class TestSliderCircleBlueprint : SliderCircleSelectionBlueprint
{
public new HitCirclePiece CirclePiece => base.CirclePiece;
public TestSliderCircleBlueprint(DrawableSlider slider, SliderPosition position)
: base(slider, position)
{
}
}
} }
} }

View File

@ -7,7 +7,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
@ -25,8 +24,6 @@ namespace osu.Game.Rulesets.Osu.Tests
typeof(SpinnerPiece) typeof(SpinnerPiece)
}; };
private readonly DrawableSpinner drawableSpinner;
public TestSceneSpinnerSelectionBlueprint() public TestSceneSpinnerSelectionBlueprint()
{ {
var spinner = new Spinner var spinner = new Spinner
@ -35,16 +32,19 @@ namespace osu.Game.Rulesets.Osu.Tests
StartTime = -1000, StartTime = -1000,
EndTime = 2000 EndTime = 2000
}; };
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }); spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 });
DrawableSpinner drawableSpinner;
Add(new Container Add(new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.5f), Size = new Vector2(0.5f),
Child = drawableSpinner = new DrawableSpinner(spinner) Child = drawableSpinner = new DrawableSpinner(spinner)
}); });
}
protected override SelectionBlueprint CreateBlueprint() => new SpinnerSelectionBlueprint(drawableSpinner) { Size = new Vector2(0.5f) }; AddBlueprint(new SpinnerSelectionBlueprint(drawableSpinner) { Size = new Vector2(0.5f) });
}
} }
} }

View File

@ -0,0 +1,25 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints
{
/// <summary>
/// A piece of a selection or placement blueprint which visualises an <see cref="OsuHitObject"/>.
/// </summary>
/// <typeparam name="T">The type of <see cref="OsuHitObject"/> which this <see cref="BlueprintPiece{T}"/> visualises.</typeparam>
public abstract class BlueprintPiece<T> : CompositeDrawable
where T : OsuHitObject
{
/// <summary>
/// Updates this <see cref="BlueprintPiece{T}"/> using the properties of a <see cref="OsuHitObject"/>.
/// </summary>
/// <param name="hitObject">The <see cref="OsuHitObject"/> to reference properties from.</param>
public virtual void UpdateFrom(T hitObject)
{
Position = hitObject.Position;
}
}
}

View File

@ -10,18 +10,13 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components
{ {
public class HitCirclePiece : HitObjectPiece public class HitCirclePiece : BlueprintPiece<HitCircle>
{ {
private readonly HitCircle hitCircle; public HitCirclePiece()
public HitCirclePiece(HitCircle hitCircle)
: base(hitCircle)
{ {
this.hitCircle = hitCircle;
Origin = Anchor.Centre; Origin = Anchor.Centre;
Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Scale = new Vector2(hitCircle.Scale);
CornerRadius = Size.X / 2; CornerRadius = Size.X / 2;
InternalChild = new RingPiece(); InternalChild = new RingPiece();
@ -31,12 +26,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
Colour = colours.Yellow; Colour = colours.Yellow;
PositionBindable.BindValueChanged(_ => UpdatePosition(), true);
StackHeightBindable.BindValueChanged(_ => UpdatePosition());
ScaleBindable.BindValueChanged(scale => Scale = new Vector2(scale.NewValue), true);
} }
protected virtual void UpdatePosition() => Position = hitCircle.StackedPosition; public override void UpdateFrom(HitCircle hitObject)
{
base.UpdateFrom(hitObject);
Scale = new Vector2(hitObject.Scale);
}
} }
} }

View File

@ -13,10 +13,19 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
{ {
public new HitCircle HitObject => (HitCircle)base.HitObject; public new HitCircle HitObject => (HitCircle)base.HitObject;
private readonly HitCirclePiece circlePiece;
public HitCirclePlacementBlueprint() public HitCirclePlacementBlueprint()
: base(new HitCircle()) : base(new HitCircle())
{ {
InternalChild = new HitCirclePiece(HitObject); InternalChild = circlePiece = new HitCirclePiece();
}
protected override void Update()
{
base.Update();
circlePiece.UpdateFrom(HitObject);
} }
protected override bool OnClick(ClickEvent e) protected override bool OnClick(ClickEvent e)

View File

@ -7,12 +7,21 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
{ {
public class HitCircleSelectionBlueprint : OsuSelectionBlueprint public class HitCircleSelectionBlueprint : OsuSelectionBlueprint<HitCircle>
{ {
protected readonly HitCirclePiece CirclePiece;
public HitCircleSelectionBlueprint(DrawableHitCircle hitCircle) public HitCircleSelectionBlueprint(DrawableHitCircle hitCircle)
: base(hitCircle) : base(hitCircle)
{ {
InternalChild = new HitCirclePiece((HitCircle)hitCircle.HitObject); InternalChild = CirclePiece = new HitCirclePiece();
}
protected override void Update()
{
base.Update();
CirclePiece.UpdateFrom(HitObject);
} }
} }
} }

View File

@ -1,36 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Osu.Objects;
using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints
{
/// <summary>
/// A piece of a blueprint which responds to changes in the state of a <see cref="OsuHitObject"/>.
/// </summary>
public abstract class HitObjectPiece : CompositeDrawable
{
protected readonly IBindable<Vector2> PositionBindable = new Bindable<Vector2>();
protected readonly IBindable<int> StackHeightBindable = new Bindable<int>();
protected readonly IBindable<float> ScaleBindable = new Bindable<float>();
private readonly OsuHitObject hitObject;
protected HitObjectPiece(OsuHitObject hitObject)
{
this.hitObject = hitObject;
}
[BackgroundDependencyLoader]
private void load()
{
PositionBindable.BindTo(hitObject.PositionBindable);
StackHeightBindable.BindTo(hitObject.StackHeightBindable);
ScaleBindable.BindTo(hitObject.ScaleBindable);
}
}
}

View File

@ -7,11 +7,12 @@ using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints namespace osu.Game.Rulesets.Osu.Edit.Blueprints
{ {
public class OsuSelectionBlueprint : SelectionBlueprint public abstract class OsuSelectionBlueprint<T> : SelectionBlueprint
where T : OsuHitObject
{ {
protected OsuHitObject OsuObject => (OsuHitObject)HitObject.HitObject; protected new T HitObject => (T)base.HitObject.HitObject;
public OsuSelectionBlueprint(DrawableHitObject hitObject) protected OsuSelectionBlueprint(DrawableHitObject hitObject)
: base(hitObject) : base(hitObject)
{ {
} }

View File

@ -1,32 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints
{
/// <summary>
/// A piece of a blueprint which responds to changes in the state of a <see cref="Slider"/>.
/// </summary>
public abstract class SliderPiece : HitObjectPiece
{
protected readonly IBindable<SliderPath> PathBindable = new Bindable<SliderPath>();
private readonly Slider slider;
protected SliderPiece(Slider slider)
: base(slider)
{
this.slider = slider;
}
[BackgroundDependencyLoader]
private void load()
{
PathBindable.BindTo(slider.PathBindable);
}
}
}

View File

@ -14,7 +14,7 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{ {
public class PathControlPointPiece : CompositeDrawable public class PathControlPointPiece : BlueprintPiece<Slider>
{ {
private readonly Slider slider; private readonly Slider slider;
private readonly int index; private readonly int index;

View File

@ -1,35 +1,29 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{ {
public class PathControlPointVisualiser : SliderPiece public class PathControlPointVisualiser : CompositeDrawable
{ {
private readonly Slider slider; private readonly Slider slider;
private readonly Container<PathControlPointPiece> pieces; private readonly Container<PathControlPointPiece> pieces;
public PathControlPointVisualiser(Slider slider) public PathControlPointVisualiser(Slider slider)
: base(slider)
{ {
this.slider = slider; this.slider = slider;
InternalChild = pieces = new Container<PathControlPointPiece> { RelativeSizeAxes = Axes.Both }; InternalChild = pieces = new Container<PathControlPointPiece> { RelativeSizeAxes = Axes.Both };
} }
[BackgroundDependencyLoader] protected override void Update()
private void load()
{ {
PathBindable.BindValueChanged(_ => updatePathControlPoints(), true); base.Update();
}
private void updatePathControlPoints()
{
while (slider.Path.ControlPoints.Length > pieces.Count) while (slider.Path.ControlPoints.Length > pieces.Count)
pieces.Add(new PathControlPointPiece(slider, pieces.Count)); pieces.Add(new PathControlPointPiece(slider, pieces.Count));
while (slider.Path.ControlPoints.Length < pieces.Count) while (slider.Path.ControlPoints.Length < pieces.Count)

View File

@ -11,19 +11,15 @@ using osuTK.Graphics;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{ {
public class SliderBodyPiece : SliderPiece public class SliderBodyPiece : BlueprintPiece<Slider>
{ {
private readonly Slider slider;
private readonly ManualSliderBody body; private readonly ManualSliderBody body;
public SliderBodyPiece(Slider slider) public SliderBodyPiece()
: base(slider)
{ {
this.slider = slider;
InternalChild = body = new ManualSliderBody InternalChild = body = new ManualSliderBody
{ {
AccentColour = Color4.Transparent, AccentColour = Color4.Transparent
}; };
} }
@ -31,19 +27,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
body.BorderColour = colours.Yellow; body.BorderColour = colours.Yellow;
PositionBindable.BindValueChanged(_ => updatePosition(), true);
ScaleBindable.BindValueChanged(scale => body.PathRadius = scale.NewValue * OsuHitObject.OBJECT_RADIUS, true);
} }
private void updatePosition() => Position = slider.StackedPosition; public override void UpdateFrom(Slider hitObject)
protected override void Update()
{ {
base.Update(); base.UpdateFrom(hitObject);
body.PathRadius = hitObject.Scale * OsuHitObject.OBJECT_RADIUS;
var vertices = new List<Vector2>(); var vertices = new List<Vector2>();
slider.Path.GetPathToProgress(vertices, 0, 1); hitObject.Path.GetPathToProgress(vertices, 0, 1);
body.SetVertices(vertices); body.SetVertices(vertices);

View File

@ -1,47 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
public class SliderCirclePiece : HitCirclePiece
{
private readonly IBindable<SliderPath> pathBindable = new Bindable<SliderPath>();
private readonly Slider slider;
private readonly SliderPosition position;
public SliderCirclePiece(Slider slider, SliderPosition position)
: base(slider.HeadCircle)
{
this.slider = slider;
this.position = position;
}
[BackgroundDependencyLoader]
private void load()
{
pathBindable.BindTo(slider.PathBindable);
pathBindable.BindValueChanged(_ => UpdatePosition(), true);
}
protected override void UpdatePosition()
{
switch (position)
{
case SliderPosition.Start:
Position = slider.StackedPosition + slider.Path.PositionAt(0);
break;
case SliderPosition.End:
Position = slider.StackedPosition + slider.Path.PositionAt(1);
break;
}
}
}
}

View File

@ -1,22 +1,34 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{ {
public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint<Slider>
{ {
public SliderCircleSelectionBlueprint(DrawableOsuHitObject hitObject, Slider slider, SliderPosition position) protected readonly HitCirclePiece CirclePiece;
: base(hitObject)
private readonly SliderPosition position;
public SliderCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position)
: base(slider)
{ {
InternalChild = new SliderCirclePiece(slider, position); this.position = position;
InternalChild = CirclePiece = new HitCirclePiece();
Select(); Select();
} }
protected override void Update()
{
base.Update();
CirclePiece.UpdateFrom(position == SliderPosition.Start ? HitObject.HeadCircle : HitObject.TailCircle);
}
// Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input. // Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input.
public override bool HandlePositionalInput => false; public override bool HandlePositionalInput => false;
} }

View File

@ -11,6 +11,7 @@ using osu.Game.Graphics;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
using osuTK; using osuTK;
using osuTK.Input; using osuTK.Input;
@ -21,6 +22,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{ {
public new Objects.Slider HitObject => (Objects.Slider)base.HitObject; public new Objects.Slider HitObject => (Objects.Slider)base.HitObject;
private SliderBodyPiece bodyPiece;
private HitCirclePiece headCirclePiece;
private HitCirclePiece tailCirclePiece;
private readonly List<Segment> segments = new List<Segment>(); private readonly List<Segment> segments = new List<Segment>();
private Vector2 cursor; private Vector2 cursor;
@ -38,9 +43,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{ {
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new SliderBodyPiece(HitObject), bodyPiece = new SliderBodyPiece(),
new SliderCirclePiece(HitObject, SliderPosition.Start), headCirclePiece = new HitCirclePiece(),
new SliderCirclePiece(HitObject, SliderPosition.End), tailCirclePiece = new HitCirclePiece(),
new PathControlPointVisualiser(HitObject), new PathControlPointVisualiser(HitObject),
}; };
@ -120,6 +125,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{ {
var newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray(); var newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray();
HitObject.Path = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints); HitObject.Path = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints);
bodyPiece.UpdateFrom(HitObject);
headCirclePiece.UpdateFrom(HitObject.HeadCircle);
tailCirclePiece.UpdateFrom(HitObject.TailCircle);
} }
private void setState(PlacementState newState) private void setState(PlacementState newState)

View File

@ -9,9 +9,11 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{ {
public class SliderSelectionBlueprint : OsuSelectionBlueprint public class SliderSelectionBlueprint : OsuSelectionBlueprint<Slider>
{ {
private readonly SliderCircleSelectionBlueprint headBlueprint; protected readonly SliderBodyPiece BodyPiece;
protected readonly SliderCircleSelectionBlueprint HeadBlueprint;
protected readonly SliderCircleSelectionBlueprint TailBlueprint;
public SliderSelectionBlueprint(DrawableSlider slider) public SliderSelectionBlueprint(DrawableSlider slider)
: base(slider) : base(slider)
@ -20,13 +22,22 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new SliderBodyPiece(sliderObject), BodyPiece = new SliderBodyPiece(),
headBlueprint = new SliderCircleSelectionBlueprint(slider.HeadCircle, sliderObject, SliderPosition.Start), HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start),
new SliderCircleSelectionBlueprint(slider.TailCircle, sliderObject, SliderPosition.End), TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End),
new PathControlPointVisualiser(sliderObject), new PathControlPointVisualiser(sliderObject),
}; };
} }
public override Vector2 SelectionPoint => headBlueprint.SelectionPoint; protected override void Update()
{
base.Update();
BodyPiece.UpdateFrom(HitObject);
}
public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint;
protected virtual SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new SliderCircleSelectionBlueprint(slider, position);
} }
} }

View File

@ -12,17 +12,13 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components
{ {
public class SpinnerPiece : HitObjectPiece public class SpinnerPiece : BlueprintPiece<Spinner>
{ {
private readonly Spinner spinner;
private readonly CircularContainer circle; private readonly CircularContainer circle;
private readonly RingPiece ring; private readonly RingPiece ring;
public SpinnerPiece(Spinner spinner) public SpinnerPiece()
: base(spinner)
{ {
this.spinner = spinner;
Origin = Anchor.Centre; Origin = Anchor.Centre;
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
@ -44,21 +40,20 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components
Origin = Anchor.Centre Origin = Anchor.Centre
} }
}; };
ring.Scale = new Vector2(spinner.Scale);
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
Colour = colours.Yellow; Colour = colours.Yellow;
PositionBindable.BindValueChanged(_ => updatePosition(), true);
StackHeightBindable.BindValueChanged(_ => updatePosition());
ScaleBindable.BindValueChanged(scale => ring.Scale = new Vector2(scale.NewValue), true);
} }
private void updatePosition() => Position = spinner.Position; public override void UpdateFrom(Spinner hitObject)
{
base.UpdateFrom(hitObject);
ring.Scale = new Vector2(hitObject.Scale);
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => circle.ReceivePositionalInputAt(screenSpacePos); public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => circle.ReceivePositionalInputAt(screenSpacePos);
} }

View File

@ -22,7 +22,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners
public SpinnerPlacementBlueprint() public SpinnerPlacementBlueprint()
: base(new Spinner { Position = OsuPlayfield.BASE_SIZE / 2 }) : base(new Spinner { Position = OsuPlayfield.BASE_SIZE / 2 })
{ {
InternalChild = piece = new SpinnerPiece(HitObject) { Alpha = 0.5f }; InternalChild = piece = new SpinnerPiece { Alpha = 0.5f };
}
protected override void Update()
{
base.Update();
piece.UpdateFrom(HitObject);
} }
protected override bool OnClick(ClickEvent e) protected override bool OnClick(ClickEvent e)

View File

@ -8,14 +8,21 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners
{ {
public class SpinnerSelectionBlueprint : OsuSelectionBlueprint public class SpinnerSelectionBlueprint : OsuSelectionBlueprint<Spinner>
{ {
private readonly SpinnerPiece piece; private readonly SpinnerPiece piece;
public SpinnerSelectionBlueprint(DrawableSpinner spinner) public SpinnerSelectionBlueprint(DrawableSpinner spinner)
: base(spinner) : base(spinner)
{ {
InternalChild = piece = new SpinnerPiece((Spinner)spinner.HitObject); InternalChild = piece = new SpinnerPiece();
}
protected override void Update()
{
base.Update();
piece.UpdateFrom(HitObject);
} }
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos); public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos);

View File

@ -54,13 +54,13 @@ namespace osu.Game.Rulesets.Osu.Objects
{ {
base.Position = value; base.Position = value;
endPositionCache.Invalidate();
if (HeadCircle != null) if (HeadCircle != null)
HeadCircle.Position = value; HeadCircle.Position = value;
if (TailCircle != null) if (TailCircle != null)
TailCircle.Position = EndPosition; TailCircle.Position = EndPosition;
endPositionCache.Invalidate();
} }
} }

View File

@ -9,7 +9,6 @@ using osuTK;
using System; using System;
using System.Linq; using System.Linq;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites;
namespace osu.Game.Overlays.Chat.Tabs namespace osu.Game.Overlays.Chat.Tabs
{ {
@ -25,19 +24,11 @@ namespace osu.Game.Overlays.Chat.Tabs
public ChannelTabControl() public ChannelTabControl()
{ {
TabContainer.Margin = new MarginPadding { Left = 50 }; Padding = new MarginPadding { Left = 50 };
TabContainer.Spacing = new Vector2(-SHEAR_WIDTH, 0); TabContainer.Spacing = new Vector2(-SHEAR_WIDTH, 0);
TabContainer.Masking = false; TabContainer.Masking = false;
AddInternal(new SpriteIcon
{
Icon = FontAwesome.Solid.Comments,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Size = new Vector2(20),
Margin = new MarginPadding(10),
});
AddTabItem(selectorTab = new ChannelSelectorTabItem()); AddTabItem(selectorTab = new ChannelSelectorTabItem());
ChannelSelectorActive.BindTo(selectorTab.Active); ChannelSelectorActive.BindTo(selectorTab.Active);

View File

@ -21,6 +21,7 @@ using osu.Game.Overlays.Chat;
using osu.Game.Overlays.Chat.Selection; using osu.Game.Overlays.Chat.Selection;
using osu.Game.Overlays.Chat.Tabs; using osu.Game.Overlays.Chat.Tabs;
using osuTK.Input; using osuTK.Input;
using osu.Framework.Graphics.Sprites;
namespace osu.Game.Overlays namespace osu.Game.Overlays
{ {
@ -156,6 +157,14 @@ namespace osu.Game.Overlays
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = Color4.Black, Colour = Color4.Black,
}, },
new SpriteIcon
{
Icon = FontAwesome.Solid.Comments,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Size = new Vector2(20),
Margin = new MarginPadding(10),
},
ChannelTabControl = CreateChannelTabControl().With(d => ChannelTabControl = CreateChannelTabControl().With(d =>
{ {
d.Anchor = Anchor.BottomLeft; d.Anchor = Anchor.BottomLeft;

View File

@ -84,7 +84,7 @@ namespace osu.Game.Overlays.Music
beatmaps.ForEach(addBeatmapSet); beatmaps.ForEach(addBeatmapSet);
beatmapBacking.BindTo(beatmap); beatmapBacking.BindTo(beatmap);
beatmapBacking.ValueChanged += _ => updateSelectedSet(); beatmapBacking.ValueChanged += _ => Scheduler.AddOnce(updateSelectedSet);
} }
private void addBeatmapSet(BeatmapSetInfo obj) private void addBeatmapSet(BeatmapSetInfo obj)
@ -109,7 +109,11 @@ namespace osu.Game.Overlays.Music
private void updateSelectedSet() private void updateSelectedSet()
{ {
foreach (PlaylistItem s in items.Children) foreach (PlaylistItem s in items.Children)
{
s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo?.ID; s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo?.ID;
if (s.Selected)
ScrollIntoView(s);
}
} }
public string SearchTerm public string SearchTerm

View File

@ -85,9 +85,15 @@ namespace osu.Game.Overlays.SearchableList
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Margin = new MarginPadding { Top = controls != null ? padding : 0 }, Margin = new MarginPadding { Top = controls != null ? padding : 0 },
}, },
Tabs = new PageTabControl<T> new Container
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Right = 225 },
Child = Tabs = new PageTabControl<T>
{
RelativeSizeAxes = Axes.X,
},
}, },
new Box //keep the tab strip part of autosize, but don't put it in the flow container new Box //keep the tab strip part of autosize, but don't put it in the flow container
{ {

View File

@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections
new AudioDevicesSettings(), new AudioDevicesSettings(),
new VolumeSettings(), new VolumeSettings(),
new OffsetSettings(), new OffsetSettings(),
new MainMenuSettings(), new MainMenuSettings()
}; };
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Linq;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -105,6 +106,8 @@ namespace osu.Game.Screens.Edit.Components
TabContainer.Spacing = Vector2.Zero; TabContainer.Spacing = Vector2.Zero;
tempo_values.ForEach(AddItem); tempo_values.ForEach(AddItem);
Current.Value = tempo_values.Last();
} }
public class PlaybackTabItem : TabItem<double> public class PlaybackTabItem : TabItem<double>

View File

@ -11,6 +11,7 @@ using osu.Framework.Logging;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components;
using osu.Game.Screens.Edit.Compose.Components.Timeline; using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osu.Game.Skinning;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Screens.Edit.Compose namespace osu.Game.Screens.Edit.Compose
@ -115,7 +116,17 @@ namespace osu.Game.Screens.Edit.Compose
return; return;
} }
composerContainer.Child = composer; var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin);
// the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation
// full access to all skin sources.
var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider));
// load the skinning hierarchy first.
// this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources.
composerContainer.Add(
beatmapSkinProvider.WithChild(
rulesetSkinProvider.WithChild(composer)));
} }
} }
} }

View File

@ -36,6 +36,11 @@ namespace osu.Game.Screens.Select
{ {
AddRangeInternal(new Drawable[] AddRangeInternal(new Drawable[]
{ {
content = new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT },
},
new BeatmapDetailAreaTabControl new BeatmapDetailAreaTabControl
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
@ -58,11 +63,6 @@ namespace osu.Game.Screens.Select
} }
}, },
}, },
content = new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT },
},
}); });
AddRange(new Drawable[] AddRange(new Drawable[]

View File

@ -20,6 +20,7 @@ namespace osu.Game.Screens.Select
public static readonly float HEIGHT = 24; public static readonly float HEIGHT = 24;
private readonly OsuTabControlCheckbox modsCheckbox; private readonly OsuTabControlCheckbox modsCheckbox;
private readonly OsuTabControl<BeatmapDetailTab> tabs; private readonly OsuTabControl<BeatmapDetailTab> tabs;
private readonly Container tabsContainer;
public Action<BeatmapDetailTab, bool> OnFilter; //passed the selected tab and if mods is checked public Action<BeatmapDetailTab, bool> OnFilter; //passed the selected tab and if mods is checked
@ -39,11 +40,15 @@ namespace osu.Game.Screens.Select
Height = 1, Height = 1,
Colour = Color4.White.Opacity(0.2f), Colour = Color4.White.Opacity(0.2f),
}, },
tabs = new OsuTabControl<BeatmapDetailTab> tabsContainer = new Container
{ {
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Child = tabs = new OsuTabControl<BeatmapDetailTab>
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both,
},
}, },
modsCheckbox = new OsuTabControlCheckbox modsCheckbox = new OsuTabControlCheckbox
{ {
@ -74,6 +79,8 @@ namespace osu.Game.Screens.Select
OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value);
modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint); modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint);
tabsContainer.Padding = new MarginPadding { Right = tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 100 };
} }
} }

View File

@ -53,7 +53,7 @@ namespace osu.Game.Skinning
if (AllowTextureLookup(componentName) && (sourceTexture = skin?.GetTexture(componentName)) != null) if (AllowTextureLookup(componentName) && (sourceTexture = skin?.GetTexture(componentName)) != null)
return sourceTexture; return sourceTexture;
return fallbackSource.GetTexture(componentName); return fallbackSource?.GetTexture(componentName);
} }
public SampleChannel GetSample(ISampleInfo sampleInfo) public SampleChannel GetSample(ISampleInfo sampleInfo)

View File

@ -1,10 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
@ -12,8 +10,6 @@ namespace osu.Game.Tests.Visual
{ {
public abstract class SelectionBlueprintTestScene : OsuTestScene public abstract class SelectionBlueprintTestScene : OsuTestScene
{ {
private SelectionBlueprint blueprint;
protected override Container<Drawable> Content => content ?? base.Content; protected override Container<Drawable> Content => content ?? base.Content;
private readonly Container content; private readonly Container content;
@ -26,25 +22,13 @@ namespace osu.Game.Tests.Visual
}); });
} }
[BackgroundDependencyLoader] protected void AddBlueprint(SelectionBlueprint blueprint)
private void load()
{ {
blueprint = CreateBlueprint(); Add(blueprint.With(d =>
blueprint.Depth = float.MinValue; {
blueprint.SelectionRequested += (_, __) => blueprint.Select(); d.Depth = float.MinValue;
d.Select();
Add(blueprint); }));
AddStep("Select", () => blueprint.Select());
AddStep("Deselect", () => blueprint.Deselect());
} }
protected override bool OnClick(ClickEvent e)
{
blueprint.Deselect();
return true;
}
protected abstract SelectionBlueprint CreateBlueprint();
} }
} }