Combine selection and input handling logic for beat snap grids across all rulesets

This commit is contained in:
Dean Herbert 2023-10-17 17:09:42 +09:00
parent 2a89a25790
commit 4381169a3f
No known key found for this signature in database
4 changed files with 53 additions and 124 deletions

View File

@ -8,7 +8,6 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Extensions.EnumExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
@ -32,10 +31,6 @@ namespace osu.Game.Rulesets.Catch.Edit
private CatchDistanceSnapGrid distanceSnapGrid = null!; private CatchDistanceSnapGrid distanceSnapGrid = null!;
private InputManager inputManager = null!;
private CatchBeatSnapGrid beatSnapGrid = null!;
private readonly BindableDouble timeRangeMultiplier = new BindableDouble(1) private readonly BindableDouble timeRangeMultiplier = new BindableDouble(1)
{ {
MinValue = 1, MinValue = 1,
@ -68,38 +63,6 @@ namespace osu.Game.Rulesets.Catch.Edit
Catcher.BASE_DASH_SPEED, -Catcher.BASE_DASH_SPEED, Catcher.BASE_DASH_SPEED, -Catcher.BASE_DASH_SPEED,
Catcher.BASE_WALK_SPEED, -Catcher.BASE_WALK_SPEED, Catcher.BASE_WALK_SPEED, -Catcher.BASE_WALK_SPEED,
})); }));
AddInternal(beatSnapGrid = new CatchBeatSnapGrid());
}
protected override void LoadComplete()
{
base.LoadComplete();
inputManager = GetContainingInputManager();
}
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
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 double ReadCurrentDistanceSnap(HitObject before, HitObject after) protected override double ReadCurrentDistanceSnap(HitObject before, HitObject after)
@ -174,6 +137,8 @@ namespace osu.Game.Rulesets.Catch.Edit
protected override ComposeBlueprintContainer CreateBlueprintContainer() => new CatchBlueprintContainer(this); protected override ComposeBlueprintContainer CreateBlueprintContainer() => new CatchBlueprintContainer(this);
protected override BeatSnapGrid CreateBeatSnapGrid() => new CatchBeatSnapGrid();
private PalpableCatchHitObject? getLastSnappableHitObject(double time) private PalpableCatchHitObject? getLastSnappableHitObject(double time)
{ {
var hitObject = EditorBeatmap.HitObjects.OfType<CatchHitObject>().LastOrDefault(h => h.GetEndTime() < time && !(h is BananaShower)); var hitObject = EditorBeatmap.HitObjects.OfType<CatchHitObject>().LastOrDefault(h => h.GetEndTime() < time && !(h is BananaShower));
@ -214,7 +179,7 @@ namespace osu.Game.Rulesets.Catch.Edit
return null; return null;
} }
double timeAtCursor = ((CatchPlayfield)Playfield).TimeAtScreenSpacePosition(inputManager.CurrentState.Mouse.Position); double timeAtCursor = ((CatchPlayfield)Playfield).TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position);
return getLastSnappableHitObject(timeAtCursor); return getLastSnappableHitObject(timeAtCursor);
default: default:

View File

@ -6,14 +6,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Input;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components;
@ -24,27 +22,12 @@ namespace osu.Game.Rulesets.Mania.Edit
public partial class ManiaHitObjectComposer : ScrollingHitObjectComposer<ManiaHitObject> public partial class ManiaHitObjectComposer : ScrollingHitObjectComposer<ManiaHitObject>
{ {
private DrawableManiaEditorRuleset drawableRuleset; private DrawableManiaEditorRuleset drawableRuleset;
private ManiaBeatSnapGrid beatSnapGrid;
private InputManager inputManager;
public ManiaHitObjectComposer(Ruleset ruleset) public ManiaHitObjectComposer(Ruleset ruleset)
: base(ruleset) : base(ruleset)
{ {
} }
[BackgroundDependencyLoader]
private void load()
{
AddInternal(beatSnapGrid = new ManiaBeatSnapGrid());
}
protected override void LoadComplete()
{
base.LoadComplete();
inputManager = GetContainingInputManager();
}
private DependencyContainer dependencies; private DependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
@ -63,35 +46,14 @@ namespace osu.Game.Rulesets.Mania.Edit
protected override ComposeBlueprintContainer CreateBlueprintContainer() protected override ComposeBlueprintContainer CreateBlueprintContainer()
=> new ManiaBlueprintContainer(this); => new ManiaBlueprintContainer(this);
protected override BeatSnapGrid CreateBeatSnapGrid() => new ManiaBeatSnapGrid();
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[] protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]
{ {
new NoteCompositionTool(), new NoteCompositionTool(),
new HoldNoteCompositionTool() new HoldNoteCompositionTool()
}; };
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
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;
}
}
public override string ConvertSelectionToString() public override string ConvertSelectionToString()
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime).Select(h => $"{h.StartTime}|{h.Column}")); => string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime).Select(h => $"{h.StartTime}|{h.Column}"));
} }

View File

@ -2,14 +2,10 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Input;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components;
@ -20,9 +16,6 @@ namespace osu.Game.Rulesets.Taiko.Edit
{ {
protected override bool ApplyHorizontalCentering => false; protected override bool ApplyHorizontalCentering => false;
private TaikoBeatSnapGrid beatSnapGrid = null!;
private InputManager inputManager = null!;
public TaikoHitObjectComposer(TaikoRuleset ruleset) public TaikoHitObjectComposer(TaikoRuleset ruleset)
: base(ruleset) : base(ruleset)
{ {
@ -41,40 +34,6 @@ namespace osu.Game.Rulesets.Taiko.Edit
protected override ComposeBlueprintContainer CreateBlueprintContainer() protected override ComposeBlueprintContainer CreateBlueprintContainer()
=> new TaikoBlueprintContainer(this); => new TaikoBlueprintContainer(this);
[BackgroundDependencyLoader] protected override BeatSnapGrid CreateBeatSnapGrid() => new TaikoBeatSnapGrid();
private void load()
{
AddInternal(beatSnapGrid = new TaikoBeatSnapGrid());
}
protected override void LoadComplete()
{
base.LoadComplete();
inputManager = GetContainingInputManager();
}
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
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;
}
}
} }
} }

View File

@ -7,6 +7,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Extensions.EnumExtensions;
@ -76,7 +77,7 @@ namespace osu.Game.Rulesets.Edit
protected readonly Container LayerBelowRuleset = new Container { RelativeSizeAxes = Axes.Both }; protected readonly Container LayerBelowRuleset = new Container { RelativeSizeAxes = Axes.Both };
private InputManager inputManager; protected InputManager InputManager { get; private set; }
private EditorRadioButtonCollection toolboxCollection; private EditorRadioButtonCollection toolboxCollection;
@ -89,6 +90,9 @@ namespace osu.Game.Rulesets.Edit
protected DrawableRuleset<TObject> DrawableRuleset { get; private set; } protected DrawableRuleset<TObject> DrawableRuleset { get; private set; }
[CanBeNull]
private BeatSnapGrid beatSnapGrid;
protected HitObjectComposer(Ruleset ruleset) protected HitObjectComposer(Ruleset ruleset)
: base(ruleset) : base(ruleset)
{ {
@ -204,7 +208,9 @@ namespace osu.Game.Rulesets.Edit
}, },
} }
} }
} },
// Must be constructed after drawable ruleset above.
(beatSnapGrid = CreateBeatSnapGrid()) ?? Empty(),
}; };
toolboxCollection.Items = CompositionTools toolboxCollection.Items = CompositionTools
@ -235,7 +241,7 @@ namespace osu.Game.Rulesets.Edit
{ {
base.LoadComplete(); base.LoadComplete();
inputManager = GetContainingInputManager(); InputManager = GetContainingInputManager();
hasTiming = EditorBeatmap.HasTiming.GetBoundCopy(); hasTiming = EditorBeatmap.HasTiming.GetBoundCopy();
hasTiming.BindValueChanged(timing => hasTiming.BindValueChanged(timing =>
@ -269,11 +275,42 @@ namespace osu.Game.Rulesets.Edit
} }
} }
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;
}
}
public override Playfield Playfield => drawableRulesetWrapper.Playfield; public override Playfield Playfield => drawableRulesetWrapper.Playfield;
public override IEnumerable<DrawableHitObject> HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects; public override IEnumerable<DrawableHitObject> HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects;
public override bool CursorInPlacementArea => drawableRulesetWrapper.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); public override bool CursorInPlacementArea => drawableRulesetWrapper.Playfield.ReceivePositionalInputAt(InputManager.CurrentState.Mouse.Position);
/// <summary> /// <summary>
/// Defines all available composition tools, listed on the left side of the editor screen as button controls. /// Defines all available composition tools, listed on the left side of the editor screen as button controls.
@ -299,6 +336,12 @@ namespace osu.Game.Rulesets.Edit
/// </summary> /// </summary>
protected virtual ComposeBlueprintContainer CreateBlueprintContainer() => new ComposeBlueprintContainer(this); protected virtual ComposeBlueprintContainer CreateBlueprintContainer() => new ComposeBlueprintContainer(this);
/// <summary>
/// Construct an optional beat snap grid.
/// </summary>
[CanBeNull]
protected virtual BeatSnapGrid CreateBeatSnapGrid() => null;
/// <summary> /// <summary>
/// Construct a drawable ruleset for the provided ruleset. /// Construct a drawable ruleset for the provided ruleset.
/// </summary> /// </summary>