mirror of
https://github.com/ppy/osu.git
synced 2025-01-18 21:02:56 +08:00
5c8ae6f851
As I look into re-implementing the ability to choose combo colour for an object (also known as "colourhax") from the editor UI, I stumble upon these wretched ternary items again and sigh a deep sigh of annoyance. The structure is overly rigid. `TernaryItem` does nothing that `DrawableTernaryItem` couldn't, except make it more annoying to add specific sub-variants of `DrawableTernaryItem` that could do more things. Yes you could sprinkle more levels of virtuals to `CreateDrawableButton()` or something, but after all, as Saint Exupéry says, "perfection is finally attained not when there is no longer anything to add, but when there is no longer anything to take away." So I'm leaning for taking one step towards perfection.
131 lines
4.6 KiB
C#
131 lines
4.6 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.Linq;
|
|
using osu.Framework.Allocation;
|
|
using osu.Framework.Bindables;
|
|
using osu.Framework.Extensions.ObjectExtensions;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osu.Framework.Graphics.Sprites;
|
|
using osu.Game.Configuration;
|
|
using osu.Game.Graphics.UserInterface;
|
|
using osu.Game.Rulesets.Edit.Tools;
|
|
using osu.Game.Rulesets.Objects;
|
|
using osu.Game.Rulesets.UI.Scrolling;
|
|
using osu.Game.Screens.Edit;
|
|
using osu.Game.Screens.Edit.Components.TernaryButtons;
|
|
using osu.Game.Screens.Edit.Compose.Components;
|
|
using osuTK;
|
|
|
|
namespace osu.Game.Rulesets.Edit
|
|
{
|
|
public abstract partial class ScrollingHitObjectComposer<TObject> : HitObjectComposer<TObject>
|
|
where TObject : HitObject
|
|
{
|
|
[Resolved]
|
|
private Editor? editor { get; set; }
|
|
|
|
private readonly Bindable<TernaryState> showSpeedChanges = new Bindable<TernaryState>();
|
|
private Bindable<bool> configShowSpeedChanges = null!;
|
|
|
|
private BeatSnapGrid? beatSnapGrid;
|
|
|
|
/// <summary>
|
|
/// Construct an optional beat snap grid.
|
|
/// </summary>
|
|
protected virtual BeatSnapGrid? CreateBeatSnapGrid() => null;
|
|
|
|
protected ScrollingHitObjectComposer(Ruleset ruleset)
|
|
: base(ruleset)
|
|
{
|
|
}
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load(OsuConfigManager config)
|
|
{
|
|
if (DrawableRuleset is ISupportConstantAlgorithmToggle toggleRuleset)
|
|
{
|
|
LeftToolbox.Add(new EditorToolboxGroup("playfield")
|
|
{
|
|
Child = new FillFlowContainer
|
|
{
|
|
RelativeSizeAxes = Axes.X,
|
|
AutoSizeAxes = Axes.Y,
|
|
Direction = FillDirection.Vertical,
|
|
Spacing = new Vector2(0, 5),
|
|
Children = new[]
|
|
{
|
|
new DrawableTernaryButton
|
|
{
|
|
Current = showSpeedChanges,
|
|
Description = "Show speed changes",
|
|
CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.TachometerAlt },
|
|
}
|
|
}
|
|
},
|
|
});
|
|
|
|
configShowSpeedChanges = config.GetBindable<bool>(OsuSetting.EditorShowSpeedChanges);
|
|
configShowSpeedChanges.BindValueChanged(enabled => showSpeedChanges.Value = enabled.NewValue ? TernaryState.True : TernaryState.False, true);
|
|
|
|
showSpeedChanges.BindValueChanged(state =>
|
|
{
|
|
bool enabled = state.NewValue == TernaryState.True;
|
|
|
|
toggleRuleset.ShowSpeedChanges.Value = enabled;
|
|
configShowSpeedChanges.Value = enabled;
|
|
}, true);
|
|
}
|
|
|
|
beatSnapGrid = CreateBeatSnapGrid();
|
|
|
|
if (beatSnapGrid != null)
|
|
AddInternal(beatSnapGrid);
|
|
|
|
EditorBeatmap.ControlPointInfo.ControlPointsChanged += expireComposeScreenOnControlPointChange;
|
|
}
|
|
|
|
protected override void UpdateAfterChildren()
|
|
{
|
|
base.UpdateAfterChildren();
|
|
|
|
updateBeatSnapGrid();
|
|
}
|
|
|
|
private void updateBeatSnapGrid()
|
|
{
|
|
if (beatSnapGrid == null)
|
|
return;
|
|
|
|
if (BlueprintContainer.CurrentTool is SelectTool)
|
|
{
|
|
if (EditorBeatmap.SelectedHitObjects.Any())
|
|
{
|
|
beatSnapGrid.SelectionTimeRange = (EditorBeatmap.SelectedHitObjects.Min(h => h.StartTime), EditorBeatmap.SelectedHitObjects.Max(h => h.GetEndTime()));
|
|
}
|
|
else
|
|
beatSnapGrid.SelectionTimeRange = null;
|
|
}
|
|
else
|
|
{
|
|
var result = FindSnappedPositionAndTime(InputManager.CurrentState.Mouse.Position);
|
|
if (result.Time is double time)
|
|
beatSnapGrid.SelectionTimeRange = (time, time);
|
|
else
|
|
beatSnapGrid.SelectionTimeRange = null;
|
|
}
|
|
}
|
|
|
|
protected override void Dispose(bool isDisposing)
|
|
{
|
|
base.Dispose(isDisposing);
|
|
|
|
if (EditorBeatmap.IsNotNull())
|
|
EditorBeatmap.ControlPointInfo.ControlPointsChanged -= expireComposeScreenOnControlPointChange;
|
|
}
|
|
|
|
private void expireComposeScreenOnControlPointChange() => editor?.ReloadComposeScreen();
|
|
}
|
|
}
|