1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-17 16:12:53 +08:00

Convert 'grid from points' button to placement tool

This commit is contained in:
OliBomby 2024-09-23 16:36:11 +02:00
parent 1a81e12192
commit 0a5a463380
5 changed files with 105 additions and 96 deletions

View File

@ -0,0 +1,83 @@
// 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 osuTK;
using osuTK.Input;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints
{
public partial class GridPlacementBlueprint : PlacementBlueprint
{
[Resolved]
private HitObjectComposer? hitObjectComposer { get; set; }
private OsuGridToolboxGroup gridToolboxGroup = null!;
private Vector2 originalOrigin;
private float originalSpacing;
private float originalRotation;
[BackgroundDependencyLoader]
private void load(OsuGridToolboxGroup gridToolboxGroup)
{
this.gridToolboxGroup = gridToolboxGroup;
originalOrigin = gridToolboxGroup.StartPosition.Value;
originalSpacing = gridToolboxGroup.Spacing.Value;
originalRotation = gridToolboxGroup.GridLinesRotation.Value;
}
public override void EndPlacement(bool commit)
{
if (!commit && PlacementActive != PlacementState.Finished)
{
gridToolboxGroup.StartPosition.Value = originalOrigin;
gridToolboxGroup.Spacing.Value = originalSpacing;
gridToolboxGroup.GridLinesRotation.Value = originalRotation;
}
base.EndPlacement(commit);
// You typically only place the grid once, so we switch back to the select tool after placement.
if (commit && hitObjectComposer is OsuHitObjectComposer osuHitObjectComposer)
osuHitObjectComposer.SetSelectTool();
}
protected override bool OnMouseDown(MouseDownEvent e)
{
switch (e.Button)
{
case MouseButton.Right:
EndPlacement(true);
return true;
case MouseButton.Left:
switch (PlacementActive)
{
case PlacementState.Waiting:
BeginPlacement(true);
return true;
case PlacementState.Active:
EndPlacement(true);
return true;
}
break;
}
return base.OnMouseDown(e);
}
public override void UpdateTimeAndPosition(SnapResult result)
{
var pos = ToLocalSpace(result.ScreenSpacePosition);
if (PlacementActive != PlacementState.Active)
gridToolboxGroup.StartPosition.Value = pos;
else
gridToolboxGroup.SetGridFromPoints(gridToolboxGroup.StartPosition.Value, pos);
}
}
}

View File

@ -1,79 +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.Input.Events; using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osuTK; using osu.Game.Rulesets.Edit.Tools;
using osuTK.Input; using osu.Game.Rulesets.Osu.Edit.Blueprints;
namespace osu.Game.Rulesets.Osu.Edit namespace osu.Game.Rulesets.Osu.Edit
{ {
public partial class GridFromPointsTool : Drawable public partial class GridFromPointsTool : CompositionTool
{ {
[Resolved] public GridFromPointsTool()
private OsuGridToolboxGroup gridToolboxGroup { get; set; } = null!; : base("Change grid")
[Resolved(canBeNull: true)]
private IPositionSnapProvider? snapProvider { get; set; }
public bool IsPlacing { get; private set; }
private Vector2? startPosition;
protected override void LoadComplete()
{ {
base.LoadComplete(); TooltipText = """
Left click to set the origin.
gridToolboxGroup.GridFromPointsClicked += BeginPlacement; Left click again to set the rotation and spacing.
Right click to only set the origin.
""";
} }
public void BeginPlacement() public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGridSnap };
{
IsPlacing = true;
startPosition = null;
}
protected override bool OnMouseDown(MouseDownEvent e) public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint();
{
if (!IsPlacing)
return base.OnMouseDown(e);
var pos = snappedLocalPosition(e);
if (!startPosition.HasValue)
startPosition = pos;
else
{
gridToolboxGroup.SetGridFromPoints(startPosition.Value, pos);
IsPlacing = false;
}
if (e.Button == MouseButton.Right)
IsPlacing = false;
return true;
}
protected override bool OnMouseMove(MouseMoveEvent e)
{
if (!IsPlacing)
return base.OnMouseMove(e);
var pos = snappedLocalPosition(e);
if (!startPosition.HasValue)
gridToolboxGroup.StartPosition.Value = pos;
else
gridToolboxGroup.SetGridFromPoints(startPosition.Value, pos);
return true;
}
private Vector2 snappedLocalPosition(UIEvent e)
{
return ToLocalSpace(snapProvider?.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition, ~SnapType.GlobalGrids).ScreenSpacePosition ?? e.ScreenSpaceMousePosition);
}
} }
} }

View File

@ -13,7 +13,6 @@ using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.UI;
@ -86,11 +85,8 @@ namespace osu.Game.Rulesets.Osu.Edit
private ExpandableSlider<float> startPositionYSlider = null!; private ExpandableSlider<float> startPositionYSlider = null!;
private ExpandableSlider<float> spacingSlider = null!; private ExpandableSlider<float> spacingSlider = null!;
private ExpandableSlider<float> gridLinesRotationSlider = null!; private ExpandableSlider<float> gridLinesRotationSlider = null!;
private RoundedButton gridFromPointsButton = null!;
private EditorRadioButtonCollection gridTypeButtons = null!; private EditorRadioButtonCollection gridTypeButtons = null!;
public event Action? GridFromPointsClicked;
public OsuGridToolboxGroup() public OsuGridToolboxGroup()
: base("grid") : base("grid")
{ {
@ -149,12 +145,6 @@ namespace osu.Game.Rulesets.Osu.Edit
Spacing = new Vector2(0f, 10f), Spacing = new Vector2(0f, 10f),
Children = new Drawable[] Children = new Drawable[]
{ {
gridFromPointsButton = new RoundedButton
{
Action = () => GridFromPointsClicked?.Invoke(),
RelativeSizeAxes = Axes.X,
Text = "Grid from points",
},
gridTypeButtons = new EditorRadioButtonCollection gridTypeButtons = new EditorRadioButtonCollection
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
@ -220,8 +210,6 @@ namespace osu.Game.Rulesets.Osu.Edit
expandingContainer?.Expanded.BindValueChanged(v => expandingContainer?.Expanded.BindValueChanged(v =>
{ {
gridFromPointsButton.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint);
gridFromPointsButton.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None;
gridTypeButtons.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint); gridTypeButtons.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint);
gridTypeButtons.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None; gridTypeButtons.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None;
}, true); }, true);

View File

@ -45,7 +45,8 @@ namespace osu.Game.Rulesets.Osu.Edit
{ {
new HitCircleCompositionTool(), new HitCircleCompositionTool(),
new SliderCompositionTool(), new SliderCompositionTool(),
new SpinnerCompositionTool() new SpinnerCompositionTool(),
new GridFromPointsTool(),
}; };
private readonly Bindable<TernaryState> rectangularGridSnapToggle = new Bindable<TernaryState>(); private readonly Bindable<TernaryState> rectangularGridSnapToggle = new Bindable<TernaryState>();
@ -61,8 +62,6 @@ namespace osu.Game.Rulesets.Osu.Edit
private Bindable<HitObject> placementObject; private Bindable<HitObject> placementObject;
private GridFromPointsTool gridFromPointsTool;
[Cached(typeof(IDistanceSnapProvider))] [Cached(typeof(IDistanceSnapProvider))]
public readonly OsuDistanceSnapProvider DistanceSnapProvider = new OsuDistanceSnapProvider(); public readonly OsuDistanceSnapProvider DistanceSnapProvider = new OsuDistanceSnapProvider();
@ -100,14 +99,6 @@ namespace osu.Game.Rulesets.Osu.Edit
OsuGridToolboxGroup.GridType.BindValueChanged(updatePositionSnapGrid, true); OsuGridToolboxGroup.GridType.BindValueChanged(updatePositionSnapGrid, true);
LayerAboveRuleset.Add(
// Place it above the playfield and blueprints, so it takes priority when handling input.
gridFromPointsTool = new GridFromPointsTool
{
RelativeSizeAxes = Axes.Both,
}
);
RightToolbox.AddRange(new Drawable[] RightToolbox.AddRange(new Drawable[]
{ {
OsuGridToolboxGroup, OsuGridToolboxGroup,
@ -291,7 +282,7 @@ namespace osu.Game.Rulesets.Osu.Edit
foreach (var b in blueprints) foreach (var b in blueprints)
{ {
if (b.IsSelected && !gridFromPointsTool.IsPlacing) if (b.IsSelected)
continue; continue;
var snapPositions = b.ScreenSpaceSnapPoints; var snapPositions = b.ScreenSpaceSnapPoints;

View File

@ -77,8 +77,6 @@ namespace osu.Game.Rulesets.Edit
protected readonly Container LayerBelowRuleset = new Container { RelativeSizeAxes = Axes.Both }; protected readonly Container LayerBelowRuleset = new Container { RelativeSizeAxes = Axes.Both };
protected readonly Container LayerAboveRuleset = new Container { RelativeSizeAxes = Axes.Both };
protected InputManager InputManager { get; private set; } protected InputManager InputManager { get; private set; }
private Box leftToolboxBackground; private Box leftToolboxBackground;
@ -145,8 +143,7 @@ namespace osu.Game.Rulesets.Edit
drawableRulesetWrapper, drawableRulesetWrapper,
// layers above playfield // layers above playfield
drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer() drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer()
.WithChild(blueprintContainer = CreateBlueprintContainer()), .WithChild(blueprintContainer = CreateBlueprintContainer())
drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(LayerAboveRuleset),
} }
}, },
new Container new Container
@ -234,7 +231,7 @@ namespace osu.Game.Rulesets.Edit
sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates.Select(b => new DrawableTernaryButton(b))); sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates.Select(b => new DrawableTernaryButton(b)));
setSelectTool(); SetSelectTool();
EditorBeatmap.SelectedHitObjects.CollectionChanged += selectionChanged; EditorBeatmap.SelectedHitObjects.CollectionChanged += selectionChanged;
} }
@ -259,7 +256,7 @@ namespace osu.Game.Rulesets.Edit
{ {
// it's important this is performed before the similar code in EditorRadioButton disables the button. // it's important this is performed before the similar code in EditorRadioButton disables the button.
if (!timing.NewValue) if (!timing.NewValue)
setSelectTool(); SetSelectTool();
}); });
EditorBeatmap.HasTiming.BindValueChanged(hasTiming => EditorBeatmap.HasTiming.BindValueChanged(hasTiming =>
@ -463,11 +460,11 @@ namespace osu.Game.Rulesets.Edit
if (EditorBeatmap.SelectedHitObjects.Any()) if (EditorBeatmap.SelectedHitObjects.Any())
{ {
// ensure in selection mode if a selection is made. // ensure in selection mode if a selection is made.
setSelectTool(); SetSelectTool();
} }
} }
private void setSelectTool() => toolboxCollection.Items.First().Select(); public void SetSelectTool() => toolboxCollection.Items.First().Select();
private void toolSelected(CompositionTool tool) private void toolSelected(CompositionTool tool)
{ {