Merge branch 'editor-composer-cleanup' into mania-mask-container

# Conflicts:
#	osu.Game/Rulesets/Edit/HitObjectComposer.cs
#	osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs
This commit is contained in:
smoogipoo
2018-07-17 16:00:46 +09:00
8 changed files with 92 additions and 43 deletions

View File

@ -2,8 +2,6 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Configuration;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit.Screens.Compose.Layers;
using OpenTK;
@ -13,8 +11,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers
{
public readonly IBindable<bool> Inverted = new Bindable<bool>();
public ManiaHitObjectMaskLayer(Playfield playfield, HitObjectComposer composer)
: base(playfield, composer)
public ManiaHitObjectMaskLayer()
{
Inverted.ValueChanged += invertedChanged;
}

View File

@ -43,6 +43,6 @@ namespace osu.Game.Rulesets.Mania.Edit
return base.CreateMaskFor(hitObject);
}
protected override HitObjectMaskLayer CreateHitObjectMaskLayer() => new ManiaHitObjectMaskLayer(RulesetContainer.Playfield, this);
protected override HitObjectMaskLayer CreateHitObjectMaskLayer() => new ManiaHitObjectMaskLayer();
}
}

View File

@ -50,6 +50,11 @@ namespace osu.Game.Beatmaps
/// </summary>
public event Action<DownloadBeatmapSetRequest> BeatmapDownloadFailed;
/// <summary>
/// Fired when a beatmap load is requested (into the interactive game UI).
/// </summary>
public Action<BeatmapSetInfo> PresentBeatmap;
/// <summary>
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
/// </summary>
@ -168,12 +173,20 @@ namespace osu.Game.Beatmaps
Task.Factory.StartNew(() =>
{
BeatmapSetInfo importedBeatmap;
// This gets scheduled back to the update thread, but we want the import to run in the background.
using (var stream = new MemoryStream(data))
using (var archive = new ZipArchiveReader(stream, beatmapSetInfo.ToString()))
Import(archive);
importedBeatmap = Import(archive);
downloadNotification.CompletionClickAction = () =>
{
PresentBeatmap?.Invoke(importedBeatmap);
return true;
};
downloadNotification.State = ProgressNotificationState.Completed;
currentDownloads.Remove(request);
}, TaskCreationOptions.LongRunning);
};

View File

@ -24,6 +24,7 @@ using osu.Framework.Input;
using osu.Framework.Input.Bindings;
using osu.Framework.Platform;
using osu.Framework.Threading;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Scoring;
using osu.Game.Overlays.Notifications;
@ -34,6 +35,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Skinning;
using OpenTK.Graphics;
using osu.Game.Overlays.Volume;
using osu.Game.Screens.Select;
namespace osu.Game
{
@ -179,6 +181,41 @@ namespace osu.Game
/// <param name="setId">The set to display.</param>
public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId);
/// <summary>
/// Present a beatmap at song select.
/// </summary>
/// <param name="beatmap">The beatmap to select.</param>
public void PresentBeatmap(BeatmapSetInfo beatmap)
{
CloseAllOverlays(false);
void setBeatmap()
{
if (Beatmap.Disabled)
{
Schedule(setBeatmap);
return;
}
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First());
}
switch (currentScreen)
{
case SongSelect _:
break;
default:
// navigate to song select if we are not already there.
var menu = (MainMenu)intro.ChildScreen;
menu.MakeCurrent();
menu.LoadToSolo();
break;
}
setBeatmap();
}
/// <summary>
/// Show a user's profile as an overlay.
/// </summary>
@ -245,6 +282,7 @@ namespace osu.Game
BeatmapManager.PostNotification = n => notifications?.Post(n);
BeatmapManager.GetStableStorage = GetStorageForStableInstall;
BeatmapManager.PresentBeatmap = PresentBeatmap;
AddRange(new Drawable[]
{

View File

@ -28,6 +28,8 @@ namespace osu.Game.Rulesets.Edit
protected RulesetContainer RulesetContainer;
private readonly List<Container> layerContainers = new List<Container>();
public IEnumerable<DrawableHitObject> HitObjects => RulesetContainer.Playfield.AllHitObjects;
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
protected HitObjectComposer(Ruleset ruleset)
@ -110,6 +112,13 @@ namespace osu.Game.Rulesets.Edit
toolboxCollection.Items[0].Select();
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
dependencies.CacheAs(this);
return dependencies;
}
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
@ -145,7 +154,7 @@ namespace osu.Game.Rulesets.Edit
/// <summary>
/// Creates a <see cref="HitObjectMaskLayer"/> depending on the ruleset.
/// </summary>
protected virtual HitObjectMaskLayer CreateHitObjectMaskLayer() => new HitObjectMaskLayer(RulesetContainer.Playfield, this);
protected virtual HitObjectMaskLayer CreateHitObjectMaskLayer() => new HitObjectMaskLayer();
/// <summary>
/// Creates a <see cref="ScalableContainer"/> which provides a layer above or below the <see cref="Playfield"/>.

View File

@ -1,25 +1,34 @@
// 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 System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
namespace osu.Game.Rulesets.UI
{
public abstract class Playfield : ScalableContainer
{
/// <summary>
/// The HitObjects contained in this Playfield.
/// The <see cref="DrawableHitObject"/> contained in this Playfield.
/// </summary>
public HitObjectContainer HitObjects { get; private set; }
/// <summary>
/// All the <see cref="Playfield"/>s nested inside this playfield.
/// All the <see cref="DrawableHitObject"/>s contained in this <see cref="Playfield"/> and all <see cref="NestedPlayfields"/>.
/// </summary>
public IReadOnlyList<Playfield> NestedPlayfields => nestedPlayfields;
private List<Playfield> nestedPlayfields;
public IEnumerable<DrawableHitObject> AllHitObjects => HitObjects?.Objects.Concat(NestedPlayfields.SelectMany(p => p.AllHitObjects)) ?? Enumerable.Empty<DrawableHitObject>();
/// <summary>
/// All <see cref="Playfield"/>s nested inside this <see cref="Playfield"/>.
/// </summary>
public IEnumerable<Playfield> NestedPlayfields => nestedPlayfields.IsValueCreated ? nestedPlayfields.Value : Enumerable.Empty<Playfield>();
private readonly Lazy<List<Playfield>> nestedPlayfields = new Lazy<List<Playfield>>();
/// <summary>
/// A container for keeping track of DrawableHitObjects.
@ -48,7 +57,7 @@ namespace osu.Game.Rulesets.UI
/// <summary>
/// Performs post-processing tasks (if any) after all DrawableHitObjects are loaded into this Playfield.
/// </summary>
public virtual void PostProcess() => nestedPlayfields?.ForEach(p => p.PostProcess());
public virtual void PostProcess() => NestedPlayfields.ForEach(p => p.PostProcess());
/// <summary>
/// Adds a DrawableHitObject to this Playfield.
@ -67,13 +76,7 @@ namespace osu.Game.Rulesets.UI
/// This does not add the <see cref="Playfield"/> to the draw hierarchy.
/// </summary>
/// <param name="otherPlayfield">The <see cref="Playfield"/> to add.</param>
protected void AddNested(Playfield otherPlayfield)
{
if (nestedPlayfields == null)
nestedPlayfields = new List<Playfield>();
nestedPlayfields.Add(otherPlayfield);
}
protected void AddNested(Playfield otherPlayfield) => nestedPlayfields.Value.Add(otherPlayfield);
/// <summary>
/// Creates the container that will be used to contain the <see cref="DrawableHitObject"/>s.

View File

@ -8,33 +8,27 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI;
namespace osu.Game.Screens.Edit.Screens.Compose.Layers
{
public class HitObjectMaskLayer : CompositeDrawable
{
protected readonly Playfield Playfield;
protected readonly HitObjectComposer Composer;
private MaskContainer maskContainer;
private HitObjectComposer composer;
public HitObjectMaskLayer(Playfield playfield, HitObjectComposer composer)
public HitObjectMaskLayer()
{
// we need the playfield as HitObjects may not be initialised until its BDL.
Playfield = playfield;
Composer = composer;
RelativeSizeAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load()
private void load(HitObjectComposer composer)
{
this.composer = composer;
maskContainer = new MaskContainer();
var maskSelection = Composer.CreateMaskSelection();
var maskSelection = composer.CreateMaskSelection();
maskContainer.MaskSelected += maskSelection.HandleSelected;
maskContainer.MaskDeselected += maskSelection.HandleDeselected;
@ -56,17 +50,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
dragLayer.CreateProxy()
};
addMasks(Playfield);
}
private void addMasks(Playfield playfield)
{
foreach (var obj in playfield.HitObjects.Objects)
foreach (var obj in composer.HitObjects)
addMask(obj);
if (playfield.NestedPlayfields != null)
foreach (var p in playfield.NestedPlayfields)
addMasks(p);
}
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
@ -81,7 +66,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create a mask for.</param>
private void addMask(DrawableHitObject hitObject)
{
var mask = Composer.CreateMaskFor(hitObject);
var mask = composer.CreateMaskFor(hitObject);
if (mask == null)
return;

View File

@ -55,7 +55,7 @@ namespace osu.Game.Screens.Menu
OnChart = delegate { Push(new ChartListing()); },
OnDirect = delegate { Push(new OnlineListing()); },
OnEdit = delegate { Push(new Editor()); },
OnSolo = delegate { Push(consumeSongSelect()); },
OnSolo = onSolo,
OnMulti = delegate { Push(new Multiplayer()); },
OnExit = Exit,
}
@ -85,6 +85,10 @@ namespace osu.Game.Screens.Menu
LoadComponentAsync(songSelect = new PlaySongSelect());
}
public void LoadToSolo() => Schedule(onSolo);
private void onSolo() => Push(consumeSongSelect());
private Screen consumeSongSelect()
{
var s = songSelect;