Add grouping of visual tests

This commit is contained in:
Dean Herbert
2019-03-25 01:02:36 +09:00
parent 8c8c761e02
commit a1c5eda05b
101 changed files with 162 additions and 163 deletions

View File

@ -0,0 +1,29 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
namespace osu.Game.Tests.Visual.Editor
{
public class TestCaseBeatDivisorControl : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(BindableBeatDivisor) };
[BackgroundDependencyLoader]
private void load()
{
Child = new BeatDivisorControl(new BindableBeatDivisor())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(90, 90)
};
}
}
}

View File

@ -0,0 +1,26 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Edit.Compose;
using osu.Game.Tests.Beatmaps;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestCaseEditorCompose : EditorClockTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(ComposeScreen) };
[BackgroundDependencyLoader]
private void load()
{
Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, Clock);
Child = new ComposeScreen();
}
}
}

View File

@ -0,0 +1,43 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Screens.Edit.Components.RadioButtons;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestCaseEditorComposeRadioButtons : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(DrawableRadioButton) };
public TestCaseEditorComposeRadioButtons()
{
RadioButtonCollection collection;
Add(collection = new RadioButtonCollection
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 150,
Items = new[]
{
new RadioButton("Item 1", () => { }),
new RadioButton("Item 2", () => { }),
new RadioButton("Item 3", () => { }),
new RadioButton("Item 4", () => { }),
new RadioButton("Item 5", () => { })
}
});
for (int i = 0; i < collection.Items.Count; i++)
{
int l = i;
AddStep($"Select item {l + 1}", () => collection.Items[l].Select());
AddStep($"Deselect item {l + 1}", () => collection.Items[l].Deselect());
}
}
}
}

View File

@ -0,0 +1,140 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestCaseEditorComposeTimeline : EditorClockTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(TimelineArea),
typeof(Timeline),
typeof(TimelineButton),
typeof(CentreMarker)
};
[BackgroundDependencyLoader]
private void load()
{
Beatmap.Value = new WaveformTestBeatmap();
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5),
Children = new Drawable[]
{
new StartStopButton(),
new AudioVisualiser(),
}
},
new TimelineArea
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Size = new Vector2(0.8f, 100)
}
};
}
private class AudioVisualiser : CompositeDrawable
{
private readonly Drawable marker;
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
private IAdjustableClock adjustableClock;
public AudioVisualiser()
{
Size = new Vector2(250, 25);
InternalChildren = new[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0.25f,
},
marker = new Box
{
RelativePositionAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
Width = 2,
}
};
}
[BackgroundDependencyLoader]
private void load(IAdjustableClock adjustableClock, IBindable<WorkingBeatmap> beatmap)
{
this.adjustableClock = adjustableClock;
this.beatmap.BindTo(beatmap);
}
protected override void Update()
{
base.Update();
if (beatmap.Value.Track.IsLoaded)
marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length);
}
}
private class StartStopButton : Button
{
private IAdjustableClock adjustableClock;
private bool started;
public StartStopButton()
{
BackgroundColour = Color4.SlateGray;
Size = new Vector2(100, 50);
Text = "Start";
Action = onClick;
}
[BackgroundDependencyLoader]
private void load(IAdjustableClock adjustableClock)
{
this.adjustableClock = adjustableClock;
}
private void onClick()
{
if (started)
{
adjustableClock.Stop();
Text = "Start";
}
else
{
adjustableClock.Start();
Text = "Stop";
}
started = !started;
}
}
}
}

View File

@ -0,0 +1,98 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Edit.Components.Menus;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestCaseEditorMenuBar : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(EditorMenuBar), typeof(ScreenSelectionTabControl) };
public TestCaseEditorMenuBar()
{
Add(new Container
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
Height = 50,
Y = 50,
Child = new EditorMenuBar
{
RelativeSizeAxes = Axes.Both,
Items = new[]
{
new MenuItem("File")
{
Items = new[]
{
new EditorMenuItem("Clear All Notes"),
new EditorMenuItem("Open Difficulty..."),
new EditorMenuItem("Save"),
new EditorMenuItem("Create a new Difficulty..."),
new EditorMenuItemSpacer(),
new EditorMenuItem("Revert to Saved"),
new EditorMenuItem("Revert to Saved (Full)"),
new EditorMenuItemSpacer(),
new EditorMenuItem("Test Beatmap"),
new EditorMenuItem("Open AiMod"),
new EditorMenuItemSpacer(),
new EditorMenuItem("Upload Beatmap..."),
new EditorMenuItem("Export Package"),
new EditorMenuItem("Export Map Package"),
new EditorMenuItem("Import from..."),
new EditorMenuItemSpacer(),
new EditorMenuItem("Open Song Folder"),
new EditorMenuItem("Open .osu in Notepad"),
new EditorMenuItem("Open .osb in Notepad"),
new EditorMenuItemSpacer(),
new EditorMenuItem("Exit"),
}
},
new MenuItem("Timing")
{
Items = new[]
{
new EditorMenuItem("Time Signature"),
new EditorMenuItem("Metronome Clicks"),
new EditorMenuItemSpacer(),
new EditorMenuItem("Add Timing Section"),
new EditorMenuItem("Add Inheriting Section"),
new EditorMenuItem("Reset Current Section"),
new EditorMenuItem("Delete Timing Section"),
new EditorMenuItem("Resnap Current Section"),
new EditorMenuItemSpacer(),
new EditorMenuItem("Timing Setup"),
new EditorMenuItemSpacer(),
new EditorMenuItem("Resnap All Notes", MenuItemType.Destructive),
new EditorMenuItem("Move all notes in time...", MenuItemType.Destructive),
new EditorMenuItem("Recalculate Slider Lengths", MenuItemType.Destructive),
new EditorMenuItem("Delete All Timing Sections", MenuItemType.Destructive),
new EditorMenuItemSpacer(),
new EditorMenuItem("Set Current Position as Preview Point"),
}
},
new MenuItem("Testing")
{
Items = new[]
{
new EditorMenuItem("Item 1"),
new EditorMenuItem("Item 2"),
new EditorMenuItem("Item 3"),
}
},
}
}
});
}
}
}

View File

@ -0,0 +1,419 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Tests.Beatmaps;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestCaseEditorSeekSnapping : EditorClockTestCase
{
public TestCaseEditorSeekSnapping()
{
BeatDivisor.Value = 4;
}
[BackgroundDependencyLoader]
private void load()
{
var testBeatmap = new Beatmap
{
ControlPointInfo = new ControlPointInfo
{
TimingPoints =
{
new TimingControlPoint { Time = 0, BeatLength = 200 },
new TimingControlPoint { Time = 100, BeatLength = 400 },
new TimingControlPoint { Time = 175, BeatLength = 800 },
new TimingControlPoint { Time = 350, BeatLength = 200 },
new TimingControlPoint { Time = 450, BeatLength = 100 },
new TimingControlPoint { Time = 500, BeatLength = 307.69230769230802 }
}
},
HitObjects =
{
new HitCircle { StartTime = 0 },
new HitCircle { StartTime = 5000 }
}
};
Beatmap.Value = new TestWorkingBeatmap(testBeatmap, Clock);
Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock };
}
/// <summary>
/// Tests whether time is correctly seeked without snapping.
/// </summary>
[Test]
public void TestSeekNoSnapping()
{
reset();
// Forwards
AddStep("Seek(0)", () => Clock.Seek(0));
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
AddStep("Seek(33)", () => Clock.Seek(33));
AddAssert("Time = 33", () => Clock.CurrentTime == 33);
AddStep("Seek(89)", () => Clock.Seek(89));
AddAssert("Time = 89", () => Clock.CurrentTime == 89);
// Backwards
AddStep("Seek(25)", () => Clock.Seek(25));
AddAssert("Time = 25", () => Clock.CurrentTime == 25);
AddStep("Seek(0)", () => Clock.Seek(0));
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
}
/// <summary>
/// Tests whether seeking to exact beat times puts us on the beat time.
/// These are the white/yellow ticks on the graph.
/// </summary>
[Test]
public void TestSeekSnappingOnBeat()
{
reset();
AddStep("Seek(0), Snap", () => Clock.SeekSnapped(0));
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
AddStep("Seek(50), Snap", () => Clock.SeekSnapped(50));
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
AddStep("Seek(100), Snap", () => Clock.SeekSnapped(100));
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
AddStep("Seek(175), Snap", () => Clock.SeekSnapped(175));
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
AddStep("Seek(350), Snap", () => Clock.SeekSnapped(350));
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
AddStep("Seek(400), Snap", () => Clock.SeekSnapped(400));
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
AddStep("Seek(450), Snap", () => Clock.SeekSnapped(450));
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
}
/// <summary>
/// Tests whether seeking to somewhere in the middle between beats puts us on the expected beats.
/// For example, snapping between a white/yellow beat should put us on either the yellow or white, depending on which one we're closer too.
/// </summary>
[Test]
public void TestSeekSnappingInBetweenBeat()
{
reset();
AddStep("Seek(24), Snap", () => Clock.SeekSnapped(24));
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
AddStep("Seek(26), Snap", () => Clock.SeekSnapped(26));
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
AddStep("Seek(150), Snap", () => Clock.SeekSnapped(150));
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
AddStep("Seek(170), Snap", () => Clock.SeekSnapped(170));
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
AddStep("Seek(274), Snap", () => Clock.SeekSnapped(274));
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
AddStep("Seek(276), Snap", () => Clock.SeekSnapped(276));
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
}
/// <summary>
/// Tests that when seeking forward with no beat snapping, beats are never explicitly snapped to, nor the next timing point (if we've skipped it).
/// </summary>
[Test]
public void TestSeekForwardNoSnapping()
{
reset();
AddStep("SeekForward", () => Clock.SeekForward());
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
AddStep("SeekForward", () => Clock.SeekForward());
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
AddStep("SeekForward", () => Clock.SeekForward());
AddAssert("Time = 200", () => Clock.CurrentTime == 200);
AddStep("SeekForward", () => Clock.SeekForward());
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
AddStep("SeekForward", () => Clock.SeekForward());
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
}
/// <summary>
/// Tests that when seeking forward with beat snapping, all beats are snapped to and timing points are never skipped.
/// </summary>
[Test]
public void TestSeekForwardSnappingOnBeat()
{
reset();
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
}
/// <summary>
/// Tests that when seeking forward from in-between two beats, the next beat or timing point is snapped to, and no beats are skipped.
/// This will also test being extremely close to the next beat/timing point, to ensure rounding is not an issue.
/// </summary>
[Test]
public void TestSeekForwardSnappingFromInBetweenBeat()
{
reset();
AddStep("Seek(49)", () => Clock.Seek(49));
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
AddStep("Seek(49.999)", () => Clock.Seek(49.999));
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
AddStep("Seek(99)", () => Clock.Seek(99));
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
AddStep("Seek(99.999)", () => Clock.Seek(99.999));
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
AddStep("Seek(174)", () => Clock.Seek(174));
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
AddStep("Seek(349)", () => Clock.Seek(349));
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
AddStep("Seek(399)", () => Clock.Seek(399));
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
AddStep("Seek(449)", () => Clock.Seek(449));
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
}
/// <summary>
/// Tests that when seeking backward with no beat snapping, beats are never explicitly snapped to, nor the next timing point (if we've skipped it).
/// </summary>
[Test]
public void TestSeekBackwardNoSnapping()
{
reset();
AddStep("Seek(450)", () => Clock.Seek(450));
AddStep("SeekBackward", () => Clock.SeekBackward());
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
AddStep("SeekBackward", () => Clock.SeekBackward());
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
AddStep("SeekBackward", () => Clock.SeekBackward());
AddAssert("Time = 150", () => Clock.CurrentTime == 150);
AddStep("SeekBackward", () => Clock.SeekBackward());
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
AddStep("SeekBackward", () => Clock.SeekBackward());
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
}
/// <summary>
/// Tests that when seeking backward with beat snapping, all beats are snapped to and timing points are never skipped.
/// </summary>
[Test]
public void TestSeekBackwardSnappingOnBeat()
{
reset();
AddStep("Seek(450)", () => Clock.Seek(450));
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
}
/// <summary>
/// Tests that when seeking backward from in-between two beats, the previous beat or timing point is snapped to, and no beats are skipped.
/// This will also test being extremely close to the previous beat/timing point, to ensure rounding is not an issue.
/// </summary>
[Test]
public void TestSeekBackwardSnappingFromInBetweenBeat()
{
reset();
AddStep("Seek(451)", () => Clock.Seek(451));
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
AddStep("Seek(450.999)", () => Clock.Seek(450.999));
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
AddStep("Seek(401)", () => Clock.Seek(401));
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
AddStep("Seek(401.999)", () => Clock.Seek(401.999));
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
}
/// <summary>
/// Tests that there are no rounding issues when snapping to beats within a timing point with a floating-point beatlength.
/// </summary>
[Test]
public void TestSeekingWithFloatingPointBeatLength()
{
reset();
double lastTime = 0;
AddStep("Seek(0)", () => Clock.Seek(0));
for (int i = 0; i < 9; i++)
{
AddStep("SeekForward, Snap", () =>
{
lastTime = Clock.CurrentTime;
Clock.SeekForward(true);
});
AddAssert("Time > lastTime", () => Clock.CurrentTime > lastTime);
}
for (int i = 0; i < 9; i++)
{
AddStep("SeekBackward, Snap", () =>
{
lastTime = Clock.CurrentTime;
Clock.SeekBackward(true);
});
AddAssert("Time < lastTime", () => Clock.CurrentTime < lastTime);
}
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
}
private void reset()
{
AddStep("Reset", () => Clock.Seek(0));
}
private class TimingPointVisualiser : CompositeDrawable
{
private readonly double length;
private readonly Drawable tracker;
public TimingPointVisualiser(IBeatmap beatmap, double length)
{
this.length = length;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Width = 0.75f;
FillFlowContainer timelineContainer;
InternalChildren = new Drawable[]
{
new Box
{
Name = "Background",
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black.Opacity(85f)
},
new Container
{
Name = "Tracks",
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding(15),
Children = new[]
{
tracker = new Box
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
RelativePositionAxes = Axes.X,
Width = 2,
Colour = Color4.Red,
},
timelineContainer = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0, 5)
},
}
}
};
var timingPoints = beatmap.ControlPointInfo.TimingPoints;
for (int i = 0; i < timingPoints.Count; i++)
{
TimingControlPoint next = i == timingPoints.Count - 1 ? null : timingPoints[i + 1];
timelineContainer.Add(new TimingPointTimeline(timingPoints[i], next?.Time ?? length, length));
}
}
protected override void Update()
{
base.Update();
tracker.X = (float)(Time.Current / length);
}
private class TimingPointTimeline : CompositeDrawable
{
public TimingPointTimeline(TimingControlPoint timingPoint, double endTime, double fullDuration)
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Box createMainTick(double time) => new Box
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomCentre,
RelativePositionAxes = Axes.X,
X = (float)(time / fullDuration),
Height = 10,
Width = 2
};
Box createBeatTick(double time) => new Box
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomCentre,
RelativePositionAxes = Axes.X,
X = (float)(time / fullDuration),
Height = 5,
Width = 2,
Colour = time > endTime ? Color4.Gray : Color4.Yellow
};
AddInternal(createMainTick(timingPoint.Time));
AddInternal(createMainTick(endTime));
for (double t = timingPoint.Time + timingPoint.BeatLength / 4; t < fullDuration; t += timingPoint.BeatLength / 4)
AddInternal(createBeatTick(t));
}
}
}
}
}

View File

@ -0,0 +1,34 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Edit.Components.Timelines.Summary;
using osu.Game.Tests.Beatmaps;
using osuTK;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestCaseEditorSummaryTimeline : EditorClockTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(SummaryTimeline) };
[BackgroundDependencyLoader]
private void load()
{
Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, null);
Add(new SummaryTimeline
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(500, 50)
});
}
}
}

View File

@ -0,0 +1,82 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Edit;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit.Compose;
using osu.Game.Screens.Edit.Compose.Components;
using osu.Game.Tests.Beatmaps;
using osuTK;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
[Cached(Type = typeof(IPlacementHandler))]
public class TestCaseHitObjectComposer : OsuTestCase, IPlacementHandler
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(SelectionHandler),
typeof(DragBox),
typeof(HitObjectComposer),
typeof(OsuHitObjectComposer),
typeof(BlueprintContainer),
typeof(NotNullAttribute),
typeof(HitCirclePiece),
typeof(HitCircleSelectionBlueprint),
typeof(HitCirclePlacementBlueprint),
};
private HitObjectComposer composer;
[BackgroundDependencyLoader]
private void load()
{
Beatmap.Value = new TestWorkingBeatmap(new Beatmap
{
HitObjects = new List<HitObject>
{
new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f },
new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f },
new Slider
{
Position = new Vector2(128, 256),
Path = new SliderPath(PathType.Linear, new[]
{
Vector2.Zero,
new Vector2(216, 0),
}),
Scale = 0.5f,
}
},
});
var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
Dependencies.CacheAs<IAdjustableClock>(clock);
Dependencies.CacheAs<IFrameBasedClock>(clock);
Child = composer = new OsuHitObjectComposer(new OsuRuleset());
}
public void BeginPlacement(HitObject hitObject)
{
}
public void EndPlacement(HitObject hitObject) => composer.Add(hitObject);
public void Delete(HitObject hitObject) => composer.Remove(hitObject);
}
}

View File

@ -0,0 +1,37 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Screens.Edit.Components;
using osu.Game.Tests.Beatmaps;
using osuTK;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestCasePlaybackControl : OsuTestCase
{
[BackgroundDependencyLoader]
private void load()
{
var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
Dependencies.CacheAs<IAdjustableClock>(clock);
Dependencies.CacheAs<IFrameBasedClock>(clock);
var playback = new PlaybackControl
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(200, 100)
};
Beatmap.Value = new TestWorkingBeatmap(new Beatmap(), Clock);
Child = playback;
}
}
}

View File

@ -0,0 +1,54 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestCaseWaveContainer : OsuTestCase
{
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
WaveContainer container;
Add(container = new WaveContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(400),
FirstWaveColour = colours.Red,
SecondWaveColour = colours.Green,
ThirdWaveColour = colours.Blue,
FourthWaveColour = colours.Pink,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black.Opacity(0.5f),
},
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = OsuFont.GetFont(size: 20),
Text = @"Wave Container",
},
},
});
AddStep(@"show", container.Show);
AddStep(@"hide", container.Hide);
}
}
}

View File

@ -0,0 +1,74 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Audio;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.Sprites;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestCaseWaveform : OsuTestCase
{
[BackgroundDependencyLoader]
private void load()
{
Beatmap.Value = new WaveformTestBeatmap();
FillFlowContainer flow;
Child = flow = new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
};
for (int i = 1; i <= 16; i *= 2)
{
var newDisplay = new WaveformGraph
{
RelativeSizeAxes = Axes.Both,
Resolution = 1f / i,
Waveform = Beatmap.Value.Waveform,
};
flow.Add(new Container
{
RelativeSizeAxes = Axes.X,
Height = 100,
Children = new Drawable[]
{
newDisplay,
new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
Alpha = 0.75f
},
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = $"Resolution: {1f / i:0.00}"
}
}
}
}
});
}
}
}
}

View File

@ -0,0 +1,129 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shapes;
using osu.Framework.MathUtils;
using osu.Game.Graphics;
using osu.Game.Graphics.Cursor;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Editor
{
public class TestCaseZoomableScrollContainer : ManualInputManagerTestCase
{
private readonly ZoomableScrollContainer scrollContainer;
private readonly Drawable innerBox;
public TestCaseZoomableScrollContainer()
{
Children = new Drawable[]
{
new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = 250,
Width = 0.75f,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(30)
},
scrollContainer = new ZoomableScrollContainer { RelativeSizeAxes = Axes.Both }
}
},
new MenuCursor()
};
scrollContainer.Add(innerBox = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourInfo.GradientHorizontal(new Color4(0.8f, 0.6f, 0.4f, 1f), new Color4(0.4f, 0.6f, 0.8f, 1f))
});
}
[Test]
public void TestZoom0()
{
reset();
AddAssert("Box at 0", () => Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft));
AddAssert("Box width = 1x", () => Precision.AlmostEquals(boxQuad.Size, scrollQuad.Size));
}
[Test]
public void TestZoom10()
{
reset();
AddStep("Set zoom = 10", () => scrollContainer.Zoom = 10);
AddAssert("Box at 1/2", () => Precision.AlmostEquals(boxQuad.Centre, scrollQuad.Centre, 1));
AddAssert("Box width = 10x", () => Precision.AlmostEquals(boxQuad.Size.X, 10 * scrollQuad.Size.X));
}
[Test]
public void TestMouseZoomInOnceOutOnce()
{
reset();
// Scroll in at 0.25
AddStep("Move mouse to 0.25x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, scrollQuad.Centre.Y)));
AddStep("Scroll by 3", () => InputManager.ScrollBy(new Vector2(0, 3)));
AddAssert("Box not at 0", () => !Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft));
AddAssert("Box 1/4 at 1/4", () => Precision.AlmostEquals(boxQuad.TopLeft.X + 0.25f * boxQuad.Size.X, scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X));
// Scroll out at 0.25
AddStep("Scroll by -3", () => InputManager.ScrollBy(new Vector2(0, -3)));
AddAssert("Box at 0", () => Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft));
AddAssert("Box 1/4 at 1/4", () => Precision.AlmostEquals(boxQuad.TopLeft.X + 0.25f * boxQuad.Size.X, scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X));
}
[Test]
public void TestMouseZoomInTwiceOutTwice()
{
reset();
// Scroll in at 0.25
AddStep("Move mouse to 0.25x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, scrollQuad.Centre.Y)));
AddStep("Scroll by 1", () => InputManager.ScrollBy(new Vector2(0, 1)));
// Scroll in at 0.6
AddStep("Move mouse to 0.75x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.75f * scrollQuad.Size.X, scrollQuad.Centre.Y)));
AddStep("Scroll by 1", () => InputManager.ScrollBy(new Vector2(0, 1)));
AddAssert("Box not at 0", () => !Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft));
// Very hard to determine actual position, so approximate
AddAssert("Box at correct position (1)", () => Precision.DefinitelyBigger(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, boxQuad.TopLeft.X + 0.25f * boxQuad.Size.X));
AddAssert("Box at correct position (2)", () => Precision.DefinitelyBigger(scrollQuad.TopLeft.X + 0.6f * scrollQuad.Size.X, boxQuad.TopLeft.X + 0.3f * boxQuad.Size.X));
AddAssert("Box at correct position (3)", () => Precision.DefinitelyBigger(boxQuad.TopLeft.X + 0.6f * boxQuad.Size.X, scrollQuad.TopLeft.X + 0.6f * scrollQuad.Size.X));
// Scroll out at 0.6
AddStep("Scroll by -1", () => InputManager.ScrollBy(new Vector2(0, -1)));
// Scroll out at 0.25
AddStep("Move mouse to 0.25x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, scrollQuad.Centre.Y)));
AddStep("Scroll by -1", () => InputManager.ScrollBy(new Vector2(0, -1)));
AddAssert("Box at 0", () => Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft));
}
private void reset()
{
AddStep("Reset", () =>
{
scrollContainer.Zoom = 0;
scrollContainer.ScrollTo(0, false);
});
}
private Quad scrollQuad => scrollContainer.ScreenSpaceDrawQuad;
private Quad boxQuad => innerBox.ScreenSpaceDrawQuad;
}
}