mirror of https://github.com/ppy/osu
Remove placement events, make everything pass top-down
This commit is contained in:
parent
62635c5ab8
commit
969477dadd
|
@ -38,8 +38,7 @@ public class TestCaseHitObjectComposer : OsuTestCase, IPlacementHandler
|
|||
typeof(HitCirclePlacementMask),
|
||||
};
|
||||
|
||||
public event Action<HitObject> PlacementStarted;
|
||||
public event Action<HitObject> PlacementFinished;
|
||||
private HitObjectComposer composer;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
|
@ -70,11 +69,13 @@ private void load()
|
|||
Dependencies.CacheAs<IAdjustableClock>(clock);
|
||||
Dependencies.CacheAs<IFrameBasedClock>(clock);
|
||||
|
||||
Child = new OsuHitObjectComposer(new OsuRuleset());
|
||||
Child = composer = new OsuHitObjectComposer(new OsuRuleset());
|
||||
}
|
||||
|
||||
public void BeginPlacement(HitObject hitObject) => PlacementStarted?.Invoke(hitObject);
|
||||
public void BeginPlacement(HitObject hitObject)
|
||||
{
|
||||
}
|
||||
|
||||
public void EndPlacement(HitObject hitObject) => PlacementFinished?.Invoke(hitObject);
|
||||
public void EndPlacement(HitObject hitObject) => composer.Add(hitObject);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,12 @@ internal EditRulesetContainer()
|
|||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
public abstract DrawableHitObject AddHitObject(HitObject hitObject);
|
||||
/// <summary>
|
||||
/// Adds a <see cref="HitObject"/> to the <see cref="Beatmap"/> and displays a visual representation of it.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="HitObject"/> to add.</param>
|
||||
/// <returns>The visual representation of <paramref name="hitObject"/>.</returns>
|
||||
internal abstract DrawableHitObject Add(HitObject hitObject);
|
||||
}
|
||||
|
||||
public abstract class EditRulesetContainer<TObject> : EditRulesetContainer
|
||||
|
@ -41,20 +46,22 @@ protected EditRulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap)
|
|||
InternalChild = rulesetContainer = CreateRulesetContainer(ruleset, workingBeatmap);
|
||||
}
|
||||
|
||||
public override DrawableHitObject AddHitObject(HitObject hitObject)
|
||||
internal override DrawableHitObject Add(HitObject hitObject)
|
||||
{
|
||||
var tObject = (TObject)hitObject;
|
||||
|
||||
// Insert into beatmap while maintaining sorting order
|
||||
// Add to beatmap, preserving sorting order
|
||||
var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime);
|
||||
beatmap.HitObjects.Insert(insertionIndex + 1, tObject);
|
||||
|
||||
// Process object
|
||||
var processor = ruleset.CreateBeatmapProcessor(beatmap);
|
||||
|
||||
processor.PreProcess();
|
||||
tObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty);
|
||||
processor.PostProcess();
|
||||
|
||||
// Add visual representation
|
||||
var drawableObject = rulesetContainer.GetVisualRepresentation(tObject);
|
||||
|
||||
rulesetContainer.Playfield.Add(drawableObject);
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Edit.Screens.Compose;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.RadioButtons;
|
||||
|
||||
|
@ -32,13 +32,10 @@ public abstract class HitObjectComposer : CompositeDrawable
|
|||
private readonly List<Container> layerContainers = new List<Container>();
|
||||
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
[Resolved]
|
||||
private IPlacementHandler placementHandler { get; set; }
|
||||
|
||||
private HitObjectMaskLayer maskLayer;
|
||||
private EditRulesetContainer rulesetContainer;
|
||||
|
||||
private readonly Bindable<HitObjectCompositionTool> compositionTool = new Bindable<HitObjectCompositionTool>();
|
||||
private HitObjectMaskLayer maskLayer;
|
||||
private PlacementContainer placementContainer;
|
||||
|
||||
protected HitObjectComposer(Ruleset ruleset)
|
||||
{
|
||||
|
@ -73,7 +70,7 @@ private void load(IBindableBeatmap beatmap, IFrameBasedClock framedClock)
|
|||
layerAboveRuleset.Children = new Drawable[]
|
||||
{
|
||||
maskLayer = new HitObjectMaskLayer(),
|
||||
new PlacementContainer(compositionTool),
|
||||
placementContainer = new PlacementContainer(),
|
||||
};
|
||||
|
||||
layerContainers.Add(layerBelowRuleset);
|
||||
|
@ -117,14 +114,11 @@ private void load(IBindableBeatmap beatmap, IFrameBasedClock framedClock)
|
|||
};
|
||||
|
||||
toolboxCollection.Items =
|
||||
CompositionTools.Select(t => new RadioButton(t.Name, () => compositionTool.Value = t))
|
||||
.Prepend(new RadioButton("Select", () => compositionTool.Value = null))
|
||||
CompositionTools.Select(t => new RadioButton(t.Name, () => placementContainer.CurrentTool = t))
|
||||
.Prepend(new RadioButton("Select", () => placementContainer.CurrentTool = null))
|
||||
.ToList();
|
||||
|
||||
toolboxCollection.Items[0].Select();
|
||||
|
||||
// Todo: no
|
||||
placementHandler.PlacementFinished += h => maskLayer.AddMask(rulesetContainer.AddHitObject(h));
|
||||
}
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
|
@ -157,6 +151,12 @@ protected override void UpdateAfterChildren()
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="HitObject"/> to the <see cref="Beatmap"/> and visualises it.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="HitObject"/> to add.</param>
|
||||
public void Add(HitObject hitObject) => maskLayer.AddMaskFor(rulesetContainer.Add(hitObject));
|
||||
|
||||
protected abstract EditRulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap);
|
||||
|
||||
protected abstract IReadOnlyList<HitObjectCompositionTool> CompositionTools { get; }
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using OpenTK.Graphics;
|
||||
|
@ -10,6 +9,7 @@
|
|||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Timeline;
|
||||
|
||||
|
@ -21,19 +21,9 @@ public class Compose : EditorScreen, IPlacementHandler
|
|||
private const float vertical_margins = 10;
|
||||
private const float horizontal_margins = 20;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the placement of a <see cref="HitObject"/> has started.
|
||||
/// </summary>
|
||||
public event Action<HitObject> PlacementStarted;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the placement of a <see cref="HitObject"/> has finished.
|
||||
/// </summary>
|
||||
public event Action<HitObject> PlacementFinished;
|
||||
|
||||
private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor();
|
||||
|
||||
private Container composerContainer;
|
||||
private HitObjectComposer composer;
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load([CanBeNull] BindableBeatDivisor beatDivisor)
|
||||
|
@ -41,6 +31,8 @@ private void load([CanBeNull] BindableBeatDivisor beatDivisor)
|
|||
if (beatDivisor != null)
|
||||
this.beatDivisor.BindTo(beatDivisor);
|
||||
|
||||
Container composerContainer;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new GridContainer
|
||||
|
@ -114,7 +106,7 @@ private void load([CanBeNull] BindableBeatDivisor beatDivisor)
|
|||
return;
|
||||
}
|
||||
|
||||
var composer = ruleset.CreateHitObjectComposer();
|
||||
composer = ruleset.CreateHitObjectComposer();
|
||||
if (composer == null)
|
||||
{
|
||||
Logger.Log($"Ruleset {ruleset.Description} doesn't support hitobject composition.");
|
||||
|
@ -125,8 +117,10 @@ private void load([CanBeNull] BindableBeatDivisor beatDivisor)
|
|||
composerContainer.Child = composer;
|
||||
}
|
||||
|
||||
public void BeginPlacement(HitObject hitObject) => PlacementStarted?.Invoke(hitObject);
|
||||
public void BeginPlacement(HitObject hitObject)
|
||||
{
|
||||
}
|
||||
|
||||
public void EndPlacement(HitObject hitObject) => PlacementFinished?.Invoke(hitObject);
|
||||
public void EndPlacement(HitObject hitObject) => composer.Add(hitObject);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose
|
||||
{
|
||||
public interface IPlacementHandler
|
||||
{
|
||||
event Action<HitObject> PlacementStarted;
|
||||
event Action<HitObject> PlacementFinished;
|
||||
|
||||
void BeginPlacement(HitObject hitObject);
|
||||
void EndPlacement(HitObject hitObject);
|
||||
}
|
||||
|
|
|
@ -13,10 +13,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
|||
public class HitObjectMaskLayer : CompositeDrawable
|
||||
{
|
||||
private MaskContainer maskContainer;
|
||||
private HitObjectComposer composer;
|
||||
|
||||
[Resolved]
|
||||
private IPlacementHandler placementHandler { get; set; }
|
||||
private HitObjectComposer composer { get; set; }
|
||||
|
||||
public HitObjectMaskLayer()
|
||||
{
|
||||
|
@ -24,10 +23,8 @@ public HitObjectMaskLayer()
|
|||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(HitObjectComposer composer)
|
||||
private void load()
|
||||
{
|
||||
this.composer = composer;
|
||||
|
||||
maskContainer = new MaskContainer();
|
||||
|
||||
var maskSelection = composer.CreateMaskSelection();
|
||||
|
@ -51,7 +48,7 @@ private void load(HitObjectComposer composer)
|
|||
};
|
||||
|
||||
foreach (var obj in composer.HitObjects)
|
||||
AddMask(obj);
|
||||
AddMaskFor(obj);
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
|
@ -64,7 +61,7 @@ protected override bool OnMouseDown(MouseDownEvent e)
|
|||
/// Adds a mask for a <see cref="DrawableHitObject"/> which adds movement support.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create a mask for.</param>
|
||||
public void AddMask(DrawableHitObject hitObject)
|
||||
public void AddMaskFor(DrawableHitObject hitObject)
|
||||
{
|
||||
var mask = composer.CreateMaskFor(hitObject);
|
||||
if (mask == null)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
|
@ -14,32 +12,37 @@ public class PlacementContainer : CompositeDrawable
|
|||
{
|
||||
private readonly Container maskContainer;
|
||||
|
||||
private readonly IBindable<HitObjectCompositionTool> compositionTool = new Bindable<HitObjectCompositionTool>();
|
||||
|
||||
[Resolved]
|
||||
private IPlacementHandler placementHandler { get; set; }
|
||||
|
||||
public PlacementContainer(IBindable<HitObjectCompositionTool> compositionTool)
|
||||
public PlacementContainer()
|
||||
{
|
||||
this.compositionTool.BindTo(compositionTool);
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
this.compositionTool.BindValueChanged(onToolChanged);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private HitObjectCompositionTool currentTool;
|
||||
|
||||
/// <summary>
|
||||
/// The current placement tool.
|
||||
/// </summary>
|
||||
public HitObjectCompositionTool CurrentTool
|
||||
{
|
||||
// Refresh the mask after each placement
|
||||
placementHandler.PlacementFinished += _ => onToolChanged(compositionTool.Value);
|
||||
get => currentTool;
|
||||
set
|
||||
{
|
||||
if (currentTool == value)
|
||||
return;
|
||||
currentTool = value;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private void onToolChanged(HitObjectCompositionTool tool)
|
||||
/// <summary>
|
||||
/// Refreshes the current placement tool.
|
||||
/// </summary>
|
||||
public void Refresh()
|
||||
{
|
||||
ClearInternal();
|
||||
|
||||
var mask = tool?.CreatePlacementMask();
|
||||
var mask = CurrentTool?.CreatePlacementMask();
|
||||
if (mask != null)
|
||||
InternalChild = mask;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue