mirror of
https://github.com/ppy/osu.git
synced 2025-01-12 20:22:55 +08:00
Merge pull request #8736 from smoogipoo/fix-red-point-placement
Rework slider control point placement to improve path progression
This commit is contained in:
commit
bdec4ca2b4
@ -1,18 +1,285 @@
|
|||||||
// 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.Framework.Utils;
|
||||||
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.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||||
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;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneSliderPlacementBlueprint : PlacementBlueprintTestScene
|
public class TestSceneSliderPlacementBlueprint : PlacementBlueprintTestScene
|
||||||
{
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup() => Schedule(() =>
|
||||||
|
{
|
||||||
|
HitObjectContainer.Clear();
|
||||||
|
ResetPlacement();
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBeginPlacementWithoutFinishing()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
assertPlaced(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceWithoutMovingMouse()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertLength(0);
|
||||||
|
assertControlPointType(0, PathType.Linear);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceWithMouseMovement()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(400, 200));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertLength(200);
|
||||||
|
assertControlPointCount(2);
|
||||||
|
assertControlPointType(0, PathType.Linear);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceNormalControlPoint()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertControlPointCount(3);
|
||||||
|
assertControlPointPosition(1, new Vector2(100, 0));
|
||||||
|
assertControlPointType(0, PathType.PerfectCurve);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceTwoNormalControlPoints()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(400, 300));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertControlPointCount(4);
|
||||||
|
assertControlPointPosition(1, new Vector2(100, 0));
|
||||||
|
assertControlPointPosition(2, new Vector2(100, 100));
|
||||||
|
assertControlPointType(0, PathType.Bezier);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceSegmentControlPoint()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertControlPointCount(3);
|
||||||
|
assertControlPointPosition(1, new Vector2(100, 0));
|
||||||
|
assertControlPointType(0, PathType.Linear);
|
||||||
|
assertControlPointType(1, PathType.Linear);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMoveToPerfectCurveThenPlaceLinear()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300));
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertControlPointCount(2);
|
||||||
|
assertControlPointType(0, PathType.Linear);
|
||||||
|
assertLength(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMoveToBezierThenPlacePerfectCurve()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(400, 300));
|
||||||
|
addMovementStep(new Vector2(300));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertControlPointCount(3);
|
||||||
|
assertControlPointType(0, PathType.PerfectCurve);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMoveToFourthOrderBezierThenPlaceThirdOrderBezier()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(400, 300));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(400));
|
||||||
|
addMovementStep(new Vector2(400, 300));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertControlPointCount(4);
|
||||||
|
assertControlPointType(0, PathType.Bezier);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceLinearSegmentThenPlaceLinearSegment()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 300));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertControlPointCount(3);
|
||||||
|
assertControlPointPosition(1, new Vector2(100, 0));
|
||||||
|
assertControlPointPosition(2, new Vector2(100));
|
||||||
|
assertControlPointType(0, PathType.Linear);
|
||||||
|
assertControlPointType(1, PathType.Linear);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceLinearSegmentThenPlacePerfectCurveSegment()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 300));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(400, 300));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertControlPointCount(4);
|
||||||
|
assertControlPointPosition(1, new Vector2(100, 0));
|
||||||
|
assertControlPointPosition(2, new Vector2(100));
|
||||||
|
assertControlPointType(0, PathType.Linear);
|
||||||
|
assertControlPointType(1, PathType.PerfectCurve);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlacePerfectCurveSegmentThenPlacePerfectCurveSegment()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 200));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(300, 300));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(400, 300));
|
||||||
|
addClickStep(MouseButton.Left);
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(400));
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertControlPointCount(5);
|
||||||
|
assertControlPointPosition(1, new Vector2(100, 0));
|
||||||
|
assertControlPointPosition(2, new Vector2(100));
|
||||||
|
assertControlPointPosition(3, new Vector2(200, 100));
|
||||||
|
assertControlPointPosition(4, new Vector2(200));
|
||||||
|
assertControlPointType(0, PathType.PerfectCurve);
|
||||||
|
assertControlPointType(2, PathType.PerfectCurve);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMovementStep(Vector2 position) => AddStep($"move mouse to {position}", () => InputManager.MoveMouseTo(InputManager.ToScreenSpace(position)));
|
||||||
|
|
||||||
|
private void addClickStep(MouseButton button)
|
||||||
|
{
|
||||||
|
AddStep($"press {button}", () => InputManager.PressButton(button));
|
||||||
|
AddStep($"release {button}", () => InputManager.ReleaseButton(button));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertPlaced(bool expected) => AddAssert($"slider {(expected ? "placed" : "not placed")}", () => (getSlider() != null) == expected);
|
||||||
|
|
||||||
|
private void assertLength(double expected) => AddAssert($"slider length is {expected}", () => Precision.AlmostEquals(expected, getSlider().Distance, 1));
|
||||||
|
|
||||||
|
private void assertControlPointCount(int expected) => AddAssert($"has {expected} control points", () => getSlider().Path.ControlPoints.Count == expected);
|
||||||
|
|
||||||
|
private void assertControlPointType(int index, PathType type) => AddAssert($"control point {index} is {type}", () => getSlider().Path.ControlPoints[index].Type.Value == type);
|
||||||
|
|
||||||
|
private void assertControlPointPosition(int index, Vector2 position) =>
|
||||||
|
AddAssert($"control point {index} at {position}", () => Precision.AlmostEquals(position, getSlider().Path.ControlPoints[index].Position.Value, 1));
|
||||||
|
|
||||||
|
private Slider getSlider() => HitObjectContainer.Count > 0 ? (Slider)((DrawableSlider)HitObjectContainer[0]).HitObject : null;
|
||||||
|
|
||||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSlider((Slider)hitObject);
|
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSlider((Slider)hitObject);
|
||||||
protected override PlacementBlueprint CreateBlueprint() => new SliderPlacementBlueprint();
|
protected override PlacementBlueprint CreateBlueprint() => new SliderPlacementBlueprint();
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
path.ClearVertices();
|
path.ClearVertices();
|
||||||
|
|
||||||
int nextIndex = controlPointIndex + 1;
|
int nextIndex = controlPointIndex + 1;
|
||||||
if (nextIndex == 0 || nextIndex == slider.Path.ControlPoints.Count)
|
if (nextIndex == 0 || nextIndex >= slider.Path.ControlPoints.Count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
path.AddVertex(Vector2.Zero);
|
path.AddVertex(Vector2.Zero);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
@ -51,6 +52,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
this.slider = slider;
|
this.slider = slider;
|
||||||
ControlPoint = controlPoint;
|
ControlPoint = controlPoint;
|
||||||
|
|
||||||
|
controlPoint.Type.BindValueChanged(_ => updateMarkerDisplay());
|
||||||
|
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
@ -183,8 +186,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
markerRing.Alpha = IsSelected.Value ? 1 : 0;
|
markerRing.Alpha = IsSelected.Value ? 1 : 0;
|
||||||
|
|
||||||
Color4 colour = ControlPoint.Type.Value != null ? colours.Red : colours.Yellow;
|
Color4 colour = ControlPoint.Type.Value != null ? colours.Red : colours.Yellow;
|
||||||
|
|
||||||
if (IsHovered || IsSelected.Value)
|
if (IsHovered || IsSelected.Value)
|
||||||
colour = Color4.White;
|
colour = colour.Lighten(1);
|
||||||
|
|
||||||
marker.Colour = colour;
|
marker.Colour = colour;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
// 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.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
@ -23,6 +26,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
private SliderBodyPiece bodyPiece;
|
private SliderBodyPiece bodyPiece;
|
||||||
private HitCirclePiece headCirclePiece;
|
private HitCirclePiece headCirclePiece;
|
||||||
private HitCirclePiece tailCirclePiece;
|
private HitCirclePiece tailCirclePiece;
|
||||||
|
private PathControlPointVisualiser controlPointVisualiser;
|
||||||
|
|
||||||
private InputManager inputManager;
|
private InputManager inputManager;
|
||||||
|
|
||||||
@ -51,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
bodyPiece = new SliderBodyPiece(),
|
bodyPiece = new SliderBodyPiece(),
|
||||||
headCirclePiece = new HitCirclePiece(),
|
headCirclePiece = new HitCirclePiece(),
|
||||||
tailCirclePiece = new HitCirclePiece(),
|
tailCirclePiece = new HitCirclePiece(),
|
||||||
new PathControlPointVisualiser(HitObject, false)
|
controlPointVisualiser = new PathControlPointVisualiser(HitObject, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
setState(PlacementState.Initial);
|
setState(PlacementState.Initial);
|
||||||
@ -73,11 +77,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PlacementState.Body:
|
case PlacementState.Body:
|
||||||
ensureCursor();
|
updateCursor();
|
||||||
|
|
||||||
// The given screen-space position may have been externally snapped, but the unsnapped position from the input manager
|
|
||||||
// is used instead since snapping control points doesn't make much sense
|
|
||||||
cursor.Position.Value = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,17 +91,27 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PlacementState.Body:
|
case PlacementState.Body:
|
||||||
switch (e.Button)
|
if (e.Button != MouseButton.Left)
|
||||||
{
|
break;
|
||||||
case MouseButton.Left:
|
|
||||||
ensureCursor();
|
|
||||||
|
|
||||||
// Detatch the cursor
|
if (canPlaceNewControlPoint(out var lastPoint))
|
||||||
cursor = null;
|
{
|
||||||
break;
|
// Place a new point by detatching the current cursor.
|
||||||
|
updateCursor();
|
||||||
|
cursor = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Transform the last point into a new segment.
|
||||||
|
Debug.Assert(lastPoint != null);
|
||||||
|
|
||||||
|
segmentStart = lastPoint;
|
||||||
|
segmentStart.Type.Value = PathType.Linear;
|
||||||
|
|
||||||
|
currentSegmentLength = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -114,16 +124,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
base.OnMouseUp(e);
|
base.OnMouseUp(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnDoubleClick(DoubleClickEvent e)
|
|
||||||
{
|
|
||||||
// Todo: This should all not occur on double click, but rather if the previous control point is hovered.
|
|
||||||
segmentStart = HitObject.Path.ControlPoints[^1];
|
|
||||||
segmentStart.Type.Value = PathType.Linear;
|
|
||||||
|
|
||||||
currentSegmentLength = 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void beginCurve()
|
private void beginCurve()
|
||||||
{
|
{
|
||||||
BeginPlacement(commitStart: true);
|
BeginPlacement(commitStart: true);
|
||||||
@ -161,17 +161,50 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureCursor()
|
private void updateCursor()
|
||||||
{
|
{
|
||||||
if (cursor == null)
|
if (canPlaceNewControlPoint(out _))
|
||||||
{
|
{
|
||||||
HitObject.Path.ControlPoints.Add(cursor = new PathControlPoint { Position = { Value = Vector2.Zero } });
|
// The cursor does not overlap a previous control point, so it can be added if not already existing.
|
||||||
currentSegmentLength++;
|
if (cursor == null)
|
||||||
|
{
|
||||||
|
HitObject.Path.ControlPoints.Add(cursor = new PathControlPoint { Position = { Value = Vector2.Zero } });
|
||||||
|
|
||||||
|
// The path type should be adjusted in the progression of updatePathType() (Linear -> PC -> Bezier).
|
||||||
|
currentSegmentLength++;
|
||||||
|
updatePathType();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the cursor position.
|
||||||
|
cursor.Position.Value = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position;
|
||||||
|
}
|
||||||
|
else if (cursor != null)
|
||||||
|
{
|
||||||
|
// The cursor overlaps a previous control point, so it's removed.
|
||||||
|
HitObject.Path.ControlPoints.Remove(cursor);
|
||||||
|
cursor = null;
|
||||||
|
|
||||||
|
// The path type should be adjusted in the reverse progression of updatePathType() (Bezier -> PC -> Linear).
|
||||||
|
currentSegmentLength--;
|
||||||
updatePathType();
|
updatePathType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether a new control point can be placed at the current mouse position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lastPoint">The last-placed control point. May be null, but is not null if <c>false</c> is returned.</param>
|
||||||
|
/// <returns>Whether a new control point can be placed at the current position.</returns>
|
||||||
|
private bool canPlaceNewControlPoint([CanBeNull] out PathControlPoint lastPoint)
|
||||||
|
{
|
||||||
|
// We cannot rely on the ordering of drawable pieces, so find the respective drawable piece by searching for the last non-cursor control point.
|
||||||
|
var last = HitObject.Path.ControlPoints.LastOrDefault(p => p != cursor);
|
||||||
|
var lastPiece = controlPointVisualiser.Pieces.Single(p => p.ControlPoint == last);
|
||||||
|
|
||||||
|
lastPoint = last;
|
||||||
|
return lastPiece?.IsHovered != true;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateSlider()
|
private void updateSlider()
|
||||||
{
|
{
|
||||||
HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.CalculatedDistance) ?? (float)HitObject.Path.CalculatedDistance;
|
HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.CalculatedDistance) ?? (float)HitObject.Path.CalculatedDistance;
|
||||||
|
@ -106,6 +106,9 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
case ScrollEvent _:
|
case ScrollEvent _:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
case DoubleClickEvent _:
|
||||||
|
return false;
|
||||||
|
|
||||||
case MouseButtonEvent _:
|
case MouseButtonEvent _:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input;
|
|
||||||
using osu.Framework.Input.Events;
|
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
@ -15,13 +13,11 @@ using osu.Game.Screens.Edit.Compose;
|
|||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
[Cached(Type = typeof(IPlacementHandler))]
|
[Cached(Type = typeof(IPlacementHandler))]
|
||||||
public abstract class PlacementBlueprintTestScene : OsuTestScene, IPlacementHandler
|
public abstract class PlacementBlueprintTestScene : OsuManualInputManagerTestScene, IPlacementHandler
|
||||||
{
|
{
|
||||||
protected Container HitObjectContainer;
|
protected readonly Container HitObjectContainer;
|
||||||
private PlacementBlueprint currentBlueprint;
|
private PlacementBlueprint currentBlueprint;
|
||||||
|
|
||||||
private InputManager inputManager;
|
|
||||||
|
|
||||||
protected PlacementBlueprintTestScene()
|
protected PlacementBlueprintTestScene()
|
||||||
{
|
{
|
||||||
Add(HitObjectContainer = CreateHitObjectContainer().With(c => c.Clock = new FramedClock(new StopwatchClock())));
|
Add(HitObjectContainer = CreateHitObjectContainer().With(c => c.Clock = new FramedClock(new StopwatchClock())));
|
||||||
@ -45,8 +41,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
inputManager = GetContainingInputManager();
|
ResetPlacement();
|
||||||
Add(currentBlueprint = CreateBlueprint());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginPlacement(HitObject hitObject)
|
public void BeginPlacement(HitObject hitObject)
|
||||||
@ -58,7 +53,13 @@ namespace osu.Game.Tests.Visual
|
|||||||
if (commit)
|
if (commit)
|
||||||
AddHitObject(CreateHitObject(hitObject));
|
AddHitObject(CreateHitObject(hitObject));
|
||||||
|
|
||||||
Remove(currentBlueprint);
|
ResetPlacement();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ResetPlacement()
|
||||||
|
{
|
||||||
|
if (currentBlueprint != null)
|
||||||
|
Remove(currentBlueprint);
|
||||||
Add(currentBlueprint = CreateBlueprint());
|
Add(currentBlueprint = CreateBlueprint());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,10 +67,11 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
protected override void Update()
|
||||||
{
|
{
|
||||||
currentBlueprint.UpdatePosition(e.ScreenSpaceMousePosition);
|
base.Update();
|
||||||
return true;
|
|
||||||
|
currentBlueprint.UpdatePosition(InputManager.CurrentState.Mouse.Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Add(Drawable drawable)
|
public override void Add(Drawable drawable)
|
||||||
@ -79,7 +81,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
if (drawable is PlacementBlueprint blueprint)
|
if (drawable is PlacementBlueprint blueprint)
|
||||||
{
|
{
|
||||||
blueprint.Show();
|
blueprint.Show();
|
||||||
blueprint.UpdatePosition(inputManager.CurrentState.Mouse.Position);
|
blueprint.UpdatePosition(InputManager.CurrentState.Mouse.Position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user