Merge remote-tracking branch 'origin/master' into editor-mask-placement

# Conflicts:
#	osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs
#	osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs
#	osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs
#	osu.Game/Rulesets/UI/RulesetContainer.cs
This commit is contained in:
smoogipoo
2018-10-16 17:28:16 +09:00
80 changed files with 683 additions and 624 deletions

View File

@ -14,6 +14,11 @@ namespace osu.Game.Rulesets.UI
public IEnumerable<DrawableHitObject> Objects => InternalChildren.Cast<DrawableHitObject>().OrderBy(h => h.HitObject.StartTime);
public IEnumerable<DrawableHitObject> AliveObjects => AliveInternalChildren.Cast<DrawableHitObject>().OrderBy(h => h.HitObject.StartTime);
public HitObjectContainer()
{
RelativeSizeAxes = Axes.Both;
}
public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject);
public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject);

View File

@ -9,17 +9,26 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Configuration;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using OpenTK;
namespace osu.Game.Rulesets.UI
{
public abstract class Playfield : ScalableContainer
public abstract class Playfield : CompositeDrawable
{
/// <summary>
/// The <see cref="DrawableHitObject"/> contained in this Playfield.
/// </summary>
public HitObjectContainer HitObjectContainer { get; private set; }
public HitObjectContainer HitObjectContainer => hitObjectContainerLazy.Value;
private readonly Lazy<HitObjectContainer> hitObjectContainerLazy;
/// <summary>
/// A function that converts gamefield coordinates to screen space.
/// </summary>
public Func<Vector2, Vector2> GamefieldToScreenSpace => HitObjectContainer.ToScreenSpace;
/// <summary>
/// All the <see cref="DrawableHitObject"/>s contained in this <see cref="Playfield"/> and all <see cref="NestedPlayfields"/>.
@ -39,18 +48,13 @@ namespace osu.Game.Rulesets.UI
public readonly BindableBool DisplayJudgements = new BindableBool(true);
/// <summary>
/// A container for keeping track of DrawableHitObjects.
/// Creates a new <see cref="Playfield"/>.
/// </summary>
/// <param name="customWidth">The width to scale the internal coordinate space to.
/// May be null if scaling based on <paramref name="customHeight"/> is desired. If <paramref name="customHeight"/> is also null, no scaling will occur.
/// </param>
/// <param name="customHeight">The height to scale the internal coordinate space to.
/// May be null if scaling based on <paramref name="customWidth"/> is desired. If <paramref name="customWidth"/> is also null, no scaling will occur.
/// </param>
protected Playfield(float? customWidth = null, float? customHeight = null)
: base(customWidth, customHeight)
protected Playfield()
{
RelativeSizeAxes = Axes.Both;
hitObjectContainerLazy = new Lazy<HitObjectContainer>(CreateHitObjectContainer);
}
private WorkingBeatmap beatmap;
@ -59,11 +63,6 @@ namespace osu.Game.Rulesets.UI
private void load(IBindableBeatmap beatmap)
{
this.beatmap = beatmap.Value;
HitObjectContainer = CreateHitObjectContainer();
HitObjectContainer.RelativeSizeAxes = Axes.Both;
Add(HitObjectContainer);
}
/// <summary>
@ -94,10 +93,14 @@ namespace osu.Game.Rulesets.UI
nestedPlayfields.Value.Add(otherPlayfield);
}
/// <summary>
/// Creates the container that will be used to contain the <see cref="DrawableHitObject"/>s.
/// </summary>
protected virtual HitObjectContainer CreateHitObjectContainer() => new HitObjectContainer();
protected override void LoadComplete()
{
base.LoadComplete();
// in the case a consumer forgets to add the HitObjectContainer, we will add it here.
if (HitObjectContainer.Parent == null)
AddInternal(HitObjectContainer);
}
protected override void Update()
{
@ -108,5 +111,10 @@ namespace osu.Game.Rulesets.UI
if (mod is IUpdatableByPlayfield updatable)
updatable.Update(this);
}
/// <summary>
/// Creates the container that will be used to contain the <see cref="DrawableHitObject"/>s.
/// </summary>
protected virtual HitObjectContainer CreateHitObjectContainer() => new HitObjectContainer();
}
}

View File

@ -22,7 +22,6 @@ using osu.Game.Overlays;
using osu.Game.Rulesets.Configuration;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring;
using OpenTK;
namespace osu.Game.Rulesets.UI
{
@ -316,25 +315,6 @@ namespace osu.Game.Rulesets.UI
Playfield.Add(drawableObject);
}
protected override void Update()
{
base.Update();
Playfield.Size = GetAspectAdjustedSize() * PlayfieldArea;
}
/// <summary>
/// Computes the size of the <see cref="Playfield"/> in relative coordinate space after aspect adjustments.
/// </summary>
/// <returns>The aspect-adjusted size.</returns>
protected virtual Vector2 GetAspectAdjustedSize() => Vector2.One;
/// <summary>
/// The area of this <see cref="RulesetContainer"/> that is available for the <see cref="Playfield"/> to use.
/// Must be specified in relative coordinate space to this <see cref="RulesetContainer"/>.
/// This affects the final size of the <see cref="Playfield"/> but does not affect the <see cref="Playfield"/>'s scale.
/// </summary>
protected virtual Vector2 PlayfieldArea => new Vector2(0.75f); // A sane default
/// <summary>
/// Creates a DrawableHitObject from a HitObject.

View File

@ -73,12 +73,10 @@ namespace osu.Game.Rulesets.UI
#region IHasReplayHandler
private ReplayInputHandler replayInputHandler;
public ReplayInputHandler ReplayInputHandler
{
get
{
return replayInputHandler;
}
get => replayInputHandler;
set
{
if (replayInputHandler != null) RemoveHandler(replayInputHandler);
@ -208,16 +206,20 @@ namespace osu.Game.Rulesets.UI
mouseDisabled = config.GetBindable<bool>(OsuSetting.MouseDisableButtons);
}
protected override bool OnMouseDown(MouseDownEvent e)
protected override bool Handle(UIEvent e)
{
if (mouseDisabled.Value && (e.Button == MouseButton.Left || e.Button == MouseButton.Right)) return false;
return base.OnMouseDown(e);
}
protected override bool OnMouseUp(MouseUpEvent e)
{
if (!CurrentState.Mouse.IsPressed(e.Button)) return false;
return base.OnMouseUp(e);
switch (e)
{
case MouseDownEvent mouseDown when mouseDown.Button == MouseButton.Left || mouseDown.Button == MouseButton.Right:
if (mouseDisabled.Value)
return false;
break;
case MouseUpEvent mouseUp:
if (!CurrentState.Mouse.IsPressed(mouseUp.Button))
return false;
break;
}
return base.Handle(e);
}
#endregion
@ -269,7 +271,7 @@ namespace osu.Game.Rulesets.UI
}
public class RulesetInputManagerInputState<T> : InputState
where T : struct
where T : struct
{
public ReplayState<T> LastReplayState;

View File

@ -1,99 +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
using System;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using OpenTK;
namespace osu.Game.Rulesets.UI
{
/// <summary>
/// A <see cref="Container"/> which can have its internal coordinate system scaled to a specific size.
/// </summary>
public class ScalableContainer : Container
{
/// <summary>
/// A function that converts coordinates from gamefield to screen space.
/// </summary>
public Func<Vector2, Vector2> GamefieldToScreenSpace => scaledContent.GamefieldToScreenSpace;
/// <summary>
/// The scaled content.
/// </summary>
private readonly ScaledContainer scaledContent;
protected override Container<Drawable> Content => scaledContent;
/// <summary>
/// A <see cref="Container"/> which can have its internal coordinate system scaled to a specific size.
/// </summary>
/// <param name="customWidth">The width to scale the internal coordinate space to.
/// May be null if scaling based on <paramref name="customHeight"/> is desired. If <paramref name="customHeight"/> is also null, no scaling will occur.
/// </param>
/// <param name="customHeight">The height to scale the internal coordinate space to.
/// May be null if scaling based on <paramref name="customWidth"/> is desired. If <paramref name="customWidth"/> is also null, no scaling will occur.
/// </param>
public ScalableContainer(float? customWidth = null, float? customHeight = null)
{
AddInternal(scaledContent = new ScaledContainer
{
CustomWidth = customWidth,
CustomHeight = customHeight,
RelativeSizeAxes = Axes.Both,
});
}
private class ScaledContainer : Container
{
/// <summary>
/// A function that converts coordinates from gamefield to screen space.
/// </summary>
public Func<Vector2, Vector2> GamefieldToScreenSpace => content.ToScreenSpace;
/// <summary>
/// The value to scale the width of the content to match.
/// If null, <see cref="CustomHeight"/> is used.
/// </summary>
public float? CustomWidth;
/// <summary>
/// The value to scale the height of the content to match.
/// if null, <see cref="CustomWidth"/> is used.
/// </summary>
public float? CustomHeight;
private readonly Container content;
protected override Container<Drawable> Content => content;
public ScaledContainer()
{
AddInternal(content = new Container { RelativeSizeAxes = Axes.Both });
}
protected override void Update()
{
base.Update();
content.Scale = sizeScale;
content.Size = Vector2.Divide(Vector2.One, sizeScale);
}
/// <summary>
/// The scale that is required for the size of the content to match <see cref="CustomWidth"/> and <see cref="CustomHeight"/>.
/// </summary>
private Vector2 sizeScale
{
get
{
if (CustomWidth.HasValue && CustomHeight.HasValue)
return Vector2.Divide(DrawSize, new Vector2(CustomWidth.Value, CustomHeight.Value));
if (CustomWidth.HasValue)
return new Vector2(DrawSize.X / CustomWidth.Value);
if (CustomHeight.HasValue)
return new Vector2(DrawSize.Y / CustomHeight.Value);
return Vector2.One;
}
}
}
}
}

View File

@ -6,19 +6,19 @@ namespace osu.Game.Rulesets.UI.Scrolling
public enum ScrollingDirection
{
/// <summary>
/// Hitobjects will scroll vertically from the bottom of the hitobject container.
/// Hit objects will scroll vertically from the bottom of the hitobject container.
/// </summary>
Up,
/// <summary>
/// Hitobjects will scroll vertically from the top of the hitobject container.
/// Hit objects will scroll vertically from the top of the hitobject container.
/// </summary>
Down,
/// <summary>
/// Hitobjects will scroll horizontally from the right of the hitobject container.
/// Hit objects will scroll horizontally from the right of the hitobject container.
/// </summary>
Left,
/// <summary>
/// Hitobjects will scroll horizontally from the left of the hitobject container.
/// Hit objects will scroll horizontally from the left of the hitobject container.
/// </summary>
Right
}

View File

@ -65,20 +65,6 @@ namespace osu.Game.Rulesets.UI.Scrolling
protected virtual SpeedChangeVisualisationMethod VisualisationMethod => SpeedChangeVisualisationMethod.Sequential;
/// <summary>
/// Creates a new <see cref="ScrollingPlayfield"/>.
/// </summary>
/// <param name="customWidth">The width to scale the internal coordinate space to.
/// May be null if scaling based on <paramref name="customHeight"/> is desired. If <paramref name="customHeight"/> is also null, no scaling will occur.
/// </param>
/// <param name="customHeight">The height to scale the internal coordinate space to.
/// May be null if scaling based on <paramref name="customWidth"/> is desired. If <paramref name="customWidth"/> is also null, no scaling will occur.
/// </param>
protected ScrollingPlayfield(float? customWidth = null, float? customHeight = null)
: base(customWidth, customHeight)
{
}
[BackgroundDependencyLoader]
private void load()
{

View File

@ -60,6 +60,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
return new MultiplierControlPoint(c.Time)
{
Velocity = Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier,
TimingPoint = lastTimingPoint,
DifficultyPoint = lastDifficultyPoint
};
@ -78,7 +79,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
// If we have no control points, add a default one
if (DefaultControlPoints.Count == 0)
DefaultControlPoints.Add(new MultiplierControlPoint());
DefaultControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier });
DefaultControlPoints.ForEach(c => applySpeedAdjustment(c, Playfield));
}
@ -88,22 +89,5 @@ namespace osu.Game.Rulesets.UI.Scrolling
playfield.HitObjects.AddControlPoint(controlPoint);
playfield.NestedPlayfields?.OfType<ScrollingPlayfield>().ForEach(p => applySpeedAdjustment(controlPoint, p));
}
/// <summary>
/// Generates a <see cref="MultiplierControlPoint"/> with the default timing change/difficulty change from the beatmap at a time.
/// </summary>
/// <param name="time">The time to create the control point at.</param>
/// <returns>The default <see cref="MultiplierControlPoint"/> at <paramref name="time"/>.</returns>
public MultiplierControlPoint CreateControlPointAt(double time)
{
if (DefaultControlPoints.Count == 0)
return new MultiplierControlPoint(time);
int index = DefaultControlPoints.BinarySearch(new MultiplierControlPoint(time));
if (index < 0)
return new MultiplierControlPoint(time);
return new MultiplierControlPoint(time, DefaultControlPoints[index]);
}
}
}