1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-19 06:31:19 +08:00
Files
osu-lazer/osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs
T
De4n e05b6f44b9 Update editor slider controls to new design (#36346)
(partially) Closes: #36233
Surpasses: #36244 

This PR meant to be one of the last steps that finally make editor use
the new forms. Initially it meant to only change one
SliderWithTextBoxInput in "Effects section" in timing screen, however
soon after it was obvious that there's many other places that still
using it. This currently won't affect
IndeterminateSliderWithTextBoxInput that is being used in hitsounds, for
example, since I think it needs more consideration.
Anyways, with this PR, SliderWithTextBoxInput, will no longer be used at
all, as it's going to be replaced with modern FormSliderBar

Comparison:
|master|this PR|
|:---:|:---:|
|<img width="510" height="316"
alt="532203751-eb965923-d3a8-441d-a7c8-5c364a6328ad"
src="https://github.com/user-attachments/assets/268b45b8-e235-494f-91a5-d00db057dba8"
/>|<img width="540" height="321"
alt="535466527-3a700a8b-bc3c-4610-998f-a4e55ee03eed"
src="https://github.com/user-attachments/assets/20cd4b58-b0bd-49bc-8c48-7de5cf8556b3"
/>|
|<img width="694" height="639"
alt="534509844-f00e4da4-53c4-45e8-80ea-1be62da6c83b"
src="https://github.com/user-attachments/assets/398c4484-a867-4df1-9de3-0940aa748a01"
/>|<img width="720" height="433" alt="изображение"
src="https://github.com/user-attachments/assets/b6359443-a224-4a55-b171-07e8f013cf46"
/>|
|<img width="715" height="353"
alt="534509421-a6ac950f-16e8-4a16-bca6-1a781f82135f"
src="https://github.com/user-attachments/assets/4854312b-772f-4b81-a800-89e58d4c715d"
/>|<img width="710" height="296" alt="изображение"
src="https://github.com/user-attachments/assets/a7fed53e-e006-4285-92c9-bb84cb603f60"
/>|
|<img width="717" height="374"
alt="534509478-80222623-7766-481d-8682-088276d415ee"
src="https://github.com/user-attachments/assets/8143b6dc-4599-45d5-bd3b-f059caf3d93d"
/>|<img width="718" height="328" alt="изображение"
src="https://github.com/user-attachments/assets/bffa04de-983c-45ae-a1ec-373701ea0e49"
/>|
|<img width="702" height="446"
alt="534509935-58954060-7ac1-4392-8754-a58f909e86aa"
src="https://github.com/user-attachments/assets/2bb67a2d-3f57-42a1-96ce-b30b4891e1a4"
/>|<img width="722" height="386" alt="изображение"
src="https://github.com/user-attachments/assets/01b7fff4-7f31-4aac-90c9-353b15f4964e"
/>|
2026-01-16 20:08:52 +09:00

206 lines
7.7 KiB
C#

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events;
using osu.Game.Configuration;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Screens.Edit.Components.RadioButtons;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
namespace osu.Game.Rulesets.Osu.Edit
{
public partial class PreciseRotationPopover : OsuPopover
{
private readonly SelectionRotationHandler rotationHandler;
private readonly OsuGridToolboxGroup gridToolbox;
private readonly Bindable<PreciseRotationInfo> rotationInfo = new Bindable<PreciseRotationInfo>(new PreciseRotationInfo(0, EditorOrigin.GridCentre));
private FormSliderBar<float> angleInput { get; set; } = null!;
private EditorRadioButtonCollection rotationOrigin = null!;
private RadioButton gridCentreButton = null!;
private RadioButton playfieldCentreButton = null!;
private RadioButton selectionCentreButton = null!;
private Bindable<EditorOrigin> configRotationOrigin = null!;
public PreciseRotationPopover(SelectionRotationHandler rotationHandler, OsuGridToolboxGroup gridToolbox)
{
this.rotationHandler = rotationHandler;
this.gridToolbox = gridToolbox;
AllowableAnchors = new[] { Anchor.CentreLeft, Anchor.CentreRight };
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
configRotationOrigin = config.GetBindable<EditorOrigin>(OsuSetting.EditorRotationOrigin);
Child = new FillFlowContainer
{
Width = 220,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(5),
Children = new Drawable[]
{
angleInput = new FormSliderBar<float>
{
Caption = "Angle (degrees)",
Current = new BindableNumber<float>
{
MinValue = -360,
MaxValue = 360,
Precision = 1
},
KeyboardStep = 1f,
TabbableContentContainer = this
},
rotationOrigin = new EditorRadioButtonCollection
{
RelativeSizeAxes = Axes.X,
Items = new[]
{
gridCentreButton = new RadioButton("Grid centre",
() => rotationInfo.Value = rotationInfo.Value with { Origin = EditorOrigin.GridCentre },
() => new SpriteIcon { Icon = FontAwesome.Regular.PlusSquare }),
playfieldCentreButton = new RadioButton("Playfield centre",
() => rotationInfo.Value = rotationInfo.Value with { Origin = EditorOrigin.PlayfieldCentre },
() => new SpriteIcon { Icon = FontAwesome.Regular.Square }),
selectionCentreButton = new RadioButton("Selection centre",
() => rotationInfo.Value = rotationInfo.Value with { Origin = EditorOrigin.SelectionCentre },
() => new SpriteIcon { Icon = FontAwesome.Solid.VectorSquare })
}
}
}
};
selectionCentreButton.Selected.DisabledChanged += isDisabled =>
{
selectionCentreButton.TooltipText = isDisabled ? "Select more than one object to perform selection-based rotation." : string.Empty;
};
}
protected override void LoadComplete()
{
base.LoadComplete();
ScheduleAfterChildren(() => angleInput.TakeFocus());
angleInput.Current.BindValueChanged(angle => rotationInfo.Value = rotationInfo.Value with { Degrees = angle.NewValue });
rotationHandler.CanRotateAroundSelectionOrigin.BindValueChanged(e =>
{
selectionCentreButton.Selected.Disabled = !e.NewValue;
}, true);
bool didSelect = false;
configRotationOrigin.BindValueChanged(val =>
{
switch (configRotationOrigin.Value)
{
case EditorOrigin.GridCentre:
if (!gridCentreButton.Selected.Disabled)
{
gridCentreButton.Select();
didSelect = true;
}
break;
case EditorOrigin.PlayfieldCentre:
if (!playfieldCentreButton.Selected.Disabled)
{
playfieldCentreButton.Select();
didSelect = true;
}
break;
case EditorOrigin.SelectionCentre:
if (!selectionCentreButton.Selected.Disabled)
{
selectionCentreButton.Select();
didSelect = true;
}
break;
}
}, true);
if (!didSelect)
rotationOrigin.Items.First(b => !b.Selected.Disabled).Select();
gridCentreButton.Selected.BindValueChanged(b =>
{
if (b.NewValue) configRotationOrigin.Value = EditorOrigin.GridCentre;
});
playfieldCentreButton.Selected.BindValueChanged(b =>
{
if (b.NewValue) configRotationOrigin.Value = EditorOrigin.PlayfieldCentre;
});
selectionCentreButton.Selected.BindValueChanged(b =>
{
if (b.NewValue) configRotationOrigin.Value = EditorOrigin.SelectionCentre;
});
rotationInfo.BindValueChanged(rotation =>
{
// can happen if the popover is dismissed by a keyboard key press while dragging UI controls
if (!rotationHandler.OperationInProgress.Value)
return;
rotationHandler.Update(rotation.NewValue.Degrees, getOriginPosition(rotation.NewValue));
});
}
private Vector2? getOriginPosition(PreciseRotationInfo rotation) =>
rotation.Origin switch
{
EditorOrigin.GridCentre => gridToolbox.StartPosition.Value,
EditorOrigin.PlayfieldCentre => OsuPlayfield.BASE_SIZE / 2,
EditorOrigin.SelectionCentre => null,
_ => throw new ArgumentOutOfRangeException(nameof(rotation))
};
protected override void PopIn()
{
base.PopIn();
rotationHandler.Begin();
}
protected override void PopOut()
{
base.PopOut();
if (IsLoaded)
rotationHandler.Commit();
}
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{
if (e.Action == GlobalAction.Select && !e.Repeat)
{
this.HidePopover();
return true;
}
return base.OnPressed(e);
}
}
public record PreciseRotationInfo(float Degrees, EditorOrigin Origin);
}