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:
commit
805ef621e9
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user