mirror of
https://github.com/ppy/osu.git
synced 2025-02-21 03:02:54 +08:00
Merge remote-tracking branch 'upstream/master' into tgi74-ctb_hr_mangling
This commit is contained in:
commit
d307b8dc2e
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
|
46
app.manifest
Normal file
46
app.manifest
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="osu!" />
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||||
|
</requestedPrivileges>
|
||||||
|
<applicationRequestMinimum>
|
||||||
|
<defaultAssemblyRequest permissionSetReference="Custom" />
|
||||||
|
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
|
||||||
|
</applicationRequestMinimum>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- Windows Vista -->
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||||
|
<!-- Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||||
|
<!-- Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
<asmv3:application>
|
||||||
|
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||||
|
<dpiAware>true</dpiAware>
|
||||||
|
</asmv3:windowsSettings>
|
||||||
|
</asmv3:application>
|
||||||
|
<dependency>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity
|
||||||
|
type="win32"
|
||||||
|
name="Microsoft.Windows.Common-Controls"
|
||||||
|
version="6.0.0.0"
|
||||||
|
processorArchitecture="*"
|
||||||
|
publicKeyToken="6595b64144ccf1df"
|
||||||
|
language="*"
|
||||||
|
/>
|
||||||
|
</dependentAssembly>
|
||||||
|
</dependency>
|
||||||
|
</asmv1:assembly>
|
@ -1 +1 @@
|
|||||||
Subproject commit 02d7a0fa4798d197cd08570ee48951edbb7c7860
|
Subproject commit 16e6a453db9a8f4454238a2911eb5f1444b7ec2a
|
@ -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>
|
||||||
|
@ -12,6 +12,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Rulesets.Catch.Replays;
|
using osu.Game.Rulesets.Catch.Replays;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
|
using osu.Game.Beatmaps.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch
|
namespace osu.Game.Rulesets.Catch
|
||||||
{
|
{
|
||||||
@ -29,6 +30,44 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
new KeyBinding(InputKey.Shift, CatchAction.Dash),
|
new KeyBinding(InputKey.Shift, CatchAction.Dash),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
|
||||||
|
{
|
||||||
|
if (mods.HasFlag(LegacyMods.Nightcore))
|
||||||
|
yield return new CatchModNightcore();
|
||||||
|
else if (mods.HasFlag(LegacyMods.DoubleTime))
|
||||||
|
yield return new CatchModDoubleTime();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Autoplay))
|
||||||
|
yield return new CatchModAutoplay();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Easy))
|
||||||
|
yield return new CatchModEasy();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Flashlight))
|
||||||
|
yield return new CatchModFlashlight();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.HalfTime))
|
||||||
|
yield return new CatchModHalfTime();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.HardRock))
|
||||||
|
yield return new CatchModHardRock();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Hidden))
|
||||||
|
yield return new CatchModHidden();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.NoFail))
|
||||||
|
yield return new CatchModNoFail();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Perfect))
|
||||||
|
yield return new CatchModPerfect();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Relax))
|
||||||
|
yield return new CatchModRelax();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.SuddenDeath))
|
||||||
|
yield return new CatchModSuddenDeath();
|
||||||
|
}
|
||||||
|
|
||||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -14,6 +14,7 @@ using osu.Framework.Input.Bindings;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Replays;
|
using osu.Game.Rulesets.Mania.Replays;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
|
using osu.Game.Beatmaps.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania
|
namespace osu.Game.Rulesets.Mania
|
||||||
{
|
{
|
||||||
@ -21,6 +22,74 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
{
|
{
|
||||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaRulesetContainer(this, beatmap, isForCurrentRuleset);
|
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaRulesetContainer(this, beatmap, isForCurrentRuleset);
|
||||||
|
|
||||||
|
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
|
||||||
|
{
|
||||||
|
if (mods.HasFlag(LegacyMods.Nightcore))
|
||||||
|
yield return new ManiaModNightcore();
|
||||||
|
else if (mods.HasFlag(LegacyMods.DoubleTime))
|
||||||
|
yield return new ManiaModDoubleTime();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Autoplay))
|
||||||
|
yield return new ManiaModAutoplay();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Easy))
|
||||||
|
yield return new ManiaModEasy();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.FadeIn))
|
||||||
|
yield return new ManiaModFadeIn();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Flashlight))
|
||||||
|
yield return new ManiaModFlashlight();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.HalfTime))
|
||||||
|
yield return new ManiaModHalfTime();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.HardRock))
|
||||||
|
yield return new ManiaModHardRock();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Hidden))
|
||||||
|
yield return new ManiaModHidden();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Key1))
|
||||||
|
yield return new ManiaModKey1();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Key2))
|
||||||
|
yield return new ManiaModKey2();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Key3))
|
||||||
|
yield return new ManiaModKey3();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Key4))
|
||||||
|
yield return new ManiaModKey4();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Key5))
|
||||||
|
yield return new ManiaModKey5();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Key6))
|
||||||
|
yield return new ManiaModKey6();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Key7))
|
||||||
|
yield return new ManiaModKey7();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Key8))
|
||||||
|
yield return new ManiaModKey8();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Key9))
|
||||||
|
yield return new ManiaModKey9();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.NoFail))
|
||||||
|
yield return new ManiaModNoFail();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Perfect))
|
||||||
|
yield return new ManiaModPerfect();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Random))
|
||||||
|
yield return new ManiaModRandom();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.SuddenDeath))
|
||||||
|
yield return new ManiaModSuddenDeath();
|
||||||
|
}
|
||||||
|
|
||||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -21,6 +21,7 @@ using osu.Game.Rulesets.Objects.Types;
|
|||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Replays;
|
using osu.Game.Rulesets.Osu.Replays;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
|
using osu.Game.Beatmaps.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu
|
namespace osu.Game.Rulesets.Osu
|
||||||
{
|
{
|
||||||
@ -66,6 +67,53 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
|
||||||
|
{
|
||||||
|
if (mods.HasFlag(LegacyMods.Nightcore))
|
||||||
|
yield return new OsuModNightcore();
|
||||||
|
else if (mods.HasFlag(LegacyMods.DoubleTime))
|
||||||
|
yield return new OsuModDoubleTime();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Autopilot))
|
||||||
|
yield return new OsuModAutopilot();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Autoplay))
|
||||||
|
yield return new OsuModAutoplay();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Easy))
|
||||||
|
yield return new OsuModEasy();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Flashlight))
|
||||||
|
yield return new OsuModFlashlight();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.HalfTime))
|
||||||
|
yield return new OsuModHalfTime();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.HardRock))
|
||||||
|
yield return new OsuModHardRock();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Hidden))
|
||||||
|
yield return new OsuModHidden();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.NoFail))
|
||||||
|
yield return new OsuModNoFail();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Perfect))
|
||||||
|
yield return new OsuModPerfect();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Relax))
|
||||||
|
yield return new OsuModRelax();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.SpunOut))
|
||||||
|
yield return new OsuModSpunOut();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.SuddenDeath))
|
||||||
|
yield return new OsuModSuddenDeath();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Target))
|
||||||
|
yield return new OsuModTarget();
|
||||||
|
}
|
||||||
|
|
||||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -12,6 +12,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
using osu.Game.Rulesets.Taiko.Replays;
|
using osu.Game.Rulesets.Taiko.Replays;
|
||||||
|
using osu.Game.Beatmaps.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko
|
namespace osu.Game.Rulesets.Taiko
|
||||||
{
|
{
|
||||||
@ -31,6 +32,44 @@ namespace osu.Game.Rulesets.Taiko
|
|||||||
new KeyBinding(InputKey.MouseRight, TaikoAction.RightRim),
|
new KeyBinding(InputKey.MouseRight, TaikoAction.RightRim),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
|
||||||
|
{
|
||||||
|
if (mods.HasFlag(LegacyMods.Nightcore))
|
||||||
|
yield return new TaikoModNightcore();
|
||||||
|
else if (mods.HasFlag(LegacyMods.DoubleTime))
|
||||||
|
yield return new TaikoModDoubleTime();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Autoplay))
|
||||||
|
yield return new TaikoModAutoplay();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Easy))
|
||||||
|
yield return new TaikoModEasy();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Flashlight))
|
||||||
|
yield return new TaikoModFlashlight();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.HalfTime))
|
||||||
|
yield return new TaikoModHalfTime();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.HardRock))
|
||||||
|
yield return new TaikoModHardRock();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Hidden))
|
||||||
|
yield return new TaikoModHidden();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.NoFail))
|
||||||
|
yield return new TaikoModNoFail();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Perfect))
|
||||||
|
yield return new TaikoModPerfect();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.Relax))
|
||||||
|
yield return new TaikoModRelax();
|
||||||
|
|
||||||
|
if (mods.HasFlag(LegacyMods.SuddenDeath))
|
||||||
|
yield return new TaikoModSuddenDeath();
|
||||||
|
}
|
||||||
|
|
||||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
62
osu.Game.Tests/Visual/TestCaseBadgeContainer.cs
Normal file
62
osu.Game.Tests/Visual/TestCaseBadgeContainer.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Overlays.Profile.Header;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestCaseBadgeContainer : OsuTestCase
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(BadgeContainer) };
|
||||||
|
|
||||||
|
public TestCaseBadgeContainer()
|
||||||
|
{
|
||||||
|
BadgeContainer badgeContainer;
|
||||||
|
|
||||||
|
Child = badgeContainer = new BadgeContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep("Show 1 badge", () => badgeContainer.ShowBadges(new[]
|
||||||
|
{
|
||||||
|
new Badge
|
||||||
|
{
|
||||||
|
AwardedAt = DateTimeOffset.Now,
|
||||||
|
Description = "Appreciates compasses",
|
||||||
|
ImageUrl = "https://assets.ppy.sh/profile-badges/mg2018-1star.png",
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
AddStep("Show 2 badges", () => badgeContainer.ShowBadges(new[]
|
||||||
|
{
|
||||||
|
new Badge
|
||||||
|
{
|
||||||
|
AwardedAt = DateTimeOffset.Now,
|
||||||
|
Description = "Contributed to osu!lazer testing",
|
||||||
|
ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.png",
|
||||||
|
},
|
||||||
|
new Badge
|
||||||
|
{
|
||||||
|
AwardedAt = DateTimeOffset.Now,
|
||||||
|
Description = "Appreciates compasses",
|
||||||
|
ImageUrl = "https://assets.ppy.sh/profile-badges/mg2018-1star.png",
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
AddStep("Show many badges", () => badgeContainer.ShowBadges(Enumerable.Range(1, 20).Select(i => new Badge
|
||||||
|
{
|
||||||
|
AwardedAt = DateTimeOffset.Now,
|
||||||
|
Description = $"Contributed to osu!lazer testing {i} times",
|
||||||
|
ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg",
|
||||||
|
}).ToArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
// 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 osu.Game.Overlays.Profile;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
@ -11,6 +10,7 @@ using System.Collections.Generic;
|
|||||||
using System;
|
using System;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Overlays.Profile.Header;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
|
@ -8,6 +8,7 @@ using NUnit.Framework;
|
|||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Profile;
|
using osu.Game.Overlays.Profile;
|
||||||
|
using osu.Game.Overlays.Profile.Header;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
@ -23,6 +24,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
typeof(UserProfileOverlay),
|
typeof(UserProfileOverlay),
|
||||||
typeof(RankGraph),
|
typeof(RankGraph),
|
||||||
typeof(LineGraph),
|
typeof(LineGraph),
|
||||||
|
typeof(BadgeContainer)
|
||||||
};
|
};
|
||||||
|
|
||||||
public TestCaseUserProfile()
|
public TestCaseUserProfile()
|
||||||
@ -53,6 +55,15 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
Mode = @"osu",
|
Mode = @"osu",
|
||||||
Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
|
Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
|
||||||
|
},
|
||||||
|
Badges = new[]
|
||||||
|
{
|
||||||
|
new Badge
|
||||||
|
{
|
||||||
|
AwardedAt = DateTimeOffset.FromUnixTimeSeconds(1505741569),
|
||||||
|
Description = "Outstanding help by being a voluntary test subject.",
|
||||||
|
ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, false));
|
}, false));
|
||||||
|
|
||||||
|
54
osu.Game.Tests/Visual/TestCaseWaveContainer.cs
Normal file
54
osu.Game.Tests/Visual/TestCaseWaveContainer.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.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 OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
[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,
|
||||||
|
TextSize = 20,
|
||||||
|
Text = @"Wave Container",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep(@"show", container.Show);
|
||||||
|
AddStep(@"hide", container.Hide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,9 @@
|
|||||||
<PropertyGroup Label="C#">
|
<PropertyGroup Label="C#">
|
||||||
<LangVersion>7</LangVersion>
|
<LangVersion>7</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationManifest>..\app.manifest</ApplicationManifest>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup Label="License">
|
<ItemGroup Label="License">
|
||||||
<None Include="..\osu.licenseheader">
|
<None Include="..\osu.licenseheader">
|
||||||
<Link>osu.licenseheader</Link>
|
<Link>osu.licenseheader</Link>
|
||||||
|
42
osu.Game/Beatmaps/Legacy/LegacyMods.cs
Normal file
42
osu.Game/Beatmaps/Legacy/LegacyMods.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps.Legacy
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum LegacyMods
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
NoFail = 1 << 0,
|
||||||
|
Easy = 1 << 1,
|
||||||
|
TouchDevice = 1 << 2,
|
||||||
|
Hidden = 1 << 3,
|
||||||
|
HardRock = 1 << 4,
|
||||||
|
SuddenDeath = 1 << 5,
|
||||||
|
DoubleTime = 1 << 6,
|
||||||
|
Relax = 1 << 7,
|
||||||
|
HalfTime = 1 << 8,
|
||||||
|
Nightcore = 1 << 9,
|
||||||
|
Flashlight = 1 << 10,
|
||||||
|
Autoplay = 1 << 11,
|
||||||
|
SpunOut = 1 << 12,
|
||||||
|
Autopilot = 1 << 13,
|
||||||
|
Perfect = 1 << 14,
|
||||||
|
Key4 = 1 << 15,
|
||||||
|
Key5 = 1 << 16,
|
||||||
|
Key6 = 1 << 17,
|
||||||
|
Key7 = 1 << 18,
|
||||||
|
Key8 = 1 << 19,
|
||||||
|
FadeIn = 1 << 20,
|
||||||
|
Random = 1 << 21,
|
||||||
|
Cinema = 1 << 22,
|
||||||
|
Target = 1 << 23,
|
||||||
|
Key9 = 1 << 24,
|
||||||
|
KeyCoop = 1 << 25,
|
||||||
|
Key1 = 1 << 26,
|
||||||
|
Key3 = 1 << 27,
|
||||||
|
Key2 = 1 << 28,
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +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 System.ComponentModel;
|
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps
|
|
||||||
{
|
|
||||||
public enum RankStatus
|
|
||||||
{
|
|
||||||
Any = 7,
|
|
||||||
[Description("Ranked & Approved")]
|
|
||||||
RankedApproved = 0,
|
|
||||||
Approved = 1,
|
|
||||||
Loved = 8,
|
|
||||||
Favourites = 2,
|
|
||||||
[Description("Mod Requests")]
|
|
||||||
ModRequests = 3,
|
|
||||||
Pending = 4,
|
|
||||||
Graveyard = 5,
|
|
||||||
[Description("My Maps")]
|
|
||||||
MyMaps = 6,
|
|
||||||
}
|
|
||||||
}
|
|
@ -84,6 +84,7 @@ namespace osu.Game.Configuration
|
|||||||
Set(OsuSetting.Version, string.Empty);
|
Set(OsuSetting.Version, string.Empty);
|
||||||
|
|
||||||
Set(OsuSetting.ScreenshotFormat, ScreenshotFormat.Jpg);
|
Set(OsuSetting.ScreenshotFormat, ScreenshotFormat.Jpg);
|
||||||
|
Set(OsuSetting.ScreenshotCaptureMenuCursor, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsuConfigManager(Storage storage) : base(storage)
|
public OsuConfigManager(Storage storage) : base(storage)
|
||||||
@ -128,6 +129,7 @@ namespace osu.Game.Configuration
|
|||||||
ShowConvertedBeatmaps,
|
ShowConvertedBeatmaps,
|
||||||
SpeedChangeVisualisation,
|
SpeedChangeVisualisation,
|
||||||
Skin,
|
Skin,
|
||||||
ScreenshotFormat
|
ScreenshotFormat,
|
||||||
|
ScreenshotCaptureMenuCursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,11 +35,13 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when a new <see cref="TModel"/> becomes available in the database.
|
/// Fired when a new <see cref="TModel"/> becomes available in the database.
|
||||||
|
/// This is not guaranteed to run on the update thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<TModel> ItemAdded;
|
public event Action<TModel> ItemAdded;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when a <see cref="TModel"/> is removed from the database.
|
/// Fired when a <see cref="TModel"/> is removed from the database.
|
||||||
|
/// This is not guaranteed to run on the update thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<TModel> ItemRemoved;
|
public event Action<TModel> ItemRemoved;
|
||||||
|
|
||||||
|
167
osu.Game/Graphics/Containers/WaveContainer.cs
Normal file
167
osu.Game/Graphics/Containers/WaveContainer.cs
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
// 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 osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
public class WaveContainer : VisibilityContainer
|
||||||
|
{
|
||||||
|
public const float APPEAR_DURATION = 800;
|
||||||
|
public const float DISAPPEAR_DURATION = 500;
|
||||||
|
|
||||||
|
private const Easing easing_show = Easing.OutSine;
|
||||||
|
private const Easing easing_hide = Easing.InSine;
|
||||||
|
|
||||||
|
private readonly Wave firstWave;
|
||||||
|
private readonly Wave secondWave;
|
||||||
|
private readonly Wave thirdWave;
|
||||||
|
private readonly Wave fourthWave;
|
||||||
|
|
||||||
|
private readonly Container<Wave> wavesContainer;
|
||||||
|
private readonly Container contentContainer;
|
||||||
|
|
||||||
|
protected override Container<Drawable> Content => contentContainer;
|
||||||
|
|
||||||
|
public Color4 FirstWaveColour
|
||||||
|
{
|
||||||
|
get => firstWave.Colour;
|
||||||
|
set => firstWave.Colour = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color4 SecondWaveColour
|
||||||
|
{
|
||||||
|
get => secondWave.Colour;
|
||||||
|
set => secondWave.Colour = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color4 ThirdWaveColour
|
||||||
|
{
|
||||||
|
get => thirdWave.Colour;
|
||||||
|
set => thirdWave.Colour = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color4 FourthWaveColour
|
||||||
|
{
|
||||||
|
get => fourthWave.Colour;
|
||||||
|
set => fourthWave.Colour = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WaveContainer()
|
||||||
|
{
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
|
AddInternal(wavesContainer = new Container<Wave>
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Masking = true,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
firstWave = new Wave
|
||||||
|
{
|
||||||
|
Rotation = 13,
|
||||||
|
FinalPosition = -930,
|
||||||
|
},
|
||||||
|
secondWave = new Wave
|
||||||
|
{
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Rotation = -7,
|
||||||
|
FinalPosition = -560,
|
||||||
|
},
|
||||||
|
thirdWave = new Wave
|
||||||
|
{
|
||||||
|
Rotation = 4,
|
||||||
|
FinalPosition = -390,
|
||||||
|
},
|
||||||
|
fourthWave = new Wave
|
||||||
|
{
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Rotation = -2,
|
||||||
|
FinalPosition = -220,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
AddInternal(contentContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopIn()
|
||||||
|
{
|
||||||
|
foreach (var w in wavesContainer.Children)
|
||||||
|
w.State = Visibility.Visible;
|
||||||
|
|
||||||
|
this.FadeIn(100, Easing.OutQuint);
|
||||||
|
contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint);
|
||||||
|
|
||||||
|
this.FadeIn(100, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopOut()
|
||||||
|
{
|
||||||
|
this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint);
|
||||||
|
contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, Easing.In);
|
||||||
|
|
||||||
|
foreach (var w in wavesContainer.Children)
|
||||||
|
w.State = Visibility.Hidden;
|
||||||
|
|
||||||
|
this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateAfterChildren()
|
||||||
|
{
|
||||||
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
|
// This is done as an optimization, such that invisible parts of the waves
|
||||||
|
// are masked away, and thus do not consume fill rate.
|
||||||
|
wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Wave : VisibilityContainer
|
||||||
|
{
|
||||||
|
public float FinalPosition;
|
||||||
|
|
||||||
|
protected override bool StartHidden => true;
|
||||||
|
|
||||||
|
public Wave()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
Width = 1.5f;
|
||||||
|
Masking = true;
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Shadow,
|
||||||
|
Colour = Color4.Black.Opacity(50),
|
||||||
|
Radius = 20f,
|
||||||
|
};
|
||||||
|
|
||||||
|
Child = new Box { RelativeSizeAxes = Axes.Both };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
// We can not use RelativeSizeAxes for Height, because the height
|
||||||
|
// of our parent diminishes as the content moves up.
|
||||||
|
Height = Parent.Parent.DrawSize.Y * 1.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopIn() => this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show);
|
||||||
|
protected override void PopOut() => this.MoveToY(Parent.Parent.DrawSize.Y, DISAPPEAR_DURATION, easing_hide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@ namespace osu.Game.Graphics.Cursor
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether any cursors can be displayed.
|
/// Whether any cursors can be displayed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanShowCursor = true;
|
internal bool CanShowCursor = true;
|
||||||
|
|
||||||
public CursorContainer Cursor { get; }
|
public CursorContainer Cursor { get; }
|
||||||
public bool ProvidingUserCursor => true;
|
public bool ProvidingUserCursor => true;
|
||||||
|
@ -12,12 +12,16 @@ using osu.Framework.Input;
|
|||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Cursor
|
namespace osu.Game.Graphics.Cursor
|
||||||
{
|
{
|
||||||
public class MenuCursor : CursorContainer
|
public class MenuCursor : CursorContainer
|
||||||
{
|
{
|
||||||
|
private readonly IBindable<bool> screenshotCursorVisibility = new Bindable<bool>(true);
|
||||||
|
public override bool IsPresent => screenshotCursorVisibility.Value && base.IsPresent;
|
||||||
|
|
||||||
protected override Drawable CreateCursor() => new Cursor();
|
protected override Drawable CreateCursor() => new Cursor();
|
||||||
|
|
||||||
private Bindable<bool> cursorRotate;
|
private Bindable<bool> cursorRotate;
|
||||||
@ -25,6 +29,15 @@ namespace osu.Game.Graphics.Cursor
|
|||||||
|
|
||||||
private bool startRotation;
|
private bool startRotation;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load([NotNull] OsuConfigManager config, [CanBeNull] ScreenshotManager screenshotManager)
|
||||||
|
{
|
||||||
|
cursorRotate = config.GetBindable<bool>(OsuSetting.CursorRotation);
|
||||||
|
|
||||||
|
if (screenshotManager != null)
|
||||||
|
screenshotCursorVisibility.BindTo(screenshotManager.CursorVisibility);
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool OnMouseMove(InputState state)
|
protected override bool OnMouseMove(InputState state)
|
||||||
{
|
{
|
||||||
if (cursorRotate && dragging)
|
if (cursorRotate && dragging)
|
||||||
@ -104,12 +117,6 @@ namespace osu.Game.Graphics.Cursor
|
|||||||
ActiveCursor.ScaleTo(0.6f, 250, Easing.In);
|
ActiveCursor.ScaleTo(0.6f, 250, Easing.In);
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuConfigManager config)
|
|
||||||
{
|
|
||||||
cursorRotate = config.GetBindable<bool>(OsuSetting.CursorRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Cursor : Container
|
public class Cursor : Container
|
||||||
{
|
{
|
||||||
private Container cursorContainer;
|
private Container cursorContainer;
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
@ -12,6 +14,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
@ -21,7 +24,17 @@ namespace osu.Game.Graphics
|
|||||||
{
|
{
|
||||||
public class ScreenshotManager : Container, IKeyBindingHandler<GlobalAction>, IHandleGlobalInput
|
public class ScreenshotManager : Container, IKeyBindingHandler<GlobalAction>, IHandleGlobalInput
|
||||||
{
|
{
|
||||||
|
private readonly BindableBool cursorVisibility = new BindableBool(true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changed when screenshots are being or have finished being taken, to control whether cursors should be visible.
|
||||||
|
/// If cursors should not be visible, cursors have 3 frames to hide themselves.
|
||||||
|
/// </summary>
|
||||||
|
public IBindable<bool> CursorVisibility => cursorVisibility;
|
||||||
|
|
||||||
private Bindable<ScreenshotFormat> screenshotFormat;
|
private Bindable<ScreenshotFormat> screenshotFormat;
|
||||||
|
private Bindable<bool> captureMenuCursor;
|
||||||
|
|
||||||
private GameHost host;
|
private GameHost host;
|
||||||
private Storage storage;
|
private Storage storage;
|
||||||
private NotificationOverlay notificationOverlay;
|
private NotificationOverlay notificationOverlay;
|
||||||
@ -36,6 +49,7 @@ namespace osu.Game.Graphics
|
|||||||
this.notificationOverlay = notificationOverlay;
|
this.notificationOverlay = notificationOverlay;
|
||||||
|
|
||||||
screenshotFormat = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat);
|
screenshotFormat = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat);
|
||||||
|
captureMenuCursor = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor);
|
||||||
|
|
||||||
shutter = audio.Sample.Get("UI/shutter");
|
shutter = audio.Sample.Get("UI/shutter");
|
||||||
}
|
}
|
||||||
@ -55,10 +69,31 @@ namespace osu.Game.Graphics
|
|||||||
|
|
||||||
public bool OnReleased(GlobalAction action) => false;
|
public bool OnReleased(GlobalAction action) => false;
|
||||||
|
|
||||||
public async void TakeScreenshotAsync()
|
private volatile int screenShotTasks;
|
||||||
|
|
||||||
|
public async Task TakeScreenshotAsync() => await Task.Run(async () =>
|
||||||
{
|
{
|
||||||
|
Interlocked.Increment(ref screenShotTasks);
|
||||||
|
|
||||||
|
if (!captureMenuCursor.Value)
|
||||||
|
{
|
||||||
|
cursorVisibility.Value = false;
|
||||||
|
|
||||||
|
// We need to wait for at most 3 draw nodes to be drawn, following which we can be assured at least one DrawNode has been generated/drawn with the set value
|
||||||
|
const int frames_to_wait = 3;
|
||||||
|
|
||||||
|
int framesWaited = 0;
|
||||||
|
ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => framesWaited++, 0, true);
|
||||||
|
while (framesWaited < frames_to_wait)
|
||||||
|
Thread.Sleep(10);
|
||||||
|
|
||||||
|
waitDelegate.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
using (var bitmap = await host.TakeScreenshotAsync())
|
using (var bitmap = await host.TakeScreenshotAsync())
|
||||||
{
|
{
|
||||||
|
Interlocked.Decrement(ref screenShotTasks);
|
||||||
|
|
||||||
var fileName = getFileName();
|
var fileName = getFileName();
|
||||||
if (fileName == null) return;
|
if (fileName == null) return;
|
||||||
|
|
||||||
@ -86,6 +121,14 @@ namespace osu.Game.Graphics
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (cursorVisibility == false && Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0)
|
||||||
|
cursorVisibility.Value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getFileName()
|
private string getFileName()
|
||||||
|
@ -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
|
||||||
|
@ -2,7 +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 osu.Game.Beatmaps;
|
using System.ComponentModel;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Direct;
|
using osu.Game.Overlays.Direct;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -13,21 +13,36 @@ namespace osu.Game.Online.API.Requests
|
|||||||
{
|
{
|
||||||
private readonly string query;
|
private readonly string query;
|
||||||
private readonly RulesetInfo ruleset;
|
private readonly RulesetInfo ruleset;
|
||||||
private readonly RankStatus rankStatus;
|
private readonly BeatmapSearchCategory searchCategory;
|
||||||
private readonly DirectSortCriteria sortCriteria;
|
private readonly DirectSortCriteria sortCriteria;
|
||||||
private readonly SortDirection direction;
|
private readonly SortDirection direction;
|
||||||
private string directionString => direction == SortDirection.Descending ? @"desc" : @"asc";
|
private string directionString => direction == SortDirection.Descending ? @"desc" : @"asc";
|
||||||
|
|
||||||
public SearchBeatmapSetsRequest(string query, RulesetInfo ruleset, RankStatus rankStatus = RankStatus.Any, DirectSortCriteria sortCriteria = DirectSortCriteria.Ranked, SortDirection direction = SortDirection.Descending)
|
public SearchBeatmapSetsRequest(string query, RulesetInfo ruleset, BeatmapSearchCategory searchCategory = BeatmapSearchCategory.Any, DirectSortCriteria sortCriteria = DirectSortCriteria.Ranked, SortDirection direction = SortDirection.Descending)
|
||||||
{
|
{
|
||||||
this.query = System.Uri.EscapeDataString(query);
|
this.query = System.Uri.EscapeDataString(query);
|
||||||
this.ruleset = ruleset;
|
this.ruleset = ruleset;
|
||||||
this.rankStatus = rankStatus;
|
this.searchCategory = searchCategory;
|
||||||
this.sortCriteria = sortCriteria;
|
this.sortCriteria = sortCriteria;
|
||||||
this.direction = direction;
|
this.direction = direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
|
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
|
||||||
protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={(int)rankStatus}&sort={sortCriteria.ToString().ToLower()}_{directionString}";
|
protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={(int)searchCategory}&sort={sortCriteria.ToString().ToLower()}_{directionString}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum BeatmapSearchCategory
|
||||||
|
{
|
||||||
|
Any = 7,
|
||||||
|
[Description("Ranked & Approved")]
|
||||||
|
RankedApproved = 0,
|
||||||
|
Approved = 1,
|
||||||
|
Loved = 8,
|
||||||
|
Favourites = 2,
|
||||||
|
Qualified = 3,
|
||||||
|
Pending = 4,
|
||||||
|
Graveyard = 5,
|
||||||
|
[Description("My Maps")]
|
||||||
|
MyMaps = 6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -56,6 +60,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
private BeatmapSetOverlay beatmapSetOverlay;
|
private BeatmapSetOverlay beatmapSetOverlay;
|
||||||
|
|
||||||
|
private ScreenshotManager screenshotManager;
|
||||||
|
|
||||||
public virtual Storage GetStorageForStableInstall() => null;
|
public virtual Storage GetStorageForStableInstall() => null;
|
||||||
|
|
||||||
private Intro intro
|
private Intro intro
|
||||||
@ -190,12 +196,16 @@ namespace osu.Game
|
|||||||
}
|
}
|
||||||
|
|
||||||
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(s.Beatmap);
|
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(s.Beatmap);
|
||||||
|
Beatmap.Value.Mods.Value = s.Mods;
|
||||||
|
|
||||||
menu.Push(new PlayerLoader(new ReplayPlayer(s.Replay)));
|
menu.Push(new PlayerLoader(new ReplayPlayer(s.Replay)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
|
// this needs to be cached before base.LoadComplete as it is used by CursorOverrideContainer.
|
||||||
|
dependencies.Cache(screenshotManager = new ScreenshotManager());
|
||||||
|
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
// The next time this is updated is in UpdateAfterChildren, which occurs too late and results
|
// The next time this is updated is in UpdateAfterChildren, which occurs too late and results
|
||||||
@ -239,7 +249,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
loadComponentSingleFile(volume = new VolumeOverlay(), overlayContent.Add);
|
loadComponentSingleFile(volume = new VolumeOverlay(), overlayContent.Add);
|
||||||
loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add);
|
loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add);
|
||||||
loadComponentSingleFile(new ScreenshotManager(), Add);
|
|
||||||
|
loadComponentSingleFile(screenshotManager, Add);
|
||||||
|
|
||||||
//overlay elements
|
//overlay elements
|
||||||
loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add);
|
loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add);
|
||||||
@ -435,7 +446,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 =>
|
||||||
|
@ -246,11 +246,11 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
if (beatmaps != null) beatmaps.ItemAdded -= handleBeatmapAdd;
|
if (beatmaps != null) beatmaps.ItemAdded -= handleBeatmapAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleBeatmapAdd(BeatmapSetInfo beatmap)
|
private void handleBeatmapAdd(BeatmapSetInfo beatmap) => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (beatmap.OnlineBeatmapSetID == BeatmapSet?.OnlineBeatmapSetID)
|
if (beatmap.OnlineBeatmapSetID == BeatmapSet?.OnlineBeatmapSetID)
|
||||||
downloadButtonsContainer.FadeOut(transition_duration);
|
downloadButtonsContainer.FadeOut(transition_duration);
|
||||||
}
|
});
|
||||||
|
|
||||||
private void download(bool noVideo)
|
private void download(bool noVideo)
|
||||||
{
|
{
|
||||||
|
@ -40,10 +40,10 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
public BeatmapSetOverlay()
|
public BeatmapSetOverlay()
|
||||||
{
|
{
|
||||||
FirstWaveColour = OsuColour.Gray(0.4f);
|
Waves.FirstWaveColour = OsuColour.Gray(0.4f);
|
||||||
SecondWaveColour = OsuColour.Gray(0.3f);
|
Waves.SecondWaveColour = OsuColour.Gray(0.3f);
|
||||||
ThirdWaveColour = OsuColour.Gray(0.2f);
|
Waves.ThirdWaveColour = OsuColour.Gray(0.2f);
|
||||||
FourthWaveColour = OsuColour.Gray(0.1f);
|
Waves.FourthWaveColour = OsuColour.Gray(0.1f);
|
||||||
|
|
||||||
Anchor = Anchor.TopCentre;
|
Anchor = Anchor.TopCentre;
|
||||||
Origin = Anchor.TopCentre;
|
Origin = Anchor.TopCentre;
|
||||||
@ -123,14 +123,14 @@ namespace osu.Game.Overlays
|
|||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
{
|
{
|
||||||
base.PopIn();
|
base.PopIn();
|
||||||
FadeEdgeEffectTo(0.25f, APPEAR_DURATION, Easing.In);
|
FadeEdgeEffectTo(0.25f, WaveContainer.APPEAR_DURATION, Easing.In);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopOut()
|
protected override void PopOut()
|
||||||
{
|
{
|
||||||
base.PopOut();
|
base.PopOut();
|
||||||
header.Details.StopPreview();
|
header.Details.StopPreview();
|
||||||
FadeEdgeEffectTo(0, DISAPPEAR_DURATION, Easing.Out);
|
FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(InputState state)
|
protected override bool OnClick(InputState state)
|
||||||
|
@ -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;
|
||||||
|
@ -7,15 +7,15 @@ 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.Game.Beatmaps;
|
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Overlays.SearchableList;
|
using osu.Game.Overlays.SearchableList;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Direct
|
namespace osu.Game.Overlays.Direct
|
||||||
{
|
{
|
||||||
public class FilterControl : SearchableListFilterControl<DirectSortCriteria, RankStatus>
|
public class FilterControl : SearchableListFilterControl<DirectSortCriteria, BeatmapSearchCategory>
|
||||||
{
|
{
|
||||||
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||||
private FillFlowContainer<RulesetToggleButton> modeButtons;
|
private FillFlowContainer<RulesetToggleButton> modeButtons;
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ using OpenTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays
|
namespace osu.Game.Overlays
|
||||||
{
|
{
|
||||||
public class DirectOverlay : SearchableListOverlay<DirectTab, DirectSortCriteria, RankStatus>
|
public class DirectOverlay : SearchableListOverlay<DirectTab, DirectSortCriteria, BeatmapSearchCategory>
|
||||||
{
|
{
|
||||||
private const float panel_padding = 10f;
|
private const float panel_padding = 10f;
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ namespace osu.Game.Overlays
|
|||||||
protected override Color4 TrianglesColourDark => OsuColour.FromHex(@"3f5265");
|
protected override Color4 TrianglesColourDark => OsuColour.FromHex(@"3f5265");
|
||||||
|
|
||||||
protected override SearchableListHeader<DirectTab> CreateHeader() => new Header();
|
protected override SearchableListHeader<DirectTab> CreateHeader() => new Header();
|
||||||
protected override SearchableListFilterControl<DirectSortCriteria, RankStatus> CreateFilterControl() => new FilterControl();
|
protected override SearchableListFilterControl<DirectSortCriteria, BeatmapSearchCategory> CreateFilterControl() => new FilterControl();
|
||||||
|
|
||||||
private IEnumerable<BeatmapSetInfo> beatmapSets;
|
private IEnumerable<BeatmapSetInfo> beatmapSets;
|
||||||
|
|
||||||
@ -89,10 +89,10 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
// osu!direct colours are not part of the standard palette
|
// osu!direct colours are not part of the standard palette
|
||||||
|
|
||||||
FirstWaveColour = OsuColour.FromHex(@"19b0e2");
|
Waves.FirstWaveColour = OsuColour.FromHex(@"19b0e2");
|
||||||
SecondWaveColour = OsuColour.FromHex(@"2280a2");
|
Waves.SecondWaveColour = OsuColour.FromHex(@"2280a2");
|
||||||
ThirdWaveColour = OsuColour.FromHex(@"005774");
|
Waves.ThirdWaveColour = OsuColour.FromHex(@"005774");
|
||||||
FourthWaveColour = OsuColour.FromHex(@"003a4e");
|
Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e");
|
||||||
|
|
||||||
ScrollFlow.Children = new Drawable[]
|
ScrollFlow.Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -188,12 +188,12 @@ namespace osu.Game.Overlays
|
|||||||
beatmaps.ItemAdded += setAdded;
|
beatmaps.ItemAdded += setAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAdded(BeatmapSetInfo set)
|
private void setAdded(BeatmapSetInfo set) => Schedule(() =>
|
||||||
{
|
{
|
||||||
// if a new map was imported, we should remove it from search results (download completed etc.)
|
// if a new map was imported, we should remove it from search results (download completed etc.)
|
||||||
panels?.FirstOrDefault(p => p.SetInfo.OnlineBeatmapSetID == set.OnlineBeatmapSetID)?.FadeOut(400).Expire();
|
panels?.FirstOrDefault(p => p.SetInfo.OnlineBeatmapSetID == set.OnlineBeatmapSetID)?.FadeOut(400).Expire();
|
||||||
BeatmapSets = BeatmapSets?.Where(b => b.OnlineBeatmapSetID != set.OnlineBeatmapSetID);
|
BeatmapSets = BeatmapSets?.Where(b => b.OnlineBeatmapSetID != set.OnlineBeatmapSetID);
|
||||||
}
|
});
|
||||||
|
|
||||||
private void updateResultCounts()
|
private void updateResultCounts()
|
||||||
{
|
{
|
||||||
@ -323,6 +323,14 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
private int distinctCount(List<string> list) => list.Distinct().ToArray().Length;
|
private int distinctCount(List<string> list) => list.Distinct().ToArray().Length;
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
|
if (beatmaps != null)
|
||||||
|
beatmaps.ItemAdded -= setAdded;
|
||||||
|
}
|
||||||
|
|
||||||
public class ResultCounts
|
public class ResultCounts
|
||||||
{
|
{
|
||||||
public readonly int Artists;
|
public readonly int Artists;
|
||||||
|
@ -18,6 +18,7 @@ using System.Linq;
|
|||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
@ -113,14 +114,14 @@ namespace osu.Game.Overlays.Mods
|
|||||||
{
|
{
|
||||||
base.PopOut();
|
base.PopOut();
|
||||||
|
|
||||||
footerContainer.MoveToX(footerContainer.DrawSize.X, DISAPPEAR_DURATION, Easing.InSine);
|
footerContainer.MoveToX(footerContainer.DrawSize.X, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||||
footerContainer.FadeOut(DISAPPEAR_DURATION, Easing.InSine);
|
footerContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||||
|
|
||||||
foreach (ModSection section in ModSectionsContainer.Children)
|
foreach (ModSection section in ModSectionsContainer.Children)
|
||||||
{
|
{
|
||||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), DISAPPEAR_DURATION, Easing.InSine);
|
section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||||
section.ButtonsContainer.MoveToX(100f, DISAPPEAR_DURATION, Easing.InSine);
|
section.ButtonsContainer.MoveToX(100f, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||||
section.ButtonsContainer.FadeOut(DISAPPEAR_DURATION, Easing.InSine);
|
section.ButtonsContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,14 +129,14 @@ namespace osu.Game.Overlays.Mods
|
|||||||
{
|
{
|
||||||
base.PopIn();
|
base.PopIn();
|
||||||
|
|
||||||
footerContainer.MoveToX(0, APPEAR_DURATION, Easing.OutQuint);
|
footerContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||||
footerContainer.FadeIn(APPEAR_DURATION, Easing.OutQuint);
|
footerContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||||
|
|
||||||
foreach (ModSection section in ModSectionsContainer.Children)
|
foreach (ModSection section in ModSectionsContainer.Children)
|
||||||
{
|
{
|
||||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), APPEAR_DURATION, Easing.OutQuint);
|
section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||||
section.ButtonsContainer.MoveToX(0, APPEAR_DURATION, Easing.OutQuint);
|
section.ButtonsContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||||
section.ButtonsContainer.FadeIn(APPEAR_DURATION, Easing.OutQuint);
|
section.ButtonsContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,14 +182,12 @@ namespace osu.Game.Overlays.Mods
|
|||||||
|
|
||||||
public ModSelectOverlay()
|
public ModSelectOverlay()
|
||||||
{
|
{
|
||||||
FirstWaveColour = OsuColour.FromHex(@"19b0e2");
|
Waves.FirstWaveColour = OsuColour.FromHex(@"19b0e2");
|
||||||
SecondWaveColour = OsuColour.FromHex(@"2280a2");
|
Waves.SecondWaveColour = OsuColour.FromHex(@"2280a2");
|
||||||
ThirdWaveColour = OsuColour.FromHex(@"005774");
|
Waves.ThirdWaveColour = OsuColour.FromHex(@"005774");
|
||||||
FourthWaveColour = OsuColour.FromHex(@"003a4e");
|
Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e");
|
||||||
|
|
||||||
Height = 510;
|
Height = 510;
|
||||||
Content.RelativeSizeAxes = Axes.X;
|
|
||||||
Content.AutoSizeAxes = Axes.Y;
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container
|
new Container
|
||||||
|
@ -74,8 +74,8 @@ namespace osu.Game.Overlays.Music
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
beatmaps.ItemAdded += list.AddBeatmapSet;
|
beatmaps.ItemAdded += handleBeatmapAdded;
|
||||||
beatmaps.ItemRemoved += list.RemoveBeatmapSet;
|
beatmaps.ItemRemoved += handleBeatmapRemoved;
|
||||||
|
|
||||||
list.BeatmapSets = beatmaps.GetAllUsableBeatmapSets();
|
list.BeatmapSets = beatmaps.GetAllUsableBeatmapSets();
|
||||||
|
|
||||||
@ -95,6 +95,9 @@ namespace osu.Game.Overlays.Music
|
|||||||
beatmapBacking.TriggerChange();
|
beatmapBacking.TriggerChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleBeatmapAdded(BeatmapSetInfo setInfo) => Schedule(() => list.AddBeatmapSet(setInfo));
|
||||||
|
private void handleBeatmapRemoved(BeatmapSetInfo setInfo) => Schedule(() => list.RemoveBeatmapSet(setInfo));
|
||||||
|
|
||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
{
|
{
|
||||||
filter.Search.HoldFocus = true;
|
filter.Search.HoldFocus = true;
|
||||||
@ -153,6 +156,17 @@ namespace osu.Game.Overlays.Music
|
|||||||
|
|
||||||
track.Restart();
|
track.Restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
|
if (beatmaps != null)
|
||||||
|
{
|
||||||
|
beatmaps.ItemAdded -= handleBeatmapAdded;
|
||||||
|
beatmaps.ItemRemoved -= handleBeatmapRemoved;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo: placeholder
|
//todo: placeholder
|
||||||
|
195
osu.Game/Overlays/Profile/Header/BadgeContainer.cs
Normal file
195
osu.Game/Overlays/Profile/Header/BadgeContainer.cs
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Profile.Header
|
||||||
|
{
|
||||||
|
public class BadgeContainer : Container
|
||||||
|
{
|
||||||
|
private static readonly Vector2 badge_size = new Vector2(86, 40);
|
||||||
|
private static readonly MarginPadding outer_padding = new MarginPadding(3);
|
||||||
|
|
||||||
|
private OsuSpriteText badgeCountText;
|
||||||
|
private FillFlowContainer badgeFlowContainer;
|
||||||
|
private FillFlowContainer outerBadgeContainer;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
Child = new Container
|
||||||
|
{
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = 4,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = colours.Gray3
|
||||||
|
},
|
||||||
|
outerBadgeContainer = new OuterBadgeContainer(onOuterHover, onOuterHoverLost)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Padding = outer_padding,
|
||||||
|
Width = DrawableBadge.DRAWABLE_BADGE_SIZE.X + outer_padding.TotalHorizontal,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
badgeCountText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Alpha = 0,
|
||||||
|
TextSize = 12,
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
Font = "Exo2.0-Regular"
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Child = badgeFlowContainer = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Scheduler.AddDelayed(rotateBadges, 3000, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rotateBadges()
|
||||||
|
{
|
||||||
|
if (outerBadgeContainer.IsHovered) return;
|
||||||
|
|
||||||
|
visibleBadge = (visibleBadge + 1) % badgeCount;
|
||||||
|
|
||||||
|
badgeFlowContainer.MoveToX(-DrawableBadge.DRAWABLE_BADGE_SIZE.X * visibleBadge, 500, Easing.InOutQuad);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int visibleBadge;
|
||||||
|
private int badgeCount;
|
||||||
|
|
||||||
|
public void ShowBadges(Badge[] badges)
|
||||||
|
{
|
||||||
|
switch (badges.Length)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Hide();
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
badgeCountText.Hide();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
badgeCountText.Show();
|
||||||
|
badgeCountText.Text = $"{badges.Length} badges";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Show();
|
||||||
|
badgeCount = badges.Length;
|
||||||
|
visibleBadge = 0;
|
||||||
|
|
||||||
|
badgeFlowContainer.Clear();
|
||||||
|
foreach (var badge in badges)
|
||||||
|
{
|
||||||
|
LoadComponentAsync(new DrawableBadge(badge)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
}, badgeFlowContainer.Add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onOuterHover()
|
||||||
|
{
|
||||||
|
badgeFlowContainer.ClearTransforms();
|
||||||
|
badgeFlowContainer.X = 0;
|
||||||
|
badgeFlowContainer.Direction = FillDirection.Full;
|
||||||
|
outerBadgeContainer.AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
badgeFlowContainer.MaximumSize = new Vector2(ChildSize.X, float.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onOuterHoverLost()
|
||||||
|
{
|
||||||
|
badgeFlowContainer.X = -DrawableBadge.DRAWABLE_BADGE_SIZE.X * visibleBadge;
|
||||||
|
badgeFlowContainer.Direction = FillDirection.Horizontal;
|
||||||
|
outerBadgeContainer.AutoSizeAxes = Axes.Y;
|
||||||
|
outerBadgeContainer.Width = DrawableBadge.DRAWABLE_BADGE_SIZE.X + outer_padding.TotalHorizontal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OuterBadgeContainer : FillFlowContainer
|
||||||
|
{
|
||||||
|
private readonly Action hoverAction;
|
||||||
|
private readonly Action hoverLostAction;
|
||||||
|
|
||||||
|
public OuterBadgeContainer(Action hoverAction, Action hoverLostAction)
|
||||||
|
{
|
||||||
|
this.hoverAction = hoverAction;
|
||||||
|
this.hoverLostAction = hoverLostAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(InputState state)
|
||||||
|
{
|
||||||
|
hoverAction();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(InputState state) => hoverLostAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DrawableBadge : Container, IHasTooltip
|
||||||
|
{
|
||||||
|
public static readonly Vector2 DRAWABLE_BADGE_SIZE = badge_size + outer_padding.Total;
|
||||||
|
|
||||||
|
private readonly Badge badge;
|
||||||
|
|
||||||
|
public DrawableBadge(Badge badge)
|
||||||
|
{
|
||||||
|
this.badge = badge;
|
||||||
|
Padding = outer_padding;
|
||||||
|
Size = DRAWABLE_BADGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(TextureStore textures)
|
||||||
|
{
|
||||||
|
Child = new Sprite
|
||||||
|
{
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Texture = textures.Get(badge.ImageUrl),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
Child.FadeInFromZero(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TooltipText => badge.Description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,10 @@
|
|||||||
// 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 System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenTK;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
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.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
@ -14,10 +15,9 @@ using osu.Game.Graphics;
|
|||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using System.Collections.Generic;
|
using OpenTK;
|
||||||
using osu.Framework.Configuration;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile
|
namespace osu.Game.Overlays.Profile.Header
|
||||||
{
|
{
|
||||||
public class RankGraph : Container
|
public class RankGraph : Container
|
||||||
{
|
{
|
@ -1,7 +1,6 @@
|
|||||||
// 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 OpenTK;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -9,8 +8,9 @@ using osu.Framework.Graphics.Cursor;
|
|||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Backgrounds;
|
using osu.Game.Graphics.Backgrounds;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile
|
namespace osu.Game.Overlays.Profile.Header
|
||||||
{
|
{
|
||||||
public class SupporterIcon : CircularContainer, IHasTooltip
|
public class SupporterIcon : CircularContainer, IHasTooltip
|
||||||
{
|
{
|
@ -17,6 +17,7 @@ using osu.Framework.Graphics.Textures;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Overlays.Profile.Header;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile
|
namespace osu.Game.Overlays.Profile
|
||||||
@ -35,6 +36,7 @@ namespace osu.Game.Overlays.Profile
|
|||||||
private readonly GradeBadge gradeSSPlus, gradeSS, gradeSPlus, gradeS, gradeA;
|
private readonly GradeBadge gradeSSPlus, gradeSS, gradeSPlus, gradeS, gradeA;
|
||||||
private readonly Box colourBar;
|
private readonly Box colourBar;
|
||||||
private readonly DrawableFlag countryFlag;
|
private readonly DrawableFlag countryFlag;
|
||||||
|
private readonly BadgeContainer badgeContainer;
|
||||||
|
|
||||||
private const float cover_height = 350;
|
private const float cover_height = 350;
|
||||||
private const float info_height = 150;
|
private const float info_height = 150;
|
||||||
@ -42,6 +44,7 @@ namespace osu.Game.Overlays.Profile
|
|||||||
private const float avatar_size = 110;
|
private const float avatar_size = 110;
|
||||||
private const float level_position = 30;
|
private const float level_position = 30;
|
||||||
private const float level_height = 60;
|
private const float level_height = 60;
|
||||||
|
private const float stats_width = 280;
|
||||||
|
|
||||||
public ProfileHeader(User user)
|
public ProfileHeader(User user)
|
||||||
{
|
{
|
||||||
@ -66,9 +69,9 @@ namespace osu.Game.Overlays.Profile
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomLeft,
|
||||||
X = UserProfileOverlay.CONTENT_X_MARGIN,
|
Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN, Bottom = 20, Right = stats_width + UserProfileOverlay.CONTENT_X_MARGIN },
|
||||||
Y = -20,
|
AutoSizeAxes = Axes.Y,
|
||||||
AutoSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.X,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new UpdateableAvatar
|
new UpdateableAvatar
|
||||||
@ -116,7 +119,15 @@ namespace osu.Game.Overlays.Profile
|
|||||||
Height = 20
|
Height = 20
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
badgeContainer = new BadgeContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
Margin = new MarginPadding { Bottom = 5 },
|
||||||
|
Alpha = 0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
colourBar = new Box
|
colourBar = new Box
|
||||||
@ -156,7 +167,7 @@ namespace osu.Game.Overlays.Profile
|
|||||||
{
|
{
|
||||||
X = -UserProfileOverlay.CONTENT_X_MARGIN,
|
X = -UserProfileOverlay.CONTENT_X_MARGIN,
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Width = 280,
|
Width = stats_width,
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -417,6 +428,8 @@ namespace osu.Game.Overlays.Profile
|
|||||||
|
|
||||||
rankGraph.User.Value = user;
|
rankGraph.User.Value = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
badgeContainer.ShowBadges(user.Badges);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryAddInfoRightLine(FontAwesome icon, string str, string url = null)
|
private void tryAddInfoRightLine(FontAwesome icon, string str, string url = 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;
|
||||||
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();
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
|||||||
{
|
{
|
||||||
LabelText = "Screenshot format",
|
LabelText = "Screenshot format",
|
||||||
Bindable = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat)
|
Bindable = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat)
|
||||||
|
},
|
||||||
|
new SettingsCheckbox
|
||||||
|
{
|
||||||
|
LabelText = "Show menu cursor in screenshots",
|
||||||
|
Bindable = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -21,9 +21,13 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
|
|
||||||
public override FontAwesome Icon => FontAwesome.fa_paint_brush;
|
public override FontAwesome Icon => FontAwesome.fa_paint_brush;
|
||||||
|
|
||||||
|
private SkinManager skins;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuConfigManager config, SkinManager skins)
|
private void load(OsuConfigManager config, SkinManager skins)
|
||||||
{
|
{
|
||||||
|
this.skins = skins;
|
||||||
|
|
||||||
FlowContent.Spacing = new Vector2(0, 5);
|
FlowContent.Spacing = new Vector2(0, 5);
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -47,15 +51,29 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void reloadSkins() => skinDropdown.Items = skins.GetAllUsableSkins().Select(s => new KeyValuePair<string, int>(s.ToString(), s.ID));
|
skins.ItemAdded += onItemsChanged;
|
||||||
skins.ItemAdded += _ => reloadSkins();
|
skins.ItemRemoved += onItemsChanged;
|
||||||
skins.ItemRemoved += _ => reloadSkins();
|
|
||||||
|
|
||||||
reloadSkins();
|
reloadSkins();
|
||||||
|
|
||||||
skinDropdown.Bindable = config.GetBindable<int>(OsuSetting.Skin);
|
skinDropdown.Bindable = config.GetBindable<int>(OsuSetting.Skin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reloadSkins() => skinDropdown.Items = skins.GetAllUsableSkins().Select(s => new KeyValuePair<string, int>(s.ToString(), s.ID));
|
||||||
|
|
||||||
|
private void onItemsChanged(SkinInfo _) => Schedule(reloadSkins);
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
|
if (skins != null)
|
||||||
|
{
|
||||||
|
skins.ItemAdded -= onItemsChanged;
|
||||||
|
skins.ItemRemoved -= onItemsChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class SizeSlider : OsuSliderBar<double>
|
private class SizeSlider : OsuSliderBar<double>
|
||||||
{
|
{
|
||||||
public override string TooltipText => Current.Value.ToString(@"0.##x");
|
public override string TooltipText => Current.Value.ToString(@"0.##x");
|
||||||
|
@ -48,10 +48,10 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
public SocialOverlay()
|
public SocialOverlay()
|
||||||
{
|
{
|
||||||
FirstWaveColour = OsuColour.FromHex(@"cb5fa0");
|
Waves.FirstWaveColour = OsuColour.FromHex(@"cb5fa0");
|
||||||
SecondWaveColour = OsuColour.FromHex(@"b04384");
|
Waves.SecondWaveColour = OsuColour.FromHex(@"b04384");
|
||||||
ThirdWaveColour = OsuColour.FromHex(@"9b2b6e");
|
Waves.ThirdWaveColour = OsuColour.FromHex(@"9b2b6e");
|
||||||
FourthWaveColour = OsuColour.FromHex(@"6d214d");
|
Waves.FourthWaveColour = OsuColour.FromHex(@"6d214d");
|
||||||
|
|
||||||
Add(loading = new LoadingAnimation());
|
Add(loading = new LoadingAnimation());
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
public UserProfileOverlay()
|
public UserProfileOverlay()
|
||||||
{
|
{
|
||||||
FirstWaveColour = OsuColour.Gray(0.4f);
|
Waves.FirstWaveColour = OsuColour.Gray(0.4f);
|
||||||
SecondWaveColour = OsuColour.Gray(0.3f);
|
Waves.SecondWaveColour = OsuColour.Gray(0.3f);
|
||||||
ThirdWaveColour = OsuColour.Gray(0.2f);
|
Waves.ThirdWaveColour = OsuColour.Gray(0.2f);
|
||||||
FourthWaveColour = OsuColour.Gray(0.1f);
|
Waves.FourthWaveColour = OsuColour.Gray(0.1f);
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
RelativePositionAxes = Axes.Both;
|
RelativePositionAxes = Axes.Both;
|
||||||
@ -64,13 +64,13 @@ namespace osu.Game.Overlays
|
|||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
{
|
{
|
||||||
base.PopIn();
|
base.PopIn();
|
||||||
FadeEdgeEffectTo(0.5f, APPEAR_DURATION, Easing.In);
|
FadeEdgeEffectTo(0.5f, WaveContainer.APPEAR_DURATION, Easing.In);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopOut()
|
protected override void PopOut()
|
||||||
{
|
{
|
||||||
base.PopOut();
|
base.PopOut();
|
||||||
FadeEdgeEffectTo(0, DISAPPEAR_DURATION, Easing.Out);
|
FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowUser(long userId)
|
public void ShowUser(long userId)
|
||||||
|
@ -1,203 +1,37 @@
|
|||||||
// 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 OpenTK.Graphics;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using System;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
|
|
||||||
namespace osu.Game.Overlays
|
namespace osu.Game.Overlays
|
||||||
{
|
{
|
||||||
public abstract class WaveOverlayContainer : OsuFocusedOverlayContainer
|
public abstract class WaveOverlayContainer : OsuFocusedOverlayContainer
|
||||||
{
|
{
|
||||||
protected const float APPEAR_DURATION = 800;
|
protected readonly WaveContainer Waves;
|
||||||
protected const float DISAPPEAR_DURATION = 500;
|
|
||||||
|
|
||||||
private const Easing easing_show = Easing.OutSine;
|
|
||||||
private const Easing easing_hide = Easing.InSine;
|
|
||||||
|
|
||||||
private readonly Wave firstWave;
|
|
||||||
private readonly Wave secondWave;
|
|
||||||
private readonly Wave thirdWave;
|
|
||||||
private readonly Wave fourthWave;
|
|
||||||
|
|
||||||
private readonly Container<Wave> wavesContainer;
|
|
||||||
|
|
||||||
private readonly Container contentContainer;
|
|
||||||
|
|
||||||
protected override bool BlockPassThroughKeyboard => true;
|
protected override bool BlockPassThroughKeyboard => true;
|
||||||
|
protected override Container<Drawable> Content => Waves;
|
||||||
protected override Container<Drawable> Content => contentContainer;
|
|
||||||
|
|
||||||
protected Color4 FirstWaveColour
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return firstWave.Colour;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (firstWave.Colour == value) return;
|
|
||||||
firstWave.Colour = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Color4 SecondWaveColour
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return secondWave.Colour;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (secondWave.Colour == value) return;
|
|
||||||
secondWave.Colour = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Color4 ThirdWaveColour
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return thirdWave.Colour;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (thirdWave.Colour == value) return;
|
|
||||||
thirdWave.Colour = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Color4 FourthWaveColour
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return fourthWave.Colour;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (fourthWave.Colour == value) return;
|
|
||||||
fourthWave.Colour = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected WaveOverlayContainer()
|
protected WaveOverlayContainer()
|
||||||
{
|
{
|
||||||
Masking = true;
|
AddInternal(Waves = new WaveContainer
|
||||||
|
|
||||||
AddInternal(wavesContainer = new Container<Wave>
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Masking = true,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
firstWave = new Wave
|
|
||||||
{
|
|
||||||
Rotation = 13,
|
|
||||||
FinalPosition = -930,
|
|
||||||
},
|
|
||||||
secondWave = new Wave
|
|
||||||
{
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Rotation = -7,
|
|
||||||
FinalPosition = -560,
|
|
||||||
},
|
|
||||||
thirdWave = new Wave
|
|
||||||
{
|
|
||||||
Rotation = 4,
|
|
||||||
FinalPosition = -390,
|
|
||||||
},
|
|
||||||
fourthWave = new Wave
|
|
||||||
{
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Rotation = -2,
|
|
||||||
FinalPosition = -220,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
AddInternal(contentContainer = new Container
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
{
|
{
|
||||||
base.PopIn();
|
base.PopIn();
|
||||||
|
Waves.Show();
|
||||||
foreach (var w in wavesContainer.Children)
|
|
||||||
w.State = Visibility.Visible;
|
|
||||||
|
|
||||||
this.FadeIn(100, Easing.OutQuint);
|
|
||||||
contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint);
|
|
||||||
|
|
||||||
this.FadeIn(100, Easing.OutQuint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopOut()
|
protected override void PopOut()
|
||||||
{
|
{
|
||||||
base.PopOut();
|
base.PopOut();
|
||||||
|
Waves.Hide();
|
||||||
this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint);
|
|
||||||
contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, Easing.In);
|
|
||||||
|
|
||||||
foreach (var w in wavesContainer.Children)
|
|
||||||
w.State = Visibility.Hidden;
|
|
||||||
|
|
||||||
this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateAfterChildren()
|
|
||||||
{
|
|
||||||
base.UpdateAfterChildren();
|
|
||||||
|
|
||||||
// This is done as an optimization, such that invisible parts of the waves
|
|
||||||
// are masked away, and thus do not consume fill rate.
|
|
||||||
wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Wave : VisibilityContainer
|
|
||||||
{
|
|
||||||
public float FinalPosition;
|
|
||||||
|
|
||||||
protected override bool StartHidden => true;
|
|
||||||
|
|
||||||
public Wave()
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X;
|
|
||||||
Width = 1.5f;
|
|
||||||
Masking = true;
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Colour = Color4.Black.Opacity(50),
|
|
||||||
Radius = 20f,
|
|
||||||
};
|
|
||||||
|
|
||||||
Child = new Box { RelativeSizeAxes = Axes.Both };
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
// We can not use RelativeSizeAxes for Height, because the height
|
|
||||||
// of our parent diminishes as the content moves up.
|
|
||||||
Height = Parent.Parent.DrawSize.Y * 1.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void PopIn() => this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show);
|
|
||||||
protected override void PopOut() => this.MoveToY(Parent.Parent.DrawSize.Y, DISAPPEAR_DURATION, easing_hide);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -14,6 +14,7 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Beatmaps.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets
|
namespace osu.Game.Rulesets
|
||||||
{
|
{
|
||||||
@ -33,6 +34,13 @@ namespace osu.Game.Rulesets
|
|||||||
|
|
||||||
public abstract IEnumerable<Mod> GetModsFor(ModType type);
|
public abstract IEnumerable<Mod> GetModsFor(ModType type);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts mods from legacy enum values. Do not override if you're not a legacy ruleset.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mods">The legacy enum which will be converted</param>
|
||||||
|
/// <returns>An enumerable of constructed <see cref="Mod"/>s</returns>
|
||||||
|
public virtual IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods) => new Mod[] { };
|
||||||
|
|
||||||
public Mod GetAutoplayMod() => GetAllMods().First(mod => mod is ModAutoplay);
|
public Mod GetAutoplayMod() => GetAllMods().First(mod => mod is ModAutoplay);
|
||||||
|
|
||||||
protected Ruleset(RulesetInfo rulesetInfo = null)
|
protected Ruleset(RulesetInfo rulesetInfo = null)
|
||||||
|
@ -9,6 +9,8 @@ using osu.Game.Rulesets.Replays;
|
|||||||
using osu.Game.Rulesets.Replays.Legacy;
|
using osu.Game.Rulesets.Replays.Legacy;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using SharpCompress.Compressors.LZMA;
|
using SharpCompress.Compressors.LZMA;
|
||||||
|
using osu.Game.Beatmaps.Legacy;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Scoring.Legacy
|
namespace osu.Game.Rulesets.Scoring.Legacy
|
||||||
{
|
{
|
||||||
@ -64,7 +66,7 @@ namespace osu.Game.Rulesets.Scoring.Legacy
|
|||||||
/* score.Perfect = */
|
/* score.Perfect = */
|
||||||
sr.ReadBoolean();
|
sr.ReadBoolean();
|
||||||
/* score.EnabledMods = (Mods)*/
|
/* score.EnabledMods = (Mods)*/
|
||||||
sr.ReadInt32();
|
score.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray();
|
||||||
/* score.HpGraphString = */
|
/* score.HpGraphString = */
|
||||||
sr.ReadString();
|
sr.ReadString();
|
||||||
/* score.Date = */
|
/* score.Date = */
|
||||||
|
@ -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[]
|
||||||
|
@ -222,7 +222,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
boxHoverLayer.FadeOut(800, Easing.OutExpo);
|
boxHoverLayer.FadeOut(800, Easing.OutExpo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool HandleKeyboardInput => state != ButtonState.Exploded;
|
public override bool HandleKeyboardInput => state == ButtonState.Expanded;
|
||||||
public override bool HandleMouseInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f;
|
public override bool HandleMouseInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f;
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,9 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
private readonly LoadingAnimation loading;
|
private readonly LoadingAnimation loading;
|
||||||
|
|
||||||
private IEnumerable<Score> scores;
|
private ScheduledDelegate showScoresDelegate;
|
||||||
|
|
||||||
|
private IEnumerable<Score> scores;
|
||||||
public IEnumerable<Score> Scores
|
public IEnumerable<Score> Scores
|
||||||
{
|
{
|
||||||
get { return scores; }
|
get { return scores; }
|
||||||
@ -59,22 +60,28 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
// ensure placeholder is hidden when displaying scores
|
// ensure placeholder is hidden when displaying scores
|
||||||
PlaceholderState = PlaceholderState.Successful;
|
PlaceholderState = PlaceholderState.Successful;
|
||||||
|
|
||||||
// schedule because we may not be loaded yet (LoadComponentAsync complains).
|
var flow = scrollFlow = new FillFlowContainer<LeaderboardScore>
|
||||||
Schedule(() =>
|
|
||||||
{
|
|
||||||
LoadComponentAsync(new FillFlowContainer<LeaderboardScore>
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Spacing = new Vector2(0f, 5f),
|
Spacing = new Vector2(0f, 5f),
|
||||||
Padding = new MarginPadding { Top = 10, Bottom = 5 },
|
Padding = new MarginPadding { Top = 10, Bottom = 5 },
|
||||||
ChildrenEnumerable = scores.Select((s, index) => new LeaderboardScore(s, index + 1) { Action = () => ScoreSelected?.Invoke(s) })
|
ChildrenEnumerable = scores.Select((s, index) => new LeaderboardScore(s, index + 1) { Action = () => ScoreSelected?.Invoke(s) })
|
||||||
}, f =>
|
};
|
||||||
|
|
||||||
|
// schedule because we may not be loaded yet (LoadComponentAsync complains).
|
||||||
|
showScoresDelegate?.Cancel();
|
||||||
|
if (!IsLoaded)
|
||||||
|
showScoresDelegate = Schedule(showScores);
|
||||||
|
else
|
||||||
|
showScores();
|
||||||
|
|
||||||
|
void showScores() => LoadComponentAsync(flow, _ =>
|
||||||
{
|
{
|
||||||
scrollContainer.Add(scrollFlow = f);
|
scrollContainer.Add(flow);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var s in f.Children)
|
foreach (var s in flow.Children)
|
||||||
{
|
{
|
||||||
using (s.BeginDelayedSequence(i++ * 50, true))
|
using (s.BeginDelayedSequence(i++ * 50, true))
|
||||||
s.Show();
|
s.Show();
|
||||||
@ -82,7 +89,6 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
scrollContainer.ScrollTo(0f, false);
|
scrollContainer.ScrollTo(0f, false);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +109,10 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
private PlaceholderState placeholderState;
|
private PlaceholderState placeholderState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update the placeholder visibility.
|
||||||
|
/// Setting this to anything other than PlaceholderState.Successful will cancel all existing retrieval requests and hide scores.
|
||||||
|
/// </summary>
|
||||||
protected PlaceholderState PlaceholderState
|
protected PlaceholderState PlaceholderState
|
||||||
{
|
{
|
||||||
get { return placeholderState; }
|
get { return placeholderState; }
|
||||||
@ -250,43 +260,45 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
loading.Show();
|
loading.Show();
|
||||||
|
|
||||||
getScoresRequest = new GetScoresRequest(Beatmap, osuGame?.Ruleset.Value ?? Beatmap.Ruleset, Scope);
|
getScoresRequest = new GetScoresRequest(Beatmap, osuGame?.Ruleset.Value ?? Beatmap.Ruleset, Scope);
|
||||||
getScoresRequest.Success += r =>
|
getScoresRequest.Success += r => Schedule(() =>
|
||||||
{
|
{
|
||||||
Scores = r.Scores;
|
Scores = r.Scores;
|
||||||
PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores;
|
PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores;
|
||||||
};
|
});
|
||||||
getScoresRequest.Failure += onUpdateFailed;
|
|
||||||
|
|
||||||
api.Queue(getScoresRequest);
|
getScoresRequest.Failure += e => Schedule(() =>
|
||||||
}
|
|
||||||
|
|
||||||
private void onUpdateFailed(Exception e)
|
|
||||||
{
|
{
|
||||||
if (e is OperationCanceledException)
|
if (e is OperationCanceledException)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PlaceholderState = PlaceholderState.NetworkFailure;
|
PlaceholderState = PlaceholderState.NetworkFailure;
|
||||||
Logger.Error(e, @"Couldn't fetch beatmap scores!");
|
Logger.Error(e, @"Couldn't fetch beatmap scores!");
|
||||||
|
});
|
||||||
|
|
||||||
|
api.Queue(getScoresRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Placeholder currentPlaceholder;
|
||||||
|
|
||||||
private void replacePlaceholder(Placeholder placeholder)
|
private void replacePlaceholder(Placeholder placeholder)
|
||||||
{
|
{
|
||||||
var existingPlaceholder = placeholderContainer.Children.LastOrDefault() as Placeholder;
|
if (placeholder != null && placeholder.Equals(currentPlaceholder))
|
||||||
|
|
||||||
if (placeholder != null && placeholder.Equals(existingPlaceholder))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
existingPlaceholder?.FadeOut(150, Easing.OutQuint).Expire();
|
currentPlaceholder?.FadeOut(150, Easing.OutQuint).Expire();
|
||||||
|
|
||||||
if (placeholder == null)
|
if (placeholder == null)
|
||||||
|
{
|
||||||
|
currentPlaceholder = null;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Scores = null;
|
placeholderContainer.Child = placeholder;
|
||||||
|
|
||||||
placeholderContainer.Add(placeholder);
|
|
||||||
|
|
||||||
placeholder.ScaleTo(0.8f).Then().ScaleTo(1, fade_duration * 3, Easing.OutQuint);
|
placeholder.ScaleTo(0.8f).Then().ScaleTo(1, fade_duration * 3, Easing.OutQuint);
|
||||||
placeholder.FadeInFromZero(fade_duration, Easing.OutQuint);
|
placeholder.FadeInFromZero(fade_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
currentPlaceholder = placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
// 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 System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
@ -10,28 +9,27 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
public abstract class OsuTestCase : TestCase
|
public abstract class OsuTestCase : TestCase
|
||||||
{
|
{
|
||||||
public override void RunTest()
|
protected override ITestCaseTestRunner CreateRunner() => new OsuTestCaseTestRunner();
|
||||||
{
|
|
||||||
using (var host = new CleanRunHeadlessGameHost($"test-{Guid.NewGuid()}", realtime: false))
|
|
||||||
host.Run(new OsuTestCaseTestRunner(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public class OsuTestCaseTestRunner : OsuGameBase
|
public class OsuTestCaseTestRunner : OsuGameBase, ITestCaseTestRunner
|
||||||
{
|
{
|
||||||
private readonly OsuTestCase testCase;
|
|
||||||
|
|
||||||
protected override string MainResourceFile => File.Exists(base.MainResourceFile) ? base.MainResourceFile : Assembly.GetExecutingAssembly().Location;
|
protected override string MainResourceFile => File.Exists(base.MainResourceFile) ? base.MainResourceFile : Assembly.GetExecutingAssembly().Location;
|
||||||
|
|
||||||
public OsuTestCaseTestRunner(OsuTestCase testCase)
|
private readonly TestCaseTestRunner.TestRunner runner;
|
||||||
|
|
||||||
|
public OsuTestCaseTestRunner()
|
||||||
{
|
{
|
||||||
this.testCase = testCase;
|
runner = new TestCaseTestRunner.TestRunner();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
Add(new TestCaseTestRunner.TestRunner(testCase));
|
|
||||||
}
|
Add(runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RunTestBlocking(TestCase test) => runner.RunTestBlocking(test);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
osu.Game/Users/Badge.cs
Normal file
20
osu.Game/Users/Badge.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// 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 Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace osu.Game.Users
|
||||||
|
{
|
||||||
|
public class Badge
|
||||||
|
{
|
||||||
|
[JsonProperty("awarded_at")]
|
||||||
|
public DateTimeOffset AwardedAt;
|
||||||
|
|
||||||
|
[JsonProperty("description")]
|
||||||
|
public string Description;
|
||||||
|
|
||||||
|
[JsonProperty("image_url")]
|
||||||
|
public string ImageUrl;
|
||||||
|
}
|
||||||
|
}
|
@ -137,6 +137,9 @@ namespace osu.Game.Users
|
|||||||
[JsonProperty(@"rankHistory")]
|
[JsonProperty(@"rankHistory")]
|
||||||
public RankHistoryData RankHistory;
|
public RankHistoryData RankHistory;
|
||||||
|
|
||||||
|
[JsonProperty("badges")]
|
||||||
|
public Badge[] Badges;
|
||||||
|
|
||||||
public override string ToString() => Username;
|
public override string ToString() => Username;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ using osu.Framework.Graphics.UserInterface;
|
|||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Overlays.Profile;
|
using osu.Game.Overlays.Profile.Header;
|
||||||
|
|
||||||
namespace osu.Game.Users
|
namespace osu.Game.Users
|
||||||
{
|
{
|
||||||
|
@ -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…
Reference in New Issue
Block a user