1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 10:42:54 +08:00

Merge branch 'master' into play-storyboard-outro

This commit is contained in:
Dean Herbert 2021-05-05 17:51:16 +09:00 committed by GitHub
commit 805ef621e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 103 additions and 58 deletions

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Replays; using osu.Game.Replays;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
@ -278,6 +279,54 @@ namespace osu.Game.Tests.NonVisual
setTime(-100, -100); setTime(-100, -100);
} }
[Test]
public void TestReplayFramesSortStability()
{
const double repeating_time = 5000;
// add a collection of frames in shuffled order time-wise; each frame also stores its original index to check stability later.
// data is hand-picked and breaks if the unstable List<T>.Sort() is used.
// in theory this can still return a false-positive with another unstable algorithm if extremely unlucky,
// but there is no conceivable fool-proof way to prevent that anyways.
replay.Frames.AddRange(new[]
{
repeating_time,
0,
3000,
repeating_time,
repeating_time,
6000,
9000,
repeating_time,
repeating_time,
1000,
11000,
21000,
4000,
repeating_time,
repeating_time,
8000,
2000,
7000,
repeating_time,
repeating_time,
10000
}.Select((time, index) => new TestReplayFrame(time, true, index)));
replay.HasReceivedAllFrames = true;
// create a new handler with the replay for the sort to be performed.
handler = new TestInputHandler(replay);
// ensure sort stability by checking that the frames with time == repeating_time are sorted in ascending frame index order themselves.
var repeatingTimeFramesData = replay.Frames
.Cast<TestReplayFrame>()
.Where(f => f.Time == repeating_time)
.Select(f => f.FrameIndex);
Assert.That(repeatingTimeFramesData, Is.Ordered.Ascending);
}
private void setReplayFrames() private void setReplayFrames()
{ {
replay.Frames = new List<ReplayFrame> replay.Frames = new List<ReplayFrame>
@ -324,11 +373,13 @@ namespace osu.Game.Tests.NonVisual
private class TestReplayFrame : ReplayFrame private class TestReplayFrame : ReplayFrame
{ {
public readonly bool IsImportant; public readonly bool IsImportant;
public readonly int FrameIndex;
public TestReplayFrame(double time, bool isImportant = false) public TestReplayFrame(double time, bool isImportant = false, int frameIndex = 0)
: base(time) : base(time)
{ {
IsImportant = isImportant; IsImportant = isImportant;
FrameIndex = frameIndex;
} }
} }

View File

@ -132,8 +132,8 @@ namespace osu.Game.Tests.Visual.Editing
{ {
AddStep("deselect", () => EditorBeatmap.SelectedHitObjects.Clear()); AddStep("deselect", () => EditorBeatmap.SelectedHitObjects.Clear());
AddUntilStep("timeline selection box is not visible", () => Editor.ChildrenOfType<Timeline>().First().ChildrenOfType<EditorSelectionHandler>().First().Alpha == 0); AddUntilStep("timeline selection box is not visible", () => Editor.ChildrenOfType<Timeline>().First().ChildrenOfType<SelectionBox>().First().Alpha == 0);
AddUntilStep("composer selection box is not visible", () => Editor.ChildrenOfType<HitObjectComposer>().First().ChildrenOfType<EditorSelectionHandler>().First().Alpha == 0); AddUntilStep("composer selection box is not visible", () => Editor.ChildrenOfType<HitObjectComposer>().First().ChildrenOfType<SelectionBox>().First().Alpha == 0);
} }
AddStep("paste hitobject", () => Editor.Paste()); AddStep("paste hitobject", () => Editor.Paste());

View File

@ -28,7 +28,7 @@ namespace osu.Game.Graphics.Containers
protected override bool BlockNonPositionalInput => true; protected override bool BlockNonPositionalInput => true;
/// <summary> /// <summary>
/// Temporary to allow for overlays in the main screen content to not dim theirselves. /// Temporary to allow for overlays in the main screen content to not dim themselves.
/// Should be eventually replaced by dimming which is aware of the target dim container (traverse parent for certain interface type?). /// Should be eventually replaced by dimming which is aware of the target dim container (traverse parent for certain interface type?).
/// </summary> /// </summary>
protected virtual bool DimMainContent => true; protected virtual bool DimMainContent => true;

View File

@ -5,6 +5,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Replays; using osu.Game.Replays;
@ -97,7 +98,7 @@ namespace osu.Game.Rulesets.Replays
{ {
// TODO: This replay frame ordering should be enforced on the Replay type. // TODO: This replay frame ordering should be enforced on the Replay type.
// Currently, the ordering can be broken if the frames are added after this construction. // Currently, the ordering can be broken if the frames are added after this construction.
replay.Frames.Sort((x, y) => x.Time.CompareTo(y.Time)); replay.Frames = replay.Frames.OrderBy(f => f.Time).ToList();
this.replay = replay; this.replay = replay;
currentFrameIndex = -1; currentFrameIndex = -1;

View File

@ -34,13 +34,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
// For non-pooled rulesets, hitobjects are already present in the playfield which allows the blueprints to be loaded in the async context.
if (Composer != null)
{
foreach (var obj in Composer.HitObjects)
AddBlueprintFor(obj.HitObject);
}
selectedHitObjects.BindTo(Beatmap.SelectedHitObjects); selectedHitObjects.BindTo(Beatmap.SelectedHitObjects);
selectedHitObjects.CollectionChanged += (selectedObjects, args) => selectedHitObjects.CollectionChanged += (selectedObjects, args) =>
{ {
@ -69,7 +62,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
if (Composer != null) if (Composer != null)
{ {
// For pooled rulesets, blueprints must be added for hitobjects already "current" as they would've not been "current" during the async load addition process above.
foreach (var obj in Composer.HitObjects) foreach (var obj in Composer.HitObjects)
AddBlueprintFor(obj.HitObject); AddBlueprintFor(obj.HitObject);

View File

@ -9,6 +9,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osuTK; using osuTK;
using osuTK.Input; using osuTK.Input;
@ -16,6 +17,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
{ {
public class SelectionBox : CompositeDrawable public class SelectionBox : CompositeDrawable
{ {
public const float BORDER_RADIUS = 3;
public Func<float, bool> OnRotation; public Func<float, bool> OnRotation;
public Func<Vector2, Anchor, bool> OnScale; public Func<Vector2, Anchor, bool> OnScale;
public Func<Direction, bool> OnFlip; public Func<Direction, bool> OnFlip;
@ -92,21 +95,32 @@ namespace osu.Game.Screens.Edit.Compose.Components
} }
} }
private string text;
public string Text
{
get => text;
set
{
if (value == text)
return;
text = value;
if (selectionDetailsText != null)
selectionDetailsText.Text = value;
}
}
private Container dragHandles; private Container dragHandles;
private FillFlowContainer buttons; private FillFlowContainer buttons;
public const float BORDER_RADIUS = 3; private OsuSpriteText selectionDetailsText;
[Resolved] [Resolved]
private OsuColour colours { get; set; } private OsuColour colours { get; set; }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load() => recreate();
{
RelativeSizeAxes = Axes.Both;
recreate();
}
protected override bool OnKeyDown(KeyDownEvent e) protected override bool OnKeyDown(KeyDownEvent e)
{ {
@ -144,6 +158,26 @@ namespace osu.Game.Screens.Edit.Compose.Components
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new Container
{
Name = "info text",
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Box
{
Colour = colours.YellowDark,
RelativeSizeAxes = Axes.Both,
},
selectionDetailsText = new OsuSpriteText
{
Padding = new MarginPadding(2),
Colour = colours.Gray0,
Font = OsuFont.Default.With(size: 11),
Text = text,
}
}
},
new Container new Container
{ {
Masking = true, Masking = true,

View File

@ -10,13 +10,11 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osuTK; using osuTK;
@ -43,10 +41,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
private readonly List<SelectionBlueprint<T>> selectedBlueprints; private readonly List<SelectionBlueprint<T>> selectedBlueprints;
private Drawable content;
private OsuSpriteText selectionDetailsText;
protected SelectionBox SelectionBox { get; private set; } protected SelectionBox SelectionBox { get; private set; }
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
@ -58,39 +52,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
AlwaysPresent = true; AlwaysPresent = true;
Alpha = 0;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
InternalChild = content = new Container InternalChild = SelectionBox = CreateSelectionBox();
{
Children = new Drawable[]
{
// todo: should maybe be inside the SelectionBox?
new Container
{
Name = "info text",
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Box
{
Colour = colours.YellowDark,
RelativeSizeAxes = Axes.Both,
},
selectionDetailsText = new OsuSpriteText
{
Padding = new MarginPadding(2),
Colour = colours.Gray0,
Font = OsuFont.Default.With(size: 11)
}
}
},
SelectionBox = CreateSelectionBox(),
}
};
SelectedItems.CollectionChanged += (sender, args) => SelectedItems.CollectionChanged += (sender, args) =>
{ {
@ -306,9 +273,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
{ {
int count = SelectedItems.Count; int count = SelectedItems.Count;
selectionDetailsText.Text = count > 0 ? count.ToString() : string.Empty; SelectionBox.Text = count > 0 ? count.ToString() : string.Empty;
this.FadeTo(count > 0 ? 1 : 0); SelectionBox.FadeTo(count > 0 ? 1 : 0);
OnSelectionChanged(); OnSelectionChanged();
} }
@ -335,8 +302,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
selectionRect = selectionRect.Inflate(5f); selectionRect = selectionRect.Inflate(5f);
content.Position = selectionRect.Location; SelectionBox.Position = selectionRect.Location;
content.Size = selectionRect.Size; SelectionBox.Size = selectionRect.Size;
} }
#endregion #endregion