Remove placement events, make everything pass top-down

This commit is contained in:
smoogipoo 2018-10-17 17:41:17 +09:00
parent 62635c5ab8
commit 969477dadd
7 changed files with 62 additions and 64 deletions

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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; }

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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;
}