From 3495510c7b651efee091bad375591b2aa7875102 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 30 Dec 2023 19:16:05 +0100 Subject: [PATCH 01/46] kinda working grid from points --- .../Edit/OsuBlueprintContainer.cs | 42 +++++++++++++++++++ .../Edit/OsuGridToolboxGroup.cs | 21 ++++++++++ 2 files changed, 63 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index 54c54fca17c1..8b391cd06e51 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . 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.Objects; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; @@ -8,16 +10,26 @@ using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; +using osuTK; namespace osu.Game.Rulesets.Osu.Edit { public partial class OsuBlueprintContainer : ComposeBlueprintContainer { + private OsuGridToolboxGroup gridToolbox = null!; + public OsuBlueprintContainer(HitObjectComposer composer) : base(composer) { } + [BackgroundDependencyLoader] + private void load(OsuGridToolboxGroup gridToolbox) + { + this.gridToolbox = gridToolbox; + gridToolbox.GridFromPointsClicked += OnGridFromPointsClicked; + } + protected override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler(); public override HitObjectSelectionBlueprint? CreateHitObjectBlueprintFor(HitObject hitObject) @@ -36,5 +48,35 @@ public OsuBlueprintContainer(HitObjectComposer composer) return base.CreateHitObjectBlueprintFor(hitObject); } + + private bool isPlacingGridFromPoints; + private Vector2? gridFromPointsStart; + + private void OnGridFromPointsClicked() + { + isPlacingGridFromPoints = true; + gridFromPointsStart = null; + } + + protected override bool OnClick(ClickEvent e) + { + if (!isPlacingGridFromPoints) + return base.OnClick(e); + + var pos = ToLocalSpace(Composer.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition).ScreenSpacePosition); + + if (!gridFromPointsStart.HasValue) + { + gridFromPointsStart = pos; + } + else + { + gridToolbox.SetGridFromPoints(gridFromPointsStart.Value, pos); + isPlacingGridFromPoints = false; + gridFromPointsStart = null; + } + + return true; + } } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 76e735449ad8..05b90696a073 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -12,6 +13,7 @@ using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.UI; @@ -90,6 +92,8 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle private ExpandableSlider gridLinesRotationSlider = null!; private EditorRadioButtonCollection gridTypeButtons = null!; + public event Action? GridFromPointsClicked; + public OsuGridToolboxGroup() : base("grid") { @@ -97,6 +101,17 @@ public OsuGridToolboxGroup() private const float max_automatic_spacing = 64; + public void SetGridFromPoints(Vector2 point1, Vector2 point2) + { + StartPositionX.Value = point1.X; + StartPositionY.Value = point1.Y; + GridLinesRotation.Value = (MathHelper.RadiansToDegrees(MathF.Atan2(point2.Y - point1.Y, point2.X - point1.X)) + 405) % 90 - 45; + float dist = Vector2.Distance(point1, point2); + while (dist > Spacing.MaxValue) + dist /= 2; + Spacing.Value = dist; + } + [BackgroundDependencyLoader] private void load() { @@ -129,6 +144,12 @@ private void load() Spacing = new Vector2(0f, 10f), Children = new Drawable[] { + new RoundedButton + { + Action = () => GridFromPointsClicked?.Invoke(), + RelativeSizeAxes = Axes.X, + Text = "Grid from points", + }, gridTypeButtons = new EditorRadioButtonCollection { RelativeSizeAxes = Axes.X, From fea0ceb49899643371e5f81bf32ccf74fac560df Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 30 Dec 2023 20:22:14 +0100 Subject: [PATCH 02/46] improve the grid from points --- .../Edit/OsuBlueprintContainer.cs | 26 ++++++++++++++- .../Edit/OsuGridToolboxGroup.cs | 32 ++++++++++++------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index 8b391cd06e51..79b6fafcab83 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -58,12 +58,17 @@ private void OnGridFromPointsClicked() gridFromPointsStart = null; } + protected override bool OnMouseDown(MouseDownEvent e) + { + return isPlacingGridFromPoints || base.OnMouseDown(e); + } + protected override bool OnClick(ClickEvent e) { if (!isPlacingGridFromPoints) return base.OnClick(e); - var pos = ToLocalSpace(Composer.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition).ScreenSpacePosition); + var pos = ToLocalSpace(Composer.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition, ~SnapType.GlobalGrids).ScreenSpacePosition); if (!gridFromPointsStart.HasValue) { @@ -78,5 +83,24 @@ protected override bool OnClick(ClickEvent e) return true; } + + protected override bool OnMouseMove(MouseMoveEvent e) + { + if (!isPlacingGridFromPoints) + return base.OnMouseMove(e); + + var pos = ToLocalSpace(Composer.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition, ~SnapType.GlobalGrids).ScreenSpacePosition); + + if (!gridFromPointsStart.HasValue) + { + gridToolbox.StartPosition.Value = pos; + } + else + { + gridToolbox.SetGridFromPoints(gridFromPointsStart.Value, pos); + } + + return true; + } } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 05b90696a073..b07d8dcd560e 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -39,7 +39,6 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle { MinValue = 0f, MaxValue = OsuPlayfield.BASE_SIZE.X, - Precision = 1f }; /// @@ -49,7 +48,6 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle { MinValue = 0f, MaxValue = OsuPlayfield.BASE_SIZE.Y, - Precision = 1f }; /// @@ -59,7 +57,6 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle { MinValue = 4f, MaxValue = 128f, - Precision = 1f }; /// @@ -69,7 +66,6 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle { MinValue = -45f, MaxValue = 45f, - Precision = 1f }; /// @@ -105,9 +101,15 @@ public void SetGridFromPoints(Vector2 point1, Vector2 point2) { StartPositionX.Value = point1.X; StartPositionY.Value = point1.Y; - GridLinesRotation.Value = (MathHelper.RadiansToDegrees(MathF.Atan2(point2.Y - point1.Y, point2.X - point1.X)) + 405) % 90 - 45; + + // Get the angle between the two points and normalize to the valid range. + float period = GridType.Value == PositionSnapGridType.Triangle ? 60 : 90; + GridLinesRotation.Value = (MathHelper.RadiansToDegrees(MathF.Atan2(point2.Y - point1.Y, point2.X - point1.X)) + + 360 + period / 2) % period - period / 2; + + // Divide the distance so that there is a good density of grid lines. float dist = Vector2.Distance(point1, point2); - while (dist > Spacing.MaxValue) + while (dist > 32) dist /= 2; Spacing.Value = dist; } @@ -181,22 +183,28 @@ protected override void LoadComplete() StartPositionX.BindValueChanged(x => { - startPositionXSlider.ContractedLabelText = $"X: {x.NewValue:N0}"; - startPositionXSlider.ExpandedLabelText = $"X Offset: {x.NewValue:N0}"; + startPositionXSlider.ContractedLabelText = $"X: {x.NewValue:#,0.##}"; + startPositionXSlider.ExpandedLabelText = $"X Offset: {x.NewValue:#,0.##}"; StartPosition.Value = new Vector2(x.NewValue, StartPosition.Value.Y); }, true); StartPositionY.BindValueChanged(y => { - startPositionYSlider.ContractedLabelText = $"Y: {y.NewValue:N0}"; - startPositionYSlider.ExpandedLabelText = $"Y Offset: {y.NewValue:N0}"; + startPositionYSlider.ContractedLabelText = $"Y: {y.NewValue:#,0.##}"; + startPositionYSlider.ExpandedLabelText = $"Y Offset: {y.NewValue:#,0.##}"; StartPosition.Value = new Vector2(StartPosition.Value.X, y.NewValue); }, true); + StartPosition.BindValueChanged(pos => + { + StartPositionX.Value = pos.NewValue.X; + StartPositionY.Value = pos.NewValue.Y; + }); + Spacing.BindValueChanged(spacing => { - spacingSlider.ContractedLabelText = $"S: {spacing.NewValue:N0}"; - spacingSlider.ExpandedLabelText = $"Spacing: {spacing.NewValue:N0}"; + spacingSlider.ContractedLabelText = $"S: {spacing.NewValue:#,0.##}"; + spacingSlider.ExpandedLabelText = $"Spacing: {spacing.NewValue:#,0.##}"; SpacingVector.Value = new Vector2(spacing.NewValue); editorBeatmap.BeatmapInfo.GridSize = (int)spacing.NewValue; }, true); From c2ea1848ca96c580f36cef4393c2dd5c145f03c1 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 30 Dec 2023 20:58:21 +0100 Subject: [PATCH 03/46] fix period --- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index b07d8dcd560e..31148f10a2e8 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -64,8 +64,8 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle /// public BindableFloat GridLinesRotation { get; } = new BindableFloat(0f) { - MinValue = -45f, - MaxValue = 45f, + MinValue = -90f, + MaxValue = 90f, }; /// @@ -103,9 +103,9 @@ public void SetGridFromPoints(Vector2 point1, Vector2 point2) StartPositionY.Value = point1.Y; // Get the angle between the two points and normalize to the valid range. - float period = GridType.Value == PositionSnapGridType.Triangle ? 60 : 90; + const float period = 180; GridLinesRotation.Value = (MathHelper.RadiansToDegrees(MathF.Atan2(point2.Y - point1.Y, point2.X - point1.X)) - + 360 + period / 2) % period - period / 2; + + period * 1.5f) % period - period * 0.5f; // Divide the distance so that there is a good density of grid lines. float dist = Vector2.Distance(point1, point2); From c952e2f6209ff0cffa7b7db01266baf2cdab73d3 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 31 Dec 2023 02:12:50 +0100 Subject: [PATCH 04/46] deselect stuff stuff when grid from points --- osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index 79b6fafcab83..a5f7185a7d39 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -56,6 +56,9 @@ private void OnGridFromPointsClicked() { isPlacingGridFromPoints = true; gridFromPointsStart = null; + + // Deselect all objects because we cant snap to objects which are selected. + DeselectAll(); } protected override bool OnMouseDown(MouseDownEvent e) From 7a0535a2ebe1e612691f16ced09137feb1aa9da3 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 31 Dec 2023 02:26:14 +0100 Subject: [PATCH 05/46] add right click for abort --- .../Edit/OsuBlueprintContainer.cs | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index a5f7185a7d39..45cf754c57b0 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -11,6 +11,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit { @@ -62,28 +63,23 @@ private void OnGridFromPointsClicked() } protected override bool OnMouseDown(MouseDownEvent e) - { - return isPlacingGridFromPoints || base.OnMouseDown(e); - } - - protected override bool OnClick(ClickEvent e) { if (!isPlacingGridFromPoints) - return base.OnClick(e); + return base.OnMouseDown(e); - var pos = ToLocalSpace(Composer.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition, ~SnapType.GlobalGrids).ScreenSpacePosition); + var pos = snappedLocalPosition(e); if (!gridFromPointsStart.HasValue) - { gridFromPointsStart = pos; - } else { gridToolbox.SetGridFromPoints(gridFromPointsStart.Value, pos); isPlacingGridFromPoints = false; - gridFromPointsStart = null; } + if (e.Button == MouseButton.Right) + isPlacingGridFromPoints = false; + return true; } @@ -92,18 +88,16 @@ protected override bool OnMouseMove(MouseMoveEvent e) if (!isPlacingGridFromPoints) return base.OnMouseMove(e); - var pos = ToLocalSpace(Composer.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition, ~SnapType.GlobalGrids).ScreenSpacePosition); + var pos = snappedLocalPosition(e); if (!gridFromPointsStart.HasValue) - { gridToolbox.StartPosition.Value = pos; - } else - { gridToolbox.SetGridFromPoints(gridFromPointsStart.Value, pos); - } return true; } + + private Vector2 snappedLocalPosition(UIEvent e) => ToLocalSpace(Composer.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition, ~SnapType.GlobalGrids).ScreenSpacePosition); } } From 85bfd6137a5f286341a14615a9ac0ea1fee8137f Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 31 Dec 2023 03:53:42 +0100 Subject: [PATCH 06/46] improve UI From 4e3fe5112d9d02171fb19e23bd26520f34590c87 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 Jan 2024 16:09:18 +0100 Subject: [PATCH 07/46] merge conflict fix --- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 31148f10a2e8..c318bac64da2 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -86,6 +86,7 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle private ExpandableSlider startPositionYSlider = null!; private ExpandableSlider spacingSlider = null!; private ExpandableSlider gridLinesRotationSlider = null!; + private RoundedButton gridFromPointsButton = null!; private EditorRadioButtonCollection gridTypeButtons = null!; public event Action? GridFromPointsClicked; @@ -146,7 +147,7 @@ private void load() Spacing = new Vector2(0f, 10f), Children = new Drawable[] { - new RoundedButton + gridFromPointsButton = new RoundedButton { Action = () => GridFromPointsClicked?.Invoke(), RelativeSizeAxes = Axes.X, @@ -217,6 +218,8 @@ protected override void LoadComplete() 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.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None; }, true); From 98505d0bba18fe4b08c06bf44d77298040c1c5e8 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 31 Dec 2023 18:58:29 +0100 Subject: [PATCH 08/46] improve grid from points tool code --- .../Edit/GridFromPointsTool.cs | 72 +++++++++++++++++++ .../Edit/OsuBlueprintContainer.cs | 63 ---------------- .../Edit/OsuHitObjectComposer.cs | 18 +++-- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 5 +- 4 files changed, 90 insertions(+), 68 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs new file mode 100644 index 000000000000..722d9d13032c --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -0,0 +1,72 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Input.Events; +using osu.Game.Rulesets.Edit; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Rulesets.Osu.Edit +{ + public partial class GridFromPointsTool : Drawable + { + [Resolved] + private OsuGridToolboxGroup gridToolboxGroup { get; set; } = null!; + + [Resolved(canBeNull: true)] + private IPositionSnapProvider? snapProvider { get; set; } + + public bool IsPlacing { get; private set; } + + private Vector2? startPosition; + + public void BeginPlacement() + { + IsPlacing = true; + startPosition = null; + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + 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); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index 45cf754c57b0..54c54fca17c1 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . 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.Objects; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; @@ -10,27 +8,16 @@ using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; -using osuTK; -using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit { public partial class OsuBlueprintContainer : ComposeBlueprintContainer { - private OsuGridToolboxGroup gridToolbox = null!; - public OsuBlueprintContainer(HitObjectComposer composer) : base(composer) { } - [BackgroundDependencyLoader] - private void load(OsuGridToolboxGroup gridToolbox) - { - this.gridToolbox = gridToolbox; - gridToolbox.GridFromPointsClicked += OnGridFromPointsClicked; - } - protected override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler(); public override HitObjectSelectionBlueprint? CreateHitObjectBlueprintFor(HitObject hitObject) @@ -49,55 +36,5 @@ private void load(OsuGridToolboxGroup gridToolbox) return base.CreateHitObjectBlueprintFor(hitObject); } - - private bool isPlacingGridFromPoints; - private Vector2? gridFromPointsStart; - - private void OnGridFromPointsClicked() - { - isPlacingGridFromPoints = true; - gridFromPointsStart = null; - - // Deselect all objects because we cant snap to objects which are selected. - DeselectAll(); - } - - protected override bool OnMouseDown(MouseDownEvent e) - { - if (!isPlacingGridFromPoints) - return base.OnMouseDown(e); - - var pos = snappedLocalPosition(e); - - if (!gridFromPointsStart.HasValue) - gridFromPointsStart = pos; - else - { - gridToolbox.SetGridFromPoints(gridFromPointsStart.Value, pos); - isPlacingGridFromPoints = false; - } - - if (e.Button == MouseButton.Right) - isPlacingGridFromPoints = false; - - return true; - } - - protected override bool OnMouseMove(MouseMoveEvent e) - { - if (!isPlacingGridFromPoints) - return base.OnMouseMove(e); - - var pos = snappedLocalPosition(e); - - if (!gridFromPointsStart.HasValue) - gridToolbox.StartPosition.Value = pos; - else - gridToolbox.SetGridFromPoints(gridFromPointsStart.Value, pos); - - return true; - } - - private Vector2 snappedLocalPosition(UIEvent e) => ToLocalSpace(Composer.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition, ~SnapType.GlobalGrids).ScreenSpacePosition); } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 02e98d75a7e1..e03531719438 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -81,13 +81,12 @@ private void load() // Give a bit of breathing room around the playfield content. PlayfieldContentContainer.Padding = new MarginPadding(10); - LayerBelowRuleset.AddRange(new Drawable[] - { + LayerBelowRuleset.Add( distanceSnapGridContainer = new Container { RelativeSizeAxes = Axes.Both } - }); + ); selectedHitObjects = EditorBeatmap.SelectedHitObjects.GetBoundCopy(); selectedHitObjects.CollectionChanged += (_, _) => updateDistanceSnapGrid(); @@ -100,6 +99,15 @@ private void load() updateDistanceSnapGrid(); OsuGridToolboxGroup.GridType.BindValueChanged(updatePositionSnapGrid, true); + OsuGridToolboxGroup.GridFromPointsClicked += () => gridFromPointsTool.BeginPlacement(); + + 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 EditorToolboxGroup[] { @@ -110,6 +118,8 @@ private void load() ); } + private GridFromPointsTool gridFromPointsTool; + private void updatePositionSnapGrid(ValueChangedEvent obj) { if (positionSnapGrid != null) @@ -278,7 +288,7 @@ private bool snapToVisibleBlueprints(Vector2 screenSpacePosition, out SnapResult foreach (var b in blueprints) { - if (b.IsSelected) + if (b.IsSelected && !gridFromPointsTool.IsPlacing) continue; var snapPositions = b.ScreenSpaceSnapPoints; diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 50e6393895c4..4f8329cc82e1 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -76,6 +76,8 @@ public abstract partial class HitObjectComposer : HitObjectComposer, IP protected readonly Container LayerBelowRuleset = new Container { RelativeSizeAxes = Axes.Both }; + protected readonly Container LayerAboveRuleset = new Container { RelativeSizeAxes = Axes.Both }; + protected InputManager InputManager { get; private set; } private EditorRadioButtonCollection toolboxCollection; @@ -137,7 +139,8 @@ private void load(OsuConfigManager config) drawableRulesetWrapper, // layers above playfield drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer() - .WithChild(BlueprintContainer = CreateBlueprintContainer()) + .WithChild(BlueprintContainer = CreateBlueprintContainer()), + drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(LayerAboveRuleset), } }, new Container From b54c9a36fea93e5bcf2ec3b05ac931eba5090c96 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 31 Dec 2023 19:08:27 +0100 Subject: [PATCH 09/46] move GridFromPointsClicked handler creation code --- osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs | 7 +++++++ osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 5 ++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index 722d9d13032c..9bbeeaafc32d 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -22,6 +22,13 @@ public partial class GridFromPointsTool : Drawable private Vector2? startPosition; + protected override void LoadComplete() + { + base.LoadComplete(); + + gridToolboxGroup.GridFromPointsClicked += BeginPlacement; + } + public void BeginPlacement() { IsPlacing = true; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index e03531719438..cd5c4f4ba963 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -63,6 +63,8 @@ protected override IEnumerable CreateTernaryButtons() private Bindable placementObject; + private GridFromPointsTool gridFromPointsTool; + [Cached(typeof(IDistanceSnapProvider))] protected readonly OsuDistanceSnapProvider DistanceSnapProvider = new OsuDistanceSnapProvider(); @@ -99,7 +101,6 @@ private void load() updateDistanceSnapGrid(); OsuGridToolboxGroup.GridType.BindValueChanged(updatePositionSnapGrid, true); - OsuGridToolboxGroup.GridFromPointsClicked += () => gridFromPointsTool.BeginPlacement(); LayerAboveRuleset.Add( // Place it above the playfield and blueprints, so it takes priority when handling input. @@ -118,8 +119,6 @@ private void load() ); } - private GridFromPointsTool gridFromPointsTool; - private void updatePositionSnapGrid(ValueChangedEvent obj) { if (positionSnapGrid != null) From f8979cff3aaf2c184f08d66fd6cc6f4aeb397f41 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 Jan 2024 16:14:20 +0100 Subject: [PATCH 10/46] fix distance --- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index c318bac64da2..b73eaecc66af 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -110,7 +110,7 @@ public void SetGridFromPoints(Vector2 point1, Vector2 point2) // Divide the distance so that there is a good density of grid lines. float dist = Vector2.Distance(point1, point2); - while (dist > 32) + while (dist >= max_automatic_spacing) dist /= 2; Spacing.Value = dist; } From 2918ecf46c3516039a28f58d2dd71042d505f574 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Thu, 1 Feb 2024 16:56:57 +0100 Subject: [PATCH 11/46] Remove Masking from PositionSnapGrid This caused issues in rendering the outline of the grid because the outline was getting masked at some resolutions. --- .../Components/LinedPositionSnapGrid.cs | 128 +++++++++++++++--- .../Compose/Components/PositionSnapGrid.cs | 2 - 2 files changed, 106 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/LinedPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/LinedPositionSnapGrid.cs index ebdd76a4e2ed..8a7f6b534474 100644 --- a/osu.Game/Screens/Edit/Compose/Components/LinedPositionSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/LinedPositionSnapGrid.cs @@ -15,18 +15,29 @@ public abstract partial class LinedPositionSnapGrid : PositionSnapGrid { protected void GenerateGridLines(Vector2 step, Vector2 drawSize) { + if (Precision.AlmostEquals(step, Vector2.Zero)) + return; + int index = 0; - var currentPosition = StartPosition.Value; // Make lines the same width independent of display resolution. float lineWidth = DrawWidth / ScreenSpaceDrawQuad.Width; - float lineLength = drawSize.Length * 2; + float rotation = MathHelper.RadiansToDegrees(MathF.Atan2(step.Y, step.X)); List generatedLines = new List(); - while (lineDefinitelyIntersectsBox(currentPosition, step.PerpendicularLeft, drawSize) || - isMovingTowardsBox(currentPosition, step, drawSize)) + while (true) { + Vector2 currentPosition = StartPosition.Value + index++ * step; + + if (!lineDefinitelyIntersectsBox(currentPosition, step.PerpendicularLeft, drawSize, out var p1, out var p2)) + { + if (!isMovingTowardsBox(currentPosition, step, drawSize)) + break; + + continue; + } + var gridLine = new Box { Colour = Colour4.White, @@ -34,15 +45,12 @@ protected void GenerateGridLines(Vector2 step, Vector2 drawSize) Origin = Anchor.Centre, RelativeSizeAxes = Axes.None, Width = lineWidth, - Height = lineLength, - Position = currentPosition, - Rotation = MathHelper.RadiansToDegrees(MathF.Atan2(step.Y, step.X)), + Height = Vector2.Distance(p1, p2), + Position = (p1 + p2) / 2, + Rotation = rotation, }; generatedLines.Add(gridLine); - - index += 1; - currentPosition = StartPosition.Value + index * step; } if (generatedLines.Count == 0) @@ -59,23 +67,99 @@ private bool isMovingTowardsBox(Vector2 currentPosition, Vector2 step, Vector2 b (currentPosition + step - box).LengthSquared < (currentPosition - box).LengthSquared; } - private bool lineDefinitelyIntersectsBox(Vector2 lineStart, Vector2 lineDir, Vector2 box) + /// + /// Determines if the line starting at and going in the direction of + /// definitely intersects the box on (0, 0) with the given width and height and returns the intersection points if it does. + /// + /// The start point of the line. + /// The direction of the line. + /// The width and height of the box. + /// The first intersection point. + /// The second intersection point. + /// Whether the line definitely intersects the box. + private bool lineDefinitelyIntersectsBox(Vector2 lineStart, Vector2 lineDir, Vector2 box, out Vector2 p1, out Vector2 p2) { - var p2 = lineStart + lineDir; + p1 = Vector2.Zero; + p2 = Vector2.Zero; + + if (Precision.AlmostEquals(lineDir.X, 0)) + { + // If the line is vertical, we only need to check if the X coordinate of the line is within the box. + if (!Precision.DefinitelyBigger(lineStart.X, 0) || !Precision.DefinitelyBigger(box.X, lineStart.X)) + return false; - double d1 = det(Vector2.Zero); - double d2 = det(new Vector2(box.X, 0)); - double d3 = det(new Vector2(0, box.Y)); - double d4 = det(box); + p1 = new Vector2(lineStart.X, 0); + p2 = new Vector2(lineStart.X, box.Y); + return true; + } + + if (Precision.AlmostEquals(lineDir.Y, 0)) + { + // If the line is horizontal, we only need to check if the Y coordinate of the line is within the box. + if (!Precision.DefinitelyBigger(lineStart.Y, 0) || !Precision.DefinitelyBigger(box.Y, lineStart.Y)) + return false; + + p1 = new Vector2(0, lineStart.Y); + p2 = new Vector2(box.X, lineStart.Y); + return true; + } - return definitelyDifferentSign(d1, d2) || definitelyDifferentSign(d3, d4) || - definitelyDifferentSign(d1, d3) || definitelyDifferentSign(d2, d4); + float m = lineDir.Y / lineDir.X; + float mInv = lineDir.X / lineDir.Y; // Use this to improve numerical stability if X is close to zero. + float b = lineStart.Y - m * lineStart.X; - double det(Vector2 p) => (p.X - lineStart.X) * (p2.Y - lineStart.Y) - (p.Y - lineStart.Y) * (p2.X - lineStart.X); + // Calculate intersection points with the sides of the box. + var p = new List(4); + + if (0 <= b && b <= box.Y) + p.Add(new Vector2(0, b)); + if (0 <= (box.Y - b) * mInv && (box.Y - b) * mInv <= box.X) + p.Add(new Vector2((box.Y - b) * mInv, box.Y)); + if (0 <= m * box.X + b && m * box.X + b <= box.Y) + p.Add(new Vector2(box.X, m * box.X + b)); + if (0 <= -b * mInv && -b * mInv <= box.X) + p.Add(new Vector2(-b * mInv, 0)); + + switch (p.Count) + { + case 4: + // If there are 4 intersection points, the line is a diagonal of the box. + if (m > 0) + { + p1 = Vector2.Zero; + p2 = box; + } + else + { + p1 = new Vector2(0, box.Y); + p2 = new Vector2(box.X, 0); + } + + break; + + case 3: + // If there are 3 intersection points, the line goes through a corner of the box. + if (p[0] == p[1]) + { + p1 = p[0]; + p2 = p[2]; + } + else + { + p1 = p[0]; + p2 = p[1]; + } + + break; + + case 2: + p1 = p[0]; + p2 = p[1]; + + break; + } - bool definitelyDifferentSign(double a, double b) => !Precision.AlmostEquals(a, 0) && - !Precision.AlmostEquals(b, 0) && - Math.Sign(a) != Math.Sign(b); + return !Precision.AlmostEquals(p1, p2); } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/PositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/PositionSnapGrid.cs index 36687ef73a7e..e576ac1e49d9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/PositionSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/PositionSnapGrid.cs @@ -21,8 +21,6 @@ public abstract partial class PositionSnapGrid : CompositeDrawable protected PositionSnapGrid() { - Masking = true; - StartPosition.BindValueChanged(_ => GridCache.Invalidate()); AddLayout(GridCache); From 93dbd7507fd61086a8c9d3422e6a02560254f4d4 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Thu, 1 Feb 2024 17:07:03 +0100 Subject: [PATCH 12/46] Fix masking in circular snap grid --- .../Edit/Compose/Components/CircularPositionSnapGrid.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularPositionSnapGrid.cs index 403a270359e3..791cb3343971 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularPositionSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularPositionSnapGrid.cs @@ -82,7 +82,12 @@ private void generateCircles(int count) generatedCircles.First().Alpha = 0.8f; - AddRangeInternal(generatedCircles); + AddInternal(new Container + { + Masking = true, + RelativeSizeAxes = Axes.Both, + Children = generatedCircles, + }); } public override Vector2 GetSnappedPosition(Vector2 original) From d2f97f5908176696709e4608e3813196682ec7d2 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Thu, 19 Sep 2024 20:18:24 +0200 Subject: [PATCH 13/46] take into account rotation period for each grid type --- .../Edit/OsuGridToolboxGroup.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 4b0353bd36d4..8752e17dadde 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -104,9 +104,11 @@ public void SetGridFromPoints(Vector2 point1, Vector2 point2) StartPositionY.Value = point1.Y; // Get the angle between the two points and normalize to the valid range. - const float period = 180; - GridLinesRotation.Value = (MathHelper.RadiansToDegrees(MathF.Atan2(point2.Y - point1.Y, point2.X - point1.X)) - + period * 1.5f) % period - period * 0.5f; + if (!GridLinesRotation.Disabled) + { + float period = GridLinesRotation.MaxValue - GridLinesRotation.MinValue; + GridLinesRotation.Value = normalizeRotation(MathHelper.RadiansToDegrees(MathF.Atan2(point2.Y - point1.Y, point2.X - point1.X)), period); + } // Divide the distance so that there is a good density of grid lines. float dist = Vector2.Distance(point1, point2); @@ -231,13 +233,13 @@ protected override void LoadComplete() switch (v.NewValue) { case PositionSnapGridType.Square: - GridLinesRotation.Value = ((GridLinesRotation.Value + 405) % 90) - 45; + GridLinesRotation.Value = normalizeRotation(GridLinesRotation.Value, 90); GridLinesRotation.MinValue = -45; GridLinesRotation.MaxValue = 45; break; case PositionSnapGridType.Triangle: - GridLinesRotation.Value = ((GridLinesRotation.Value + 390) % 60) - 30; + GridLinesRotation.Value = normalizeRotation(GridLinesRotation.Value, 60); GridLinesRotation.MinValue = -30; GridLinesRotation.MaxValue = 30; break; @@ -245,6 +247,11 @@ protected override void LoadComplete() }, true); } + private float normalizeRotation(float rotation, float period) + { + return ((rotation + 360 + period * 0.5f) % period) - period * 0.5f; + } + private void nextGridSize() { Spacing.Value = Spacing.Value * 2 >= max_automatic_spacing ? Spacing.Value / 8 : Spacing.Value * 2; From 1a81e12192b6b6d2c1c8d1b9256cb2242e8d66e3 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 23 Sep 2024 16:33:36 +0200 Subject: [PATCH 14/46] Refactor PlacementBlueprint to not be hitobject specific --- .../CatchPlacementBlueprintTestScene.cs | 2 +- ...TestSceneBananaShowerPlacementBlueprint.cs | 4 +- .../TestSceneFruitPlacementBlueprint.cs | 2 +- .../TestSceneJuiceStreamPlacementBlueprint.cs | 2 +- .../Edit/BananaShowerCompositionTool.cs | 4 +- .../Blueprints/CatchPlacementBlueprint.cs | 2 +- .../Edit/CatchHitObjectComposer.cs | 4 +- .../Edit/FruitCompositionTool.cs | 4 +- .../Edit/JuiceStreamCompositionTool.cs | 4 +- .../ManiaPlacementBlueprintTestScene.cs | 2 +- .../TestSceneHoldNotePlacementBlueprint.cs | 2 +- .../Editor/TestSceneNotePlacementBlueprint.cs | 2 +- .../Blueprints/ManiaPlacementBlueprint.cs | 2 +- .../Edit/HoldNoteCompositionTool.cs | 4 +- .../Edit/ManiaHitObjectComposer.cs | 2 +- .../Edit/NoteCompositionTool.cs | 4 +- .../TestSceneHitCirclePlacementBlueprint.cs | 2 +- .../TestSceneSliderPlacementBlueprint.cs | 2 +- .../TestSceneSpinnerPlacementBlueprint.cs | 2 +- .../HitCircles/HitCirclePlacementBlueprint.cs | 2 +- .../Sliders/SliderPlacementBlueprint.cs | 2 +- .../Spinners/SpinnerPlacementBlueprint.cs | 2 +- .../Edit/HitCircleCompositionTool.cs | 4 +- .../Edit/OsuHitObjectComposer.cs | 2 +- .../Edit/SliderCompositionTool.cs | 4 +- .../Edit/SpinnerCompositionTool.cs | 4 +- .../Edit/Blueprints/HitPlacementBlueprint.cs | 2 +- .../Blueprints/TaikoSpanPlacementBlueprint.cs | 2 +- .../Edit/DrumRollCompositionTool.cs | 4 +- .../Edit/HitCompositionTool.cs | 4 +- .../Edit/SwellCompositionTool.cs | 4 +- .../Edit/TaikoHitObjectComposer.cs | 2 +- .../Editing/TestScenePlacementBlueprint.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 +- .../Edit/HitObjectCompositionToolButton.cs | 4 +- .../Edit/HitObjectPlacementBlueprint.cs | 126 ++++++++++++++++++ osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 122 +++-------------- ...tCompositionTool.cs => CompositionTool.cs} | 4 +- osu.Game/Rulesets/Edit/Tools/SelectTool.cs | 4 +- .../Components/ComposeBlueprintContainer.cs | 22 +-- .../Visual/PlacementBlueprintTestScene.cs | 8 +- 41 files changed, 212 insertions(+), 174 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/HitObjectPlacementBlueprint.cs rename osu.Game/Rulesets/Edit/Tools/{HitObjectCompositionTool.cs => CompositionTool.cs} (84%) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs index aae759d934ec..0578010c256f 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs @@ -71,7 +71,7 @@ protected override void AddHitObject(DrawableHitObject hitObject) contentContainer.Playfield.HitObjectContainer.Add(hitObject); } - protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint) + protected override SnapResult SnapForBlueprint(HitObjectPlacementBlueprint blueprint) { var result = base.SnapForBlueprint(blueprint); result.Time = Math.Round(HitObjectContainer.TimeAtScreenSpacePosition(result.ScreenSpacePosition) / TIME_SNAP) * TIME_SNAP; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs index ed37ff4ef3bb..badd8e967dea 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs @@ -22,7 +22,7 @@ public partial class TestSceneBananaShowerPlacementBlueprint : CatchPlacementBlu { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableBananaShower((BananaShower)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new BananaShowerPlacementBlueprint(); + protected override HitObjectPlacementBlueprint CreateBlueprint() => new BananaShowerPlacementBlueprint(); protected override void AddHitObject(DrawableHitObject hitObject) { @@ -71,7 +71,7 @@ public void TestFinishWithZeroDuration() AddClickStep(MouseButton.Left); AddClickStep(MouseButton.Right); AddAssert("banana shower is not placed", () => LastObject == null); - AddAssert("state is waiting", () => CurrentBlueprint?.PlacementActive == PlacementBlueprint.PlacementState.Waiting); + AddAssert("state is waiting", () => CurrentBlueprint?.PlacementActive == HitObjectPlacementBlueprint.PlacementState.Waiting); } [Test] diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs index 75d3c3753a93..80cd948e265a 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs @@ -19,7 +19,7 @@ public partial class TestSceneFruitPlacementBlueprint : CatchPlacementBlueprintT { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableFruit((Fruit)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new FruitPlacementBlueprint(); + protected override HitObjectPlacementBlueprint CreateBlueprint() => new FruitPlacementBlueprint(); [Test] public void TestFruitPlacementPosition() diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs index d010bb02adcf..8bd60078c62f 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs @@ -114,7 +114,7 @@ public void TestMoveBeforeFirstVertex() protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableJuiceStream((JuiceStream)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new JuiceStreamPlacementBlueprint(); + protected override HitObjectPlacementBlueprint CreateBlueprint() => new JuiceStreamPlacementBlueprint(); private void addMoveAndClickSteps(double time, float position, bool end = false) { diff --git a/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs index 31075db7d1d1..be93ba0242ed 100644 --- a/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs +++ b/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Catch.Edit { - public class BananaShowerCompositionTool : HitObjectCompositionTool + public class BananaShowerCompositionTool : CompositionTool { public BananaShowerCompositionTool() : base(nameof(BananaShower)) @@ -19,6 +19,6 @@ public BananaShowerCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Spinners); - public override PlacementBlueprint CreatePlacementBlueprint() => new BananaShowerPlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new BananaShowerPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs index 1a2990e4acff..aa862375c526 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints { - public partial class CatchPlacementBlueprint : PlacementBlueprint + public partial class CatchPlacementBlueprint : HitObjectPlacementBlueprint where THitObject : CatchHitObject, new() { protected new THitObject HitObject => (THitObject)base.HitObject; diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 83f48816f965..8460e238f671 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -84,7 +84,7 @@ protected override DrawableRuleset CreateDrawableRuleset(Ruleset protected override BeatSnapGrid CreateBeatSnapGrid() => new CatchBeatSnapGrid(); - protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] + protected override IReadOnlyList CompositionTools => new CompositionTool[] { new FruitCompositionTool(), new JuiceStreamCompositionTool(), @@ -168,7 +168,7 @@ public override SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePositio if (EditorBeatmap.PlacementObject.Value is JuiceStream) { // Juice stream path is not subject to snapping. - if (BlueprintContainer.CurrentPlacement.PlacementActive is PlacementBlueprint.PlacementState.Active) + if (BlueprintContainer.CurrentPlacement.PlacementActive is HitObjectPlacementBlueprint.PlacementState.Active) return null; } diff --git a/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs index f776fe39c1c7..71c1e6690320 100644 --- a/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs +++ b/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Catch.Edit { - public class FruitCompositionTool : HitObjectCompositionTool + public class FruitCompositionTool : CompositionTool { public FruitCompositionTool() : base(nameof(Fruit)) @@ -19,6 +19,6 @@ public FruitCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Circles); - public override PlacementBlueprint CreatePlacementBlueprint() => new FruitPlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new FruitPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs index cb66e2952e87..7a567820f370 100644 --- a/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs +++ b/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Catch.Edit { - public class JuiceStreamCompositionTool : HitObjectCompositionTool + public class JuiceStreamCompositionTool : CompositionTool { public JuiceStreamCompositionTool() : base(nameof(JuiceStream)) @@ -19,6 +19,6 @@ public JuiceStreamCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Sliders); - public override PlacementBlueprint CreatePlacementBlueprint() => new JuiceStreamPlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new JuiceStreamPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs index d2a44122aa38..5e633c3161a6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs @@ -47,7 +47,7 @@ protected ManiaPlacementBlueprintTestScene() }); } - protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint) + protected override SnapResult SnapForBlueprint(HitObjectPlacementBlueprint blueprint) { double time = column.TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position); var pos = column.ScreenSpacePositionAtTime(time); diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs index b79bcb7682de..2006879ab386 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public partial class TestSceneHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHoldNote((HoldNote)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint(); + protected override HitObjectPlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs index a446f13cbf79..0cb9639cd177 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs @@ -64,6 +64,6 @@ public void TestPlaceAfterCurrentTimeDownwards() private Note getNote() => this.ChildrenOfType().FirstOrDefault()?.HitObject; protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableNote((Note)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint(); + protected override HitObjectPlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 5e0512b5dcb8..a68bd5d6d68a 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public abstract partial class ManiaPlacementBlueprint : PlacementBlueprint + public abstract partial class ManiaPlacementBlueprint : HitObjectPlacementBlueprint where T : ManiaHitObject { protected new T HitObject => (T)base.HitObject; diff --git a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs index 99e1ce04b129..592f8d9af7c9 100644 --- a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mania.Edit { - public class HoldNoteCompositionTool : HitObjectCompositionTool + public class HoldNoteCompositionTool : CompositionTool { public HoldNoteCompositionTool() : base("Hold") @@ -18,6 +18,6 @@ public HoldNoteCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Sliders); - public override PlacementBlueprint CreatePlacementBlueprint() => new HoldNotePlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new HoldNotePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 02a4f3a022f0..e3b4fa2fb7b3 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -46,7 +46,7 @@ protected override ComposeBlueprintContainer CreateBlueprintContainer() protected override BeatSnapGrid CreateBeatSnapGrid() => new ManiaBeatSnapGrid(); - protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] + protected override IReadOnlyList CompositionTools => new CompositionTool[] { new NoteCompositionTool(), new HoldNoteCompositionTool() diff --git a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs index 08ee05ad3f70..2e54d635251c 100644 --- a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mania.Edit { - public class NoteCompositionTool : HitObjectCompositionTool + public class NoteCompositionTool : CompositionTool { public NoteCompositionTool() : base(nameof(Note)) @@ -19,6 +19,6 @@ public NoteCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Circles); - public override PlacementBlueprint CreatePlacementBlueprint() => new NotePlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new NotePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs index a49afd82f3e2..a105d860bf17 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor public partial class TestSceneHitCirclePlacementBlueprint : PlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHitCircle((HitCircle)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new HitCirclePlacementBlueprint(); + protected override HitObjectPlacementBlueprint CreateBlueprint() => new HitCirclePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs index aa6a6f08d878..019565ae2920 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs @@ -514,6 +514,6 @@ private void assertControlPointPosition(int index, Vector2 position) => private Slider? getSlider() => HitObjectContainer.Count > 0 ? ((DrawableSlider)HitObjectContainer[0]).HitObject : null; protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSlider((Slider)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new SliderPlacementBlueprint(); + protected override HitObjectPlacementBlueprint CreateBlueprint() => new SliderPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs index 0e8673319ea8..d7b5cc73bec2 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs @@ -15,6 +15,6 @@ public partial class TestSceneSpinnerPlacementBlueprint : PlacementBlueprintTest { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSpinner((Spinner)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new SpinnerPlacementBlueprint(); + protected override HitObjectPlacementBlueprint CreateBlueprint() => new SpinnerPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index 20ad99baa24f..78a0e36dc2eb 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { - public partial class HitCirclePlacementBlueprint : PlacementBlueprint + public partial class HitCirclePlacementBlueprint : HitObjectPlacementBlueprint { public new HitCircle HitObject => (HitCircle)base.HitObject; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 42945295b8ad..6ffe27dc1328 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public partial class SliderPlacementBlueprint : PlacementBlueprint + public partial class SliderPlacementBlueprint : HitObjectPlacementBlueprint { public new Slider HitObject => (Slider)base.HitObject; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index f59be0e0e984..17d2dcd75cbb 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners { - public partial class SpinnerPlacementBlueprint : PlacementBlueprint + public partial class SpinnerPlacementBlueprint : HitObjectPlacementBlueprint { public new Spinner HitObject => (Spinner)base.HitObject; diff --git a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs index c41ae10b2e10..d3116ede30b3 100644 --- a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Edit { - public class HitCircleCompositionTool : HitObjectCompositionTool + public class HitCircleCompositionTool : CompositionTool { public HitCircleCompositionTool() : base(nameof(HitCircle)) @@ -19,6 +19,6 @@ public HitCircleCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Circles); - public override PlacementBlueprint CreatePlacementBlueprint() => new HitCirclePlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new HitCirclePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 68e57060ad00..e6a9a95b6ba4 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -41,7 +41,7 @@ public OsuHitObjectComposer(Ruleset ruleset) protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods) => new DrawableOsuEditorRuleset(ruleset, beatmap, mods); - protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] + protected override IReadOnlyList CompositionTools => new CompositionTool[] { new HitCircleCompositionTool(), new SliderCompositionTool(), diff --git a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs index 617cc1c19b3d..d697a2ebe6c5 100644 --- a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Edit { - public class SliderCompositionTool : HitObjectCompositionTool + public class SliderCompositionTool : CompositionTool { public SliderCompositionTool() : base(nameof(Slider)) @@ -26,6 +26,6 @@ Right click to finish. public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Sliders); - public override PlacementBlueprint CreatePlacementBlueprint() => new SliderPlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new SliderPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs index c8160617c924..de1506e4a948 100644 --- a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Edit { - public class SpinnerCompositionTool : HitObjectCompositionTool + public class SpinnerCompositionTool : CompositionTool { public SpinnerCompositionTool() : base(nameof(Spinner)) @@ -19,6 +19,6 @@ public SpinnerCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Spinners); - public override PlacementBlueprint CreatePlacementBlueprint() => new SpinnerPlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new SpinnerPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs index 329fff5b423f..7f45123bd69d 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { - public partial class HitPlacementBlueprint : PlacementBlueprint + public partial class HitPlacementBlueprint : HitObjectPlacementBlueprint { private readonly HitPiece piece; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs index cd52398086ff..de3a4d96eb5e 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { - public partial class TaikoSpanPlacementBlueprint : PlacementBlueprint + public partial class TaikoSpanPlacementBlueprint : HitObjectPlacementBlueprint { private readonly HitPiece headPiece; private readonly HitPiece tailPiece; diff --git a/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs b/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs index f332441875cd..ba0fda67712b 100644 --- a/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs +++ b/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Taiko.Edit { - public class DrumRollCompositionTool : HitObjectCompositionTool + public class DrumRollCompositionTool : CompositionTool { public DrumRollCompositionTool() : base(nameof(DrumRoll)) @@ -19,6 +19,6 @@ public DrumRollCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Sliders); - public override PlacementBlueprint CreatePlacementBlueprint() => new DrumRollPlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new DrumRollPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs b/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs index fa5084189390..f58defba83e8 100644 --- a/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs +++ b/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Taiko.Edit { - public class HitCompositionTool : HitObjectCompositionTool + public class HitCompositionTool : CompositionTool { public HitCompositionTool() : base(nameof(Hit)) @@ -19,6 +19,6 @@ public HitCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Circles); - public override PlacementBlueprint CreatePlacementBlueprint() => new HitPlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new HitPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs b/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs index 4d4ee8effed1..4ec623e29ef1 100644 --- a/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs +++ b/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Taiko.Edit { - public class SwellCompositionTool : HitObjectCompositionTool + public class SwellCompositionTool : CompositionTool { public SwellCompositionTool() : base(nameof(Swell)) @@ -19,6 +19,6 @@ public SwellCompositionTool() public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Spinners); - public override PlacementBlueprint CreatePlacementBlueprint() => new SwellPlacementBlueprint(); + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new SwellPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs index 6020f6e04c3c..d97a854ff785 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs @@ -21,7 +21,7 @@ public TaikoHitObjectComposer(TaikoRuleset ruleset) { } - protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] + protected override IReadOnlyList CompositionTools => new CompositionTool[] { new HitCompositionTool(), new DrumRollCompositionTool(), diff --git a/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs b/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs index fe74e1b34618..6f3342f8ce73 100644 --- a/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs +++ b/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs @@ -122,7 +122,7 @@ public void TestAbortPlacementViaGlobalAction() AddAssert("editor is still current", () => Editor.IsCurrentScreen()); AddAssert("slider not placed", () => EditorBeatmap.HitObjects.Count, () => Is.EqualTo(0)); AddAssert("no active placement", () => this.ChildrenOfType().Single().CurrentPlacement.PlacementActive, - () => Is.EqualTo(PlacementBlueprint.PlacementState.Waiting)); + () => Is.EqualTo(HitObjectPlacementBlueprint.PlacementState.Waiting)); } [Test] diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 87c35eafb085..b83c8acec6c3 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -326,7 +326,7 @@ protected override void Update() /// /// A "select" tool is automatically added as the first tool. /// - protected abstract IReadOnlyList CompositionTools { get; } + protected abstract IReadOnlyList CompositionTools { get; } /// /// A collection of states which will be displayed to the user in the toolbox. @@ -469,7 +469,7 @@ private void selectionChanged(object sender, NotifyCollectionChangedEventArgs ch private void setSelectTool() => toolboxCollection.Items.First().Select(); - private void toolSelected(HitObjectCompositionTool tool) + private void toolSelected(CompositionTool tool) { BlueprintContainer.CurrentTool = tool; diff --git a/osu.Game/Rulesets/Edit/HitObjectCompositionToolButton.cs b/osu.Game/Rulesets/Edit/HitObjectCompositionToolButton.cs index ba566ff5c08e..641d60dbd344 100644 --- a/osu.Game/Rulesets/Edit/HitObjectCompositionToolButton.cs +++ b/osu.Game/Rulesets/Edit/HitObjectCompositionToolButton.cs @@ -9,9 +9,9 @@ namespace osu.Game.Rulesets.Edit { public class HitObjectCompositionToolButton : RadioButton { - public HitObjectCompositionTool Tool { get; } + public CompositionTool Tool { get; } - public HitObjectCompositionToolButton(HitObjectCompositionTool tool, Action? action) + public HitObjectCompositionToolButton(CompositionTool tool, Action? action) : base(tool.Name, action, tool.CreateIcon) { Tool = tool; diff --git a/osu.Game/Rulesets/Edit/HitObjectPlacementBlueprint.cs b/osu.Game/Rulesets/Edit/HitObjectPlacementBlueprint.cs new file mode 100644 index 000000000000..74025b426089 --- /dev/null +++ b/osu.Game/Rulesets/Edit/HitObjectPlacementBlueprint.cs @@ -0,0 +1,126 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using System.Threading; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Screens.Edit; +using osu.Game.Screens.Edit.Compose; + +namespace osu.Game.Rulesets.Edit +{ + /// + /// A blueprint which governs the creation of a new to actualisation. + /// + public abstract partial class HitObjectPlacementBlueprint : PlacementBlueprint + { + /// + /// Whether the sample bank should be taken from the previous hit object. + /// + public bool AutomaticBankAssignment { get; set; } + + /// + /// The that is being placed. + /// + public readonly HitObject HitObject; + + [Resolved] + protected EditorClock EditorClock { get; private set; } = null!; + + [Resolved] + private EditorBeatmap beatmap { get; set; } = null!; + + private Bindable startTimeBindable = null!; + + private HitObject? getPreviousHitObject() => beatmap.HitObjects.TakeWhile(h => h.StartTime <= startTimeBindable.Value).LastOrDefault(); + + [Resolved] + private IPlacementHandler placementHandler { get; set; } = null!; + + protected HitObjectPlacementBlueprint(HitObject hitObject) + { + HitObject = hitObject; + + // adding the default hit sample should be the case regardless of the ruleset. + HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_NORMAL)); + } + + [BackgroundDependencyLoader] + private void load() + { + startTimeBindable = HitObject.StartTimeBindable.GetBoundCopy(); + startTimeBindable.BindValueChanged(_ => ApplyDefaultsToHitObject(), true); + } + + protected override void BeginPlacement(bool commitStart = false) + { + base.BeginPlacement(commitStart); + + placementHandler.BeginPlacement(HitObject); + } + + public override void EndPlacement(bool commit) + { + base.EndPlacement(commit); + + placementHandler.EndPlacement(HitObject, IsValidForPlacement && commit); + } + + /// + /// Updates the time and position of this based on the provided snap information. + /// + /// The snap result information. + public override void UpdateTimeAndPosition(SnapResult result) + { + if (PlacementActive == PlacementState.Waiting) + { + HitObject.StartTime = result.Time ?? EditorClock.CurrentTime; + + if (HitObject is IHasComboInformation comboInformation) + comboInformation.UpdateComboInformation(getPreviousHitObject() as IHasComboInformation); + } + + var lastHitObject = getPreviousHitObject(); + + if (AutomaticBankAssignment) + { + // Create samples based on the sample settings of the previous hit object + if (lastHitObject != null) + { + for (int i = 0; i < HitObject.Samples.Count; i++) + HitObject.Samples[i] = lastHitObject.CreateHitSampleInfo(HitObject.Samples[i].Name); + } + } + else + { + var lastHitNormal = lastHitObject?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL); + + if (lastHitNormal != null) + { + // Only inherit the volume from the previous hit object + for (int i = 0; i < HitObject.Samples.Count; i++) + HitObject.Samples[i] = HitObject.Samples[i].With(newVolume: lastHitNormal.Volume); + } + } + + if (HitObject is IHasRepeats hasRepeats) + { + // Make sure all the node samples are identical to the hit object's samples + for (int i = 0; i < hasRepeats.NodeSamples.Count; i++) + hasRepeats.NodeSamples[i] = HitObject.Samples.Select(o => o.With()).ToList(); + } + } + + /// + /// Invokes , + /// refreshing and parameters for the . + /// + protected void ApplyDefaultsToHitObject() => HitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty); + } +} diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index a50a7f416991..d2a54e8e03a2 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -1,29 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; -using System.Threading; -using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; -using osu.Game.Audio; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; -using osu.Game.Screens.Edit; -using osu.Game.Screens.Edit.Compose; using osuTK; using osuTK.Input; namespace osu.Game.Rulesets.Edit { /// - /// A blueprint which governs the creation of a new to actualisation. + /// A blueprint which governs the placement of something. /// public abstract partial class PlacementBlueprint : CompositeDrawable, IKeyBindingHandler { @@ -32,29 +22,6 @@ public abstract partial class PlacementBlueprint : CompositeDrawable, IKeyBindin /// public PlacementState PlacementActive { get; private set; } - /// - /// Whether the sample bank should be taken from the previous hit object. - /// - public bool AutomaticBankAssignment { get; set; } - - /// - /// The that is being placed. - /// - public readonly HitObject HitObject; - - [Resolved] - protected EditorClock EditorClock { get; private set; } = null!; - - [Resolved] - private EditorBeatmap beatmap { get; set; } = null!; - - private Bindable startTimeBindable = null!; - - private HitObject? getPreviousHitObject() => beatmap.HitObjects.TakeWhile(h => h.StartTime <= startTimeBindable.Value).LastOrDefault(); - - [Resolved] - private IPlacementHandler placementHandler { get; set; } = null!; - /// /// Whether this blueprint is currently in a state that can be committed. /// @@ -64,13 +31,8 @@ public abstract partial class PlacementBlueprint : CompositeDrawable, IKeyBindin /// protected virtual bool IsValidForPlacement => true; - protected PlacementBlueprint(HitObject hitObject) + protected PlacementBlueprint() { - HitObject = hitObject; - - // adding the default hit sample should be the case regardless of the ruleset. - HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_NORMAL)); - RelativeSizeAxes = Axes.Both; // This is required to allow the blueprint's position to be updated via OnMouseMove/Handle @@ -78,30 +40,22 @@ protected PlacementBlueprint(HitObject hitObject) AlwaysPresent = true; } - [BackgroundDependencyLoader] - private void load() - { - startTimeBindable = HitObject.StartTimeBindable.GetBoundCopy(); - startTimeBindable.BindValueChanged(_ => ApplyDefaultsToHitObject(), true); - } - /// - /// Signals that the placement of has started. + /// Signals that the placement has started. /// - /// Whether this call is committing a value for HitObject.StartTime and continuing with further adjustments. - protected void BeginPlacement(bool commitStart = false) + /// Whether this call is committing a value and continuing with further adjustments. + protected virtual void BeginPlacement(bool commitStart = false) { - placementHandler.BeginPlacement(HitObject); if (commitStart) PlacementActive = PlacementState.Active; } /// /// Signals that the placement of has finished. - /// This will destroy this , and add the HitObject.StartTime to the . + /// This will destroy this , and commit the changes. /// - /// Whether the object should be committed. Note that a commit may fail if is false. - public void EndPlacement(bool commit) + /// Whether the changes should be committed. Note that a commit may fail if is false. + public virtual void EndPlacement(bool commit) { switch (PlacementActive) { @@ -114,10 +68,17 @@ public void EndPlacement(bool commit) break; } - placementHandler.EndPlacement(HitObject, IsValidForPlacement && commit); PlacementActive = PlacementState.Finished; } + /// + /// Updates the time and position of this based on the provided snap information. + /// + /// The snap result information. + public virtual void UpdateTimeAndPosition(SnapResult result) + { + } + public bool OnPressed(KeyBindingPressEvent e) { if (PlacementActive == PlacementState.Waiting) @@ -138,57 +99,6 @@ public void OnReleased(KeyBindingReleaseEvent e) { } - /// - /// Updates the time and position of this based on the provided snap information. - /// - /// The snap result information. - public virtual void UpdateTimeAndPosition(SnapResult result) - { - if (PlacementActive == PlacementState.Waiting) - { - HitObject.StartTime = result.Time ?? EditorClock.CurrentTime; - - if (HitObject is IHasComboInformation comboInformation) - comboInformation.UpdateComboInformation(getPreviousHitObject() as IHasComboInformation); - } - - var lastHitObject = getPreviousHitObject(); - - if (AutomaticBankAssignment) - { - // Create samples based on the sample settings of the previous hit object - if (lastHitObject != null) - { - for (int i = 0; i < HitObject.Samples.Count; i++) - HitObject.Samples[i] = lastHitObject.CreateHitSampleInfo(HitObject.Samples[i].Name); - } - } - else - { - var lastHitNormal = lastHitObject?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL); - - if (lastHitNormal != null) - { - // Only inherit the volume from the previous hit object - for (int i = 0; i < HitObject.Samples.Count; i++) - HitObject.Samples[i] = HitObject.Samples[i].With(newVolume: lastHitNormal.Volume); - } - } - - if (HitObject is IHasRepeats hasRepeats) - { - // Make sure all the node samples are identical to the hit object's samples - for (int i = 0; i < hasRepeats.NodeSamples.Count; i++) - hasRepeats.NodeSamples[i] = HitObject.Samples.Select(o => o.With()).ToList(); - } - } - - /// - /// Invokes , - /// refreshing and parameters for the . - /// - protected void ApplyDefaultsToHitObject() => HitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty); - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; protected override bool Handle(UIEvent e) diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/CompositionTool.cs similarity index 84% rename from osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs rename to osu.Game/Rulesets/Edit/Tools/CompositionTool.cs index ba1dc817bb19..f509302daa90 100644 --- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/CompositionTool.cs @@ -6,13 +6,13 @@ namespace osu.Game.Rulesets.Edit.Tools { - public abstract class HitObjectCompositionTool + public abstract class CompositionTool { public readonly string Name; public LocalisableString TooltipText { get; init; } - protected HitObjectCompositionTool(string name) + protected CompositionTool(string name) { Name = name; } diff --git a/osu.Game/Rulesets/Edit/Tools/SelectTool.cs b/osu.Game/Rulesets/Edit/Tools/SelectTool.cs index a272e9f480d9..7f8889bfcaec 100644 --- a/osu.Game/Rulesets/Edit/Tools/SelectTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/SelectTool.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Edit.Tools { - public class SelectTool : HitObjectCompositionTool + public class SelectTool : CompositionTool { public SelectTool() : base("Select") @@ -18,6 +18,6 @@ public SelectTool() public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorSelect }; - public override PlacementBlueprint CreatePlacementBlueprint() => null; + public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => null; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index f1294ccc3cb8..f0296d45aa45 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -41,6 +41,8 @@ public partial class ComposeBlueprintContainer : EditorBlueprintContainer public PlacementBlueprint CurrentPlacement { get; private set; } + public HitObjectPlacementBlueprint CurrentHitObjectPlacement => CurrentPlacement as HitObjectPlacementBlueprint; + [Resolved(canBeNull: true)] private EditorScreenWithTimeline editorScreen { get; set; } @@ -164,13 +166,13 @@ private void nudgeSelection(Vector2 delta) private void updatePlacementNewCombo() { - if (CurrentPlacement?.HitObject is IHasComboInformation c) + if (CurrentHitObjectPlacement?.HitObject is IHasComboInformation c) c.NewCombo = NewCombo.Value == TernaryState.True; } private void updatePlacementSamples() { - if (CurrentPlacement == null) return; + if (CurrentHitObjectPlacement == null) return; foreach (var kvp in SelectionHandler.SelectionSampleStates) sampleChanged(kvp.Key, kvp.Value.Value); @@ -181,9 +183,9 @@ private void updatePlacementSamples() private void sampleChanged(string sampleName, TernaryState state) { - if (CurrentPlacement == null) return; + if (CurrentHitObjectPlacement == null) return; - var samples = CurrentPlacement.HitObject.Samples; + var samples = CurrentHitObjectPlacement.HitObject.Samples; var existingSample = samples.FirstOrDefault(s => s.Name == sampleName); @@ -196,19 +198,19 @@ private void sampleChanged(string sampleName, TernaryState state) case TernaryState.True: if (existingSample == null) - samples.Add(CurrentPlacement.HitObject.CreateHitSampleInfo(sampleName)); + samples.Add(CurrentHitObjectPlacement.HitObject.CreateHitSampleInfo(sampleName)); break; } } private void bankChanged(string bankName, TernaryState state) { - if (CurrentPlacement == null) return; + if (CurrentHitObjectPlacement == null) return; if (bankName == EditorSelectionHandler.HIT_BANK_AUTO) - CurrentPlacement.AutomaticBankAssignment = state == TernaryState.True; + CurrentHitObjectPlacement.AutomaticBankAssignment = state == TernaryState.True; else if (state == TernaryState.True) - CurrentPlacement.HitObject.Samples = CurrentPlacement.HitObject.Samples.Select(s => s.With(newBank: bankName)).ToList(); + CurrentHitObjectPlacement.HitObject.Samples = CurrentHitObjectPlacement.HitObject.Samples.Select(s => s.With(newBank: bankName)).ToList(); } public readonly Bindable NewCombo = new Bindable { Description = "New Combo" }; @@ -386,12 +388,12 @@ private void removePlacement() CurrentPlacement = null; } - private HitObjectCompositionTool currentTool; + private CompositionTool currentTool; /// /// The current placement tool. /// - public HitObjectCompositionTool CurrentTool + public CompositionTool CurrentTool { get => currentTool; diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs index 0027e0349297..c8d9ef8fc8df 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual public abstract partial class PlacementBlueprintTestScene : OsuManualInputManagerTestScene, IPlacementHandler { protected readonly Container HitObjectContainer; - protected PlacementBlueprint CurrentBlueprint { get; private set; } + protected HitObjectPlacementBlueprint CurrentBlueprint { get; private set; } protected PlacementBlueprintTestScene() { @@ -87,14 +87,14 @@ protected override void Update() CurrentBlueprint.UpdateTimeAndPosition(SnapForBlueprint(CurrentBlueprint)); } - protected virtual SnapResult SnapForBlueprint(PlacementBlueprint blueprint) => + protected virtual SnapResult SnapForBlueprint(HitObjectPlacementBlueprint blueprint) => new SnapResult(InputManager.CurrentState.Mouse.Position, null); public override void Add(Drawable drawable) { base.Add(drawable); - if (drawable is PlacementBlueprint blueprint) + if (drawable is HitObjectPlacementBlueprint blueprint) { blueprint.Show(); blueprint.UpdateTimeAndPosition(SnapForBlueprint(blueprint)); @@ -106,6 +106,6 @@ public override void Add(Drawable drawable) protected virtual Container CreateHitObjectContainer() => new Container { RelativeSizeAxes = Axes.Both }; protected abstract DrawableHitObject CreateHitObject(HitObject hitObject); - protected abstract PlacementBlueprint CreateBlueprint(); + protected abstract HitObjectPlacementBlueprint CreateBlueprint(); } } From 0a5a4633807d20d4d95e36e9969112328d89781f Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 23 Sep 2024 16:36:11 +0200 Subject: [PATCH 15/46] Convert 'grid from points' button to placement tool --- .../Edit/Blueprints/GridPlacementBlueprint.cs | 83 +++++++++++++++++++ .../Edit/GridFromPointsTool.cs | 78 ++++------------- .../Edit/OsuGridToolboxGroup.cs | 12 --- .../Edit/OsuHitObjectComposer.cs | 15 +--- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 13 ++- 5 files changed, 105 insertions(+), 96 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs new file mode 100644 index 000000000000..f632828f629d --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs @@ -0,0 +1,83 @@ +// Copyright (c) ppy Pty Ltd . 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); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index 9bbeeaafc32d..1714dacd1777 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -1,79 +1,29 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Input.Events; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; using osu.Game.Rulesets.Edit; -using osuTK; -using osuTK.Input; +using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Osu.Edit.Blueprints; namespace osu.Game.Rulesets.Osu.Edit { - public partial class GridFromPointsTool : Drawable + public partial class GridFromPointsTool : CompositionTool { - [Resolved] - private OsuGridToolboxGroup gridToolboxGroup { get; set; } = null!; - - [Resolved(canBeNull: true)] - private IPositionSnapProvider? snapProvider { get; set; } - - public bool IsPlacing { get; private set; } - - private Vector2? startPosition; - - protected override void LoadComplete() - { - base.LoadComplete(); - - gridToolboxGroup.GridFromPointsClicked += BeginPlacement; - } - - public void BeginPlacement() - { - IsPlacing = true; - startPosition = null; - } - - protected override bool OnMouseDown(MouseDownEvent e) + public GridFromPointsTool() + : base("Change grid") { - 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; + TooltipText = """ + Left click to set the origin. + Left click again to set the rotation and spacing. + Right click to only set the origin. + """; } - protected override bool OnMouseMove(MouseMoveEvent e) - { - if (!IsPlacing) - return base.OnMouseMove(e); - - var pos = snappedLocalPosition(e); + public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGridSnap }; - 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); - } + public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 8752e17dadde..db2909a6afa8 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -13,7 +13,6 @@ using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; -using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.UI; @@ -86,11 +85,8 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle private ExpandableSlider startPositionYSlider = null!; private ExpandableSlider spacingSlider = null!; private ExpandableSlider gridLinesRotationSlider = null!; - private RoundedButton gridFromPointsButton = null!; private EditorRadioButtonCollection gridTypeButtons = null!; - public event Action? GridFromPointsClicked; - public OsuGridToolboxGroup() : base("grid") { @@ -149,12 +145,6 @@ private void load() Spacing = new Vector2(0f, 10f), Children = new Drawable[] { - gridFromPointsButton = new RoundedButton - { - Action = () => GridFromPointsClicked?.Invoke(), - RelativeSizeAxes = Axes.X, - Text = "Grid from points", - }, gridTypeButtons = new EditorRadioButtonCollection { RelativeSizeAxes = Axes.X, @@ -220,8 +210,6 @@ protected override void LoadComplete() 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.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None; }, true); diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index e6a9a95b6ba4..3e24a48d4960 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -45,7 +45,8 @@ protected override DrawableRuleset CreateDrawableRuleset(Ruleset r { new HitCircleCompositionTool(), new SliderCompositionTool(), - new SpinnerCompositionTool() + new SpinnerCompositionTool(), + new GridFromPointsTool(), }; private readonly Bindable rectangularGridSnapToggle = new Bindable(); @@ -61,8 +62,6 @@ protected override IEnumerable CreateTernaryButtons() private Bindable placementObject; - private GridFromPointsTool gridFromPointsTool; - [Cached(typeof(IDistanceSnapProvider))] public readonly OsuDistanceSnapProvider DistanceSnapProvider = new OsuDistanceSnapProvider(); @@ -100,14 +99,6 @@ private void load() 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[] { OsuGridToolboxGroup, @@ -291,7 +282,7 @@ private bool snapToVisibleBlueprints(Vector2 screenSpacePosition, out SnapResult foreach (var b in blueprints) { - if (b.IsSelected && !gridFromPointsTool.IsPlacing) + if (b.IsSelected) continue; var snapPositions = b.ScreenSpaceSnapPoints; diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index b83c8acec6c3..2053f9ff5dc3 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -77,8 +77,6 @@ public abstract partial class HitObjectComposer : HitObjectComposer, IP protected readonly Container LayerBelowRuleset = new Container { RelativeSizeAxes = Axes.Both }; - protected readonly Container LayerAboveRuleset = new Container { RelativeSizeAxes = Axes.Both }; - protected InputManager InputManager { get; private set; } private Box leftToolboxBackground; @@ -145,8 +143,7 @@ private void load(OsuConfigManager config, [CanBeNull] Editor editor) drawableRulesetWrapper, // layers above playfield drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer() - .WithChild(blueprintContainer = CreateBlueprintContainer()), - drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(LayerAboveRuleset), + .WithChild(blueprintContainer = CreateBlueprintContainer()) } }, new Container @@ -234,7 +231,7 @@ private void load(OsuConfigManager config, [CanBeNull] Editor editor) sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates.Select(b => new DrawableTernaryButton(b))); - setSelectTool(); + SetSelectTool(); EditorBeatmap.SelectedHitObjects.CollectionChanged += selectionChanged; } @@ -259,7 +256,7 @@ protected override void LoadComplete() { // it's important this is performed before the similar code in EditorRadioButton disables the button. if (!timing.NewValue) - setSelectTool(); + SetSelectTool(); }); EditorBeatmap.HasTiming.BindValueChanged(hasTiming => @@ -463,11 +460,11 @@ private void selectionChanged(object sender, NotifyCollectionChangedEventArgs ch if (EditorBeatmap.SelectedHitObjects.Any()) { // 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) { From fe106217718ce733a9acc1d886f94e0e25a4ca5b Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 23 Sep 2024 16:39:09 +0200 Subject: [PATCH 16/46] Clarify criteria of grid spacing subdivision --- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index db2909a6afa8..487d73693f15 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -107,6 +107,7 @@ public void SetGridFromPoints(Vector2 point1, Vector2 point2) } // Divide the distance so that there is a good density of grid lines. + // This matches the maximum grid size of the grid size cycling hotkey. float dist = Vector2.Distance(point1, point2); while (dist >= max_automatic_spacing) dist /= 2; From 0f0f490598a575cfa934628f4f7d461767b27f46 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 23 Sep 2024 17:24:09 +0200 Subject: [PATCH 17/46] Don't snap to global grid while placing grid --- osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs | 2 ++ osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 2 ++ .../Edit/Compose/Components/ComposeBlueprintContainer.cs | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs index f632828f629d..d45d82579f39 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs @@ -70,6 +70,8 @@ protected override bool OnMouseDown(MouseDownEvent e) return base.OnMouseDown(e); } + public override SnapType SnapType => ~SnapType.GlobalGrids; + public override void UpdateTimeAndPosition(SnapResult result) { var pos = ToLocalSpace(result.ScreenSpacePosition); diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index d2a54e8e03a2..2b346d750ffd 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -71,6 +71,8 @@ public virtual void EndPlacement(bool commit) PlacementActive = PlacementState.Finished; } + public virtual SnapType SnapType => SnapType.All; + /// /// Updates the time and position of this based on the provided snap information. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index f0296d45aa45..cbec8fc7a34f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -297,7 +297,7 @@ private void refreshTool() private void updatePlacementPosition() { - var snapResult = Composer.FindSnappedPositionAndTime(InputManager.CurrentState.Mouse.Position); + var snapResult = Composer.FindSnappedPositionAndTime(InputManager.CurrentState.Mouse.Position, CurrentPlacement.SnapType); // if no time was found from positional snapping, we should still quantize to the beat. snapResult.Time ??= Beatmap.SnapTime(EditorClock.CurrentTime, null); From b274ed9427b040aaa441be6227c8e6f0d7f1dd13 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 23 Sep 2024 17:34:45 +0200 Subject: [PATCH 18/46] fix warnings --- .../Editor/TestSceneBananaShowerPlacementBlueprint.cs | 2 +- osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs | 2 +- osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs index badd8e967dea..296d34d628e2 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs @@ -71,7 +71,7 @@ public void TestFinishWithZeroDuration() AddClickStep(MouseButton.Left); AddClickStep(MouseButton.Right); AddAssert("banana shower is not placed", () => LastObject == null); - AddAssert("state is waiting", () => CurrentBlueprint?.PlacementActive == HitObjectPlacementBlueprint.PlacementState.Waiting); + AddAssert("state is waiting", () => CurrentBlueprint?.PlacementActive == PlacementBlueprint.PlacementState.Waiting); } [Test] diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 8460e238f671..7323c7a91aff 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -168,7 +168,7 @@ public override SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePositio if (EditorBeatmap.PlacementObject.Value is JuiceStream) { // Juice stream path is not subject to snapping. - if (BlueprintContainer.CurrentPlacement.PlacementActive is HitObjectPlacementBlueprint.PlacementState.Active) + if (BlueprintContainer.CurrentPlacement.PlacementActive is PlacementBlueprint.PlacementState.Active) return null; } diff --git a/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs b/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs index 6f3342f8ce73..fe74e1b34618 100644 --- a/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs +++ b/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs @@ -122,7 +122,7 @@ public void TestAbortPlacementViaGlobalAction() AddAssert("editor is still current", () => Editor.IsCurrentScreen()); AddAssert("slider not placed", () => EditorBeatmap.HitObjects.Count, () => Is.EqualTo(0)); AddAssert("no active placement", () => this.ChildrenOfType().Single().CurrentPlacement.PlacementActive, - () => Is.EqualTo(HitObjectPlacementBlueprint.PlacementState.Waiting)); + () => Is.EqualTo(PlacementBlueprint.PlacementState.Waiting)); } [Test] From 4e2bc0d1bdae7b7f55476de675a1e1caf1d25500 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 28 Sep 2024 15:56:37 +0200 Subject: [PATCH 19/46] place grid with drag instead --- .../Edit/Blueprints/GridPlacementBlueprint.cs | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs index d45d82579f39..a5b9efd9309b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs @@ -44,30 +44,34 @@ public override void EndPlacement(bool commit) osuHitObjectComposer.SetSelectTool(); } - protected override bool OnMouseDown(MouseDownEvent e) + protected override bool OnClick(ClickEvent e) { - switch (e.Button) + if (e.Button == MouseButton.Left) { - 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; + EndPlacement(true); + return true; } - return base.OnMouseDown(e); + return base.OnClick(e); + } + + protected override bool OnDragStart(DragStartEvent e) + { + if (e.Button == MouseButton.Left) + { + BeginPlacement(true); + return true; + } + + return base.OnDragStart(e); + } + + protected override void OnDragEnd(DragEndEvent e) + { + if (PlacementActive == PlacementState.Active) + EndPlacement(true); + + base.OnDragEnd(e); } public override SnapType SnapType => ~SnapType.GlobalGrids; From b1e381a391fb1b3a64d141c38c92fe8abab34b33 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 28 Sep 2024 15:59:07 +0200 Subject: [PATCH 20/46] Update tooltip for drag --- osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index 1714dacd1777..396fac475479 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -17,8 +17,7 @@ public GridFromPointsTool() { TooltipText = """ Left click to set the origin. - Left click again to set the rotation and spacing. - Right click to only set the origin. + Click and drag to set the origin, rotation and spacing. """; } From 1c6e42671acfe269955355ce2d7c875f3568861b Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 28 Sep 2024 17:04:11 +0200 Subject: [PATCH 21/46] return grid placement tool to right toolbox --- osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs | 9 --------- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 12 ++++++++++++ osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 4 +++- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 8 ++++++++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index 396fac475479..f357d3024f82 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Osu.Edit.Blueprints; @@ -15,14 +12,8 @@ public partial class GridFromPointsTool : CompositionTool public GridFromPointsTool() : base("Change grid") { - TooltipText = """ - Left click to set the origin. - Click and drag to set the origin, rotation and spacing. - """; } - public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGridSnap }; - public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 487d73693f15..b08ecb0e6121 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -13,6 +13,7 @@ using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.UI; @@ -85,8 +86,11 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle private ExpandableSlider startPositionYSlider = null!; private ExpandableSlider spacingSlider = null!; private ExpandableSlider gridLinesRotationSlider = null!; + private RoundedButton gridFromPointsButton = null!; private EditorRadioButtonCollection gridTypeButtons = null!; + public event Action? GridFromPointsClicked; + public OsuGridToolboxGroup() : base("grid") { @@ -146,6 +150,12 @@ private void load() Spacing = new Vector2(0f, 10f), Children = new Drawable[] { + gridFromPointsButton = new RoundedButton + { + Action = () => GridFromPointsClicked?.Invoke(), + RelativeSizeAxes = Axes.X, + Text = "Grid from points", + }, gridTypeButtons = new EditorRadioButtonCollection { RelativeSizeAxes = Axes.X, @@ -211,6 +221,8 @@ protected override void LoadComplete() 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.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None; }, true); diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 3e24a48d4960..d9ae312b29e9 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -46,9 +46,10 @@ protected override DrawableRuleset CreateDrawableRuleset(Ruleset r new HitCircleCompositionTool(), new SliderCompositionTool(), new SpinnerCompositionTool(), - new GridFromPointsTool(), }; + private readonly GridFromPointsTool gridFromPointsTool = new GridFromPointsTool(); + private readonly Bindable rectangularGridSnapToggle = new Bindable(); protected override Drawable CreateHitObjectInspector() => new OsuHitObjectInspector(); @@ -98,6 +99,7 @@ private void load() updateDistanceSnapGrid(); OsuGridToolboxGroup.GridType.BindValueChanged(updatePositionSnapGrid, true); + OsuGridToolboxGroup.GridFromPointsClicked += () => SetCustomTool(gridFromPointsTool); RightToolbox.AddRange(new Drawable[] { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 2053f9ff5dc3..cf1607acde81 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -466,6 +466,14 @@ private void selectionChanged(object sender, NotifyCollectionChangedEventArgs ch public void SetSelectTool() => toolboxCollection.Items.First().Select(); + protected void SetCustomTool(CompositionTool tool) + { + foreach (var toolBoxRadioButton in toolboxCollection.Items) + toolBoxRadioButton.Deselect(); + + toolSelected(tool); + } + private void toolSelected(CompositionTool tool) { BlueprintContainer.CurrentTool = tool; From 3e4cd0aeacf6b5c795261f5d2adae60624d4a003 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 28 Sep 2024 17:04:20 +0200 Subject: [PATCH 22/46] Add tooltip to rounded button --- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 4 ++++ osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index b08ecb0e6121..a5771c595b89 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -155,6 +155,10 @@ private void load() Action = () => GridFromPointsClicked?.Invoke(), RelativeSizeAxes = Axes.X, Text = "Grid from points", + TooltipText = """ + Left click to set the origin. + Click and drag to set the origin, rotation and spacing. + """ }, gridTypeButtons = new EditorRadioButtonCollection { diff --git a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs index 6aded3fe3223..a993867a93a9 100644 --- a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Backgrounds; @@ -17,7 +18,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { - public partial class RoundedButton : OsuButton, IFilterable + public partial class RoundedButton : OsuButton, IFilterable, IHasTooltip { protected TrianglesV2? Triangles { get; private set; } @@ -107,5 +108,6 @@ public bool MatchingFilter } public bool FilteringActive { get; set; } + public LocalisableString TooltipText { get; set; } } } From 4568af8fdae457c121fb53712c62acd6eb79372a Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 28 Sep 2024 17:26:39 +0200 Subject: [PATCH 23/46] Combine drag and clicky interactions --- .../Edit/Blueprints/GridPlacementBlueprint.cs | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs index a5b9efd9309b..d0caec269f1a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs @@ -47,12 +47,31 @@ public override void EndPlacement(bool commit) protected override bool OnClick(ClickEvent e) { if (e.Button == MouseButton.Left) + { + switch (PlacementActive) + { + case PlacementState.Waiting: + BeginPlacement(true); + return true; + + case PlacementState.Active: + EndPlacement(true); + return true; + } + } + + return base.OnClick(e); + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + if (e.Button == MouseButton.Right) { EndPlacement(true); return true; } - return base.OnClick(e); + return base.OnMouseDown(e); } protected override bool OnDragStart(DragStartEvent e) @@ -83,7 +102,18 @@ public override void UpdateTimeAndPosition(SnapResult result) if (PlacementActive != PlacementState.Active) gridToolboxGroup.StartPosition.Value = pos; else - gridToolboxGroup.SetGridFromPoints(gridToolboxGroup.StartPosition.Value, pos); + { + // Default to the original spacing and rotation if the distance is too small. + if (Vector2.Distance(gridToolboxGroup.StartPosition.Value, pos) < 2) + { + gridToolboxGroup.Spacing.Value = originalSpacing; + gridToolboxGroup.GridLinesRotation.Value = originalRotation; + } + else + { + gridToolboxGroup.SetGridFromPoints(gridToolboxGroup.StartPosition.Value, pos); + } + } } } } From 1912b1fcf3b5743459ab2981a81c6260f3f22f52 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 28 Sep 2024 17:33:24 +0200 Subject: [PATCH 24/46] Revert "Add tooltip to rounded button" This reverts commit 3e4cd0aeacf6b5c795261f5d2adae60624d4a003. --- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 4 ---- osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs | 4 +--- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index a5771c595b89..b08ecb0e6121 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -155,10 +155,6 @@ private void load() Action = () => GridFromPointsClicked?.Invoke(), RelativeSizeAxes = Axes.X, Text = "Grid from points", - TooltipText = """ - Left click to set the origin. - Click and drag to set the origin, rotation and spacing. - """ }, gridTypeButtons = new EditorRadioButtonCollection { diff --git a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs index a993867a93a9..6aded3fe3223 100644 --- a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Backgrounds; @@ -18,7 +17,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { - public partial class RoundedButton : OsuButton, IFilterable, IHasTooltip + public partial class RoundedButton : OsuButton, IFilterable { protected TrianglesV2? Triangles { get; private set; } @@ -108,6 +107,5 @@ public bool MatchingFilter } public bool FilteringActive { get; set; } - public LocalisableString TooltipText { get; set; } } } From 4de73dd9c8fc79d4e91402cb7ff7dadc2854fecf Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 1 Oct 2024 15:28:13 +0200 Subject: [PATCH 25/46] Reapply "Add tooltip to rounded button" This reverts commit 1912b1fcf3b5743459ab2981a81c6260f3f22f52. --- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 4 ++++ osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index b08ecb0e6121..a5771c595b89 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -155,6 +155,10 @@ private void load() Action = () => GridFromPointsClicked?.Invoke(), RelativeSizeAxes = Axes.X, Text = "Grid from points", + TooltipText = """ + Left click to set the origin. + Click and drag to set the origin, rotation and spacing. + """ }, gridTypeButtons = new EditorRadioButtonCollection { diff --git a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs index 6aded3fe3223..a993867a93a9 100644 --- a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Backgrounds; @@ -17,7 +18,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { - public partial class RoundedButton : OsuButton, IFilterable + public partial class RoundedButton : OsuButton, IFilterable, IHasTooltip { protected TrianglesV2? Triangles { get; private set; } @@ -107,5 +108,6 @@ public bool MatchingFilter } public bool FilteringActive { get; set; } + public LocalisableString TooltipText { get; set; } } } From 9fa2849b14fe6499a6740547a9db5f7ece23fcb4 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 1 Oct 2024 15:34:12 +0200 Subject: [PATCH 26/46] Fixed tooltip inheritors of RoundedButton --- osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs | 3 ++- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 5 ++--- osu.Game/Overlays/Settings/SettingsButton.cs | 4 +--- osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs | 5 ++--- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs index a993867a93a9..9b57ebb20021 100644 --- a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs @@ -108,6 +108,7 @@ public bool MatchingFilter } public bool FilteringActive { get; set; } - public LocalisableString TooltipText { get; set; } + + public virtual LocalisableString TooltipText { get; set; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index cbdb2ea190bc..eab394c8f654 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -7,7 +7,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; @@ -21,7 +20,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { - public partial class FavouriteButton : HeaderButton, IHasTooltip + public partial class FavouriteButton : HeaderButton { public readonly Bindable BeatmapSet = new Bindable(); @@ -32,7 +31,7 @@ public partial class FavouriteButton : HeaderButton, IHasTooltip private readonly IBindable localUser = new Bindable(); - public LocalisableString TooltipText + public override LocalisableString TooltipText { get { diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index a83744475875..d964a3357858 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Settings { - public partial class SettingsButton : RoundedButton, IHasTooltip, IConditionalFilterable + public partial class SettingsButton : RoundedButton, IConditionalFilterable { public SettingsButton() { @@ -20,8 +20,6 @@ public SettingsButton() Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS }; } - public LocalisableString TooltipText { get; set; } - public IEnumerable Keywords { get; set; } = Array.Empty(); public BindableBool CanBeShown { get; } = new BindableBool(true); diff --git a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs index 2e669fd1b225..56e2719e9c87 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online; @@ -11,7 +10,7 @@ namespace osu.Game.Screens.OnlinePlay.Components { - public abstract partial class ReadyButton : RoundedButton, IHasTooltip + public abstract partial class ReadyButton : RoundedButton { public new readonly BindableBool Enabled = new BindableBool(); @@ -29,7 +28,7 @@ private void load(OnlinePlayBeatmapAvailabilityTracker beatmapTracker) private void updateState() => base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value; - public virtual LocalisableString TooltipText + public override LocalisableString TooltipText { get { From c84bb4b7978dd4e0be87c2a17912b2f204f95207 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 1 Oct 2024 15:38:21 +0200 Subject: [PATCH 27/46] Update tooltip --- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index a5771c595b89..9ef1aa0ff86f 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -157,7 +157,9 @@ private void load() Text = "Grid from points", TooltipText = """ Left click to set the origin. - Click and drag to set the origin, rotation and spacing. + Left click again to set the spacing and rotation. + Right click to only set the origin. + Click and drag to set the origin, spacing and rotation. """ }, gridTypeButtons = new EditorRadioButtonCollection From 4959045851609627cd8326cf4e2ceedd3f5578ac Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 1 Oct 2024 15:53:39 +0200 Subject: [PATCH 28/46] Remove 'Centre on selected object' button --- .../Edit/OsuGridToolboxGroup.cs | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 563135a1ddb8..089a8a84cd02 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -16,7 +16,6 @@ using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.UI; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components.RadioButtons; @@ -88,7 +87,6 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle private ExpandableSlider spacingSlider = null!; private ExpandableSlider gridLinesRotationSlider = null!; private RoundedButton gridFromPointsButton = null!; - private ExpandableButton useSelectedObjectPositionButton = null!; private EditorRadioButtonCollection gridTypeButtons = null!; public event Action? GridFromPointsClicked; @@ -135,19 +133,6 @@ private void load() Current = StartPositionY, KeyboardStep = 1, }, - useSelectedObjectPositionButton = new ExpandableButton - { - ExpandedLabelText = "Centre on selected object", - Action = () => - { - if (editorBeatmap.SelectedHitObjects.Count != 1) - return; - - StartPosition.Value = ((IHasPosition)editorBeatmap.SelectedHitObjects.Single()).Position; - updateEnabledStates(); - }, - RelativeSizeAxes = Axes.X, - }, spacingSlider = new ExpandableSlider { Current = Spacing, @@ -260,25 +245,15 @@ protected override void LoadComplete() } }, true); - editorBeatmap.BeatmapReprocessed += updateEnabledStates; - editorBeatmap.SelectedHitObjects.BindCollectionChanged((_, _) => updateEnabledStates()); 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.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None; - updateEnabledStates(); }, true); } - private void updateEnabledStates() - { - useSelectedObjectPositionButton.Enabled.Value = expandingContainer?.Expanded.Value == true - && editorBeatmap.SelectedHitObjects.Count == 1 - && StartPosition.Value != ((IHasPosition)editorBeatmap.SelectedHitObjects.Single()).Position; - } - private float normalizeRotation(float rotation, float period) { return ((rotation + 360 + period * 0.5f) % period) - period * 0.5f; From 4bbefa360cd6b9c2358530f157b6f3d19f16f68e Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 1 Oct 2024 15:57:34 +0200 Subject: [PATCH 29/46] fix using directive --- osu.Game/Overlays/Settings/SettingsButton.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index d964a3357858..196ddca95307 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -6,7 +6,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterfaceV2; From 80dffa905a2596ba43805f3653d91b4eeed6ff1f Mon Sep 17 00:00:00 2001 From: OliBomby Date: Thu, 3 Oct 2024 11:13:49 +0200 Subject: [PATCH 30/46] Use new keyword instead of overriding TooltipText to remove setter --- osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs | 2 +- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 2 +- osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs index 9b57ebb20021..5875874cf619 100644 --- a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs @@ -109,6 +109,6 @@ public bool MatchingFilter public bool FilteringActive { get; set; } - public virtual LocalisableString TooltipText { get; set; } + public LocalisableString TooltipText { get; set; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index eab394c8f654..9d6d61708289 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -31,7 +31,7 @@ public partial class FavouriteButton : HeaderButton private readonly IBindable localUser = new Bindable(); - public override LocalisableString TooltipText + public new LocalisableString TooltipText { get { diff --git a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs index 56e2719e9c87..95fb48e3ce7e 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs @@ -28,7 +28,7 @@ private void load(OnlinePlayBeatmapAvailabilityTracker beatmapTracker) private void updateState() => base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value; - public override LocalisableString TooltipText + public new virtual LocalisableString TooltipText { get { From 2c39ecbda3ee3b20958b0904519b534788f61477 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Thu, 3 Oct 2024 11:16:37 +0200 Subject: [PATCH 31/46] Add xmldoc to SnapType --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 2b346d750ffd..a36de0243395 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -71,6 +71,9 @@ public virtual void EndPlacement(bool commit) PlacementActive = PlacementState.Finished; } + /// + /// Determines which objects to snap to for the snap result in . + /// public virtual SnapType SnapType => SnapType.All; /// From ad734b1a136b72d6304a00aca8aed4c090acbddd Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 5 Oct 2024 15:10:36 +0200 Subject: [PATCH 32/46] Revert "Use new keyword instead of overriding TooltipText to remove setter" This reverts commit 80dffa905a2596ba43805f3653d91b4eeed6ff1f. --- osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs | 2 +- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 2 +- osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs index 5875874cf619..9b57ebb20021 100644 --- a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs @@ -109,6 +109,6 @@ public bool MatchingFilter public bool FilteringActive { get; set; } - public LocalisableString TooltipText { get; set; } + public virtual LocalisableString TooltipText { get; set; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 9d6d61708289..eab394c8f654 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -31,7 +31,7 @@ public partial class FavouriteButton : HeaderButton private readonly IBindable localUser = new Bindable(); - public new LocalisableString TooltipText + public override LocalisableString TooltipText { get { diff --git a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs index 95fb48e3ce7e..56e2719e9c87 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs @@ -28,7 +28,7 @@ private void load(OnlinePlayBeatmapAvailabilityTracker beatmapTracker) private void updateState() => base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value; - public new virtual LocalisableString TooltipText + public override LocalisableString TooltipText { get { From cc29e8c16d2580108df16b7c63685c12e85b81db Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 5 Oct 2024 15:16:29 +0200 Subject: [PATCH 33/46] introduce tooltip to rounded button with subclass instead --- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 9 ++++++++- osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs | 5 +---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 089a8a84cd02..4ac8d55ec363 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -7,10 +7,12 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; @@ -150,7 +152,7 @@ private void load() Spacing = new Vector2(0f, 10f), Children = new Drawable[] { - gridFromPointsButton = new RoundedButton + gridFromPointsButton = new TooltipRoundedButton { Action = () => GridFromPointsClicked?.Invoke(), RelativeSizeAxes = Axes.X, @@ -311,6 +313,11 @@ public OutlineTriangle(bool outlineOnly, float size) } } + public partial class TooltipRoundedButton : RoundedButton, IHasTooltip + { + public virtual LocalisableString TooltipText { get; set; } + } + public enum PositionSnapGridType { Square, diff --git a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs index 9b57ebb20021..6aded3fe3223 100644 --- a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Backgrounds; @@ -18,7 +17,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { - public partial class RoundedButton : OsuButton, IFilterable, IHasTooltip + public partial class RoundedButton : OsuButton, IFilterable { protected TrianglesV2? Triangles { get; private set; } @@ -108,7 +107,5 @@ public bool MatchingFilter } public bool FilteringActive { get; set; } - - public virtual LocalisableString TooltipText { get; set; } } } From ae8abc7f3576309bd68076c23d7358b02a94637d Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 5 Oct 2024 21:46:00 +0200 Subject: [PATCH 34/46] fix readybutton and favouritebutton --- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 5 +++-- osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index eab394c8f654..cbdb2ea190bc 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { - public partial class FavouriteButton : HeaderButton + public partial class FavouriteButton : HeaderButton, IHasTooltip { public readonly Bindable BeatmapSet = new Bindable(); @@ -31,7 +32,7 @@ public partial class FavouriteButton : HeaderButton private readonly IBindable localUser = new Bindable(); - public override LocalisableString TooltipText + public LocalisableString TooltipText { get { diff --git a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs index 56e2719e9c87..20203fedac00 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online; @@ -10,7 +11,7 @@ namespace osu.Game.Screens.OnlinePlay.Components { - public abstract partial class ReadyButton : RoundedButton + public abstract partial class ReadyButton : RoundedButton, IHasTooltip { public new readonly BindableBool Enabled = new BindableBool(); @@ -28,7 +29,7 @@ private void load(OnlinePlayBeatmapAvailabilityTracker beatmapTracker) private void updateState() => base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value; - public override LocalisableString TooltipText + public LocalisableString TooltipText { get { From 75f15ccabad3d5680dd82c4e2910524353512631 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Oct 2024 16:04:24 +0900 Subject: [PATCH 35/46] Maybe fix compilation? Fuck knows if this is correct. --- osu.Game/Overlays/Settings/SettingsButton.cs | 2 ++ osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index 196ddca95307..52ea8caed9a6 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -24,6 +24,8 @@ public SettingsButton() public BindableBool CanBeShown { get; } = new BindableBool(true); IBindable IConditionalFilterable.CanBeShown => CanBeShown; + public virtual LocalisableString TooltipText { get; set; } + public override IEnumerable FilterTerms { get diff --git a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs index 20203fedac00..2e669fd1b225 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs @@ -29,7 +29,7 @@ private void load(OnlinePlayBeatmapAvailabilityTracker beatmapTracker) private void updateState() => base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value; - public LocalisableString TooltipText + public virtual LocalisableString TooltipText { get { From 0a7d2395d2f437fb9cf9611cb4bffee114576ad1 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 7 Oct 2024 10:43:24 +0200 Subject: [PATCH 36/46] fix tooltip in SettingsButton --- osu.Game/Overlays/Settings/SettingsButton.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index 52ea8caed9a6..3f5d612eb8e2 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -6,12 +6,13 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Overlays.Settings { - public partial class SettingsButton : RoundedButton, IConditionalFilterable + public partial class SettingsButton : RoundedButton, IHasTooltip, IConditionalFilterable { public SettingsButton() { @@ -24,7 +25,7 @@ public SettingsButton() public BindableBool CanBeShown { get; } = new BindableBool(true); IBindable IConditionalFilterable.CanBeShown => CanBeShown; - public virtual LocalisableString TooltipText { get; set; } + public LocalisableString TooltipText { get; set; } public override IEnumerable FilterTerms { From 7b998219d733b01de79013e74de8102bf26e1b6c Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 7 Oct 2024 12:04:14 +0200 Subject: [PATCH 37/46] move grid placement tool to left toolbox --- .../Edit/GridFromPointsTool.cs | 11 ++++++++ .../Edit/OsuGridToolboxGroup.cs | 25 ------------------- .../Edit/OsuHitObjectComposer.cs | 4 +-- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 8 ------ 4 files changed, 12 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index f357d3024f82..638833f581db 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Osu.Edit.Blueprints; @@ -12,8 +15,16 @@ public partial class GridFromPointsTool : CompositionTool public GridFromPointsTool() : base("Change grid") { + TooltipText = """ + Left click to set the origin. + Left click again to set the spacing and rotation. + Right click to only set the origin. + Click and drag to set the origin, spacing and rotation. + """; } + public override Drawable? CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGridSnap }; + public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 4ac8d55ec363..f71243a10923 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -7,15 +7,12 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; -using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; -using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.UI; @@ -88,11 +85,8 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle private ExpandableSlider startPositionYSlider = null!; private ExpandableSlider spacingSlider = null!; private ExpandableSlider gridLinesRotationSlider = null!; - private RoundedButton gridFromPointsButton = null!; private EditorRadioButtonCollection gridTypeButtons = null!; - public event Action? GridFromPointsClicked; - public OsuGridToolboxGroup() : base("grid") { @@ -152,18 +146,6 @@ private void load() Spacing = new Vector2(0f, 10f), Children = new Drawable[] { - gridFromPointsButton = new TooltipRoundedButton - { - Action = () => GridFromPointsClicked?.Invoke(), - RelativeSizeAxes = Axes.X, - Text = "Grid from points", - TooltipText = """ - Left click to set the origin. - Left click again to set the spacing and rotation. - Right click to only set the origin. - Click and drag to set the origin, spacing and rotation. - """ - }, gridTypeButtons = new EditorRadioButtonCollection { RelativeSizeAxes = Axes.X, @@ -249,8 +231,6 @@ protected override void LoadComplete() 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.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None; }, true); @@ -313,11 +293,6 @@ public OutlineTriangle(bool outlineOnly, float size) } } - public partial class TooltipRoundedButton : RoundedButton, IHasTooltip - { - public virtual LocalisableString TooltipText { get; set; } - } - public enum PositionSnapGridType { Square, diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index dcfe6eeca779..7c50558b9253 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -46,10 +46,9 @@ protected override DrawableRuleset CreateDrawableRuleset(Ruleset r new HitCircleCompositionTool(), new SliderCompositionTool(), new SpinnerCompositionTool(), + new GridFromPointsTool() }; - private readonly GridFromPointsTool gridFromPointsTool = new GridFromPointsTool(); - private readonly Bindable rectangularGridSnapToggle = new Bindable(); protected override Drawable CreateHitObjectInspector() => new OsuHitObjectInspector(); @@ -99,7 +98,6 @@ private void load() updateDistanceSnapGrid(); OsuGridToolboxGroup.GridType.BindValueChanged(updatePositionSnapGrid, true); - OsuGridToolboxGroup.GridFromPointsClicked += () => SetCustomTool(gridFromPointsTool); RightToolbox.AddRange(new Drawable[] { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 1c6bed5fa871..b52228ccb9ea 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -466,14 +466,6 @@ private void selectionChanged(object sender, NotifyCollectionChangedEventArgs ch public void SetSelectTool() => toolboxCollection.Items.First().Select(); - protected void SetCustomTool(CompositionTool tool) - { - foreach (var toolBoxRadioButton in toolboxCollection.Items) - toolBoxRadioButton.Deselect(); - - toolSelected(tool); - } - private void toolSelected(CompositionTool tool) { BlueprintContainer.CurrentTool = tool; From a755ae70a300c9f1fd5aaf821913f202b9f9711b Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 7 Oct 2024 12:13:56 +0200 Subject: [PATCH 38/46] fix warning --- osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index 638833f581db..b429d47e6d8c 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -23,7 +23,7 @@ Right click to only set the origin. """; } - public override Drawable? CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGridSnap }; + public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGridSnap }; public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint(); } From 533ed609fbf51ef82a5bb7943defd99caf2b807b Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 7 Oct 2024 16:19:01 +0200 Subject: [PATCH 39/46] Fix crash on placing circular grid --- .../Edit/Blueprints/GridPlacementBlueprint.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs index d0caec269f1a..4f23be2bee91 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs @@ -34,7 +34,8 @@ public override void EndPlacement(bool commit) { gridToolboxGroup.StartPosition.Value = originalOrigin; gridToolboxGroup.Spacing.Value = originalSpacing; - gridToolboxGroup.GridLinesRotation.Value = originalRotation; + if (!gridToolboxGroup.GridLinesRotation.Disabled) + gridToolboxGroup.GridLinesRotation.Value = originalRotation; } base.EndPlacement(commit); @@ -107,7 +108,8 @@ public override void UpdateTimeAndPosition(SnapResult result) if (Vector2.Distance(gridToolboxGroup.StartPosition.Value, pos) < 2) { gridToolboxGroup.Spacing.Value = originalSpacing; - gridToolboxGroup.GridLinesRotation.Value = originalRotation; + if (!gridToolboxGroup.GridLinesRotation.Disabled) + gridToolboxGroup.GridLinesRotation.Value = originalRotation; } else { From db10202642d12ce594ad8b66fe3d7658f7166524 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 7 Oct 2024 16:51:53 +0200 Subject: [PATCH 40/46] Use new place grid icon --- osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs | 2 +- osu.Game/Graphics/OsuIcon.cs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index b429d47e6d8c..bc143886ce70 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -23,7 +23,7 @@ Right click to only set the origin. """; } - public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGridSnap }; + public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorPlaceGrid }; public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint(); } diff --git a/osu.Game/Graphics/OsuIcon.cs b/osu.Game/Graphics/OsuIcon.cs index 9879ef5d148d..77ab83ece6ca 100644 --- a/osu.Game/Graphics/OsuIcon.cs +++ b/osu.Game/Graphics/OsuIcon.cs @@ -178,6 +178,7 @@ public static class OsuIcon public static IconUsage EditorWhistle => get(OsuIconMapping.EditorWhistle); public static IconUsage Tortoise => get(OsuIconMapping.Tortoise); public static IconUsage Hare => get(OsuIconMapping.Hare); + public static IconUsage EditorPlaceGrid => get(OsuIconMapping.EditorPlaceGrid); private static IconUsage get(OsuIconMapping glyph) => new IconUsage((char)glyph, FONT_NAME); @@ -392,6 +393,9 @@ private enum OsuIconMapping [Description(@"hare")] Hare, + + [Description(@"Editor/place-grid")] + EditorPlaceGrid, } public class OsuIconStore : ITextureStore, ITexturedGlyphLookupStore From 076c8dec5a9e6c54406a291324776479eb080425 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 7 Oct 2024 19:06:32 +0200 Subject: [PATCH 41/46] Revert "Use new place grid icon" This reverts commit db10202642d12ce594ad8b66fe3d7658f7166524. --- osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs | 2 +- osu.Game/Graphics/OsuIcon.cs | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index bc143886ce70..b429d47e6d8c 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -23,7 +23,7 @@ Right click to only set the origin. """; } - public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorPlaceGrid }; + public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGridSnap }; public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint(); } diff --git a/osu.Game/Graphics/OsuIcon.cs b/osu.Game/Graphics/OsuIcon.cs index 77ab83ece6ca..9879ef5d148d 100644 --- a/osu.Game/Graphics/OsuIcon.cs +++ b/osu.Game/Graphics/OsuIcon.cs @@ -178,7 +178,6 @@ public static class OsuIcon public static IconUsage EditorWhistle => get(OsuIconMapping.EditorWhistle); public static IconUsage Tortoise => get(OsuIconMapping.Tortoise); public static IconUsage Hare => get(OsuIconMapping.Hare); - public static IconUsage EditorPlaceGrid => get(OsuIconMapping.EditorPlaceGrid); private static IconUsage get(OsuIconMapping glyph) => new IconUsage((char)glyph, FONT_NAME); @@ -393,9 +392,6 @@ private enum OsuIconMapping [Description(@"hare")] Hare, - - [Description(@"Editor/place-grid")] - EditorPlaceGrid, } public class OsuIconStore : ITextureStore, ITexturedGlyphLookupStore From 66459c50de4be931ee26be13245a6b9ff812d1ee Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 7 Oct 2024 19:09:09 +0200 Subject: [PATCH 42/46] Rename to 'Grid' --- osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index b429d47e6d8c..7d4d925ac4aa 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Edit public partial class GridFromPointsTool : CompositionTool { public GridFromPointsTool() - : base("Change grid") + : base("Grid") { TooltipText = """ Left click to set the origin. From dc267733d13d0a4f3edfc74f567d62bd42d22472 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 7 Oct 2024 19:09:21 +0200 Subject: [PATCH 43/46] Use FA icon instead --- osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index 7d4d925ac4aa..5d6bc6f52581 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Osu.Edit.Blueprints; @@ -23,7 +22,7 @@ Right click to only set the origin. """; } - public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGridSnap }; + public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.Solid.DraftingCompass }; public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint(); } From b1be31cd6a31f9a4837be62cba783b74addb8c06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2024 17:34:51 +0900 Subject: [PATCH 44/46] Switch back to last tool after using grid tool, rather than always select tool --- .../Edit/Blueprints/GridPlacementBlueprint.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs index 4f23be2bee91..be33e0e8c862 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs @@ -42,7 +42,7 @@ public override void EndPlacement(bool 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(); + osuHitObjectComposer.SetLastTool(); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index b52228ccb9ea..0499e10607ad 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -90,6 +90,9 @@ public abstract partial class HitObjectComposer : HitObjectComposer, IP private Bindable autoSeekOnPlacement; private readonly Bindable composerFocusMode = new Bindable(); + [CanBeNull] + private RadioButton lastTool; + protected DrawableRuleset DrawableRuleset { get; private set; } protected HitObjectComposer(Ruleset ruleset) @@ -213,8 +216,7 @@ private void load(OsuConfigManager config, [CanBeNull] Editor editor) }, }; - toolboxCollection.Items = CompositionTools - .Prepend(new SelectTool()) + toolboxCollection.Items = (CompositionTools.Prepend(new SelectTool())) .Select(t => new HitObjectCompositionToolButton(t, () => toolSelected(t))) .ToList(); @@ -466,8 +468,12 @@ private void selectionChanged(object sender, NotifyCollectionChangedEventArgs ch public void SetSelectTool() => toolboxCollection.Items.First().Select(); + public void SetLastTool() => (lastTool ?? toolboxCollection.Items.First()).Select(); + private void toolSelected(CompositionTool tool) { + lastTool = toolboxCollection.Items.OfType().FirstOrDefault(i => i.Tool == BlueprintContainer.CurrentTool); + BlueprintContainer.CurrentTool = tool; if (!(tool is SelectTool)) From e794862da59c0836df08107c7915d690ff84145f Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 8 Oct 2024 10:46:10 +0200 Subject: [PATCH 45/46] update comment --- osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs index be33e0e8c862..85042e0e32e4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs @@ -40,7 +40,7 @@ public override void EndPlacement(bool commit) base.EndPlacement(commit); - // You typically only place the grid once, so we switch back to the select tool after placement. + // You typically only place the grid once, so we switch back to the last tool after placement. if (commit && hitObjectComposer is OsuHitObjectComposer osuHitObjectComposer) osuHitObjectComposer.SetLastTool(); } From de2f9dec39c193108c8919aefe24cb6fda5d6a29 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 8 Oct 2024 10:51:35 +0200 Subject: [PATCH 46/46] Let right-click reset grid to default values --- .../Edit/Blueprints/GridPlacementBlueprint.cs | 5 +++++ osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs | 2 +- osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs index 85042e0e32e4..b13663cb446b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs @@ -68,6 +68,11 @@ protected override bool OnMouseDown(MouseDownEvent e) { if (e.Button == MouseButton.Right) { + // Reset the grid to the default values. + gridToolboxGroup.StartPosition.Value = gridToolboxGroup.StartPosition.Default; + gridToolboxGroup.Spacing.Value = gridToolboxGroup.Spacing.Default; + if (!gridToolboxGroup.GridLinesRotation.Disabled) + gridToolboxGroup.GridLinesRotation.Value = gridToolboxGroup.GridLinesRotation.Default; EndPlacement(true); return true; } diff --git a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs index 5d6bc6f52581..626153a7fdaa 100644 --- a/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs @@ -17,7 +17,7 @@ public GridFromPointsTool() TooltipText = """ Left click to set the origin. Left click again to set the spacing and rotation. - Right click to only set the origin. + Right click to reset to default. Click and drag to set the origin, spacing and rotation. """; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index f71243a10923..2b88860cc8ae 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -71,7 +71,7 @@ public partial class OsuGridToolboxGroup : EditorToolboxGroup, IKeyBindingHandle /// Read-only bindable representing the grid's origin. /// Equivalent to new Vector2(StartPositionX, StartPositionY) /// - public Bindable StartPosition { get; } = new Bindable(); + public Bindable StartPosition { get; } = new Bindable(OsuPlayfield.BASE_SIZE / 2); /// /// Read-only bindable representing the grid's spacing in both the X and Y dimension.