1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-29 02:52:54 +08:00

Add better scale adjustements to TaikoPlayfield.

It will now keep the original width while scaling everything inside to match the playfield height.
This commit is contained in:
smoogipooo 2017-04-10 14:28:01 +09:00
parent 30b5b6f7e2
commit d6f388f8fd

View File

@ -16,14 +16,14 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using System.Linq; using System.Linq;
using osu.Game.Modes.Taiko.Objects.Drawables; using osu.Game.Modes.Taiko.Objects.Drawables;
using System;
namespace osu.Game.Modes.Taiko.UI namespace osu.Game.Modes.Taiko.UI
{ {
public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgement> public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgement>
{ {
/// <summary> /// <summary>
/// The play field height. This is relative to the size of hit objects /// The default play field height.
/// such that the playfield is just a bit larger than strong hits.
/// </summary> /// </summary>
public const float DEFAULT_PLAYFIELD_HEIGHT = 168f; public const float DEFAULT_PLAYFIELD_HEIGHT = 168f;
@ -53,12 +53,15 @@ namespace osu.Game.Modes.Taiko.UI
public TaikoPlayfield() public TaikoPlayfield()
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
// Default height
Height = DEFAULT_PLAYFIELD_HEIGHT; Height = DEFAULT_PLAYFIELD_HEIGHT;
AddInternal(new Drawable[] AddInternal(new Drawable[]
{ {
rightBackgroundContainer = new Container rightBackgroundContainer = new Container
{ {
Name = "Transparent playfield background",
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
BorderThickness = 2, BorderThickness = 2,
Masking = true, Masking = true,
@ -77,14 +80,22 @@ namespace osu.Game.Modes.Taiko.UI
}, },
} }
}, },
new ScaleFixContainer
{
RelativeSizeAxes = Axes.X,
Height = DEFAULT_PLAYFIELD_HEIGHT,
Children = new[]
{
new Container new Container
{ {
Name = "Transparent playfield elements",
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = left_area_size }, Padding = new MarginPadding { Left = left_area_size },
Children = new Drawable[] Children = new Drawable[]
{ {
new Container new Container
{ {
Name = "Hit target container",
X = hit_target_offset, X = hit_target_offset,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Children = new Drawable[] Children = new Drawable[]
@ -93,8 +104,7 @@ namespace osu.Game.Modes.Taiko.UI
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(DEFAULT_PLAYFIELD_HEIGHT), RelativeSizeAxes = Axes.Y,
FillMode = FillMode.Fit,
BlendingMode = BlendingMode.Additive BlendingMode = BlendingMode.Additive
}, },
barLineContainer = new Container<DrawableBarLine> barLineContainer = new Container<DrawableBarLine>
@ -105,17 +115,14 @@ namespace osu.Game.Modes.Taiko.UI
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre, Origin = Anchor.Centre,
FillMode = FillMode.Fit
}, },
hitObjectContainer = new HitObjectContainer hitObjectContainer = new Container
{ {
Height = DEFAULT_PLAYFIELD_HEIGHT, RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit
}, },
judgementContainer = new Container<DrawableTaikoJudgement> judgementContainer = new Container<DrawableTaikoJudgement>
{ {
Size = new Vector2(DEFAULT_PLAYFIELD_HEIGHT), RelativeSizeAxes = Axes.Y,
FillMode = FillMode.Fit,
BlendingMode = BlendingMode.Additive BlendingMode = BlendingMode.Additive
}, },
}, },
@ -124,8 +131,8 @@ namespace osu.Game.Modes.Taiko.UI
}, },
leftBackgroundContainer = new Container leftBackgroundContainer = new Container
{ {
RelativeSizeAxes = Axes.Y, Name = "Left overlay",
Width = left_area_size, Size = new Vector2(left_area_size, DEFAULT_PLAYFIELD_HEIGHT),
BorderThickness = 1, BorderThickness = 1,
Children = new Drawable[] Children = new Drawable[]
{ {
@ -139,7 +146,6 @@ namespace osu.Game.Modes.Taiko.UI
Origin = Anchor.Centre, Origin = Anchor.Centre,
RelativePositionAxes = Axes.X, RelativePositionAxes = Axes.X,
Position = new Vector2(0.10f, 0), Position = new Vector2(0.10f, 0),
FillMode = FillMode.Fit,
Scale = new Vector2(0.9f) Scale = new Vector2(0.9f)
}, },
new Box new Box
@ -151,8 +157,11 @@ namespace osu.Game.Modes.Taiko.UI
}, },
} }
}, },
}
},
topLevelHitContainer = new Container topLevelHitContainer = new Container
{ {
Name = "Top level hit objects",
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
} }
}); });
@ -216,20 +225,53 @@ namespace osu.Game.Modes.Taiko.UI
} }
/// <summary> /// <summary>
/// Container for hit objects. Locks width to parent width even through scale. /// This is a very special type of container. It serves a similar purpose to <see cref="FillMode.Fit"/>, however unlike <see cref="FillMode.Fit"/>,
/// this will only adjust the scale relative to the height of its parent and will maintain the original width relative to its parent.
///
/// <para>
/// By adjusting the scale relative to the height of its parent, the aspect ratio of this container's children is maintained, however this is undesirable
/// in the case where the hit object container should not have its width adjusted by scale. To counteract this, another container is nested inside this
/// container which takes care of reversing the width adjustment while appearing transparent to the user.
/// </para>
/// </summary> /// </summary>
private class HitObjectContainer : Container private class ScaleFixContainer : Container
{ {
public HitObjectContainer() protected override Container<Drawable> Content => widthAdjustmentContainer;
private readonly WidthAdjustmentContainer widthAdjustmentContainer;
/// <summary>
/// We only want to apply DrawScale in the Y-axis to preserve aspect ratio and <see cref="TaikoPlayfield"/> doesn't care about having its width adjusted.
/// </summary>
protected override Vector2 DrawScale => Scale * RelativeToAbsoluteFactor.Y / DrawHeight;
public ScaleFixContainer()
{ {
RelativeSizeAxes = Axes.X; AddInternal(widthAdjustmentContainer = new WidthAdjustmentContainer { ParentDrawScaleReference = () => DrawScale.X });
}
/// <summary>
/// The container type that reverses the <see cref="Drawable.DrawScale"/> width adjustment.
/// </summary>
private class WidthAdjustmentContainer : Container
{
/// <summary>
/// This container needs to know its parent's <see cref="Drawable.DrawScale"/> so it can reverse the width adjustment caused by <see cref="Drawable.DrawScale"/>.
/// </summary>
public Func<float> ParentDrawScaleReference;
public WidthAdjustmentContainer()
{
// This container doesn't care about height, it should always fill its parent
RelativeSizeAxes = Axes.Y;
} }
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
Width = 1 / DrawScale.X; // Reverse the DrawScale adjustment
Width = Parent.DrawSize.X / ParentDrawScaleReference();
}
} }
} }
} }