diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs index 21427ba281..7cafd10454 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs @@ -1,7 +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 System; using System.Linq; using NUnit.Framework; using osu.Framework.Testing; @@ -101,8 +100,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor return grid switch { RectangularPositionSnapGrid rectangular => rectangular.StartPosition.Value + GeometryUtils.RotateVector(rectangular.Spacing.Value, -rectangular.GridLineRotation.Value), - TriangularPositionSnapGrid triangular => triangular.StartPosition.Value + GeometryUtils.RotateVector(new Vector2(triangular.Spacing.Value / 2, triangular.Spacing.Value / 2 * MathF.Sqrt(3)), -triangular.GridLineRotation.Value), - CircularPositionSnapGrid circular => circular.StartPosition.Value + GeometryUtils.RotateVector(new Vector2(circular.Spacing.Value, 0), -45), _ => Vector2.Zero }; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 76e735449a..e82ca780ad 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -1,13 +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 System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; @@ -16,9 +12,7 @@ using osu.Game.Input.Bindings; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.UI; using osu.Game.Screens.Edit; -using osu.Game.Screens.Edit.Components.RadioButtons; using osuTK; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Edit { @@ -82,13 +76,10 @@ namespace osu.Game.Rulesets.Osu.Edit /// public Bindable SpacingVector { get; } = new Bindable(); - public Bindable GridType { get; } = new Bindable(); - private ExpandableSlider startPositionXSlider = null!; private ExpandableSlider startPositionYSlider = null!; private ExpandableSlider spacingSlider = null!; private ExpandableSlider gridLinesRotationSlider = null!; - private EditorRadioButtonCollection gridTypeButtons = null!; public OsuGridToolboxGroup() : base("grid") @@ -122,31 +113,6 @@ namespace osu.Game.Rulesets.Osu.Edit Current = GridLinesRotation, KeyboardStep = 1, }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(0f, 10f), - Children = new Drawable[] - { - gridTypeButtons = new EditorRadioButtonCollection - { - RelativeSizeAxes = Axes.X, - Items = new[] - { - new RadioButton("Square", - () => GridType.Value = PositionSnapGridType.Square, - () => new SpriteIcon { Icon = FontAwesome.Regular.Square }), - new RadioButton("Triangle", - () => GridType.Value = PositionSnapGridType.Triangle, - () => new OutlineTriangle(true, 20)), - new RadioButton("Circle", - () => GridType.Value = PositionSnapGridType.Circle, - () => new SpriteIcon { Icon = FontAwesome.Regular.Circle }), - } - }, - } - }, }; Spacing.Value = editorBeatmap.BeatmapInfo.GridSize; @@ -156,8 +122,6 @@ namespace osu.Game.Rulesets.Osu.Edit { base.LoadComplete(); - gridTypeButtons.Items.First().Select(); - StartPositionX.BindValueChanged(x => { startPositionXSlider.ContractedLabelText = $"X: {x.NewValue:N0}"; @@ -185,12 +149,6 @@ namespace osu.Game.Rulesets.Osu.Edit gridLinesRotationSlider.ContractedLabelText = $"R: {rotation.NewValue:#,0.##}"; gridLinesRotationSlider.ExpandedLabelText = $"Rotation: {rotation.NewValue:#,0.##}"; }, true); - - expandingContainer?.Expanded.BindValueChanged(v => - { - gridTypeButtons.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint); - gridTypeButtons.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None; - }, true); } private void nextGridSize() @@ -213,42 +171,5 @@ namespace osu.Game.Rulesets.Osu.Edit public void OnReleased(KeyBindingReleaseEvent e) { } - - public partial class OutlineTriangle : BufferedContainer - { - public OutlineTriangle(bool outlineOnly, float size) - : base(cachedFrameBuffer: true) - { - Size = new Vector2(size); - - InternalChildren = new Drawable[] - { - new EquilateralTriangle { RelativeSizeAxes = Axes.Both }, - }; - - if (outlineOnly) - { - AddInternal(new EquilateralTriangle - { - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.Y, - Y = 0.48f, - Colour = Color4.Black, - Size = new Vector2(size - 7), - Blending = BlendingParameters.None, - }); - } - - Blending = BlendingParameters.Additive; - } - } - } - - public enum PositionSnapGridType - { - Square, - Triangle, - Circle, } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 84d5adbc52..51bb74926f 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Edit // we may be entering the screen with a selection already active updateDistanceSnapGrid(); - OsuGridToolboxGroup.GridType.BindValueChanged(updatePositionSnapGrid, true); + updatePositionSnapGrid(); RightToolbox.AddRange(new EditorToolboxGroup[] { @@ -110,45 +110,18 @@ namespace osu.Game.Rulesets.Osu.Edit ); } - private void updatePositionSnapGrid(ValueChangedEvent obj) + private void updatePositionSnapGrid() { if (positionSnapGrid != null) LayerBelowRuleset.Remove(positionSnapGrid, true); - switch (obj.NewValue) - { - case PositionSnapGridType.Square: - var rectangularPositionSnapGrid = new RectangularPositionSnapGrid(); + var rectangularPositionSnapGrid = new RectangularPositionSnapGrid(); - rectangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.SpacingVector); - rectangularPositionSnapGrid.GridLineRotation.BindTo(OsuGridToolboxGroup.GridLinesRotation); + rectangularPositionSnapGrid.StartPosition.BindTo(OsuGridToolboxGroup.StartPosition); + rectangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.SpacingVector); + rectangularPositionSnapGrid.GridLineRotation.BindTo(OsuGridToolboxGroup.GridLinesRotation); - positionSnapGrid = rectangularPositionSnapGrid; - break; - - case PositionSnapGridType.Triangle: - var triangularPositionSnapGrid = new TriangularPositionSnapGrid(); - - triangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.Spacing); - triangularPositionSnapGrid.GridLineRotation.BindTo(OsuGridToolboxGroup.GridLinesRotation); - - positionSnapGrid = triangularPositionSnapGrid; - break; - - case PositionSnapGridType.Circle: - var circularPositionSnapGrid = new CircularPositionSnapGrid(); - - circularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.Spacing); - - positionSnapGrid = circularPositionSnapGrid; - break; - - default: - throw new NotImplementedException($"{OsuGridToolboxGroup.GridType} has an incorrect value."); - } - - // Bind the start position to the toolbox sliders. - positionSnapGrid.StartPosition.BindTo(OsuGridToolboxGroup.StartPosition); + positionSnapGrid = rectangularPositionSnapGrid; positionSnapGrid.RelativeSizeAxes = Axes.Both; LayerBelowRuleset.Add(positionSnapGrid); diff --git a/osu.Game.Tests/Visual/Editing/TestScenePositionSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestScenePositionSnapGrid.cs index 7e66edc2dd..2721bc3602 100644 --- a/osu.Game.Tests/Visual/Editing/TestScenePositionSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestScenePositionSnapGrid.cs @@ -70,51 +70,6 @@ namespace osu.Game.Tests.Visual.Editing })); } - [TestCaseSource(nameof(test_cases))] - public void TestTriangularGrid(Vector2 position, Vector2 spacing, float rotation) - { - TriangularPositionSnapGrid grid = null; - - AddStep("create grid", () => - { - Child = grid = new TriangularPositionSnapGrid - { - RelativeSizeAxes = Axes.Both, - }; - grid.StartPosition.Value = position; - grid.Spacing.Value = spacing.X; - grid.GridLineRotation.Value = rotation; - }); - - AddStep("add snapping cursor", () => Add(new SnappingCursorContainer - { - RelativeSizeAxes = Axes.Both, - GetSnapPosition = pos => grid.GetSnappedPosition(grid.ToLocalSpace(pos)) - })); - } - - [TestCaseSource(nameof(test_cases))] - public void TestCircularGrid(Vector2 position, Vector2 spacing, float rotation) - { - CircularPositionSnapGrid grid = null; - - AddStep("create grid", () => - { - Child = grid = new CircularPositionSnapGrid - { - RelativeSizeAxes = Axes.Both, - }; - grid.StartPosition.Value = position; - grid.Spacing.Value = spacing.X; - }); - - AddStep("add snapping cursor", () => Add(new SnappingCursorContainer - { - RelativeSizeAxes = Axes.Both, - GetSnapPosition = pos => grid.GetSnappedPosition(grid.ToLocalSpace(pos)) - })); - } - private partial class SnappingCursorContainer : CompositeDrawable { public Func GetSnapPosition; diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularPositionSnapGrid.cs deleted file mode 100644 index 403a270359..0000000000 --- a/osu.Game/Screens/Edit/Compose/Components/CircularPositionSnapGrid.cs +++ /dev/null @@ -1,101 +0,0 @@ -// 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.Collections.Generic; -using System.Linq; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Utils; -using osuTK; - -namespace osu.Game.Screens.Edit.Compose.Components -{ - public partial class CircularPositionSnapGrid : PositionSnapGrid - { - /// - /// The spacing between grid lines of this . - /// - public BindableFloat Spacing { get; } = new BindableFloat(1f) - { - MinValue = 0f, - }; - - public CircularPositionSnapGrid() - { - Spacing.BindValueChanged(_ => GridCache.Invalidate()); - } - - protected override void CreateContent() - { - var drawSize = DrawSize; - - // Calculate the maximum distance from the origin to the edge of the grid. - float maxDist = MathF.Max( - MathF.Max(StartPosition.Value.Length, (StartPosition.Value - drawSize).Length), - MathF.Max((StartPosition.Value - new Vector2(drawSize.X, 0)).Length, (StartPosition.Value - new Vector2(0, drawSize.Y)).Length) - ); - - generateCircles((int)(maxDist / Spacing.Value) + 1); - - GenerateOutline(drawSize); - } - - private void generateCircles(int count) - { - // Make lines the same width independent of display resolution. - float lineWidth = 2 * DrawWidth / ScreenSpaceDrawQuad.Width; - - List generatedCircles = new List(); - - for (int i = 0; i < count; i++) - { - // Add a minimum diameter so the center circle is clearly visible. - float diameter = MathF.Max(lineWidth * 1.5f, i * Spacing.Value * 2); - - var gridCircle = new CircularContainer - { - BorderColour = Colour4.White, - BorderThickness = lineWidth, - Alpha = 0.2f, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.None, - Width = diameter, - Height = diameter, - Position = StartPosition.Value, - Masking = true, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - AlwaysPresent = true, - Alpha = 0f, - } - }; - - generatedCircles.Add(gridCircle); - } - - if (generatedCircles.Count == 0) - return; - - generatedCircles.First().Alpha = 0.8f; - - AddRangeInternal(generatedCircles); - } - - public override Vector2 GetSnappedPosition(Vector2 original) - { - Vector2 relativeToStart = original - StartPosition.Value; - - if (relativeToStart.LengthSquared < Precision.FLOAT_EPSILON) - return StartPosition.Value; - - float length = relativeToStart.Length; - float wantedLength = MathF.Round(length / Spacing.Value) * Spacing.Value; - - return StartPosition.Value + Vector2.Multiply(relativeToStart, wantedLength / length); - } - } -} diff --git a/osu.Game/Screens/Edit/Compose/Components/TriangularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/TriangularPositionSnapGrid.cs deleted file mode 100644 index 93d2c6a74a..0000000000 --- a/osu.Game/Screens/Edit/Compose/Components/TriangularPositionSnapGrid.cs +++ /dev/null @@ -1,89 +0,0 @@ -// 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 osu.Framework.Bindables; -using osu.Game.Utils; -using osuTK; - -namespace osu.Game.Screens.Edit.Compose.Components -{ - public partial class TriangularPositionSnapGrid : LinedPositionSnapGrid - { - /// - /// The spacing between grid lines of this . - /// - public BindableFloat Spacing { get; } = new BindableFloat(1f) - { - MinValue = 0f, - }; - - /// - /// The rotation in degrees of the grid lines of this . - /// - public BindableFloat GridLineRotation { get; } = new BindableFloat(); - - public TriangularPositionSnapGrid() - { - Spacing.BindValueChanged(_ => GridCache.Invalidate()); - GridLineRotation.BindValueChanged(_ => GridCache.Invalidate()); - } - - private const float sqrt3 = 1.73205080757f; - private const float sqrt3_over2 = 0.86602540378f; - private const float one_over_sqrt3 = 0.57735026919f; - - protected override void CreateContent() - { - var drawSize = DrawSize; - float stepSpacing = Spacing.Value * sqrt3_over2; - var step1 = GeometryUtils.RotateVector(new Vector2(stepSpacing, 0), -GridLineRotation.Value - 30); - var step2 = GeometryUtils.RotateVector(new Vector2(stepSpacing, 0), -GridLineRotation.Value - 90); - var step3 = GeometryUtils.RotateVector(new Vector2(stepSpacing, 0), -GridLineRotation.Value - 150); - - GenerateGridLines(step1, drawSize); - GenerateGridLines(-step1, drawSize); - - GenerateGridLines(step2, drawSize); - GenerateGridLines(-step2, drawSize); - - GenerateGridLines(step3, drawSize); - GenerateGridLines(-step3, drawSize); - - GenerateOutline(drawSize); - } - - public override Vector2 GetSnappedPosition(Vector2 original) - { - Vector2 relativeToStart = GeometryUtils.RotateVector(original - StartPosition.Value, GridLineRotation.Value); - Vector2 hex = pixelToHex(relativeToStart); - - return StartPosition.Value + GeometryUtils.RotateVector(hexToPixel(hex), -GridLineRotation.Value); - } - - private Vector2 pixelToHex(Vector2 pixel) - { - float x = pixel.X / Spacing.Value; - float y = pixel.Y / Spacing.Value; - // Algorithm from Charles Chambers - // with modifications and comments by Chris Cox 2023 - // - float t = sqrt3 * y + 1; // scaled y, plus phase - float temp1 = MathF.Floor(t + x); // (y+x) diagonal, this calc needs floor - float temp2 = t - x; // (y-x) diagonal, no floor needed - float temp3 = 2 * x + 1; // scaled horizontal, no floor needed, needs +1 to get correct phase - float qf = (temp1 + temp3) / 3.0f; // pseudo x with fraction - float rf = (temp1 + temp2) / 3.0f; // pseudo y with fraction - float q = MathF.Floor(qf); // pseudo x, quantized and thus requires floor - float r = MathF.Floor(rf); // pseudo y, quantized and thus requires floor - return new Vector2(q, r); - } - - private Vector2 hexToPixel(Vector2 hex) - { - // Taken from - // with modifications for the different definition of size. - return new Vector2(Spacing.Value * (hex.X - hex.Y / 2), Spacing.Value * one_over_sqrt3 * 1.5f * hex.Y); - } - } -}