mirror of
https://github.com/osukey/osukey.git
synced 2025-04-29 10:47:22 +09:00
Merge remote-tracking branch 'upstream/master' into wave-container
This commit is contained in:
commit
ae77c010e2
40
.gitattributes
vendored
40
.gitattributes
vendored
@ -1,19 +1,23 @@
|
|||||||
# This won't normalise line endings, but it will ensure that merge drivers use CRLF
|
# Autodetect text files and ensure that we normalise their
|
||||||
* -text eol=crlf
|
# line endings to lf internally. When checked out they may
|
||||||
|
# use different line endings.
|
||||||
|
* text=auto
|
||||||
|
|
||||||
# Currently in-use binary file extensions
|
# Check out with crlf (Windows) line endings
|
||||||
*.blend binary
|
*.sln text eol=crlf
|
||||||
*.bmp binary
|
*.csproj text eol=crlf
|
||||||
*.dll binary
|
*.cs text diff=csharp eol=crlf
|
||||||
*.exe binary
|
*.resx text eol=crlf
|
||||||
*.icns binary
|
*.vsixmanifest text eol=crlf
|
||||||
*.ico binary
|
packages.config text eol=crlf
|
||||||
*.jpg binary
|
App.config text eol=crlf
|
||||||
*.osz2 binary
|
*.bat text eol=crlf
|
||||||
*.pdn binary
|
*.cmd text eol=crlf
|
||||||
*.psd binary
|
*.snippet text eol=crlf
|
||||||
*.PSD binary
|
|
||||||
*.tga binary
|
# Check out with lf (UNIX) line endings
|
||||||
*.ttf binary
|
*.sh text eol=lf
|
||||||
*.wav binary
|
.gitignore text eol=lf
|
||||||
*.xnb binary
|
.gitattributes text eol=lf
|
||||||
|
*.md text eol=lf
|
||||||
|
.travis.yml text eol=lf
|
@ -1 +1 @@
|
|||||||
Subproject commit 02d7a0fa4798d197cd08570ee48951edbb7c7860
|
Subproject commit eb6362eaf1317b0fa27b2c9e559bd9a0f1ce357c
|
@ -11,7 +11,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="NuGet.CommandLine" Version="4.5.1" />
|
<PackageReference Include="NuGet.CommandLine" Version="4.5.1" />
|
||||||
<PackageReference Include="NUnit" Version="3.8.1" />
|
<PackageReference Include="NUnit" Version="3.10.1" />
|
||||||
<PackageReference Include="squirrel.windows" Version="1.7.8" Condition="'$(TargetFramework)' == 'net461'" />
|
<PackageReference Include="squirrel.windows" Version="1.7.8" Condition="'$(TargetFramework)' == 'net461'" />
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.4.0" />
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
|
|
||||||
private readonly Stack<BeatmapSetInfo> selectedSets = new Stack<BeatmapSetInfo>();
|
private readonly Stack<BeatmapSetInfo> selectedSets = new Stack<BeatmapSetInfo>();
|
||||||
|
private readonly HashSet<int> eagerSelectedIDs = new HashSet<int>();
|
||||||
|
|
||||||
private BeatmapInfo currentSelection;
|
private BeatmapInfo currentSelection;
|
||||||
|
|
||||||
@ -80,6 +81,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
testEmptyTraversal();
|
testEmptyTraversal();
|
||||||
testHiding();
|
testHiding();
|
||||||
testSelectingFilteredRuleset();
|
testSelectingFilteredRuleset();
|
||||||
|
testCarouselRootIsRandom();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureRandomFetchSuccess() =>
|
private void ensureRandomFetchSuccess() =>
|
||||||
@ -151,6 +153,17 @@ namespace osu.Game.Tests.Visual
|
|||||||
AddAssert("Selection is visible", selectedBeatmapVisible);
|
AddAssert("Selection is visible", selectedBeatmapVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkNonmatchingFilter()
|
||||||
|
{
|
||||||
|
AddStep("Toggle non-matching filter", () =>
|
||||||
|
{
|
||||||
|
carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false);
|
||||||
|
carousel.Filter(new FilterCriteria(), false);
|
||||||
|
eagerSelectedIDs.Add(carousel.SelectedBeatmapSet.ID);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Test keyboard traversal
|
/// Test keyboard traversal
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -403,6 +416,23 @@ namespace osu.Game.Tests.Visual
|
|||||||
AddStep("remove single ruleset set", () => carousel.RemoveBeatmapSet(testSingle));
|
AddStep("remove single ruleset set", () => carousel.RemoveBeatmapSet(testSingle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testCarouselRootIsRandom()
|
||||||
|
{
|
||||||
|
List<BeatmapSetInfo> beatmapSets = new List<BeatmapSetInfo>();
|
||||||
|
|
||||||
|
for (int i = 1; i <= 50; i++)
|
||||||
|
beatmapSets.Add(createTestBeatmapSet(i));
|
||||||
|
|
||||||
|
AddStep("Load 50 Beatmaps", () => { carousel.BeatmapSets = beatmapSets; });
|
||||||
|
advanceSelection(direction: 1, diff: false);
|
||||||
|
checkNonmatchingFilter();
|
||||||
|
checkNonmatchingFilter();
|
||||||
|
checkNonmatchingFilter();
|
||||||
|
checkNonmatchingFilter();
|
||||||
|
checkNonmatchingFilter();
|
||||||
|
AddAssert("Selection was random", () => eagerSelectedIDs.Count > 1);
|
||||||
|
}
|
||||||
|
|
||||||
private BeatmapSetInfo createTestBeatmapSet(int id)
|
private BeatmapSetInfo createTestBeatmapSet(int id)
|
||||||
{
|
{
|
||||||
return new BeatmapSetInfo
|
return new BeatmapSetInfo
|
||||||
|
@ -5,7 +5,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Timing;
|
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Screens.Edit.Screens.Compose;
|
using osu.Game.Screens.Edit.Screens.Compose;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
@ -13,24 +12,15 @@ using osu.Game.Tests.Beatmaps;
|
|||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestCaseEditorCompose : OsuTestCase
|
public class TestCaseEditorCompose : EditorClockTestCase
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(Compose) };
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(Compose) };
|
||||||
|
|
||||||
private DependencyContainer dependencies;
|
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
|
||||||
=> dependencies = new DependencyContainer(parent);
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuGameBase osuGame)
|
private void load(OsuGameBase osuGame)
|
||||||
{
|
{
|
||||||
osuGame.Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
osuGame.Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||||
|
|
||||||
var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
|
|
||||||
dependencies.CacheAs<IAdjustableClock>(clock);
|
|
||||||
dependencies.CacheAs<IFrameBasedClock>(clock);
|
|
||||||
|
|
||||||
var compose = new Compose();
|
var compose = new Compose();
|
||||||
compose.Beatmap.BindTo(osuGame.Beatmap);
|
compose.Beatmap.BindTo(osuGame.Beatmap);
|
||||||
|
|
||||||
|
@ -3,52 +3,35 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio.Track;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Timing;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Edit.Tools;
|
using osu.Game.Rulesets.Edit.Tools;
|
||||||
using osu.Game.Rulesets.Osu;
|
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Screens.Edit.Screens.Compose;
|
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
public class TestCaseEditorSeekSnapping : OsuTestCase
|
public class TestCaseEditorSeekSnapping : EditorClockTestCase
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(HitObjectComposer) };
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(HitObjectComposer) };
|
||||||
|
|
||||||
private Track track;
|
public TestCaseEditorSeekSnapping()
|
||||||
private HitObjectComposer composer;
|
{
|
||||||
|
BeatDivisor.Value = 4;
|
||||||
private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(4);
|
}
|
||||||
|
|
||||||
private DecoupleableInterpolatingFramedClock clock;
|
|
||||||
|
|
||||||
private DependencyContainer dependencies;
|
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
|
||||||
=> dependencies = new DependencyContainer(parent);
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuGameBase osuGame)
|
private void load(OsuGameBase osuGame)
|
||||||
{
|
{
|
||||||
clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
|
|
||||||
dependencies.CacheAs<IAdjustableClock>(clock);
|
|
||||||
dependencies.CacheAs<IFrameBasedClock>(clock);
|
|
||||||
dependencies.Cache(beatDivisor);
|
|
||||||
|
|
||||||
var testBeatmap = new Beatmap
|
var testBeatmap = new Beatmap
|
||||||
{
|
{
|
||||||
ControlPointInfo = new ControlPointInfo
|
ControlPointInfo = new ControlPointInfo
|
||||||
@ -71,22 +54,8 @@ namespace osu.Game.Tests.Visual
|
|||||||
};
|
};
|
||||||
|
|
||||||
osuGame.Beatmap.Value = new TestWorkingBeatmap(testBeatmap);
|
osuGame.Beatmap.Value = new TestWorkingBeatmap(testBeatmap);
|
||||||
track = osuGame.Beatmap.Value.Track;
|
|
||||||
|
|
||||||
Child = new GridContainer
|
Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock };
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Content = new[]
|
|
||||||
{
|
|
||||||
new Drawable[] { composer = new TestHitObjectComposer(new OsuRuleset()) },
|
|
||||||
new Drawable[] { new TimingPointVisualiser(testBeatmap, track) { Clock = clock } },
|
|
||||||
},
|
|
||||||
RowDimensions = new[]
|
|
||||||
{
|
|
||||||
new Dimension(GridSizeMode.Distributed),
|
|
||||||
new Dimension(GridSizeMode.AutoSize),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
testSeekNoSnapping();
|
testSeekNoSnapping();
|
||||||
testSeekSnappingOnBeat();
|
testSeekSnappingOnBeat();
|
||||||
@ -107,18 +76,18 @@ namespace osu.Game.Tests.Visual
|
|||||||
reset();
|
reset();
|
||||||
|
|
||||||
// Forwards
|
// Forwards
|
||||||
AddStep("Seek(0)", () => composer.SeekTo(0));
|
AddStep("Seek(0)", () => Clock.Seek(0));
|
||||||
AddAssert("Time = 0", () => clock.CurrentTime == 0);
|
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
|
||||||
AddStep("Seek(33)", () => composer.SeekTo(33));
|
AddStep("Seek(33)", () => Clock.Seek(33));
|
||||||
AddAssert("Time = 33", () => clock.CurrentTime == 33);
|
AddAssert("Time = 33", () => Clock.CurrentTime == 33);
|
||||||
AddStep("Seek(89)", () => composer.SeekTo(89));
|
AddStep("Seek(89)", () => Clock.Seek(89));
|
||||||
AddAssert("Time = 89", () => clock.CurrentTime == 89);
|
AddAssert("Time = 89", () => Clock.CurrentTime == 89);
|
||||||
|
|
||||||
// Backwards
|
// Backwards
|
||||||
AddStep("Seek(25)", () => composer.SeekTo(25));
|
AddStep("Seek(25)", () => Clock.Seek(25));
|
||||||
AddAssert("Time = 25", () => clock.CurrentTime == 25);
|
AddAssert("Time = 25", () => Clock.CurrentTime == 25);
|
||||||
AddStep("Seek(0)", () => composer.SeekTo(0));
|
AddStep("Seek(0)", () => Clock.Seek(0));
|
||||||
AddAssert("Time = 0", () => clock.CurrentTime == 0);
|
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -129,20 +98,20 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
AddStep("Seek(0), Snap", () => composer.SeekTo(0, true));
|
AddStep("Seek(0), Snap", () => Clock.SeekSnapped(0));
|
||||||
AddAssert("Time = 0", () => clock.CurrentTime == 0);
|
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
|
||||||
AddStep("Seek(50), Snap", () => composer.SeekTo(50, true));
|
AddStep("Seek(50), Snap", () => Clock.SeekSnapped(50));
|
||||||
AddAssert("Time = 50", () => clock.CurrentTime == 50);
|
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
|
||||||
AddStep("Seek(100), Snap", () => composer.SeekTo(100, true));
|
AddStep("Seek(100), Snap", () => Clock.SeekSnapped(100));
|
||||||
AddAssert("Time = 100", () => clock.CurrentTime == 100);
|
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
|
||||||
AddStep("Seek(175), Snap", () => composer.SeekTo(175, true));
|
AddStep("Seek(175), Snap", () => Clock.SeekSnapped(175));
|
||||||
AddAssert("Time = 175", () => clock.CurrentTime == 175);
|
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
|
||||||
AddStep("Seek(350), Snap", () => composer.SeekTo(350, true));
|
AddStep("Seek(350), Snap", () => Clock.SeekSnapped(350));
|
||||||
AddAssert("Time = 350", () => clock.CurrentTime == 350);
|
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
|
||||||
AddStep("Seek(400), Snap", () => composer.SeekTo(400, true));
|
AddStep("Seek(400), Snap", () => Clock.SeekSnapped(400));
|
||||||
AddAssert("Time = 400", () => clock.CurrentTime == 400);
|
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
|
||||||
AddStep("Seek(450), Snap", () => composer.SeekTo(450, true));
|
AddStep("Seek(450), Snap", () => Clock.SeekSnapped(450));
|
||||||
AddAssert("Time = 450", () => clock.CurrentTime == 450);
|
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -154,18 +123,18 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
AddStep("Seek(24), Snap", () => composer.SeekTo(24, true));
|
AddStep("Seek(24), Snap", () => Clock.SeekSnapped(24));
|
||||||
AddAssert("Time = 0", () => clock.CurrentTime == 0);
|
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
|
||||||
AddStep("Seek(26), Snap", () => composer.SeekTo(26, true));
|
AddStep("Seek(26), Snap", () => Clock.SeekSnapped(26));
|
||||||
AddAssert("Time = 50", () => clock.CurrentTime == 50);
|
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
|
||||||
AddStep("Seek(150), Snap", () => composer.SeekTo(150, true));
|
AddStep("Seek(150), Snap", () => Clock.SeekSnapped(150));
|
||||||
AddAssert("Time = 100", () => clock.CurrentTime == 100);
|
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
|
||||||
AddStep("Seek(170), Snap", () => composer.SeekTo(170, true));
|
AddStep("Seek(170), Snap", () => Clock.SeekSnapped(170));
|
||||||
AddAssert("Time = 175", () => clock.CurrentTime == 175);
|
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
|
||||||
AddStep("Seek(274), Snap", () => composer.SeekTo(274, true));
|
AddStep("Seek(274), Snap", () => Clock.SeekSnapped(274));
|
||||||
AddAssert("Time = 175", () => clock.CurrentTime == 175);
|
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
|
||||||
AddStep("Seek(276), Snap", () => composer.SeekTo(276, true));
|
AddStep("Seek(276), Snap", () => Clock.SeekSnapped(276));
|
||||||
AddAssert("Time = 350", () => clock.CurrentTime == 350);
|
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -175,16 +144,16 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
AddStep("SeekForward", () => composer.SeekForward());
|
AddStep("SeekForward", () => Clock.SeekForward());
|
||||||
AddAssert("Time = 50", () => clock.CurrentTime == 50);
|
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
|
||||||
AddStep("SeekForward", () => composer.SeekForward());
|
AddStep("SeekForward", () => Clock.SeekForward());
|
||||||
AddAssert("Time = 100", () => clock.CurrentTime == 100);
|
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
|
||||||
AddStep("SeekForward", () => composer.SeekForward());
|
AddStep("SeekForward", () => Clock.SeekForward());
|
||||||
AddAssert("Time = 200", () => clock.CurrentTime == 200);
|
AddAssert("Time = 200", () => Clock.CurrentTime == 200);
|
||||||
AddStep("SeekForward", () => composer.SeekForward());
|
AddStep("SeekForward", () => Clock.SeekForward());
|
||||||
AddAssert("Time = 400", () => clock.CurrentTime == 400);
|
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
|
||||||
AddStep("SeekForward", () => composer.SeekForward());
|
AddStep("SeekForward", () => Clock.SeekForward());
|
||||||
AddAssert("Time = 450", () => clock.CurrentTime == 450);
|
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -194,18 +163,18 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 50", () => clock.CurrentTime == 50);
|
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 100", () => clock.CurrentTime == 100);
|
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 175", () => clock.CurrentTime == 175);
|
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 350", () => clock.CurrentTime == 350);
|
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 400", () => clock.CurrentTime == 400);
|
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 450", () => clock.CurrentTime == 450);
|
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -216,30 +185,30 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
AddStep("Seek(49)", () => composer.SeekTo(49));
|
AddStep("Seek(49)", () => Clock.Seek(49));
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 50", () => clock.CurrentTime == 50);
|
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
|
||||||
AddStep("Seek(49.999)", () => composer.SeekTo(49.999));
|
AddStep("Seek(49.999)", () => Clock.Seek(49.999));
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 50", () => clock.CurrentTime == 50);
|
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
|
||||||
AddStep("Seek(99)", () => composer.SeekTo(99));
|
AddStep("Seek(99)", () => Clock.Seek(99));
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 100", () => clock.CurrentTime == 100);
|
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
|
||||||
AddStep("Seek(99.999)", () => composer.SeekTo(99.999));
|
AddStep("Seek(99.999)", () => Clock.Seek(99.999));
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 100", () => clock.CurrentTime == 100);
|
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
|
||||||
AddStep("Seek(174)", () => composer.SeekTo(174));
|
AddStep("Seek(174)", () => Clock.Seek(174));
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 175", () => clock.CurrentTime == 175);
|
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
|
||||||
AddStep("Seek(349)", () => composer.SeekTo(349));
|
AddStep("Seek(349)", () => Clock.Seek(349));
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 350", () => clock.CurrentTime == 350);
|
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
|
||||||
AddStep("Seek(399)", () => composer.SeekTo(399));
|
AddStep("Seek(399)", () => Clock.Seek(399));
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 400", () => clock.CurrentTime == 400);
|
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
|
||||||
AddStep("Seek(449)", () => composer.SeekTo(449));
|
AddStep("Seek(449)", () => Clock.Seek(449));
|
||||||
AddStep("SeekForward, Snap", () => composer.SeekForward(true));
|
AddStep("SeekForward, Snap", () => Clock.SeekForward(true));
|
||||||
AddAssert("Time = 450", () => clock.CurrentTime == 450);
|
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -249,19 +218,19 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
AddStep("Seek(450)", () => composer.SeekTo(450));
|
AddStep("Seek(450)", () => Clock.Seek(450));
|
||||||
AddStep("SeekBackward", () => composer.SeekBackward());
|
AddStep("SeekBackward", () => Clock.SeekBackward());
|
||||||
AddAssert("Time = 425", () => clock.CurrentTime == 425);
|
AddAssert("Time = 425", () => Clock.CurrentTime == 425);
|
||||||
AddStep("SeekBackward", () => composer.SeekBackward());
|
AddStep("SeekBackward", () => Clock.SeekBackward());
|
||||||
AddAssert("Time = 375", () => clock.CurrentTime == 375);
|
AddAssert("Time = 375", () => Clock.CurrentTime == 375);
|
||||||
AddStep("SeekBackward", () => composer.SeekBackward());
|
AddStep("SeekBackward", () => Clock.SeekBackward());
|
||||||
AddAssert("Time = 325", () => clock.CurrentTime == 325);
|
AddAssert("Time = 325", () => Clock.CurrentTime == 325);
|
||||||
AddStep("SeekBackward", () => composer.SeekBackward());
|
AddStep("SeekBackward", () => Clock.SeekBackward());
|
||||||
AddAssert("Time = 125", () => clock.CurrentTime == 125);
|
AddAssert("Time = 125", () => Clock.CurrentTime == 125);
|
||||||
AddStep("SeekBackward", () => composer.SeekBackward());
|
AddStep("SeekBackward", () => Clock.SeekBackward());
|
||||||
AddAssert("Time = 25", () => clock.CurrentTime == 25);
|
AddAssert("Time = 25", () => Clock.CurrentTime == 25);
|
||||||
AddStep("SeekBackward", () => composer.SeekBackward());
|
AddStep("SeekBackward", () => Clock.SeekBackward());
|
||||||
AddAssert("Time = 0", () => clock.CurrentTime == 0);
|
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -271,19 +240,19 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
AddStep("Seek(450)", () => composer.SeekTo(450));
|
AddStep("Seek(450)", () => Clock.Seek(450));
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 400", () => clock.CurrentTime == 400);
|
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 350", () => clock.CurrentTime == 350);
|
AddAssert("Time = 350", () => Clock.CurrentTime == 350);
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 175", () => clock.CurrentTime == 175);
|
AddAssert("Time = 175", () => Clock.CurrentTime == 175);
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 100", () => clock.CurrentTime == 100);
|
AddAssert("Time = 100", () => Clock.CurrentTime == 100);
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 50", () => clock.CurrentTime == 50);
|
AddAssert("Time = 50", () => Clock.CurrentTime == 50);
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 0", () => clock.CurrentTime == 0);
|
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -294,18 +263,18 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
AddStep("Seek(451)", () => composer.SeekTo(451));
|
AddStep("Seek(451)", () => Clock.Seek(451));
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 450", () => clock.CurrentTime == 450);
|
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
|
||||||
AddStep("Seek(450.999)", () => composer.SeekTo(450.999));
|
AddStep("Seek(450.999)", () => Clock.Seek(450.999));
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 450", () => clock.CurrentTime == 450);
|
AddAssert("Time = 450", () => Clock.CurrentTime == 450);
|
||||||
AddStep("Seek(401)", () => composer.SeekTo(401));
|
AddStep("Seek(401)", () => Clock.Seek(401));
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 400", () => clock.CurrentTime == 400);
|
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
|
||||||
AddStep("Seek(401.999)", () => composer.SeekTo(401.999));
|
AddStep("Seek(401.999)", () => Clock.Seek(401.999));
|
||||||
AddStep("SeekBackward, Snap", () => composer.SeekBackward(true));
|
AddStep("SeekBackward, Snap", () => Clock.SeekBackward(true));
|
||||||
AddAssert("Time = 400", () => clock.CurrentTime == 400);
|
AddAssert("Time = 400", () => Clock.CurrentTime == 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -317,34 +286,34 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
double lastTime = 0;
|
double lastTime = 0;
|
||||||
|
|
||||||
AddStep("Seek(0)", () => composer.SeekTo(0));
|
AddStep("Seek(0)", () => Clock.Seek(0));
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
AddStep("SeekForward, Snap", () =>
|
AddStep("SeekForward, Snap", () =>
|
||||||
{
|
{
|
||||||
lastTime = clock.CurrentTime;
|
lastTime = Clock.CurrentTime;
|
||||||
composer.SeekForward(true);
|
Clock.SeekForward(true);
|
||||||
});
|
});
|
||||||
AddAssert("Time > lastTime", () => clock.CurrentTime > lastTime);
|
AddAssert("Time > lastTime", () => Clock.CurrentTime > lastTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
AddStep("SeekBackward, Snap", () =>
|
AddStep("SeekBackward, Snap", () =>
|
||||||
{
|
{
|
||||||
lastTime = clock.CurrentTime;
|
lastTime = Clock.CurrentTime;
|
||||||
composer.SeekBackward(true);
|
Clock.SeekBackward(true);
|
||||||
});
|
});
|
||||||
AddAssert("Time < lastTime", () => clock.CurrentTime < lastTime);
|
AddAssert("Time < lastTime", () => Clock.CurrentTime < lastTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddAssert("Time = 0", () => clock.CurrentTime == 0);
|
AddAssert("Time = 0", () => Clock.CurrentTime == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reset()
|
private void reset()
|
||||||
{
|
{
|
||||||
AddStep("Reset", () => composer.SeekTo(0));
|
AddStep("Reset", () => Clock.Seek(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestHitObjectComposer : HitObjectComposer
|
private class TestHitObjectComposer : HitObjectComposer
|
||||||
@ -359,13 +328,13 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
private class TimingPointVisualiser : CompositeDrawable
|
private class TimingPointVisualiser : CompositeDrawable
|
||||||
{
|
{
|
||||||
private readonly Track track;
|
private readonly double length;
|
||||||
|
|
||||||
private readonly Drawable tracker;
|
private readonly Drawable tracker;
|
||||||
|
|
||||||
public TimingPointVisualiser(Beatmap beatmap, Track track)
|
public TimingPointVisualiser(Beatmap beatmap, double length)
|
||||||
{
|
{
|
||||||
this.track = track;
|
this.length = length;
|
||||||
|
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
@ -417,7 +386,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
for (int i = 0; i < timingPoints.Count; i++)
|
for (int i = 0; i < timingPoints.Count; i++)
|
||||||
{
|
{
|
||||||
TimingControlPoint next = i == timingPoints.Count - 1 ? null : timingPoints[i + 1];
|
TimingControlPoint next = i == timingPoints.Count - 1 ? null : timingPoints[i + 1];
|
||||||
timelineContainer.Add(new TimingPointTimeline(timingPoints[i], next?.Time ?? beatmap.HitObjects.Last().StartTime, track.Length));
|
timelineContainer.Add(new TimingPointTimeline(timingPoints[i], next?.Time ?? length, length));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +394,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
tracker.X = (float)(Time.Current / track.Length);
|
tracker.X = (float)(Time.Current / length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TimingPointTimeline : CompositeDrawable
|
private class TimingPointTimeline : CompositeDrawable
|
||||||
|
@ -6,36 +6,22 @@ using System.Collections.Generic;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||||
using osu.Framework.Configuration;
|
|
||||||
using osu.Framework.Timing;
|
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestCaseEditorSummaryTimeline : OsuTestCase
|
public class TestCaseEditorSummaryTimeline : EditorClockTestCase
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(SummaryTimeline) };
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(SummaryTimeline) };
|
||||||
|
|
||||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
|
||||||
|
|
||||||
private DependencyContainer dependencies;
|
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
|
||||||
=> dependencies = new DependencyContainer(parent);
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load(OsuGameBase osuGame)
|
||||||
{
|
{
|
||||||
beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
osuGame.Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||||
|
|
||||||
var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
|
|
||||||
dependencies.CacheAs<IAdjustableClock>(clock);
|
|
||||||
dependencies.CacheAs<IFrameBasedClock>(clock);
|
|
||||||
|
|
||||||
SummaryTimeline summaryTimeline;
|
SummaryTimeline summaryTimeline;
|
||||||
Add(summaryTimeline = new SummaryTimeline
|
Add(summaryTimeline = new SummaryTimeline
|
||||||
@ -45,7 +31,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
Size = new Vector2(500, 50)
|
Size = new Vector2(500, 50)
|
||||||
});
|
});
|
||||||
|
|
||||||
summaryTimeline.Beatmap.BindTo(beatmap);
|
summaryTimeline.Beatmap.BindTo(osuGame.Beatmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,90 +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.Game.Beatmaps.ControlPoints;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class TestCaseGamefield : OsuTestCase
|
|
||||||
{
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
/*int time = 500;
|
|
||||||
for (int i = 0; i < 100; i++)
|
|
||||||
{
|
|
||||||
objects.Add(new HitCircle
|
|
||||||
{
|
|
||||||
StartTime = time,
|
|
||||||
Position = new Vector2(RNG.Next(0, (int)OsuPlayfield.BASE_SIZE.X), RNG.Next(0, (int)OsuPlayfield.BASE_SIZE.Y)),
|
|
||||||
Scale = RNG.NextSingle(0.5f, 1.0f),
|
|
||||||
});
|
|
||||||
|
|
||||||
time += RNG.Next(50, 500);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
var controlPointInfo = new ControlPointInfo();
|
|
||||||
controlPointInfo.TimingPoints.Add(new TimingControlPoint
|
|
||||||
{
|
|
||||||
BeatLength = 200
|
|
||||||
});
|
|
||||||
|
|
||||||
/*WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap
|
|
||||||
{
|
|
||||||
HitObjects = objects,
|
|
||||||
BeatmapInfo = new BeatmapInfo
|
|
||||||
{
|
|
||||||
Difficulty = new BeatmapDifficulty(),
|
|
||||||
Ruleset = rulesets.Query<RulesetInfo>().First(),
|
|
||||||
Metadata = new BeatmapMetadata
|
|
||||||
{
|
|
||||||
Artist = @"Unknown",
|
|
||||||
Title = @"Sample Beatmap",
|
|
||||||
Author = @"peppy",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ControlPointInfo = controlPointInfo
|
|
||||||
});
|
|
||||||
|
|
||||||
AddRange(new Drawable[]
|
|
||||||
{
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
//ensure we are at offset 0
|
|
||||||
Clock = new FramedClock(),
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new OsuRulesetContainer(new OsuRuleset(), beatmap, false)
|
|
||||||
{
|
|
||||||
Scale = new Vector2(0.5f),
|
|
||||||
Anchor = Anchor.TopLeft,
|
|
||||||
Origin = Anchor.TopLeft
|
|
||||||
},
|
|
||||||
new TaikoRulesetContainer(new TaikoRuleset(),beatmap, false)
|
|
||||||
{
|
|
||||||
Scale = new Vector2(0.5f),
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight
|
|
||||||
},
|
|
||||||
new CatchRulesetContainer(new CatchRuleset(),beatmap, false)
|
|
||||||
{
|
|
||||||
Scale = new Vector2(0.5f),
|
|
||||||
Anchor = Anchor.BottomLeft,
|
|
||||||
Origin = Anchor.BottomLeft
|
|
||||||
},
|
|
||||||
new ManiaRulesetContainer(new ManiaRuleset(),beatmap, false)
|
|
||||||
{
|
|
||||||
Scale = new Vector2(0.5f),
|
|
||||||
Anchor = Anchor.BottomRight,
|
|
||||||
Origin = Anchor.BottomRight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -10,7 +10,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
{
|
{
|
||||||
public BackButton()
|
public BackButton()
|
||||||
{
|
{
|
||||||
Text = @"Back";
|
Text = @"back";
|
||||||
Icon = FontAwesome.fa_osu_left_o;
|
Icon = FontAwesome.fa_osu_left_o;
|
||||||
Anchor = Anchor.BottomLeft;
|
Anchor = Anchor.BottomLeft;
|
||||||
Origin = Anchor.BottomLeft;
|
Origin = Anchor.BottomLeft;
|
||||||
|
@ -37,13 +37,7 @@ namespace osu.Game.Online.API
|
|||||||
|
|
||||||
public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser());
|
public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser());
|
||||||
|
|
||||||
public string Token
|
protected bool HasLogin => authentication.Token.Value != null || !string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password);
|
||||||
{
|
|
||||||
get { return authentication.Token?.ToString(); }
|
|
||||||
set { authentication.Token = string.IsNullOrEmpty(value) ? null : OAuthToken.Parse(value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool HasLogin => Token != null || !string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password);
|
|
||||||
|
|
||||||
private readonly CancellationTokenSource cancellationToken = new CancellationTokenSource();
|
private readonly CancellationTokenSource cancellationToken = new CancellationTokenSource();
|
||||||
|
|
||||||
@ -57,11 +51,15 @@ namespace osu.Game.Online.API
|
|||||||
log = Logger.GetLogger(LoggingTarget.Network);
|
log = Logger.GetLogger(LoggingTarget.Network);
|
||||||
|
|
||||||
ProvidedUsername = config.Get<string>(OsuSetting.Username);
|
ProvidedUsername = config.Get<string>(OsuSetting.Username);
|
||||||
Token = config.Get<string>(OsuSetting.Token);
|
|
||||||
|
authentication.TokenString = config.Get<string>(OsuSetting.Token);
|
||||||
|
authentication.Token.ValueChanged += onTokenChanged;
|
||||||
|
|
||||||
Task.Factory.StartNew(run, cancellationToken.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
Task.Factory.StartNew(run, cancellationToken.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onTokenChanged(OAuthToken token) => config.Set(OsuSetting.Token, config.Get<bool>(OsuSetting.SavePassword) ? authentication.TokenString : string.Empty);
|
||||||
|
|
||||||
private readonly List<IOnlineComponent> components = new List<IOnlineComponent>();
|
private readonly List<IOnlineComponent> components = new List<IOnlineComponent>();
|
||||||
|
|
||||||
internal new void Schedule(Action action) => base.Schedule(action);
|
internal new void Schedule(Action action) => base.Schedule(action);
|
||||||
@ -306,9 +304,6 @@ namespace osu.Game.Online.API
|
|||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
config.Set(OsuSetting.Token, config.Get<bool>(OsuSetting.SavePassword) ? Token : string.Empty);
|
|
||||||
config.Save();
|
|
||||||
|
|
||||||
flushQueue();
|
flushQueue();
|
||||||
cancellationToken.Cancel();
|
cancellationToken.Cancel();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.IO.Network;
|
using osu.Framework.IO.Network;
|
||||||
|
|
||||||
namespace osu.Game.Online.API
|
namespace osu.Game.Online.API
|
||||||
@ -12,7 +13,13 @@ namespace osu.Game.Online.API
|
|||||||
private readonly string clientSecret;
|
private readonly string clientSecret;
|
||||||
private readonly string endpoint;
|
private readonly string endpoint;
|
||||||
|
|
||||||
public OAuthToken Token;
|
public readonly Bindable<OAuthToken> Token = new Bindable<OAuthToken>();
|
||||||
|
|
||||||
|
public string TokenString
|
||||||
|
{
|
||||||
|
get => Token.Value?.ToString();
|
||||||
|
set => Token.Value = string.IsNullOrEmpty(value) ? null : OAuthToken.Parse(value);
|
||||||
|
}
|
||||||
|
|
||||||
internal OAuth(string clientId, string clientSecret, string endpoint)
|
internal OAuth(string clientId, string clientSecret, string endpoint)
|
||||||
{
|
{
|
||||||
@ -47,7 +54,7 @@ namespace osu.Game.Online.API
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token = req.ResponseObject;
|
Token.Value = req.ResponseObject;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,14 +73,14 @@ namespace osu.Game.Online.API
|
|||||||
{
|
{
|
||||||
req.Perform();
|
req.Perform();
|
||||||
|
|
||||||
Token = req.ResponseObject;
|
Token.Value = req.ResponseObject;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
//todo: potentially only kill the refresh token on certain exception types.
|
//todo: potentially only kill the refresh token on certain exception types.
|
||||||
Token = null;
|
Token.Value = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,15 +102,15 @@ namespace osu.Game.Online.API
|
|||||||
if (accessTokenValid) return true;
|
if (accessTokenValid) return true;
|
||||||
|
|
||||||
// if not, let's try using our refresh token to request a new access token.
|
// if not, let's try using our refresh token to request a new access token.
|
||||||
if (!string.IsNullOrEmpty(Token?.RefreshToken))
|
if (!string.IsNullOrEmpty(Token.Value?.RefreshToken))
|
||||||
// ReSharper disable once PossibleNullReferenceException
|
// ReSharper disable once PossibleNullReferenceException
|
||||||
AuthenticateWithRefresh(Token.RefreshToken);
|
AuthenticateWithRefresh(Token.Value.RefreshToken);
|
||||||
|
|
||||||
return accessTokenValid;
|
return accessTokenValid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool accessTokenValid => Token?.IsValid ?? false;
|
private bool accessTokenValid => Token.Value?.IsValid ?? false;
|
||||||
|
|
||||||
internal bool HasValidAccessToken => RequestAccessToken() != null;
|
internal bool HasValidAccessToken => RequestAccessToken() != null;
|
||||||
|
|
||||||
@ -111,12 +118,12 @@ namespace osu.Game.Online.API
|
|||||||
{
|
{
|
||||||
if (!ensureAccessToken()) return null;
|
if (!ensureAccessToken()) return null;
|
||||||
|
|
||||||
return Token.AccessToken;
|
return Token.Value.AccessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Clear()
|
internal void Clear()
|
||||||
{
|
{
|
||||||
Token = null;
|
Token.Value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessTokenRequestRefresh : AccessTokenRequest
|
private class AccessTokenRequestRefresh : AccessTokenRequest
|
||||||
|
@ -36,6 +36,10 @@ using osu.Game.Overlays.Volume;
|
|||||||
|
|
||||||
namespace osu.Game
|
namespace osu.Game
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The full osu! experience. Builds on top of <see cref="OsuGameBase"/> to add menus and binding logic
|
||||||
|
/// for initial components that are generally retrieved via DI.
|
||||||
|
/// </summary>
|
||||||
public class OsuGame : OsuGameBase, IKeyBindingHandler<GlobalAction>
|
public class OsuGame : OsuGameBase, IKeyBindingHandler<GlobalAction>
|
||||||
{
|
{
|
||||||
public Toolbar Toolbar;
|
public Toolbar Toolbar;
|
||||||
@ -435,7 +439,7 @@ namespace osu.Game
|
|||||||
sensitivity.Value = 1;
|
sensitivity.Value = 1;
|
||||||
sensitivity.Disabled = true;
|
sensitivity.Disabled = true;
|
||||||
|
|
||||||
frameworkConfig.Set(FrameworkSetting.ActiveInputHandlers, string.Empty);
|
frameworkConfig.Set(FrameworkSetting.IgnoredInputHandlers, string.Empty);
|
||||||
frameworkConfig.GetBindable<ConfineMouseMode>(FrameworkSetting.ConfineMouseMode).SetDefault();
|
frameworkConfig.GetBindable<ConfineMouseMode>(FrameworkSetting.ConfineMouseMode).SetDefault();
|
||||||
return true;
|
return true;
|
||||||
case GlobalAction.ToggleToolbar:
|
case GlobalAction.ToggleToolbar:
|
||||||
|
@ -34,6 +34,11 @@ using osu.Game.Skinning;
|
|||||||
|
|
||||||
namespace osu.Game
|
namespace osu.Game
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The most basic <see cref="Game"/> that can be used to host osu! components and systems.
|
||||||
|
/// Unlike <see cref="OsuGame"/>, this class will not load any kind of UI, allowing it to be used
|
||||||
|
/// for provide dependencies to test cases without interfering with them.
|
||||||
|
/// </summary>
|
||||||
public class OsuGameBase : Framework.Game, ICanAcceptFiles
|
public class OsuGameBase : Framework.Game, ICanAcceptFiles
|
||||||
{
|
{
|
||||||
protected OsuConfigManager LocalConfig;
|
protected OsuConfigManager LocalConfig;
|
||||||
|
@ -44,7 +44,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
Beatmap.Value = BeatmapSet.Beatmaps.First();
|
Beatmap.Value = BeatmapSet.Beatmaps.First();
|
||||||
plays.Value = BeatmapSet.OnlineInfo.PlayCount;
|
plays.Value = BeatmapSet.OnlineInfo.PlayCount;
|
||||||
favourites.Value = BeatmapSet.OnlineInfo.FavouriteCount;
|
favourites.Value = BeatmapSet.OnlineInfo.FavouriteCount;
|
||||||
difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.Select(b => new DifficultySelectorButton(b)
|
difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty).Select(b => new DifficultySelectorButton(b)
|
||||||
{
|
{
|
||||||
State = DifficultySelectorState.NotSelected,
|
State = DifficultySelectorState.NotSelected,
|
||||||
OnHovered = beatmap =>
|
OnHovered = beatmap =>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
@ -208,7 +209,7 @@ namespace osu.Game.Overlays.Direct
|
|||||||
{
|
{
|
||||||
var icons = new List<DifficultyIcon>();
|
var icons = new List<DifficultyIcon>();
|
||||||
|
|
||||||
foreach (var b in SetInfo.Beatmaps)
|
foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty))
|
||||||
icons.Add(new DifficultyIcon(b));
|
icons.Add(new DifficultyIcon(b));
|
||||||
|
|
||||||
return icons;
|
return icons;
|
||||||
|
@ -173,8 +173,9 @@ namespace osu.Game.Overlays.Direct
|
|||||||
if (trackLoader != d) return;
|
if (trackLoader != d) return;
|
||||||
|
|
||||||
Preview = d?.Preview;
|
Preview = d?.Preview;
|
||||||
Playing.TriggerChange();
|
updatePreviewTrack(Playing);
|
||||||
loading = false;
|
loading = false;
|
||||||
|
|
||||||
Add(trackLoader);
|
Add(trackLoader);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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 OpenTK;
|
using OpenTK;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -19,6 +20,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
|
|||||||
|
|
||||||
private DirectPanel currentlyPlaying;
|
private DirectPanel currentlyPlaying;
|
||||||
|
|
||||||
|
public event Action<PaginatedBeatmapContainer> BeganPlayingPreview;
|
||||||
|
|
||||||
public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<User> user, string header, string missing = "None... yet.")
|
public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<User> user, string header, string missing = "None... yet.")
|
||||||
: base(user, header, missing)
|
: base(user, header, missing)
|
||||||
{
|
{
|
||||||
@ -56,17 +59,25 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
|
|||||||
|
|
||||||
panel.PreviewPlaying.ValueChanged += isPlaying =>
|
panel.PreviewPlaying.ValueChanged += isPlaying =>
|
||||||
{
|
{
|
||||||
if (!isPlaying) return;
|
StopPlayingPreview();
|
||||||
|
|
||||||
if (currentlyPlaying != null && currentlyPlaying != panel)
|
|
||||||
currentlyPlaying.PreviewPlaying.Value = false;
|
|
||||||
|
|
||||||
|
if (isPlaying)
|
||||||
|
{
|
||||||
|
BeganPlayingPreview?.Invoke(this);
|
||||||
currentlyPlaying = panel;
|
currentlyPlaying = panel;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Api.Queue(req);
|
Api.Queue(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void StopPlayingPreview()
|
||||||
|
{
|
||||||
|
if (currentlyPlaying == null) return;
|
||||||
|
currentlyPlaying.PreviewPlaying.Value = false;
|
||||||
|
currentlyPlaying = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.Linq;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Overlays.Profile.Sections.Beatmaps;
|
using osu.Game.Overlays.Profile.Sections.Beatmaps;
|
||||||
|
|
||||||
@ -21,6 +22,15 @@ namespace osu.Game.Overlays.Profile.Sections
|
|||||||
new PaginatedBeatmapContainer(BeatmapSetType.Unranked, User, "Pending Beatmaps"),
|
new PaginatedBeatmapContainer(BeatmapSetType.Unranked, User, "Pending Beatmaps"),
|
||||||
new PaginatedBeatmapContainer(BeatmapSetType.Graveyard, User, "Graveyarded Beatmaps"),
|
new PaginatedBeatmapContainer(BeatmapSetType.Graveyard, User, "Graveyarded Beatmaps"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
foreach (var paginatedBeatmapContainer in Children.OfType<PaginatedBeatmapContainer>())
|
||||||
|
{
|
||||||
|
paginatedBeatmapContainer.BeganPlayingPreview += _ =>
|
||||||
|
{
|
||||||
|
foreach (var bc in Children.OfType<PaginatedBeatmapContainer>())
|
||||||
|
bc.StopPlayingPreview();
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
protected override string Header => "Mouse";
|
protected override string Header => "Mouse";
|
||||||
|
|
||||||
private readonly BindableBool rawInputToggle = new BindableBool();
|
private readonly BindableBool rawInputToggle = new BindableBool();
|
||||||
private Bindable<string> activeInputHandlers;
|
private Bindable<string> ignoredInputHandler;
|
||||||
private SensitivitySetting sensitivity;
|
private SensitivitySetting sensitivity;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -61,20 +61,18 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
const string raw_mouse_handler = @"OpenTKRawMouseHandler";
|
const string raw_mouse_handler = @"OpenTKRawMouseHandler";
|
||||||
const string standard_mouse_handler = @"OpenTKMouseHandler";
|
const string standard_mouse_handler = @"OpenTKMouseHandler";
|
||||||
|
|
||||||
activeInputHandlers.Value = enabled ?
|
ignoredInputHandler.Value = enabled ? standard_mouse_handler : raw_mouse_handler;
|
||||||
activeInputHandlers.Value.Replace(standard_mouse_handler, raw_mouse_handler) :
|
|
||||||
activeInputHandlers.Value.Replace(raw_mouse_handler, standard_mouse_handler);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
activeInputHandlers = config.GetBindable<string>(FrameworkSetting.ActiveInputHandlers);
|
ignoredInputHandler = config.GetBindable<string>(FrameworkSetting.IgnoredInputHandlers);
|
||||||
activeInputHandlers.ValueChanged += handlers =>
|
ignoredInputHandler.ValueChanged += handler =>
|
||||||
{
|
{
|
||||||
bool raw = handlers.Contains("Raw");
|
bool raw = !handler.Contains("Raw");
|
||||||
rawInputToggle.Value = raw;
|
rawInputToggle.Value = raw;
|
||||||
sensitivity.Bindable.Disabled = !raw;
|
sensitivity.Bindable.Disabled = !raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
activeInputHandlers.TriggerChange();
|
ignoredInputHandler.TriggerChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SensitivitySetting : SettingsSlider<double, SensitivitySlider>
|
private class SensitivitySetting : SettingsSlider<double, SensitivitySlider>
|
||||||
|
@ -4,20 +4,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input;
|
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.MathUtils;
|
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Edit.Tools;
|
using osu.Game.Rulesets.Edit.Tools;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Screens.Edit.Screens.Compose;
|
|
||||||
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
||||||
using osu.Game.Screens.Edit.Screens.Compose.RadioButtons;
|
using osu.Game.Screens.Edit.Screens.Compose.RadioButtons;
|
||||||
|
|
||||||
@ -33,9 +29,6 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
private readonly List<Container> layerContainers = new List<Container>();
|
private readonly List<Container> layerContainers = new List<Container>();
|
||||||
|
|
||||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||||
private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor();
|
|
||||||
|
|
||||||
private IAdjustableClock adjustableClock;
|
|
||||||
|
|
||||||
protected HitObjectComposer(Ruleset ruleset)
|
protected HitObjectComposer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
@ -44,14 +37,9 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader]
|
||||||
private void load([NotNull] OsuGameBase osuGame, [NotNull] IAdjustableClock adjustableClock, [NotNull] IFrameBasedClock framedClock, [CanBeNull] BindableBeatDivisor beatDivisor)
|
private void load(OsuGameBase osuGame, IFrameBasedClock framedClock)
|
||||||
{
|
{
|
||||||
this.adjustableClock = adjustableClock;
|
|
||||||
|
|
||||||
if (beatDivisor != null)
|
|
||||||
this.beatDivisor.BindTo(beatDivisor);
|
|
||||||
|
|
||||||
beatmap.BindTo(osuGame.Beatmap);
|
beatmap.BindTo(osuGame.Beatmap);
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -135,106 +123,6 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnWheel(InputState state)
|
|
||||||
{
|
|
||||||
if (state.Mouse.WheelDelta > 0)
|
|
||||||
SeekBackward(true);
|
|
||||||
else
|
|
||||||
SeekForward(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Seeks the current time one beat-snapped beat-length backwards.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="snapped">Whether to snap to the closest beat.</param>
|
|
||||||
public void SeekBackward(bool snapped = false) => seek(-1, snapped);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Seeks the current time one beat-snapped beat-length forwards.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="snapped">Whether to snap to the closest beat.</param>
|
|
||||||
public void SeekForward(bool snapped = false) => seek(1, snapped);
|
|
||||||
|
|
||||||
private void seek(int direction, bool snapped)
|
|
||||||
{
|
|
||||||
var cpi = beatmap.Value.Beatmap.ControlPointInfo;
|
|
||||||
|
|
||||||
var timingPoint = cpi.TimingPointAt(adjustableClock.CurrentTime);
|
|
||||||
if (direction < 0 && timingPoint.Time == adjustableClock.CurrentTime)
|
|
||||||
{
|
|
||||||
// When going backwards and we're at the boundary of two timing points, we compute the seek distance with the timing point which we are seeking into
|
|
||||||
int activeIndex = cpi.TimingPoints.IndexOf(timingPoint);
|
|
||||||
while (activeIndex > 0 && adjustableClock.CurrentTime == timingPoint.Time)
|
|
||||||
timingPoint = cpi.TimingPoints[--activeIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
double seekAmount = timingPoint.BeatLength / beatDivisor;
|
|
||||||
double seekTime = adjustableClock.CurrentTime + seekAmount * direction;
|
|
||||||
|
|
||||||
if (!snapped || cpi.TimingPoints.Count == 0)
|
|
||||||
{
|
|
||||||
adjustableClock.Seek(seekTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We will be snapping to beats within timingPoint
|
|
||||||
seekTime -= timingPoint.Time;
|
|
||||||
|
|
||||||
// Determine the index from timingPoint of the closest beat to seekTime, accounting for scrolling direction
|
|
||||||
int closestBeat;
|
|
||||||
if (direction > 0)
|
|
||||||
closestBeat = (int)Math.Floor(seekTime / seekAmount);
|
|
||||||
else
|
|
||||||
closestBeat = (int)Math.Ceiling(seekTime / seekAmount);
|
|
||||||
|
|
||||||
seekTime = timingPoint.Time + closestBeat * seekAmount;
|
|
||||||
|
|
||||||
// Due to the rounding above, we may end up on the current beat. This will effectively cause 0 seeking to happen, but we don't want this.
|
|
||||||
// Instead, we'll go to the next beat in the direction when this is the case
|
|
||||||
if (Precision.AlmostEquals(adjustableClock.CurrentTime, seekTime))
|
|
||||||
{
|
|
||||||
closestBeat += direction > 0 ? 1 : -1;
|
|
||||||
seekTime = timingPoint.Time + closestBeat * seekAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (seekTime < timingPoint.Time && timingPoint != cpi.TimingPoints.First())
|
|
||||||
seekTime = timingPoint.Time;
|
|
||||||
|
|
||||||
var nextTimingPoint = cpi.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time);
|
|
||||||
if (seekTime > nextTimingPoint?.Time)
|
|
||||||
seekTime = nextTimingPoint.Time;
|
|
||||||
|
|
||||||
adjustableClock.Seek(seekTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SeekTo(double seekTime, bool snapped = false)
|
|
||||||
{
|
|
||||||
if (!snapped)
|
|
||||||
{
|
|
||||||
adjustableClock.Seek(seekTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var timingPoint = beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(seekTime);
|
|
||||||
double beatSnapLength = timingPoint.BeatLength / beatDivisor;
|
|
||||||
|
|
||||||
// We will be snapping to beats within the timing point
|
|
||||||
seekTime -= timingPoint.Time;
|
|
||||||
|
|
||||||
// Determine the index from the current timing point of the closest beat to seekTime
|
|
||||||
int closestBeat = (int)Math.Round(seekTime / beatSnapLength);
|
|
||||||
seekTime = timingPoint.Time + closestBeat * beatSnapLength;
|
|
||||||
|
|
||||||
// Depending on beatSnapLength, we may snap to a beat that is beyond timingPoint's end time, but we want to instead snap to
|
|
||||||
// the next timing point's start time
|
|
||||||
var nextTimingPoint = beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time);
|
|
||||||
if (seekTime > nextTimingPoint?.Time)
|
|
||||||
seekTime = nextTimingPoint.Time;
|
|
||||||
|
|
||||||
adjustableClock.Seek(seekTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool;
|
private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool;
|
||||||
|
|
||||||
protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true);
|
protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true);
|
||||||
|
@ -55,11 +55,9 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
|||||||
if (Beatmap.Value.Track.Length == double.PositiveInfinity) return;
|
if (Beatmap.Value.Track.Length == double.PositiveInfinity) return;
|
||||||
|
|
||||||
float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth);
|
float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth);
|
||||||
seekTo(markerPos / DrawWidth * Beatmap.Value.Track.Length);
|
adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void seekTo(double time) => adjustableClock.Seek(time);
|
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
@ -12,6 +12,7 @@ using osu.Game.Screens.Edit.Menus;
|
|||||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Screens.Edit.Screens;
|
using osu.Game.Screens.Edit.Screens;
|
||||||
@ -32,6 +33,10 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
private EditorScreen currentScreen;
|
private EditorScreen currentScreen;
|
||||||
|
|
||||||
|
private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor();
|
||||||
|
|
||||||
|
private EditorClock clock;
|
||||||
|
|
||||||
private DependencyContainer dependencies;
|
private DependencyContainer dependencies;
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
||||||
@ -42,11 +47,12 @@ namespace osu.Game.Screens.Edit
|
|||||||
{
|
{
|
||||||
// TODO: should probably be done at a RulesetContainer level to share logic with Player.
|
// TODO: should probably be done at a RulesetContainer level to share logic with Player.
|
||||||
var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
|
var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
|
||||||
var adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
|
clock = new EditorClock(Beatmap.Value.Beatmap.ControlPointInfo, beatDivisor) { IsCoupled = false };
|
||||||
adjustableClock.ChangeSource(sourceClock);
|
clock.ChangeSource(sourceClock);
|
||||||
|
|
||||||
dependencies.CacheAs<IAdjustableClock>(adjustableClock);
|
dependencies.CacheAs<IFrameBasedClock>(clock);
|
||||||
dependencies.CacheAs<IFrameBasedClock>(adjustableClock);
|
dependencies.CacheAs<IAdjustableClock>(clock);
|
||||||
|
dependencies.Cache(beatDivisor);
|
||||||
|
|
||||||
EditorMenuBar menuBar;
|
EditorMenuBar menuBar;
|
||||||
TimeInfoContainer timeInfo;
|
TimeInfoContainer timeInfo;
|
||||||
@ -147,7 +153,6 @@ namespace osu.Game.Screens.Edit
|
|||||||
menuBar.Mode.ValueChanged += onModeChanged;
|
menuBar.Mode.ValueChanged += onModeChanged;
|
||||||
|
|
||||||
bottomBackground.Colour = colours.Gray2;
|
bottomBackground.Colour = colours.Gray2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void exportBeatmap()
|
private void exportBeatmap()
|
||||||
@ -176,6 +181,15 @@ namespace osu.Game.Screens.Edit
|
|||||||
screenContainer.Add(currentScreen);
|
screenContainer.Add(currentScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool OnWheel(InputState state)
|
||||||
|
{
|
||||||
|
if (state.Mouse.WheelDelta > 0)
|
||||||
|
clock.SeekBackward(true);
|
||||||
|
else
|
||||||
|
clock.SeekForward(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnResuming(Screen last)
|
protected override void OnResuming(Screen last)
|
||||||
{
|
{
|
||||||
Beatmap.Value.Track?.Stop();
|
Beatmap.Value.Track?.Stop();
|
||||||
|
117
osu.Game/Screens/Edit/EditorClock.cs
Normal file
117
osu.Game/Screens/Edit/EditorClock.cs
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// 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;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.MathUtils;
|
||||||
|
using osu.Framework.Timing;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Screens.Edit.Screens.Compose;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A decoupled clock which adds editor-specific functionality, such as snapping to a user-defined beat divisor.
|
||||||
|
/// </summary>
|
||||||
|
public class EditorClock : DecoupleableInterpolatingFramedClock
|
||||||
|
{
|
||||||
|
public ControlPointInfo ControlPointInfo;
|
||||||
|
|
||||||
|
private readonly BindableBeatDivisor beatDivisor;
|
||||||
|
|
||||||
|
public EditorClock(ControlPointInfo controlPointInfo, BindableBeatDivisor beatDivisor)
|
||||||
|
{
|
||||||
|
this.beatDivisor = beatDivisor;
|
||||||
|
|
||||||
|
ControlPointInfo = controlPointInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Seek to the closest snappable beat from a time.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">The raw position which should be seeked around.</param>
|
||||||
|
/// <returns>Whether the seek could be performed.</returns>
|
||||||
|
public bool SeekSnapped(double position)
|
||||||
|
{
|
||||||
|
var timingPoint = ControlPointInfo.TimingPointAt(position);
|
||||||
|
double beatSnapLength = timingPoint.BeatLength / beatDivisor;
|
||||||
|
|
||||||
|
// We will be snapping to beats within the timing point
|
||||||
|
position -= timingPoint.Time;
|
||||||
|
|
||||||
|
// Determine the index from the current timing point of the closest beat to position
|
||||||
|
int closestBeat = (int)Math.Round(position / beatSnapLength);
|
||||||
|
position = timingPoint.Time + closestBeat * beatSnapLength;
|
||||||
|
|
||||||
|
// Depending on beatSnapLength, we may snap to a beat that is beyond timingPoint's end time, but we want to instead snap to
|
||||||
|
// the next timing point's start time
|
||||||
|
var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time);
|
||||||
|
if (position > nextTimingPoint?.Time)
|
||||||
|
position = nextTimingPoint.Time;
|
||||||
|
|
||||||
|
return Seek(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Seeks backwards by one beat length.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="snapped">Whether to snap to the closest beat after seeking.</param>
|
||||||
|
public void SeekBackward(bool snapped = false) => seek(-1, snapped);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Seeks forwards by one beat length.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="snapped">Whether to snap to the closest beat after seeking.</param>
|
||||||
|
public void SeekForward(bool snapped = false) => seek(1, snapped);
|
||||||
|
|
||||||
|
private void seek(int direction, bool snapped)
|
||||||
|
{
|
||||||
|
var timingPoint = ControlPointInfo.TimingPointAt(CurrentTime);
|
||||||
|
if (direction < 0 && timingPoint.Time == CurrentTime)
|
||||||
|
{
|
||||||
|
// When going backwards and we're at the boundary of two timing points, we compute the seek distance with the timing point which we are seeking into
|
||||||
|
int activeIndex = ControlPointInfo.TimingPoints.IndexOf(timingPoint);
|
||||||
|
while (activeIndex > 0 && CurrentTime == timingPoint.Time)
|
||||||
|
timingPoint = ControlPointInfo.TimingPoints[--activeIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
double seekAmount = timingPoint.BeatLength / beatDivisor;
|
||||||
|
double seekTime = CurrentTime + seekAmount * direction;
|
||||||
|
|
||||||
|
if (!snapped || ControlPointInfo.TimingPoints.Count == 0)
|
||||||
|
{
|
||||||
|
Seek(seekTime);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will be snapping to beats within timingPoint
|
||||||
|
seekTime -= timingPoint.Time;
|
||||||
|
|
||||||
|
// Determine the index from timingPoint of the closest beat to seekTime, accounting for scrolling direction
|
||||||
|
int closestBeat;
|
||||||
|
if (direction > 0)
|
||||||
|
closestBeat = (int)Math.Floor(seekTime / seekAmount);
|
||||||
|
else
|
||||||
|
closestBeat = (int)Math.Ceiling(seekTime / seekAmount);
|
||||||
|
|
||||||
|
seekTime = timingPoint.Time + closestBeat * seekAmount;
|
||||||
|
|
||||||
|
// Due to the rounding above, we may end up on the current beat. This will effectively cause 0 seeking to happen, but we don't want this.
|
||||||
|
// Instead, we'll go to the next beat in the direction when this is the case
|
||||||
|
if (Precision.AlmostEquals(CurrentTime, seekTime))
|
||||||
|
{
|
||||||
|
closestBeat += direction > 0 ? 1 : -1;
|
||||||
|
seekTime = timingPoint.Time + closestBeat * seekAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seekTime < timingPoint.Time && timingPoint != ControlPointInfo.TimingPoints.First())
|
||||||
|
seekTime = timingPoint.Time;
|
||||||
|
|
||||||
|
var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time);
|
||||||
|
if (seekTime > nextTimingPoint?.Time)
|
||||||
|
seekTime = nextTimingPoint.Time;
|
||||||
|
|
||||||
|
Seek(seekTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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 JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
@ -21,15 +22,11 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
|||||||
|
|
||||||
private Container composerContainer;
|
private Container composerContainer;
|
||||||
|
|
||||||
private DependencyContainer dependencies;
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load([CanBeNull] BindableBeatDivisor beatDivisor)
|
||||||
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
|
||||||
=> dependencies = new DependencyContainer(parent);
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
{
|
||||||
dependencies.Cache(beatDivisor);
|
if (beatDivisor != null)
|
||||||
|
this.beatDivisor.BindTo(beatDivisor);
|
||||||
|
|
||||||
ScrollableTimeline timeline;
|
ScrollableTimeline timeline;
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
|
@ -309,11 +309,6 @@ namespace osu.Game.Screens.Play
|
|||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
},
|
},
|
||||||
new MetadataLine("Composer", string.Empty)
|
|
||||||
{
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
},
|
|
||||||
new MetadataLine("Mapper", metadata.AuthorString)
|
new MetadataLine("Mapper", metadata.AuthorString)
|
||||||
{
|
{
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
|
@ -66,7 +66,7 @@ namespace osu.Game.Screens.Select
|
|||||||
get { return beatmapSets.Select(g => g.BeatmapSet); }
|
get { return beatmapSets.Select(g => g.BeatmapSet); }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
CarouselGroup newRoot = new CarouselGroupEagerSelect();
|
CarouselRoot newRoot = new CarouselRoot(this);
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
@ -102,10 +102,11 @@ namespace osu.Game.Screens.Select
|
|||||||
private readonly Stack<CarouselBeatmap> randomSelectedBeatmaps = new Stack<CarouselBeatmap>();
|
private readonly Stack<CarouselBeatmap> randomSelectedBeatmaps = new Stack<CarouselBeatmap>();
|
||||||
|
|
||||||
protected List<DrawableCarouselItem> Items = new List<DrawableCarouselItem>();
|
protected List<DrawableCarouselItem> Items = new List<DrawableCarouselItem>();
|
||||||
private CarouselGroup root = new CarouselGroupEagerSelect();
|
private CarouselRoot root;
|
||||||
|
|
||||||
public BeatmapCarousel()
|
public BeatmapCarousel()
|
||||||
{
|
{
|
||||||
|
root = new CarouselRoot(this);
|
||||||
Child = new OsuContextMenuContainer
|
Child = new OsuContextMenuContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
@ -627,5 +628,23 @@ namespace osu.Game.Screens.Select
|
|||||||
// layer transformations on top, with a similar reasoning to the previous comment.
|
// layer transformations on top, with a similar reasoning to the previous comment.
|
||||||
p.SetMultiplicativeAlpha(MathHelper.Clamp(1.75f - 1.5f * dist, 0, 1));
|
p.SetMultiplicativeAlpha(MathHelper.Clamp(1.75f - 1.5f * dist, 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class CarouselRoot : CarouselGroupEagerSelect
|
||||||
|
{
|
||||||
|
private readonly BeatmapCarousel carousel;
|
||||||
|
|
||||||
|
public CarouselRoot(BeatmapCarousel carousel)
|
||||||
|
{
|
||||||
|
this.carousel = carousel;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PerformSelection()
|
||||||
|
{
|
||||||
|
if (LastSelected == null)
|
||||||
|
carousel.SelectNextRandom();
|
||||||
|
else
|
||||||
|
base.PerformSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,16 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The last selected item.
|
||||||
|
/// </summary>
|
||||||
|
protected CarouselItem LastSelected { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// We need to keep track of the index for cases where the selection is removed but we want to select a new item based on its old location.
|
/// We need to keep track of the index for cases where the selection is removed but we want to select a new item based on its old location.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int lastSelectedIndex;
|
private int lastSelectedIndex;
|
||||||
|
|
||||||
private CarouselItem lastSelected;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// To avoid overhead during filter operations, we don't attempt any selections until after all
|
/// To avoid overhead during filter operations, we don't attempt any selections until after all
|
||||||
/// children have been filtered. This bool will be true during the base <see cref="Filter(FilterCriteria)"/>
|
/// children have been filtered. This bool will be true during the base <see cref="Filter(FilterCriteria)"/>
|
||||||
@ -47,7 +50,7 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
{
|
{
|
||||||
base.RemoveChild(i);
|
base.RemoveChild(i);
|
||||||
|
|
||||||
if (i != lastSelected)
|
if (i != LastSelected)
|
||||||
updateSelectedIndex();
|
updateSelectedIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +86,11 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
// we only perform eager selection if none of our children are in a selected state already.
|
// we only perform eager selection if none of our children are in a selected state already.
|
||||||
if (Children.Any(i => i.State == CarouselItemState.Selected)) return;
|
if (Children.Any(i => i.State == CarouselItemState.Selected)) return;
|
||||||
|
|
||||||
|
PerformSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void PerformSelection()
|
||||||
|
{
|
||||||
CarouselItem nextToSelect =
|
CarouselItem nextToSelect =
|
||||||
Children.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered) ??
|
Children.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered) ??
|
||||||
Children.Reverse().Skip(InternalChildren.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered);
|
Children.Reverse().Skip(InternalChildren.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered);
|
||||||
@ -95,10 +103,10 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
|
|
||||||
private void updateSelected(CarouselItem newSelection)
|
private void updateSelected(CarouselItem newSelection)
|
||||||
{
|
{
|
||||||
lastSelected = newSelection;
|
LastSelected = newSelection;
|
||||||
updateSelectedIndex();
|
updateSelectedIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSelectedIndex() => lastSelectedIndex = lastSelected == null ? 0 : Math.Max(0, InternalChildren.IndexOf(lastSelected));
|
private void updateSelectedIndex() => lastSelectedIndex = LastSelected == null ? 0 : Math.Max(0, InternalChildren.IndexOf(LastSelected));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
79
osu.Game/Tests/Visual/EditorClockTestCase.cs
Normal file
79
osu.Game/Tests/Visual/EditorClockTestCase.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Framework.Timing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Screens.Edit;
|
||||||
|
using osu.Game.Screens.Edit.Screens.Compose;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a clock, beat-divisor, and scrolling capability for test cases of editor components that
|
||||||
|
/// are preferrably tested within the presence of a clock and seek controls.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class EditorClockTestCase : OsuTestCase
|
||||||
|
{
|
||||||
|
protected readonly BindableBeatDivisor BeatDivisor = new BindableBeatDivisor();
|
||||||
|
protected readonly EditorClock Clock;
|
||||||
|
|
||||||
|
private DependencyContainer dependencies;
|
||||||
|
|
||||||
|
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
||||||
|
=> dependencies = new DependencyContainer(parent);
|
||||||
|
|
||||||
|
private OsuGameBase osuGame;
|
||||||
|
|
||||||
|
protected EditorClockTestCase()
|
||||||
|
{
|
||||||
|
Clock = new EditorClock(new ControlPointInfo(), BeatDivisor) { IsCoupled = false };
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuGameBase osuGame)
|
||||||
|
{
|
||||||
|
this.osuGame = osuGame;
|
||||||
|
|
||||||
|
dependencies.Cache(BeatDivisor);
|
||||||
|
dependencies.CacheAs<IFrameBasedClock>(Clock);
|
||||||
|
dependencies.CacheAs<IAdjustableClock>(Clock);
|
||||||
|
|
||||||
|
osuGame.Beatmap.ValueChanged += beatmapChanged;
|
||||||
|
beatmapChanged(osuGame.Beatmap.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void beatmapChanged(WorkingBeatmap working)
|
||||||
|
{
|
||||||
|
Clock.ControlPointInfo = working.Beatmap.ControlPointInfo;
|
||||||
|
Clock.ChangeSource((IAdjustableClock)working.Track ?? new StopwatchClock());
|
||||||
|
Clock.ProcessFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
Clock.ProcessFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnWheel(InputState state)
|
||||||
|
{
|
||||||
|
if (state.Mouse.WheelDelta > 0)
|
||||||
|
Clock.SeekBackward(true);
|
||||||
|
else
|
||||||
|
Clock.SeekForward(true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
osuGame.Beatmap.ValueChanged -= beatmapChanged;
|
||||||
|
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.0.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.0.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.18.1" />
|
<PackageReference Include="SharpCompress" Version="0.18.1" />
|
||||||
<PackageReference Include="NUnit" Version="3.8.1" />
|
<PackageReference Include="NUnit" Version="3.10.1" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="4.4.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="4.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -15,7 +15,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.1" />
|
||||||
<PackageReference Include="DeepEqual" Version="1.6.0" />
|
<PackageReference Include="DeepEqual" Version="1.6.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.1" />
|
||||||
<PackageReference Include="NUnit" Version="3.8.1" />
|
<PackageReference Include="NUnit" Version="3.10.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user