1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-07 16:22:56 +08:00

Remove dependence of placement blueprints on IPositionSnapProvider

This commit is contained in:
Bartłomiej Dach 2025-01-21 13:49:29 +01:00
parent 15b6e28ebe
commit a6987f5c95
No known key found for this signature in database
20 changed files with 137 additions and 57 deletions

View File

@ -7,6 +7,7 @@ using osu.Framework.Utils;
using osu.Game.Rulesets.Catch.Edit.Blueprints.Components;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Edit;
using osuTK;
using osuTK.Input;
namespace osu.Game.Rulesets.Catch.Edit.Blueprints
@ -59,11 +60,13 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
return base.OnMouseDown(e);
}
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
var result = Composer?.FindSnappedPositionAndTime(screenSpacePosition) ?? new SnapResult(screenSpacePosition, fallbackTime);
base.UpdateTimeAndPosition(result);
if (!(result.Time is double time)) return;
if (!(result.Time is double time)) return result;
switch (PlacementActive)
{
@ -78,6 +81,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
HitObject.StartTime = Math.Min(placementStartTime, placementEndTime);
HitObject.EndTime = Math.Max(placementStartTime, placementEndTime);
return result;
}
}
}

View File

@ -9,7 +9,7 @@ using osu.Game.Rulesets.UI.Scrolling;
namespace osu.Game.Rulesets.Catch.Edit.Blueprints
{
public partial class CatchPlacementBlueprint<THitObject> : HitObjectPlacementBlueprint
public abstract partial class CatchPlacementBlueprint<THitObject> : HitObjectPlacementBlueprint
where THitObject : CatchHitObject, new()
{
protected new THitObject HitObject => (THitObject)base.HitObject;
@ -19,7 +19,10 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
[Resolved]
private Playfield playfield { get; set; } = null!;
public CatchPlacementBlueprint()
[Resolved]
protected CatchHitObjectComposer? Composer { get; private set; }
protected CatchPlacementBlueprint()
: base(new THitObject())
{
}

View File

@ -5,6 +5,7 @@ using osu.Framework.Input.Events;
using osu.Game.Rulesets.Catch.Edit.Blueprints.Components;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Edit;
using osuTK;
using osuTK.Input;
namespace osu.Game.Rulesets.Catch.Edit.Blueprints
@ -41,11 +42,20 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
return true;
}
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
base.UpdateTimeAndPosition(result);
var gridSnapResult = Composer?.FindSnappedPositionAndTime(screenSpacePosition) ?? new SnapResult(screenSpacePosition, fallbackTime);
gridSnapResult.ScreenSpacePosition.X = screenSpacePosition.X;
var distanceSnapResult = Composer?.TryDistanceSnap(gridSnapResult.ScreenSpacePosition);
var result = distanceSnapResult != null && Vector2.Distance(gridSnapResult.ScreenSpacePosition, distanceSnapResult.ScreenSpacePosition) < CatchHitObjectComposer.DISTANCE_SNAP_RADIUS
? distanceSnapResult
: gridSnapResult;
UpdateTimeAndPosition(result);
HitObject.X = ToLocalSpace(result.ScreenSpacePosition).X;
return result;
}
}
}

View File

@ -83,8 +83,16 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
return base.OnMouseDown(e);
}
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
var gridSnapResult = Composer?.FindSnappedPositionAndTime(screenSpacePosition) ?? new SnapResult(screenSpacePosition, fallbackTime);
gridSnapResult.ScreenSpacePosition.X = screenSpacePosition.X;
var distanceSnapResult = Composer?.TryDistanceSnap(gridSnapResult.ScreenSpacePosition);
var result = distanceSnapResult != null && Vector2.Distance(gridSnapResult.ScreenSpacePosition, distanceSnapResult.ScreenSpacePosition) < CatchHitObjectComposer.DISTANCE_SNAP_RADIUS
? distanceSnapResult
: gridSnapResult;
switch (PlacementActive)
{
case PlacementState.Waiting:
@ -99,7 +107,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
break;
default:
return;
return result;
}
// Make sure the up-to-date position is used for outlines.
@ -113,6 +121,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
ApplyDefaultsToHitObject();
scrollingPath.UpdatePathFrom(HitObjectContainer, HitObject);
nestedOutlineContainer.UpdateNestedObjectsFrom(HitObjectContainer, HitObject);
return result;
}
private double positionToTime(float relativeYPosition)

View File

@ -23,6 +23,7 @@ using osuTK;
namespace osu.Game.Rulesets.Catch.Edit
{
[Cached]
public partial class CatchHitObjectComposer : ScrollingHitObjectComposer<CatchHitObject>, IKeyBindingHandler<GlobalAction>
{
public const float DISTANCE_SNAP_RADIUS = 50;

View File

@ -98,9 +98,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
private double originalStartTime;
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
base.UpdateTimeAndPosition(result);
var result = base.UpdateTimeAndPosition(screenSpacePosition, fallbackTime);
if (PlacementActive == PlacementState.Active)
{
@ -121,6 +121,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
if (result.Time is double startTime)
originalStartTime = HitObject.StartTime = startTime;
}
return result;
}
}
}

View File

@ -1,8 +1,8 @@
// 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.
#nullable disable
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Edit;
@ -20,13 +20,18 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
{
protected new T HitObject => (T)base.HitObject;
private Column column;
[Resolved]
private ManiaHitObjectComposer? composer { get; set; }
public Column Column
private Column? column;
public Column? Column
{
get => column;
set
{
ArgumentNullException.ThrowIfNull(value);
if (value == column)
return;
@ -53,9 +58,11 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
return true;
}
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
base.UpdateTimeAndPosition(result);
var result = composer?.FindSnappedPositionAndTime(screenSpacePosition) ?? new SnapResult(screenSpacePosition, fallbackTime);
UpdateTimeAndPosition(result);
if (result.Playfield is Column col)
{
@ -76,6 +83,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
if (PlacementActive == PlacementState.Waiting)
Column = col;
}
return result;
}
private float getNoteHeight(Column resultPlayfield) =>

View File

@ -8,6 +8,7 @@ using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Mania.Objects;
using osuTK;
using osuTK.Input;
namespace osu.Game.Rulesets.Mania.Edit.Blueprints
@ -35,15 +36,17 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
};
}
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double referenceTime)
{
base.UpdateTimeAndPosition(result);
var result = base.UpdateTimeAndPosition(screenSpacePosition, referenceTime);
if (result.Playfield != null)
{
piece.Width = result.Playfield.DrawWidth;
piece.Position = ToLocalSpace(result.ScreenSpacePosition);
}
return result;
}
protected override bool OnMouseDown(MouseDownEvent e)

View File

@ -19,6 +19,7 @@ using osuTK;
namespace osu.Game.Rulesets.Mania.Edit
{
[Cached]
public partial class ManiaHitObjectComposer : ScrollingHitObjectComposer<ManiaHitObject>
{
private DrawableManiaEditorRuleset drawableRuleset = null!;

View File

@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
public partial class GridPlacementBlueprint : PlacementBlueprint
{
[Resolved]
private HitObjectComposer? hitObjectComposer { get; set; }
private OsuHitObjectComposer? hitObjectComposer { get; set; }
private OsuGridToolboxGroup gridToolboxGroup = null!;
private Vector2 originalOrigin;
@ -95,12 +95,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
base.OnDragEnd(e);
}
public override SnapType SnapType => ~SnapType.GlobalGrids;
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double referenceTime)
{
if (State.Value == Visibility.Hidden)
return;
return new SnapResult(screenSpacePosition, referenceTime);
var result = hitObjectComposer?.TrySnapToNearbyObjects(screenSpacePosition) ?? new SnapResult(screenSpacePosition, referenceTime);
var pos = ToLocalSpace(result.ScreenSpacePosition);
@ -120,6 +120,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
gridToolboxGroup.SetGridFromPoints(gridToolboxGroup.StartPosition.Value, pos);
}
}
return result;
}
protected override void PopOut()

View File

@ -1,10 +1,12 @@
// 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.Input.Events;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
using osuTK;
using osuTK.Input;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
@ -15,6 +17,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
private readonly HitCirclePiece circlePiece;
[Resolved]
private OsuHitObjectComposer? composer { get; set; }
public HitCirclePlacementBlueprint()
: base(new HitCircle())
{
@ -45,10 +50,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
return base.OnMouseDown(e);
}
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
base.UpdateTimeAndPosition(result);
var result = composer?.TrySnapToNearbyObjects(screenSpacePosition)
?? composer?.TrySnapToDistanceGrid(screenSpacePosition)
?? composer?.TrySnapToPositionGrid(screenSpacePosition)
?? new SnapResult(screenSpacePosition, fallbackTime);
UpdateTimeAndPosition(result);
HitObject.Position = ToLocalSpace(result.ScreenSpacePosition);
return result;
}
}
}

View File

@ -25,6 +25,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
public new Slider HitObject => (Slider)base.HitObject;
[Resolved]
private OsuHitObjectComposer? composer { get; set; }
private SliderBodyPiece bodyPiece = null!;
private HitCirclePiece headCirclePiece = null!;
private HitCirclePiece tailCirclePiece = null!;
@ -40,9 +43,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
private int currentSegmentLength;
private bool usingCustomSegmentType;
[Resolved]
private IPositionSnapProvider? positionSnapProvider { get; set; }
[Resolved]
private IDistanceSnapProvider? distanceSnapProvider { get; set; }
@ -106,9 +106,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
[Resolved]
private EditorBeatmap editorBeatmap { get; set; } = null!;
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
base.UpdateTimeAndPosition(result);
var result = composer?.TrySnapToNearbyObjects(screenSpacePosition)
?? composer?.TrySnapToDistanceGrid(screenSpacePosition)
?? composer?.TrySnapToPositionGrid(screenSpacePosition)
?? new SnapResult(screenSpacePosition, fallbackTime);
UpdateTimeAndPosition(result);
switch (state)
{
@ -131,6 +136,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
updateCursor();
break;
}
return result;
}
protected override bool OnMouseDown(MouseDownEvent e)
@ -375,7 +382,17 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
private Vector2 getCursorPosition()
{
var result = positionSnapProvider?.FindSnappedPositionAndTime(inputManager.CurrentState.Mouse.Position, state == SliderPlacementState.ControlPoints ? SnapType.GlobalGrids : SnapType.All);
SnapResult? result = null;
var mousePosition = inputManager.CurrentState.Mouse.Position;
if (state != SliderPlacementState.ControlPoints)
{
result ??= composer?.TrySnapToNearbyObjects(mousePosition);
result ??= composer?.TrySnapToDistanceGrid(mousePosition);
}
result ??= composer?.TrySnapToPositionGrid(mousePosition);
return ToLocalSpace(result?.ScreenSpacePosition ?? inputManager.CurrentState.Mouse.Position) - HitObject.Position;
}

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.UI;
using osuTK;
using osuTK.Input;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners
@ -70,5 +71,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners
? Math.Max(HitObject.StartTime, EditorClock.CurrentTime)
: Math.Max(HitObject.StartTime + beatSnapProvider.GetBeatLengthAtTime(HitObject.StartTime), beatSnapProvider.SnapTime(EditorClock.CurrentTime));
}
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
var result = new SnapResult(screenSpacePosition, fallbackTime);
UpdateTimeAndPosition(result);
return result;
}
}
}

View File

@ -32,6 +32,7 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit
{
[Cached]
public partial class OsuHitObjectComposer : HitObjectComposer<OsuHitObject>
{
public OsuHitObjectComposer(Ruleset ruleset)

View File

@ -1,6 +1,7 @@
// 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.Input.Events;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Taiko.Objects;
@ -16,6 +17,9 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
public new Hit HitObject => (Hit)base.HitObject;
[Resolved]
private TaikoHitObjectComposer? composer { get; set; }
public HitPlacementBlueprint()
: base(new Hit())
{
@ -40,10 +44,12 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
return true;
}
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
var result = composer?.FindSnappedPositionAndTime(screenSpacePosition) ?? new SnapResult(screenSpacePosition, fallbackTime);
piece.Position = ToLocalSpace(result.ScreenSpacePosition);
base.UpdateTimeAndPosition(result);
UpdateTimeAndPosition(result);
return result;
}
}
}

View File

@ -1,9 +1,8 @@
// 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.
#nullable disable
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Input.Events;
using osu.Framework.Utils;
@ -26,12 +25,15 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
private readonly IHasDuration spanPlacementObject;
[Resolved]
private TaikoHitObjectComposer? composer { get; set; }
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(spanPlacementObject.Duration, 0);
public TaikoSpanPlacementBlueprint(HitObject hitObject)
: base(hitObject)
{
spanPlacementObject = hitObject as IHasDuration;
spanPlacementObject = (hitObject as IHasDuration)!;
RelativeSizeAxes = Axes.Both;
@ -79,9 +81,11 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
EndPlacement(true);
}
public override void UpdateTimeAndPosition(SnapResult result)
public override SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime)
{
base.UpdateTimeAndPosition(result);
var result = composer?.FindSnappedPositionAndTime(screenSpacePosition) ?? new SnapResult(screenSpacePosition, fallbackTime);
UpdateTimeAndPosition(result);
if (PlacementActive == PlacementState.Active)
{
@ -116,6 +120,8 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
originalPosition = ToLocalSpace(result.ScreenSpacePosition);
}
}
return result;
}
}
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
@ -12,6 +13,7 @@ using osu.Game.Screens.Edit.Compose.Components;
namespace osu.Game.Rulesets.Taiko.Edit
{
[Cached]
public partial class TaikoHitObjectComposer : ScrollingHitObjectComposer<TaikoHitObject>
{
protected override bool ApplyHorizontalCentering => false;

View File

@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Edit
/// Updates the time and position of this <see cref="PlacementBlueprint"/> based on the provided snap information.
/// </summary>
/// <param name="result">The snap result information.</param>
public override void UpdateTimeAndPosition(SnapResult result)
public void UpdateTimeAndPosition(SnapResult result)
{
if (PlacementActive == PlacementState.Waiting)
{

View File

@ -7,6 +7,7 @@ using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Objects;
using osuTK;
using osuTK.Input;
namespace osu.Game.Rulesets.Edit
@ -75,18 +76,7 @@ namespace osu.Game.Rulesets.Edit
PlacementActive = PlacementState.Finished;
}
/// <summary>
/// Determines which objects to snap to for the snap result in <see cref="UpdateTimeAndPosition"/>.
/// </summary>
public virtual SnapType SnapType => SnapType.All;
/// <summary>
/// Updates the time and position of this <see cref="PlacementBlueprint"/> based on the provided snap information.
/// </summary>
/// <param name="result">The snap result information.</param>
public virtual void UpdateTimeAndPosition(SnapResult result)
{
}
public abstract SnapResult UpdateTimeAndPosition(Vector2 screenSpacePosition, double fallbackTime);
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{

View File

@ -340,12 +340,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void updatePlacementTimeAndPosition()
{
SnapResult snapResult = new SnapResult(InputManager.CurrentState.Mouse.Position, null); // Composer.FindSnappedPositionAndTime(InputManager.CurrentState.Mouse.Position, CurrentPlacement.SnapType); TODO
// if no time was found from positional snapping, we should still quantize to the beat.
snapResult.Time ??= Beatmap.SnapTime(EditorClock.CurrentTime, null);
CurrentPlacement.UpdateTimeAndPosition(snapResult);
CurrentPlacement.UpdateTimeAndPosition(InputManager.CurrentState.Mouse.Position, Beatmap.SnapTime(EditorClock.CurrentTime, null));
}
#endregion