1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-28 02:43:19 +08:00

Add beat snap grid to the composer

This commit is contained in:
smoogipoo 2019-10-16 20:20:07 +09:00
parent d3e38f5e5a
commit c4704f6a29
2 changed files with 92 additions and 6 deletions

View File

@ -2,10 +2,12 @@
// 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.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.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
@ -52,5 +54,31 @@ namespace osu.Game.Rulesets.Osu.Edit
return base.CreateBlueprintFor(hitObject); return base.CreateBlueprintFor(hitObject);
} }
protected override DistanceSnapGrid CreateDistanceSnapGrid(IEnumerable<HitObject> selectedHitObjects)
{
var objects = selectedHitObjects.ToList();
if (objects.Count == 0)
{
var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime < EditorClock.CurrentTime);
if (lastObject == null)
return null;
return new OsuDistanceSnapGrid(lastObject);
}
else
{
double minTime = objects.Min(h => h.StartTime);
var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime < minTime);
if (lastObject == null)
return null;
return new OsuDistanceSnapGrid(lastObject);
}
}
} }
} }

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
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.Graphics; using osu.Framework.Graphics;
@ -33,12 +34,17 @@ namespace osu.Game.Rulesets.Edit
protected EditorBeatmap<TObject> EditorBeatmap { get; private set; } protected EditorBeatmap<TObject> EditorBeatmap { get; private set; }
protected readonly Ruleset Ruleset; protected readonly Ruleset Ruleset;
[Resolved]
protected IFrameBasedClock EditorClock { get; private set; }
private IWorkingBeatmap workingBeatmap; private IWorkingBeatmap workingBeatmap;
private Beatmap<TObject> playableBeatmap; private Beatmap<TObject> playableBeatmap;
private IBeatmapProcessor beatmapProcessor; private IBeatmapProcessor beatmapProcessor;
private DrawableEditRulesetWrapper<TObject> drawableRulesetWrapper; private DrawableEditRulesetWrapper<TObject> drawableRulesetWrapper;
private BlueprintContainer blueprintContainer; private BlueprintContainer blueprintContainer;
private Container distanceSnapGridContainer;
private DistanceSnapGrid distanceSnapGrid;
private readonly List<Container> layerContainers = new List<Container>(); private readonly List<Container> layerContainers = new List<Container>();
private InputManager inputManager; private InputManager inputManager;
@ -65,11 +71,13 @@ namespace osu.Game.Rulesets.Edit
return; return;
} }
var layerBelowRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer(); var layerBelowRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChildren(new Drawable[]
layerBelowRuleset.Child = new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both }; {
distanceSnapGridContainer = new Container { RelativeSizeAxes = Axes.Both },
new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both }
});
var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer(); var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(blueprintContainer = new BlueprintContainer());
layerAboveRuleset.Child = blueprintContainer = new BlueprintContainer();
layerContainers.Add(layerBelowRuleset); layerContainers.Add(layerBelowRuleset);
layerContainers.Add(layerAboveRuleset); layerContainers.Add(layerAboveRuleset);
@ -112,11 +120,13 @@ namespace osu.Game.Rulesets.Edit
}; };
toolboxCollection.Items = toolboxCollection.Items =
CompositionTools.Select(t => new RadioButton(t.Name, () => blueprintContainer.CurrentTool = t)) CompositionTools.Select(t => new RadioButton(t.Name, () => selectTool(t)))
.Prepend(new RadioButton("Select", () => blueprintContainer.CurrentTool = null)) .Prepend(new RadioButton("Select", () => selectTool(null)))
.ToList(); .ToList();
toolboxCollection.Items[0].Select(); toolboxCollection.Items[0].Select();
blueprintContainer.SelectionChanged += selectionChanged;
} }
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
@ -149,6 +159,14 @@ namespace osu.Game.Rulesets.Edit
inputManager = GetContainingInputManager(); inputManager = GetContainingInputManager();
} }
protected override void Update()
{
base.Update();
if (EditorClock.ElapsedFrameTime != 0 && blueprintContainer.CurrentTool != null)
showGridFor(Enumerable.Empty<HitObject>());
}
protected override void UpdateAfterChildren() protected override void UpdateAfterChildren()
{ {
base.UpdateAfterChildren(); base.UpdateAfterChildren();
@ -162,6 +180,38 @@ namespace osu.Game.Rulesets.Edit
}); });
} }
private void selectionChanged(IEnumerable<HitObject> selectedHitObjects)
{
var hitObjects = selectedHitObjects.ToArray();
if (!hitObjects.Any())
distanceSnapGridContainer.Hide();
else
showGridFor(hitObjects);
}
private void selectTool(HitObjectCompositionTool tool)
{
blueprintContainer.CurrentTool = tool;
if (tool == null)
distanceSnapGridContainer.Hide();
else
showGridFor(Enumerable.Empty<HitObject>());
}
private void showGridFor(IEnumerable<HitObject> selectedHitObjects)
{
distanceSnapGridContainer.Clear();
distanceSnapGrid = CreateDistanceSnapGrid(selectedHitObjects);
if (distanceSnapGrid != null)
{
distanceSnapGridContainer.Child = distanceSnapGrid;
distanceSnapGridContainer.Show();
}
}
private void addHitObject(HitObject hitObject) => updateHitObject(hitObject); private void addHitObject(HitObject hitObject) => updateHitObject(hitObject);
private void removeHitObject(HitObject hitObject) private void removeHitObject(HitObject hitObject)
@ -232,5 +282,13 @@ namespace osu.Game.Rulesets.Edit
/// Creates a <see cref="SelectionHandler"/> which outlines <see cref="DrawableHitObject"/>s and handles movement of selections. /// Creates a <see cref="SelectionHandler"/> which outlines <see cref="DrawableHitObject"/>s and handles movement of selections.
/// </summary> /// </summary>
public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler(); public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler();
/// <summary>
/// Creates the <see cref="DistanceSnapGrid"/> applicable for a <see cref="HitObject"/> selection.
/// </summary>
/// <param name="selectedHitObjects">The <see cref="HitObject"/> selection.</param>
/// <returns>The <see cref="DistanceSnapGrid"/> for <paramref name="selectedHitObjects"/>.</returns>
[CanBeNull]
protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable<HitObject> selectedHitObjects) => null;
} }
} }