Refactor HitObjectComposer for readability (#5880)

Refactor HitObjectComposer for readability
This commit is contained in:
Dean Herbert 2019-08-30 00:46:37 +09:00 committed by GitHub
commit dbc598887a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 112 deletions

View File

@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Edit
[Cached(Type = typeof(IManiaHitObjectComposer))] [Cached(Type = typeof(IManiaHitObjectComposer))]
public class ManiaHitObjectComposer : HitObjectComposer<ManiaHitObject>, IManiaHitObjectComposer public class ManiaHitObjectComposer : HitObjectComposer<ManiaHitObject>, IManiaHitObjectComposer
{ {
protected new DrawableManiaEditRuleset DrawableRuleset { get; private set; } private DrawableManiaEditRuleset drawableRuleset;
public ManiaHitObjectComposer(Ruleset ruleset) public ManiaHitObjectComposer(Ruleset ruleset)
: base(ruleset) : base(ruleset)
@ -33,23 +33,23 @@ namespace osu.Game.Rulesets.Mania.Edit
/// </summary> /// </summary>
/// <param name="screenSpacePosition">The screen-space position.</param> /// <param name="screenSpacePosition">The screen-space position.</param>
/// <returns>The column which intersects with <paramref name="screenSpacePosition"/>.</returns> /// <returns>The column which intersects with <paramref name="screenSpacePosition"/>.</returns>
public Column ColumnAt(Vector2 screenSpacePosition) => DrawableRuleset.GetColumnByPosition(screenSpacePosition); public Column ColumnAt(Vector2 screenSpacePosition) => drawableRuleset.GetColumnByPosition(screenSpacePosition);
private DependencyContainer dependencies; private DependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
=> dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); => dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
public int TotalColumns => ((ManiaPlayfield)DrawableRuleset.Playfield).TotalColumns; public int TotalColumns => ((ManiaPlayfield)drawableRuleset.Playfield).TotalColumns;
protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
{ {
DrawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods); drawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods);
// This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it // This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it
dependencies.CacheAs(DrawableRuleset.ScrollingInfo); dependencies.CacheAs(drawableRuleset.ScrollingInfo);
return DrawableRuleset; return drawableRuleset;
} }
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[] protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]

View File

@ -11,37 +11,25 @@ using osu.Game.Screens.Edit;
namespace osu.Game.Rulesets.Edit namespace osu.Game.Rulesets.Edit
{ {
public abstract class DrawableEditRuleset : CompositeDrawable /// <summary>
{ /// A wrapper for a <see cref="DrawableRuleset{TObject}"/>. Handles adding visual representations of <see cref="HitObject"/>s to the underlying <see cref="DrawableRuleset{TObject}"/>.
/// <summary> /// </summary>
/// The <see cref="Playfield"/> contained by this <see cref="DrawableEditRuleset"/>. internal class DrawableEditRulesetWrapper<TObject> : CompositeDrawable
/// </summary>
public abstract Playfield Playfield { get; }
public abstract PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer();
internal DrawableEditRuleset()
{
RelativeSizeAxes = Axes.Both;
}
}
public class DrawableEditRuleset<TObject> : DrawableEditRuleset
where TObject : HitObject where TObject : HitObject
{ {
public override Playfield Playfield => drawableRuleset.Playfield; public Playfield Playfield => drawableRuleset.Playfield;
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => drawableRuleset.CreatePlayfieldAdjustmentContainer();
private readonly DrawableRuleset<TObject> drawableRuleset; private readonly DrawableRuleset<TObject> drawableRuleset;
[Resolved] [Resolved]
private IEditorBeatmap<TObject> beatmap { get; set; } private IEditorBeatmap<TObject> beatmap { get; set; }
public DrawableEditRuleset(DrawableRuleset<TObject> drawableRuleset) public DrawableEditRulesetWrapper(DrawableRuleset<TObject> drawableRuleset)
{ {
this.drawableRuleset = drawableRuleset; this.drawableRuleset = drawableRuleset;
RelativeSizeAxes = Axes.Both;
InternalChild = drawableRuleset; InternalChild = drawableRuleset;
} }
@ -76,6 +64,8 @@ namespace osu.Game.Rulesets.Edit
drawableRuleset.Playfield.PostProcess(); drawableRuleset.Playfield.PostProcess();
} }
public PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => drawableRuleset.CreatePlayfieldAdjustmentContainer();
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);

View File

@ -25,40 +25,40 @@ using osu.Game.Screens.Edit.Compose.Components;
namespace osu.Game.Rulesets.Edit namespace osu.Game.Rulesets.Edit
{ {
public abstract class HitObjectComposer : CompositeDrawable [Cached(Type = typeof(IPlacementHandler))]
public abstract class HitObjectComposer<TObject> : HitObjectComposer, IPlacementHandler
where TObject : HitObject
{ {
public IEnumerable<DrawableHitObject> HitObjects => DrawableRuleset.Playfield.AllHitObjects; protected IRulesetConfigManager Config { get; private set; }
protected readonly Ruleset Ruleset; protected readonly Ruleset Ruleset;
protected readonly IBindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>(); private IBindable<WorkingBeatmap> workingBeatmap;
private Beatmap<TObject> playableBeatmap;
protected IRulesetConfigManager Config { get; private set; } private EditorBeatmap<TObject> editorBeatmap;
private IBeatmapProcessor beatmapProcessor;
private readonly List<Container> layerContainers = new List<Container>();
protected DrawableEditRuleset DrawableRuleset { get; private set; }
private DrawableEditRulesetWrapper<TObject> drawableRulesetWrapper;
private BlueprintContainer blueprintContainer; private BlueprintContainer blueprintContainer;
private readonly List<Container> layerContainers = new List<Container>();
private InputManager inputManager; private InputManager inputManager;
internal HitObjectComposer(Ruleset ruleset) protected HitObjectComposer(Ruleset ruleset)
{ {
Ruleset = ruleset; Ruleset = ruleset;
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindable<WorkingBeatmap> beatmap, IFrameBasedClock framedClock) private void load(IFrameBasedClock framedClock)
{ {
Beatmap.BindTo(beatmap);
try try
{ {
DrawableRuleset = CreateDrawableRuleset(); drawableRulesetWrapper = new DrawableEditRulesetWrapper<TObject>(CreateDrawableRuleset(Ruleset, workingBeatmap.Value, Array.Empty<Mod>()))
DrawableRuleset.Clock = framedClock; {
Clock = framedClock
};
} }
catch (Exception e) catch (Exception e)
{ {
@ -66,10 +66,10 @@ namespace osu.Game.Rulesets.Edit
return; return;
} }
var layerBelowRuleset = DrawableRuleset.CreatePlayfieldAdjustmentContainer(); var layerBelowRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer();
layerBelowRuleset.Child = new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both }; layerBelowRuleset.Child = new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both };
var layerAboveRuleset = DrawableRuleset.CreatePlayfieldAdjustmentContainer(); var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer();
layerAboveRuleset.Child = blueprintContainer = new BlueprintContainer(); layerAboveRuleset.Child = blueprintContainer = new BlueprintContainer();
layerContainers.Add(layerBelowRuleset); layerContainers.Add(layerBelowRuleset);
@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Edit
Children = new Drawable[] Children = new Drawable[]
{ {
layerBelowRuleset, layerBelowRuleset,
DrawableRuleset, drawableRulesetWrapper,
layerAboveRuleset layerAboveRuleset
} }
} }
@ -120,73 +120,9 @@ namespace osu.Game.Rulesets.Edit
toolboxCollection.Items[0].Select(); toolboxCollection.Items[0].Select();
} }
protected override void LoadComplete()
{
base.LoadComplete();
inputManager = GetContainingInputManager();
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{ {
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); workingBeatmap = parent.Get<IBindable<WorkingBeatmap>>().GetBoundCopy();
dependencies.CacheAs(this);
Config = dependencies.Get<RulesetConfigCache>().GetConfigFor(Ruleset);
return dependencies;
}
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
layerContainers.ForEach(l =>
{
l.Anchor = DrawableRuleset.Playfield.Anchor;
l.Origin = DrawableRuleset.Playfield.Origin;
l.Position = DrawableRuleset.Playfield.Position;
l.Size = DrawableRuleset.Playfield.Size;
});
}
/// <summary>
/// Whether the user's cursor is currently in an area of the <see cref="HitObjectComposer"/> that is valid for placement.
/// </summary>
public virtual bool CursorInPlacementArea => DrawableRuleset.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position);
internal abstract DrawableEditRuleset CreateDrawableRuleset();
protected abstract IReadOnlyList<HitObjectCompositionTool> CompositionTools { get; }
/// <summary>
/// Creates a <see cref="SelectionBlueprint"/> for a specific <see cref="DrawableHitObject"/>.
/// </summary>
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create the overlay for.</param>
public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null;
/// <summary>
/// Creates a <see cref="SelectionHandler"/> which outlines <see cref="DrawableHitObject"/>s and handles movement of selections.
/// </summary>
public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler();
}
[Cached(Type = typeof(IPlacementHandler))]
public abstract class HitObjectComposer<TObject> : HitObjectComposer, IPlacementHandler
where TObject : HitObject
{
private Beatmap<TObject> playableBeatmap;
private EditorBeatmap<TObject> editorBeatmap;
private IBeatmapProcessor beatmapProcessor;
protected HitObjectComposer(Ruleset ruleset)
: base(ruleset)
{
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
var workingBeatmap = parent.Get<IBindable<WorkingBeatmap>>();
playableBeatmap = (Beatmap<TObject>)workingBeatmap.Value.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty<Mod>()); playableBeatmap = (Beatmap<TObject>)workingBeatmap.Value.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty<Mod>());
beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap);
@ -199,9 +135,31 @@ namespace osu.Game.Rulesets.Edit
dependencies.CacheAs<IEditorBeatmap>(editorBeatmap); dependencies.CacheAs<IEditorBeatmap>(editorBeatmap);
dependencies.CacheAs<IEditorBeatmap<TObject>>(editorBeatmap); dependencies.CacheAs<IEditorBeatmap<TObject>>(editorBeatmap);
Config = dependencies.Get<RulesetConfigCache>().GetConfigFor(Ruleset);
return base.CreateChildDependencies(dependencies); return base.CreateChildDependencies(dependencies);
} }
protected override void LoadComplete()
{
base.LoadComplete();
inputManager = GetContainingInputManager();
}
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
layerContainers.ForEach(l =>
{
l.Anchor = drawableRulesetWrapper.Playfield.Anchor;
l.Origin = drawableRulesetWrapper.Playfield.Origin;
l.Position = drawableRulesetWrapper.Playfield.Position;
l.Size = drawableRulesetWrapper.Playfield.Size;
});
}
private void addHitObject(HitObject hitObject) private void addHitObject(HitObject hitObject)
{ {
beatmapProcessor?.PreProcess(); beatmapProcessor?.PreProcess();
@ -215,8 +173,10 @@ namespace osu.Game.Rulesets.Edit
beatmapProcessor?.PostProcess(); beatmapProcessor?.PostProcess();
} }
internal override DrawableEditRuleset CreateDrawableRuleset() public override IEnumerable<DrawableHitObject> HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects;
=> new DrawableEditRuleset<TObject>(CreateDrawableRuleset(Ruleset, Beatmap.Value, Array.Empty<Mod>())); public override bool CursorInPlacementArea => drawableRulesetWrapper.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position);
protected abstract IReadOnlyList<HitObjectCompositionTool> CompositionTools { get; }
protected abstract DrawableRuleset<TObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods); protected abstract DrawableRuleset<TObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods);
@ -239,4 +199,34 @@ namespace osu.Game.Rulesets.Edit
} }
} }
} }
[Cached(typeof(HitObjectComposer))]
public abstract class HitObjectComposer : CompositeDrawable
{
internal HitObjectComposer()
{
RelativeSizeAxes = Axes.Both;
}
/// <summary>
/// All the <see cref="DrawableHitObject"/>s.
/// </summary>
public abstract IEnumerable<DrawableHitObject> HitObjects { get; }
/// <summary>
/// Whether the user's cursor is currently in an area of the <see cref="HitObjectComposer"/> that is valid for placement.
/// </summary>
public abstract bool CursorInPlacementArea { get; }
/// <summary>
/// Creates a <see cref="SelectionBlueprint"/> for a specific <see cref="DrawableHitObject"/>.
/// </summary>
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create the overlay for.</param>
public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null;
/// <summary>
/// Creates a <see cref="SelectionHandler"/> which outlines <see cref="DrawableHitObject"/>s and handles movement of selections.
/// </summary>
public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler();
}
} }