1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-31 05:32:57 +08:00

Merge branch 'master' into alt-eagerselect

This commit is contained in:
Endrik 2018-04-06 12:37:16 +03:00 committed by GitHub
commit c7440201fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 270 additions and 151 deletions

@ -1 +1 @@
Subproject commit 85b3494117ccef1b396b70957e1cffaba06e2b54 Subproject commit e4b0b57f5d3a80c09dcdfb6c8d30962e842b9fc3

View File

@ -0,0 +1,62 @@
// 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.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Screens.Play;
using osu.Game.Tests.Visual;
using OpenTK;
namespace osu.Game.Rulesets.Catch.Tests
{
public class TestCaseAutoJuiceStream : TestCasePlayer
{
public TestCaseAutoJuiceStream()
: base(new CatchRuleset())
{
}
protected override Beatmap CreateBeatmap(Ruleset ruleset)
{
var beatmap = new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 },
Ruleset = ruleset.RulesetInfo
}
};
for (int i = 0; i < 100; i++)
{
float width = (i % 10 + 1) / 20f;
beatmap.HitObjects.Add(new JuiceStream
{
X = 0.5f - width / 2,
ControlPoints = new List<Vector2>
{
Vector2.Zero,
new Vector2(width * CatchPlayfield.BASE_WIDTH, 0)
},
CurveType = CurveType.Linear,
Distance = width * CatchPlayfield.BASE_WIDTH,
StartTime = i * 2000,
NewCombo = i % 8 == 0
});
}
return beatmap;
}
protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset)
{
beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
return base.CreatePlayer(beatmap, ruleset);
}
}
}

View File

@ -108,6 +108,7 @@ namespace osu.Game.Rulesets.Catch.Replays
case BananaShower.Banana _: case BananaShower.Banana _:
case TinyDroplet _: case TinyDroplet _:
case Droplet _: case Droplet _:
case Fruit _:
moveToNext(nestedObj); moveToNext(nestedObj);
break; break;
} }

View File

@ -30,10 +30,10 @@ namespace osu.Game.Rulesets.Catch.UI
Anchor = Anchor.TopCentre; Anchor = Anchor.TopCentre;
Origin = Anchor.TopCentre; Origin = Anchor.TopCentre;
ScaledContent.Anchor = Anchor.BottomLeft; base.Content.Anchor = Anchor.BottomLeft;
ScaledContent.Origin = Anchor.BottomLeft; base.Content.Origin = Anchor.BottomLeft;
ScaledContent.AddRange(new Drawable[] base.Content.AddRange(new Drawable[]
{ {
explodingFruitContainer = new Container explodingFruitContainer = new Container
{ {

View File

@ -8,5 +8,6 @@ namespace osu.Game.Rulesets.Osu.Edit
public class OsuEditPlayfield : OsuPlayfield public class OsuEditPlayfield : OsuPlayfield
{ {
protected override bool ProxyApproachCircles => false; protected override bool ProxyApproachCircles => false;
protected override bool DisplayJudgements => false;
} }
} }

View File

@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModAutoplay : ModAutoplay<OsuHitObject> public class OsuModAutoplay : ModAutoplay<OsuHitObject>
{ {
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray();
protected override Score CreateReplayScore(Beatmap<OsuHitObject> beatmap) protected override Score CreateReplayScore(Beatmap<OsuHitObject> beatmap)
{ {

View File

@ -9,6 +9,6 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModNoFail : ModNoFail public class OsuModNoFail : ModNoFail
{ {
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
} }
} }

View File

@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModRelax : ModRelax public class OsuModRelax : ModRelax
{ {
public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things.";
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
} }
} }

View File

@ -9,6 +9,6 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModSuddenDeath : ModSuddenDeath public class OsuModSuddenDeath : ModSuddenDeath
{ {
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
} }
} }

View File

@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Replays
{ {
new ReplayState<OsuAction> new ReplayState<OsuAction>
{ {
Mouse = new ReplayMouseState(ToScreenSpace(Position ?? Vector2.Zero)), Mouse = new ReplayMouseState(GamefieldToScreenSpace(Position ?? Vector2.Zero)),
PressedActions = CurrentFrame.Actions PressedActions = CurrentFrame.Actions
} }
}; };

View File

@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Osu.UI
// Todo: This should not be a thing, but is currently required for the editor // Todo: This should not be a thing, but is currently required for the editor
// https://github.com/ppy/osu-framework/issues/1283 // https://github.com/ppy/osu-framework/issues/1283
protected virtual bool ProxyApproachCircles => true; protected virtual bool ProxyApproachCircles => true;
protected virtual bool DisplayJudgements => true;
public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); public static readonly Vector2 BASE_SIZE = new Vector2(512, 384);
@ -73,7 +74,7 @@ namespace osu.Game.Rulesets.Osu.UI
private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) private void onJudgement(DrawableHitObject judgedObject, Judgement judgement)
{ {
if (!judgedObject.DisplayJudgement) if (!judgedObject.DisplayJudgement || !DisplayJudgements)
return; return;
DrawableOsuJudgement explosion = new DrawableOsuJudgement(judgement, judgedObject) DrawableOsuJudgement explosion = new DrawableOsuJudgement(judgement, judgedObject)

View File

@ -2,7 +2,9 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
@ -10,10 +12,12 @@ namespace osu.Game.Tests.Visual
[TestFixture] [TestFixture]
public class TestCaseBreadcrumbs : OsuTestCase public class TestCaseBreadcrumbs : OsuTestCase
{ {
private readonly BreadcrumbControl<BreadcrumbTab> breadcrumbs;
public TestCaseBreadcrumbs() public TestCaseBreadcrumbs()
{ {
BreadcrumbControl<BreadcrumbTab> c;
Add(c = new BreadcrumbControl<BreadcrumbTab> Add(breadcrumbs = new BreadcrumbControl<BreadcrumbTab>
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
@ -21,9 +25,15 @@ namespace osu.Game.Tests.Visual
Width = 0.5f, Width = 0.5f,
}); });
AddStep(@"first", () => c.Current.Value = BreadcrumbTab.Click); AddStep(@"first", () => breadcrumbs.Current.Value = BreadcrumbTab.Click);
AddStep(@"second", () => c.Current.Value = BreadcrumbTab.The); AddStep(@"second", () => breadcrumbs.Current.Value = BreadcrumbTab.The);
AddStep(@"third", () => c.Current.Value = BreadcrumbTab.Circles); AddStep(@"third", () => breadcrumbs.Current.Value = BreadcrumbTab.Circles);
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
breadcrumbs.StripColour = colours.Blue;
} }
private enum BreadcrumbTab private enum BreadcrumbTab

View File

@ -122,7 +122,7 @@ namespace osu.Game.Tests.Visual
Direction = direction; Direction = direction;
Padding = new MarginPadding(2); Padding = new MarginPadding(2);
ScaledContent.Masking = true; Content.Masking = true;
AddInternal(new Box AddInternal(new Box
{ {

View File

@ -16,7 +16,7 @@ namespace osu.Game.Beatmaps.Formats
public TOutput Decode(StreamReader primaryStream, params StreamReader[] otherStreams) public TOutput Decode(StreamReader primaryStream, params StreamReader[] otherStreams)
{ {
var output = CreateTemplateObject(); var output = CreateTemplateObject();
foreach (StreamReader stream in new[] { primaryStream }.Concat(otherStreams)) foreach (StreamReader stream in otherStreams.Prepend(primaryStream))
ParseStreamInto(stream, output); ParseStreamInto(stream, output);
return output; return output;
} }

View File

@ -81,13 +81,13 @@ namespace osu.Game.Beatmaps.Formats
handleDifficulty(line); handleDifficulty(line);
return; return;
case Section.Events: case Section.Events:
handleEvents(line); handleEvent(line);
return; return;
case Section.TimingPoints: case Section.TimingPoints:
handleTimingPoints(line); handleTimingPoint(line);
return; return;
case Section.HitObjects: case Section.HitObjects:
handleHitObjects(line); handleHitObject(line);
return; return;
} }
@ -246,7 +246,7 @@ namespace osu.Game.Beatmaps.Formats
} }
} }
private void handleEvents(string line) private void handleEvent(string line)
{ {
string[] split = line.Split(','); string[] split = line.Split(',');
@ -275,7 +275,9 @@ namespace osu.Game.Beatmaps.Formats
} }
} }
private void handleTimingPoints(string line) private void handleTimingPoint(string line)
{
try
{ {
string[] split = line.Split(','); string[] split = line.Split(',');
@ -360,8 +362,12 @@ namespace osu.Game.Beatmaps.Formats
}); });
} }
} }
catch (FormatException e)
{
}
}
private void handleHitObjects(string line) private void handleHitObject(string line)
{ {
// If the ruleset wasn't specified, assume the osu!standard ruleset. // If the ruleset wasn't specified, assume the osu!standard ruleset.
if (parser == null) if (parser == null)

View File

@ -17,6 +17,8 @@ namespace osu.Game.Graphics.UserInterface
protected override TabItem<T> CreateTabItem(T value) => new BreadcrumbTabItem(value); protected override TabItem<T> CreateTabItem(T value) => new BreadcrumbTabItem(value);
protected override float StripWidth() => base.StripWidth() - (padding + 8);
public BreadcrumbControl() public BreadcrumbControl()
{ {
Height = 26; Height = 26;

View File

@ -14,22 +14,36 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.MathUtils;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
public class OsuTabControl<T> : TabControl<T> public class OsuTabControl<T> : TabControl<T>
{ {
private readonly Box strip;
protected override Dropdown<T> CreateDropdown() => new OsuTabDropdown(); protected override Dropdown<T> CreateDropdown() => new OsuTabDropdown();
protected override TabItem<T> CreateTabItem(T value) => new OsuTabItem(value); protected override TabItem<T> CreateTabItem(T value) => new OsuTabItem(value);
protected virtual float StripWidth() => TabContainer.Children.Sum(c => c.IsPresent ? c.DrawWidth + TabContainer.Spacing.X : 0) - TabContainer.Spacing.X;
protected virtual float StripHeight() => 1;
private static bool isEnumType => typeof(T).IsEnum; private static bool isEnumType => typeof(T).IsEnum;
public OsuTabControl() public OsuTabControl()
{ {
TabContainer.Spacing = new Vector2(10f, 0f); TabContainer.Spacing = new Vector2(10f, 0f);
Add(strip = new Box
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Height = StripHeight(),
Colour = Color4.White.Opacity(0),
});
if (isEnumType) if (isEnumType)
foreach (var val in (T[])Enum.GetValues(typeof(T))) foreach (var val in (T[])Enum.GetValues(typeof(T)))
AddItem(val); AddItem(val);
@ -57,6 +71,12 @@ namespace osu.Game.Graphics.UserInterface
} }
} }
public Color4 StripColour
{
get => strip.Colour;
set => strip.Colour = value;
}
protected override TabFillFlowContainer CreateTabFlow() => new OsuTabFillFlowContainer protected override TabFillFlowContainer CreateTabFlow() => new OsuTabFillFlowContainer
{ {
Direction = FillDirection.Full, Direction = FillDirection.Full,
@ -65,6 +85,15 @@ namespace osu.Game.Graphics.UserInterface
Masking = true Masking = true
}; };
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
// dont bother calculating if the strip is invisible
if (strip.Colour.MaxAlpha > 0)
strip.Width = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint);
}
public class OsuTabItem : TabItem<T>, IHasAccentColour public class OsuTabItem : TabItem<T>, IHasAccentColour
{ {
protected readonly SpriteText Text; protected readonly SpriteText Text;

View File

@ -45,7 +45,7 @@ namespace osu.Game.Input.Bindings
}; };
protected override IEnumerable<Drawable> KeyBindingInputQueue => protected override IEnumerable<Drawable> KeyBindingInputQueue =>
handler == null ? base.KeyBindingInputQueue : new[] { handler }.Concat(base.KeyBindingInputQueue); handler == null ? base.KeyBindingInputQueue : base.KeyBindingInputQueue.Prepend(handler);
} }
public enum GlobalAction public enum GlobalAction

View File

@ -13,9 +13,9 @@ namespace osu.Game.Input.Handlers
public abstract class ReplayInputHandler : InputHandler public abstract class ReplayInputHandler : InputHandler
{ {
/// <summary> /// <summary>
/// A function provided to convert replay coordinates from gamefield to screen space. /// A function that converts coordinates from gamefield to screen space.
/// </summary> /// </summary>
public Func<Vector2, Vector2> ToScreenSpace { protected get; set; } public Func<Vector2, Vector2> GamefieldToScreenSpace { protected get; set; }
/// <summary> /// <summary>
/// Update the current frame based on an incoming time value. /// Update the current frame based on an incoming time value.

View File

@ -13,7 +13,6 @@ namespace osu.Game.Overlays.Direct
public class Header : SearchableListHeader<DirectTab> public class Header : SearchableListHeader<DirectTab>
{ {
protected override Color4 BackgroundColour => OsuColour.FromHex(@"252f3a"); protected override Color4 BackgroundColour => OsuColour.FromHex(@"252f3a");
protected override float TabStripWidth => 298;
protected override DirectTab DefaultTab => DirectTab.Search; protected override DirectTab DefaultTab => DirectTab.Search;
protected override Drawable CreateHeaderText() => new OsuSpriteText { Text = @"osu!direct", TextSize = 25 }; protected override Drawable CreateHeaderText() => new OsuSpriteText { Text = @"osu!direct", TextSize = 25 };

View File

@ -47,7 +47,7 @@ namespace osu.Game.Overlays.KeyBinding
private FillFlowContainer<KeyButton> buttons; private FillFlowContainer<KeyButton> buttons;
public IEnumerable<string> FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())); public IEnumerable<string> FilterTerms => bindings.Select(b => b.KeyCombination.ReadableString()).Prepend(text.Text);
public KeyBindingRow(object action, IEnumerable<Framework.Input.Bindings.KeyBinding> bindings) public KeyBindingRow(object action, IEnumerable<Framework.Input.Bindings.KeyBinding> bindings)
{ {

View File

@ -14,12 +14,9 @@ namespace osu.Game.Overlays.SearchableList
{ {
public abstract class SearchableListHeader<T> : Container public abstract class SearchableListHeader<T> : Container
{ {
private readonly Box tabStrip;
public readonly HeaderTabControl<T> Tabs; public readonly HeaderTabControl<T> Tabs;
protected abstract Color4 BackgroundColour { get; } protected abstract Color4 BackgroundColour { get; }
protected abstract float TabStripWidth { get; } //can be removed once (if?) TabControl support auto sizing
protected abstract T DefaultTab { get; } protected abstract T DefaultTab { get; }
protected abstract Drawable CreateHeaderText(); protected abstract Drawable CreateHeaderText();
protected abstract FontAwesome Icon { get; } protected abstract FontAwesome Icon { get; }
@ -63,13 +60,6 @@ namespace osu.Game.Overlays.SearchableList
CreateHeaderText(), CreateHeaderText(),
}, },
}, },
tabStrip = new Box
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Width = TabStripWidth,
Height = 1,
},
Tabs = new HeaderTabControl<T> Tabs = new HeaderTabControl<T>
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
@ -87,7 +77,7 @@ namespace osu.Game.Overlays.SearchableList
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
tabStrip.Colour = colours.Green; Tabs.StripColour = colours.Green;
} }
} }
} }

View File

@ -17,7 +17,6 @@ namespace osu.Game.Overlays.Social
private OsuSpriteText browser; private OsuSpriteText browser;
protected override Color4 BackgroundColour => OsuColour.FromHex(@"38202e"); protected override Color4 BackgroundColour => OsuColour.FromHex(@"38202e");
protected override float TabStripWidth => 438;
protected override SocialTab DefaultTab => SocialTab.AllPlayers; protected override SocialTab DefaultTab => SocialTab.AllPlayers;
protected override FontAwesome Icon => FontAwesome.fa_users; protected override FontAwesome Icon => FontAwesome.fa_users;

View File

@ -128,10 +128,8 @@ namespace osu.Game.Rulesets.Edit
selectionLayer.SelectionFinished += hitObjectMaskLayer.AddSelectionOverlay; selectionLayer.SelectionFinished += hitObjectMaskLayer.AddSelectionOverlay;
toolboxCollection.Items = toolboxCollection.Items =
new[] { new RadioButton("Select", () => setCompositionTool(null)) }
.Concat(
CompositionTools.Select(t => new RadioButton(t.Name, () => setCompositionTool(t))) CompositionTools.Select(t => new RadioButton(t.Name, () => setCompositionTool(t)))
) .Prepend(new RadioButton("Select", () => setCompositionTool(null)))
.ToList(); .ToList();
toolboxCollection.Items[0].Select(); toolboxCollection.Items[0].Select();

View File

@ -23,6 +23,8 @@ namespace osu.Game.Rulesets.Judgements
{ {
private const float judgement_size = 80; private const float judgement_size = 80;
private OsuColour colours;
protected readonly Judgement Judgement; protected readonly Judgement Judgement;
public readonly DrawableHitObject JudgedObject; public readonly DrawableHitObject JudgedObject;
@ -45,11 +47,13 @@ namespace osu.Game.Rulesets.Judgements
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
this.colours = colours;
Child = new SkinnableDrawable($"Play/{Judgement.Result}", _ => JudgementText = new OsuSpriteText Child = new SkinnableDrawable($"Play/{Judgement.Result}", _ => JudgementText = new OsuSpriteText
{ {
Text = Judgement.Result.GetDescription().ToUpper(), Text = Judgement.Result.GetDescription().ToUpper(),
Font = @"Venera", Font = @"Venera",
Colour = Judgement.Result == HitResult.Miss ? colours.Red : Color4.White, Colour = judgementColour(Judgement.Result),
Scale = new Vector2(0.85f, 1), Scale = new Vector2(0.85f, 1),
TextSize = 12 TextSize = 12
}, restrictSize: false); }, restrictSize: false);
@ -84,5 +88,24 @@ namespace osu.Game.Rulesets.Judgements
Expire(true); Expire(true);
} }
private Color4 judgementColour(HitResult judgement)
{
switch (judgement)
{
case HitResult.Perfect:
case HitResult.Great:
return colours.Blue;
case HitResult.Ok:
case HitResult.Good:
return colours.Green;
case HitResult.Meh:
return colours.Yellow;
case HitResult.Miss:
return colours.Red;
}
return Color4.White;
}
} }
} }

View File

@ -290,7 +290,7 @@ namespace osu.Game.Rulesets.UI
base.SetReplay(replay); base.SetReplay(replay);
if (ReplayInputManager?.ReplayInputHandler != null) if (ReplayInputManager?.ReplayInputHandler != null)
ReplayInputManager.ReplayInputHandler.ToScreenSpace = input => Playfield.ScaledContent.ToScreenSpace(input); ReplayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace;
} }
/// <summary> /// <summary>

View File

@ -1,6 +1,7 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using OpenTK; using OpenTK;
@ -12,13 +13,16 @@ namespace osu.Game.Rulesets.UI
/// </summary> /// </summary>
public class ScalableContainer : Container public class ScalableContainer : Container
{ {
/// <summary>
/// A function that converts coordinates from gamefield to screen space.
/// </summary>
public Func<Vector2, Vector2> GamefieldToScreenSpace => scaledContent.GamefieldToScreenSpace;
/// <summary> /// <summary>
/// The scaled content. /// The scaled content.
/// </summary> /// </summary>
public readonly Container ScaledContent; private readonly ScaledContainer scaledContent;
protected override Container<Drawable> Content => scaledContent;
protected override Container<Drawable> Content => content;
private readonly Container content;
/// <summary> /// <summary>
/// A <see cref="Container"/> which can have its internal coordinate system scaled to a specific size. /// A <see cref="Container"/> which can have its internal coordinate system scaled to a specific size.
@ -31,17 +35,21 @@ namespace osu.Game.Rulesets.UI
/// </param> /// </param>
public ScalableContainer(float? customWidth = null, float? customHeight = null) public ScalableContainer(float? customWidth = null, float? customHeight = null)
{ {
AddInternal(ScaledContent = new ScaledContainer AddInternal(scaledContent = new ScaledContainer
{ {
CustomWidth = customWidth, CustomWidth = customWidth,
CustomHeight = customHeight, CustomHeight = customHeight,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Child = content = new Container { RelativeSizeAxes = Axes.Both }
}); });
} }
private class ScaledContainer : Container private class ScaledContainer : Container
{ {
/// <summary>
/// A function that converts coordinates from gamefield to screen space.
/// </summary>
public Func<Vector2, Vector2> GamefieldToScreenSpace => content.ToScreenSpace;
/// <summary> /// <summary>
/// The value to scale the width of the content to match. /// The value to scale the width of the content to match.
/// If null, <see cref="CustomHeight"/> is used. /// If null, <see cref="CustomHeight"/> is used.
@ -54,6 +62,22 @@ namespace osu.Game.Rulesets.UI
/// </summary> /// </summary>
public float? CustomHeight; 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> /// <summary>
/// The scale that is required for the size of the content to match <see cref="CustomWidth"/> and <see cref="CustomHeight"/>. /// The scale that is required for the size of the content to match <see cref="CustomWidth"/> and <see cref="CustomHeight"/>.
/// </summary> /// </summary>
@ -70,17 +94,6 @@ namespace osu.Game.Rulesets.UI
return Vector2.One; return Vector2.One;
} }
} }
/// <summary>
/// Scale the content to the required container size by multiplying by <see cref="sizeScale"/>.
/// </summary>
protected override Vector2 DrawScale => sizeScale * base.DrawScale;
protected override void Update()
{
base.Update();
RelativeChildSize = new Vector2(CustomWidth.HasValue ? sizeScale.X : RelativeChildSize.X, CustomHeight.HasValue ? sizeScale.Y : RelativeChildSize.Y);
}
} }
} }
} }

View File

@ -150,7 +150,7 @@ namespace osu.Game.Screens.Select
var mods = modSelect.SelectedMods.Value; var mods = modSelect.SelectedMods.Value;
if (mods.All(m => m.GetType() != autoType)) if (mods.All(m => m.GetType() != autoType))
{ {
modSelect.SelectedMods.Value = mods.Concat(new[] { auto }); modSelect.SelectedMods.Value = mods.Append(auto);
removeAutoModOnResume = true; removeAutoModOnResume = true;
} }
} }

View File

@ -1,15 +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 NUnit.Framework;
using osu.Framework.Testing;
namespace osu.Game.Tests
{
[TestFixture]
internal class TestTestCase : TestCase
{
// This TestCase is required for nunit to not throw errors
// See: https://github.com/nunit/nunit/issues/1118
}
}