mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 07:06:35 +09:00
Merge pull request #3643 from smoogipoo/editor-mask-placement
Implement editor hitobject placement
This commit is contained in:
@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo);
|
||||
|
||||
protected override DrawableHitObject<CatchHitObject> GetVisualRepresentation(CatchHitObject h)
|
||||
public override DrawableHitObject<CatchHitObject> GetVisualRepresentation(CatchHitObject h)
|
||||
{
|
||||
switch (h)
|
||||
{
|
||||
|
@ -1,22 +1,23 @@
|
||||
// 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.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
using osu.Game.Rulesets.Mania.Edit.Masks;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit
|
||||
{
|
||||
public class ManiaHitObjectComposer : HitObjectComposer
|
||||
public class ManiaHitObjectComposer : HitObjectComposer<ManiaHitObject>
|
||||
{
|
||||
protected new ManiaConfigManager Config => (ManiaConfigManager)base.Config;
|
||||
|
||||
@ -32,13 +33,10 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new ManiaEditRulesetContainer(ruleset, beatmap);
|
||||
protected override RulesetContainer<ManiaHitObject> CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
=> new ManiaEditRulesetContainer(ruleset, beatmap);
|
||||
|
||||
protected override IReadOnlyList<ICompositionTool> CompositionTools => new ICompositionTool[]
|
||||
{
|
||||
new HitObjectCompositionTool<Note>("Note"),
|
||||
new HitObjectCompositionTool<HoldNote>("Hold"),
|
||||
};
|
||||
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => Array.Empty<HitObjectCompositionTool>();
|
||||
|
||||
public override SelectionMask CreateMaskFor(DrawableHitObject hitObject)
|
||||
{
|
||||
|
@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant);
|
||||
|
||||
protected override DrawableHitObject<ManiaHitObject> GetVisualRepresentation(ManiaHitObject h)
|
||||
public override DrawableHitObject<ManiaHitObject> GetVisualRepresentation(ManiaHitObject h)
|
||||
{
|
||||
switch (h)
|
||||
{
|
||||
|
@ -0,0 +1,19 @@
|
||||
// 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.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseHitCirclePlacementMask : HitObjectPlacementMaskTestCase
|
||||
{
|
||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHitCircle((HitCircle)hitObject);
|
||||
protected override PlacementMask CreateMask() => new HitCirclePlacementMask();
|
||||
}
|
||||
}
|
20
osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs
Normal file
20
osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs
Normal file
@ -0,0 +1,20 @@
|
||||
// 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.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
public class HitCircleCompositionTool : HitObjectCompositionTool
|
||||
{
|
||||
public HitCircleCompositionTool()
|
||||
: base(nameof(HitCircle))
|
||||
{
|
||||
}
|
||||
|
||||
public override PlacementMask CreatePlacementMask() => new HitCirclePlacementMask();
|
||||
}
|
||||
}
|
@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks.Components
|
||||
InternalChild = new RingPiece();
|
||||
|
||||
hitCircle.PositionChanged += _ => UpdatePosition();
|
||||
hitCircle.StackHeightChanged += _ => UpdatePosition();
|
||||
hitCircle.ScaleChanged += _ => Scale = new Vector2(hitCircle.Scale);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -0,0 +1,42 @@
|
||||
// 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.Input.Events;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks.Components;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks
|
||||
{
|
||||
public class HitCirclePlacementMask : PlacementMask
|
||||
{
|
||||
public new HitCircle HitObject => (HitCircle)base.HitObject;
|
||||
|
||||
public HitCirclePlacementMask()
|
||||
: base(new HitCircle())
|
||||
{
|
||||
InternalChild = new HitCirclePiece(HitObject);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
// Fixes a 1-frame position discrpancy due to the first mouse move event happening in the next frame
|
||||
HitObject.Position = GetContainingInputManager().CurrentState.Mouse.Position;
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
HitObject.StartTime = EditorClock.CurrentTime;
|
||||
EndPlacement();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
HitObject.Position = e.MousePosition;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -17,20 +17,19 @@ using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
public class OsuHitObjectComposer : HitObjectComposer
|
||||
public class OsuHitObjectComposer : HitObjectComposer<OsuHitObject>
|
||||
{
|
||||
public OsuHitObjectComposer(Ruleset ruleset)
|
||||
: base(ruleset)
|
||||
{
|
||||
}
|
||||
|
||||
protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new OsuEditRulesetContainer(ruleset, beatmap);
|
||||
protected override RulesetContainer<OsuHitObject> CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
=> new OsuEditRulesetContainer(ruleset, beatmap);
|
||||
|
||||
protected override IReadOnlyList<ICompositionTool> CompositionTools => new ICompositionTool[]
|
||||
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new[]
|
||||
{
|
||||
new HitObjectCompositionTool<HitCircle>(),
|
||||
new HitObjectCompositionTool<Slider>(),
|
||||
new HitObjectCompositionTool<Spinner>()
|
||||
new HitCircleCompositionTool(),
|
||||
};
|
||||
|
||||
protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both };
|
||||
|
@ -61,6 +61,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
Size = circle.DrawSize;
|
||||
|
||||
HitObject.PositionChanged += _ => Position = HitObject.StackedPosition;
|
||||
HitObject.StackHeightChanged += _ => Position = HitObject.StackedPosition;
|
||||
HitObject.ScaleChanged += s => Scale = new Vector2(s);
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
|
@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
public const double OBJECT_RADIUS = 64;
|
||||
|
||||
public event Action<Vector2> PositionChanged;
|
||||
public event Action<int> StackHeightChanged;
|
||||
public event Action<float> ScaleChanged;
|
||||
|
||||
public double TimePreempt = 600;
|
||||
public double TimeFadeIn = 400;
|
||||
@ -44,13 +46,39 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
|
||||
public Vector2 StackedEndPosition => EndPosition + StackOffset;
|
||||
|
||||
public virtual int StackHeight { get; set; }
|
||||
private int stackHeight;
|
||||
|
||||
public int StackHeight
|
||||
{
|
||||
get => stackHeight;
|
||||
set
|
||||
{
|
||||
if (stackHeight == value)
|
||||
return;
|
||||
stackHeight = value;
|
||||
|
||||
StackHeightChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 StackOffset => new Vector2(StackHeight * Scale * -6.4f);
|
||||
|
||||
public double Radius => OBJECT_RADIUS * Scale;
|
||||
|
||||
public float Scale { get; set; } = 1;
|
||||
private float scale = 1;
|
||||
|
||||
public float Scale
|
||||
{
|
||||
get => scale;
|
||||
set
|
||||
{
|
||||
if (scale == value)
|
||||
return;
|
||||
scale = value;
|
||||
|
||||
ScaleChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool NewCombo { get; set; }
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo);
|
||||
|
||||
protected override DrawableHitObject<OsuHitObject> GetVisualRepresentation(OsuHitObject h)
|
||||
public override DrawableHitObject<OsuHitObject> GetVisualRepresentation(OsuHitObject h)
|
||||
{
|
||||
switch (h)
|
||||
{
|
||||
|
@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
protected override Playfield CreatePlayfield() => new TaikoPlayfield(Beatmap.ControlPointInfo);
|
||||
|
||||
protected override DrawableHitObject<TaikoHitObject> GetVisualRepresentation(TaikoHitObject h)
|
||||
public override DrawableHitObject<TaikoHitObject> GetVisualRepresentation(TaikoHitObject h)
|
||||
{
|
||||
switch (h)
|
||||
{
|
||||
|
@ -13,14 +13,18 @@ using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Edit;
|
||||
using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks;
|
||||
using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks.Components;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Screens.Edit.Screens.Compose;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseHitObjectComposer : OsuTestCase
|
||||
[Cached(Type = typeof(IPlacementHandler))]
|
||||
public class TestCaseHitObjectComposer : OsuTestCase, IPlacementHandler
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@ -29,9 +33,14 @@ namespace osu.Game.Tests.Visual
|
||||
typeof(HitObjectComposer),
|
||||
typeof(OsuHitObjectComposer),
|
||||
typeof(HitObjectMaskLayer),
|
||||
typeof(NotNullAttribute)
|
||||
typeof(NotNullAttribute),
|
||||
typeof(HitCirclePiece),
|
||||
typeof(HitCircleSelectionMask),
|
||||
typeof(HitCirclePlacementMask),
|
||||
};
|
||||
|
||||
private HitObjectComposer composer;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -59,7 +68,15 @@ namespace osu.Game.Tests.Visual
|
||||
Dependencies.CacheAs<IAdjustableClock>(clock);
|
||||
Dependencies.CacheAs<IFrameBasedClock>(clock);
|
||||
|
||||
Child = new OsuHitObjectComposer(new OsuRuleset());
|
||||
Child = composer = new OsuHitObjectComposer(new OsuRuleset());
|
||||
}
|
||||
|
||||
public void BeginPlacement(HitObject hitObject)
|
||||
{
|
||||
}
|
||||
|
||||
public void EndPlacement(HitObject hitObject) => composer.Add(hitObject);
|
||||
|
||||
public void Delete(HitObject hitObject) => composer.Remove(hitObject);
|
||||
}
|
||||
}
|
||||
|
106
osu.Game/Rulesets/Edit/EditRulesetContainer.cs
Normal file
106
osu.Game/Rulesets/Edit/EditRulesetContainer.cs
Normal file
@ -0,0 +1,106 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit
|
||||
{
|
||||
public abstract class EditRulesetContainer : CompositeDrawable
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="Playfield"/> contained by this <see cref="EditRulesetContainer"/>.
|
||||
/// </summary>
|
||||
public abstract Playfield Playfield { get; }
|
||||
|
||||
internal EditRulesetContainer()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a <see cref="HitObject"/> from the <see cref="Beatmap"/> and the display.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="HitObject"/> to remove.</param>
|
||||
/// <returns>The visual representation of the removed <paramref name="hitObject"/>.</returns>
|
||||
internal abstract DrawableHitObject Remove(HitObject hitObject);
|
||||
}
|
||||
|
||||
public class EditRulesetContainer<TObject> : EditRulesetContainer
|
||||
where TObject : HitObject
|
||||
{
|
||||
public override Playfield Playfield => rulesetContainer.Playfield;
|
||||
|
||||
private Ruleset ruleset => rulesetContainer.Ruleset;
|
||||
private Beatmap<TObject> beatmap => rulesetContainer.Beatmap;
|
||||
|
||||
private readonly RulesetContainer<TObject> rulesetContainer;
|
||||
|
||||
public EditRulesetContainer(RulesetContainer<TObject> rulesetContainer)
|
||||
{
|
||||
this.rulesetContainer = rulesetContainer;
|
||||
|
||||
InternalChild = rulesetContainer;
|
||||
|
||||
Playfield.DisplayJudgements.Value = false;
|
||||
}
|
||||
|
||||
internal override DrawableHitObject Add(HitObject hitObject)
|
||||
{
|
||||
var tObject = (TObject)hitObject;
|
||||
|
||||
// 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);
|
||||
rulesetContainer.Playfield.PostProcess();
|
||||
|
||||
return drawableObject;
|
||||
}
|
||||
|
||||
internal override DrawableHitObject Remove(HitObject hitObject)
|
||||
{
|
||||
var tObject = (TObject)hitObject;
|
||||
|
||||
// Remove from beatmap
|
||||
beatmap.HitObjects.Remove(tObject);
|
||||
|
||||
// Process the beatmap
|
||||
var processor = ruleset.CreateBeatmapProcessor(beatmap);
|
||||
|
||||
processor.PreProcess();
|
||||
processor.PostProcess();
|
||||
|
||||
// Remove visual representation
|
||||
var drawableObject = Playfield.AllHitObjects.Single(d => d.HitObject == hitObject);
|
||||
|
||||
rulesetContainer.Playfield.Remove(drawableObject);
|
||||
rulesetContainer.Playfield.PostProcess();
|
||||
|
||||
return drawableObject;
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ using osu.Framework.Timing;
|
||||
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.Layers;
|
||||
@ -22,21 +23,24 @@ namespace osu.Game.Rulesets.Edit
|
||||
{
|
||||
public abstract class HitObjectComposer : CompositeDrawable
|
||||
{
|
||||
private readonly Ruleset ruleset;
|
||||
|
||||
public IEnumerable<DrawableHitObject> HitObjects => rulesetContainer.Playfield.AllHitObjects;
|
||||
|
||||
protected ICompositionTool CurrentTool { get; private set; }
|
||||
protected readonly Ruleset Ruleset;
|
||||
|
||||
protected readonly IBindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
protected IRulesetConfigManager Config { get; private set; }
|
||||
|
||||
private readonly List<Container> layerContainers = new List<Container>();
|
||||
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
private RulesetContainer rulesetContainer;
|
||||
private EditRulesetContainer rulesetContainer;
|
||||
|
||||
protected HitObjectComposer(Ruleset ruleset)
|
||||
private HitObjectMaskLayer maskLayer;
|
||||
private PlacementContainer placementContainer;
|
||||
|
||||
internal HitObjectComposer(Ruleset ruleset)
|
||||
{
|
||||
this.ruleset = ruleset;
|
||||
Ruleset = ruleset;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
@ -44,11 +48,11 @@ namespace osu.Game.Rulesets.Edit
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IBindableBeatmap beatmap, IFrameBasedClock framedClock)
|
||||
{
|
||||
this.beatmap.BindTo(beatmap);
|
||||
Beatmap.BindTo(beatmap);
|
||||
|
||||
try
|
||||
{
|
||||
rulesetContainer = CreateRulesetContainer(ruleset, beatmap.Value);
|
||||
rulesetContainer = CreateRulesetContainer();
|
||||
rulesetContainer.Clock = framedClock;
|
||||
}
|
||||
catch (Exception e)
|
||||
@ -57,14 +61,15 @@ namespace osu.Game.Rulesets.Edit
|
||||
return;
|
||||
}
|
||||
|
||||
var layerBelowRuleset = new BorderLayer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = CreateLayerContainer()
|
||||
};
|
||||
var layerBelowRuleset = CreateLayerContainer();
|
||||
layerBelowRuleset.Child = new BorderLayer { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
var layerAboveRuleset = CreateLayerContainer();
|
||||
layerAboveRuleset.Child = new HitObjectMaskLayer();
|
||||
layerAboveRuleset.Children = new Drawable[]
|
||||
{
|
||||
maskLayer = new HitObjectMaskLayer(),
|
||||
placementContainer = new PlacementContainer(),
|
||||
};
|
||||
|
||||
layerContainers.Add(layerBelowRuleset);
|
||||
layerContainers.Add(layerAboveRuleset);
|
||||
@ -107,8 +112,8 @@ namespace osu.Game.Rulesets.Edit
|
||||
};
|
||||
|
||||
toolboxCollection.Items =
|
||||
CompositionTools.Select(t => new RadioButton(t.Name, () => setCompositionTool(t)))
|
||||
.Prepend(new RadioButton("Select", () => setCompositionTool(null)))
|
||||
CompositionTools.Select(t => new RadioButton(t.Name, () => placementContainer.CurrentTool = t))
|
||||
.Prepend(new RadioButton("Select", () => placementContainer.CurrentTool = null))
|
||||
.ToList();
|
||||
|
||||
toolboxCollection.Items[0].Select();
|
||||
@ -119,18 +124,11 @@ namespace osu.Game.Rulesets.Edit
|
||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
|
||||
dependencies.CacheAs(this);
|
||||
Config = dependencies.Get<RulesetConfigCache>().GetConfigFor(ruleset);
|
||||
Config = dependencies.Get<RulesetConfigCache>().GetConfigFor(Ruleset);
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
rulesetContainer.Playfield.DisplayJudgements.Value = false;
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
@ -144,11 +142,21 @@ namespace osu.Game.Rulesets.Edit
|
||||
});
|
||||
}
|
||||
|
||||
private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool;
|
||||
/// <summary>
|
||||
/// Adds a <see cref="HitObject"/> to the <see cref="Beatmaps.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));
|
||||
placementContainer.Refresh();
|
||||
}
|
||||
|
||||
protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap);
|
||||
public void Remove(HitObject hitObject) => maskLayer.RemoveMaskFor(rulesetContainer.Remove(hitObject));
|
||||
|
||||
protected abstract IReadOnlyList<ICompositionTool> CompositionTools { get; }
|
||||
internal abstract EditRulesetContainer CreateRulesetContainer();
|
||||
|
||||
protected abstract IReadOnlyList<HitObjectCompositionTool> CompositionTools { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SelectionMask"/> for a specific <see cref="DrawableHitObject"/>.
|
||||
@ -167,4 +175,18 @@ namespace osu.Game.Rulesets.Edit
|
||||
/// </summary>
|
||||
protected virtual Container CreateLayerContainer() => new Container { RelativeSizeAxes = Axes.Both };
|
||||
}
|
||||
|
||||
public abstract class HitObjectComposer<TObject> : HitObjectComposer
|
||||
where TObject : HitObject
|
||||
{
|
||||
protected HitObjectComposer(Ruleset ruleset)
|
||||
: base(ruleset)
|
||||
{
|
||||
}
|
||||
|
||||
internal override EditRulesetContainer CreateRulesetContainer()
|
||||
=> new EditRulesetContainer<TObject>(CreateRulesetContainer(Ruleset, Beatmap.Value));
|
||||
|
||||
protected abstract RulesetContainer<TObject> CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap);
|
||||
}
|
||||
}
|
||||
|
94
osu.Game/Rulesets/Edit/PlacementMask.cs
Normal file
94
osu.Game/Rulesets/Edit/PlacementMask.cs
Normal file
@ -0,0 +1,94 @@
|
||||
// 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.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Screens.Edit.Screens.Compose;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit
|
||||
{
|
||||
/// <summary>
|
||||
/// A mask which governs the creation of a new <see cref="HitObject"/> to actualisation.
|
||||
/// </summary>
|
||||
public abstract class PlacementMask : CompositeDrawable, IRequireHighFrequencyMousePosition
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="HitObject"/> that is being placed.
|
||||
/// </summary>
|
||||
protected readonly HitObject HitObject;
|
||||
|
||||
protected IClock EditorClock { get; private set; }
|
||||
|
||||
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
[Resolved]
|
||||
private IPlacementHandler placementHandler { get; set; }
|
||||
|
||||
protected PlacementMask(HitObject hitObject)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IBindableBeatmap beatmap, IAdjustableClock clock)
|
||||
{
|
||||
this.beatmap.BindTo(beatmap);
|
||||
|
||||
EditorClock = clock;
|
||||
|
||||
ApplyDefaultsToHitObject();
|
||||
}
|
||||
|
||||
private bool placementBegun;
|
||||
|
||||
/// <summary>
|
||||
/// Signals that the placement of <see cref="HitObject"/> has started.
|
||||
/// </summary>
|
||||
protected void BeginPlacement()
|
||||
{
|
||||
placementHandler.BeginPlacement(HitObject);
|
||||
placementBegun = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signals that the placement of <see cref="HitObject"/> has finished.
|
||||
/// This will destroy this <see cref="PlacementMask"/>, and add the <see cref="HitObject"/> to the <see cref="Beatmap"/>.
|
||||
/// </summary>
|
||||
protected void EndPlacement()
|
||||
{
|
||||
if (!placementBegun)
|
||||
BeginPlacement();
|
||||
placementHandler.EndPlacement(HitObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes <see cref="HitObject.ApplyDefaults"/>, refreshing <see cref="HitObject.NestedHitObjects"/> and parameters for the <see cref="HitObject"/>.
|
||||
/// </summary>
|
||||
protected void ApplyDefaultsToHitObject() => HitObject.ApplyDefaults(beatmap.Value.Beatmap.ControlPointInfo, beatmap.Value.Beatmap.BeatmapInfo.BaseDifficulty);
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parent?.ReceivePositionalInputAt(screenSpacePos) ?? false;
|
||||
|
||||
protected override bool Handle(UIEvent e)
|
||||
{
|
||||
base.Handle(e);
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case MouseEvent _:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +1,17 @@
|
||||
// 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.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Tools
|
||||
{
|
||||
public class HitObjectCompositionTool<T> : ICompositionTool
|
||||
where T : HitObject
|
||||
public abstract class HitObjectCompositionTool
|
||||
{
|
||||
public string Name { get; }
|
||||
public readonly string Name;
|
||||
|
||||
public HitObjectCompositionTool()
|
||||
: this(typeof(T).Name)
|
||||
{
|
||||
}
|
||||
|
||||
public HitObjectCompositionTool(string name)
|
||||
protected HitObjectCompositionTool(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public abstract PlacementMask CreatePlacementMask();
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Tools
|
||||
{
|
||||
public interface ICompositionTool
|
||||
{
|
||||
string Name { get; }
|
||||
}
|
||||
}
|
@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.UI
|
||||
/// </summary>
|
||||
public readonly CursorContainer Cursor;
|
||||
|
||||
protected readonly Ruleset Ruleset;
|
||||
public readonly Ruleset Ruleset;
|
||||
|
||||
protected IRulesetConfigManager Config { get; private set; }
|
||||
|
||||
@ -305,17 +305,7 @@ namespace osu.Game.Rulesets.UI
|
||||
private void loadObjects()
|
||||
{
|
||||
foreach (TObject h in Beatmap.HitObjects)
|
||||
{
|
||||
var drawableObject = GetVisualRepresentation(h);
|
||||
|
||||
if (drawableObject == null)
|
||||
continue;
|
||||
|
||||
drawableObject.OnNewResult += (_, r) => OnNewResult?.Invoke(r);
|
||||
drawableObject.OnRevertResult += (_, r) => OnRevertResult?.Invoke(r);
|
||||
|
||||
Playfield.Add(drawableObject);
|
||||
}
|
||||
AddRepresentation(h);
|
||||
|
||||
Playfield.PostProcess();
|
||||
|
||||
@ -323,12 +313,30 @@ namespace osu.Game.Rulesets.UI
|
||||
mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and adds the visual representation of a <see cref="TObject"/> to this <see cref="RulesetContainer{TObject}"/>.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="TObject"/> to add the visual representation for.</param>
|
||||
internal void AddRepresentation(TObject hitObject)
|
||||
{
|
||||
var drawableObject = GetVisualRepresentation(hitObject);
|
||||
|
||||
if (drawableObject == null)
|
||||
return;
|
||||
|
||||
drawableObject.OnNewResult += (_, r) => OnNewResult?.Invoke(r);
|
||||
drawableObject.OnRevertResult += (_, r) => OnRevertResult?.Invoke(r);
|
||||
|
||||
Playfield.Add(drawableObject);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a DrawableHitObject from a HitObject.
|
||||
/// </summary>
|
||||
/// <param name="h">The HitObject to make drawable.</param>
|
||||
/// <returns>The DrawableHitObject.</returns>
|
||||
protected abstract DrawableHitObject<TObject> GetVisualRepresentation(TObject h);
|
||||
public abstract DrawableHitObject<TObject> GetVisualRepresentation(TObject h);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -9,18 +9,21 @@ using osu.Framework.Graphics;
|
||||
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;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose
|
||||
{
|
||||
public class Compose : EditorScreen
|
||||
[Cached(Type = typeof(IPlacementHandler))]
|
||||
public class Compose : EditorScreen, IPlacementHandler
|
||||
{
|
||||
private const float vertical_margins = 10;
|
||||
private const float horizontal_margins = 20;
|
||||
|
||||
private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor();
|
||||
|
||||
private Container composerContainer;
|
||||
private HitObjectComposer composer;
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load([CanBeNull] BindableBeatDivisor beatDivisor)
|
||||
@ -28,6 +31,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
||||
if (beatDivisor != null)
|
||||
this.beatDivisor.BindTo(beatDivisor);
|
||||
|
||||
Container composerContainer;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new GridContainer
|
||||
@ -101,7 +106,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
||||
return;
|
||||
}
|
||||
|
||||
var composer = ruleset.CreateHitObjectComposer();
|
||||
composer = ruleset.CreateHitObjectComposer();
|
||||
if (composer == null)
|
||||
{
|
||||
Logger.Log($"Ruleset {ruleset.Description} doesn't support hitobject composition.");
|
||||
@ -111,5 +116,13 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
||||
|
||||
composerContainer.Child = composer;
|
||||
}
|
||||
|
||||
public void BeginPlacement(HitObject hitObject)
|
||||
{
|
||||
}
|
||||
|
||||
public void EndPlacement(HitObject hitObject) => composer.Add(hitObject);
|
||||
|
||||
public void Delete(HitObject hitObject) => composer.Remove(hitObject);
|
||||
}
|
||||
}
|
||||
|
28
osu.Game/Screens/Edit/Screens/Compose/IPlacementHandler.cs
Normal file
28
osu.Game/Screens/Edit/Screens/Compose/IPlacementHandler.cs
Normal file
@ -0,0 +1,28 @@
|
||||
// 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.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose
|
||||
{
|
||||
public interface IPlacementHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Notifies that a placement has begun.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="HitObject"/> being placed.</param>
|
||||
void BeginPlacement(HitObject hitObject);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies that a placement has finished.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="HitObject"/> that has been placed.</param>
|
||||
void EndPlacement(HitObject hitObject);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a <see cref="HitObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="HitObject"/> to delete.</param>
|
||||
void Delete(HitObject hitObject);
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -13,7 +14,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
public class HitObjectMaskLayer : CompositeDrawable
|
||||
{
|
||||
private MaskContainer maskContainer;
|
||||
private HitObjectComposer composer;
|
||||
|
||||
[Resolved]
|
||||
private HitObjectComposer composer { get; set; }
|
||||
|
||||
public HitObjectMaskLayer()
|
||||
{
|
||||
@ -21,10 +24,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(HitObjectComposer composer)
|
||||
private void load()
|
||||
{
|
||||
this.composer = composer;
|
||||
|
||||
maskContainer = new MaskContainer();
|
||||
|
||||
var maskSelection = composer.CreateMaskSelection();
|
||||
@ -48,7 +49,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
};
|
||||
|
||||
foreach (var obj in composer.HitObjects)
|
||||
addMask(obj);
|
||||
AddMaskFor(obj);
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
@ -61,7 +62,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
/// 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>
|
||||
private void addMask(DrawableHitObject hitObject)
|
||||
public void AddMaskFor(DrawableHitObject hitObject)
|
||||
{
|
||||
var mask = composer.CreateMaskFor(hitObject);
|
||||
if (mask == null)
|
||||
@ -69,5 +70,19 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
|
||||
maskContainer.Add(mask);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a mask for a <see cref="DrawableHitObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="DrawableHitObject"/> for which to remove the mask.</param>
|
||||
public void RemoveMaskFor(DrawableHitObject hitObject)
|
||||
{
|
||||
var maskToRemove = maskContainer.Single(m => m.HitObject == hitObject);
|
||||
if (maskToRemove == null)
|
||||
return;
|
||||
|
||||
maskToRemove.Deselect();
|
||||
maskContainer.Remove(maskToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,18 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Input.States;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Types;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
{
|
||||
@ -26,6 +29,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
|
||||
private Drawable outline;
|
||||
|
||||
[Resolved]
|
||||
private IPlacementHandler placementHandler { get; set; }
|
||||
|
||||
public MaskSelection()
|
||||
{
|
||||
selectedMasks = new List<SelectionMask>();
|
||||
@ -69,6 +75,22 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
if (e.Repeat)
|
||||
return base.OnKeyDown(e);
|
||||
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Delete:
|
||||
foreach (var h in selectedMasks.ToList())
|
||||
placementHandler.Delete(h.HitObject.HitObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnKeyDown(e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Selection Handling
|
||||
|
@ -0,0 +1,50 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using Container = System.ComponentModel.Container;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
{
|
||||
public class PlacementContainer : CompositeDrawable
|
||||
{
|
||||
private readonly Container maskContainer;
|
||||
|
||||
public PlacementContainer()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
private HitObjectCompositionTool currentTool;
|
||||
|
||||
/// <summary>
|
||||
/// The current placement tool.
|
||||
/// </summary>
|
||||
public HitObjectCompositionTool CurrentTool
|
||||
{
|
||||
get => currentTool;
|
||||
set
|
||||
{
|
||||
if (currentTool == value)
|
||||
return;
|
||||
currentTool = value;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the current placement tool.
|
||||
/// </summary>
|
||||
public void Refresh()
|
||||
{
|
||||
ClearInternal();
|
||||
|
||||
var mask = CurrentTool?.CreatePlacementMask();
|
||||
if (mask != null)
|
||||
InternalChild = mask;
|
||||
}
|
||||
}
|
||||
}
|
65
osu.Game/Tests/Visual/HitObjectPlacementMaskTestCase.cs
Normal file
65
osu.Game/Tests/Visual/HitObjectPlacementMaskTestCase.cs
Normal file
@ -0,0 +1,65 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Screens.Edit.Screens.Compose;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[Cached(Type = typeof(IPlacementHandler))]
|
||||
public abstract class HitObjectPlacementMaskTestCase : OsuTestCase, IPlacementHandler
|
||||
{
|
||||
private readonly Container hitObjectContainer;
|
||||
private PlacementMask currentMask;
|
||||
|
||||
protected HitObjectPlacementMaskTestCase()
|
||||
{
|
||||
Beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize = 2;
|
||||
|
||||
Add(hitObjectContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Clock = new FramedClock(new StopwatchClock())
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(currentMask = CreateMask());
|
||||
}
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
dependencies.CacheAs<IAdjustableClock>(new StopwatchClock());
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public void BeginPlacement(HitObject hitObject)
|
||||
{
|
||||
}
|
||||
|
||||
public void EndPlacement(HitObject hitObject)
|
||||
{
|
||||
hitObjectContainer.Add(CreateHitObject(hitObject));
|
||||
|
||||
Remove(currentMask);
|
||||
Add(currentMask = CreateMask());
|
||||
}
|
||||
|
||||
public void Delete(HitObject hitObject)
|
||||
{
|
||||
}
|
||||
|
||||
protected abstract DrawableHitObject CreateHitObject(HitObject hitObject);
|
||||
protected abstract PlacementMask CreateMask();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user