mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 10:12:54 +08:00
Merge branch 'master' into multiplayer-abort
This commit is contained in:
commit
5a2240838b
@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2023.1127.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2023.1201.1" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
@ -5,4 +5,12 @@
|
||||
<!-- for editor usage -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||
</manifest>
|
||||
<!--
|
||||
READ_MEDIA_* permissions are available only on API 33 or greater. Devices with older android versions
|
||||
don't understand the new permissions, so request the old READ_EXTERNAL_STORAGE permission to get storage access.
|
||||
Since the old permission has no effect on >= API 33, don't request it.
|
||||
|
||||
Care needs to be taken to ensure runtime permission checks target the correct permission for the API level.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
|
||||
</manifest>
|
||||
|
31
osu.Game.Rulesets.Mania.Tests/ManiaHealthProcessorTest.cs
Normal file
31
osu.Game.Rulesets.Mania.Tests/ManiaHealthProcessorTest.cs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ManiaHealthProcessorTest
|
||||
{
|
||||
[Test]
|
||||
public void TestNoDrain()
|
||||
{
|
||||
var processor = new ManiaHealthProcessor(0);
|
||||
processor.ApplyBeatmap(new ManiaBeatmap(new StageDefinition(4))
|
||||
{
|
||||
HitObjects =
|
||||
{
|
||||
new Note { StartTime = 0 },
|
||||
new Note { StartTime = 1000 },
|
||||
}
|
||||
});
|
||||
|
||||
// No matter what, mania doesn't have passive HP drain.
|
||||
Assert.That(processor.DrainRate, Is.Zero);
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,15 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
||||
{
|
||||
}
|
||||
|
||||
protected override double ComputeDrainRate()
|
||||
{
|
||||
// Base call is run only to compute HP recovery (namely, `HpMultiplierNormal`).
|
||||
// This closely mirrors (broken) behaviour of stable and as such is preserved unchanged.
|
||||
base.ComputeDrainRate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected override IEnumerable<HitObject> EnumerateTopLevelHitObjects() => Beatmap.HitObjects;
|
||||
|
||||
protected override IEnumerable<HitObject> EnumerateNestedHitObjects(HitObject hitObject) => hitObject.NestedHitObjects;
|
||||
|
@ -12,9 +12,12 @@ using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Overlays.SkinEditor;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Edit.Components;
|
||||
using osu.Game.Screens.Play;
|
||||
@ -38,6 +41,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
advanceToSongSelect();
|
||||
openSkinEditor();
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
switchToGameplayScene();
|
||||
|
||||
BarHitErrorMeter hitErrorMeter = null;
|
||||
@ -98,6 +104,10 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
advanceToSongSelect();
|
||||
openSkinEditor();
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
switchToGameplayScene();
|
||||
|
||||
AddUntilStep("wait for components", () => skinEditor.ChildrenOfType<SkinBlueprint>().Any());
|
||||
@ -162,6 +172,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
openSkinEditor();
|
||||
AddStep("select DT", () => Game.SelectedMods.Value = new Mod[] { new OsuModDoubleTime() });
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
switchToGameplayScene();
|
||||
|
||||
AddAssert("DT still selected", () => ((Player)Game.ScreenStack.CurrentScreen).Mods.Value.Single() is OsuModDoubleTime);
|
||||
@ -174,6 +187,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
openSkinEditor();
|
||||
AddStep("select relax and spun out", () => Game.SelectedMods.Value = new Mod[] { new OsuModRelax(), new OsuModSpunOut() });
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
switchToGameplayScene();
|
||||
|
||||
AddAssert("no mod selected", () => !((Player)Game.ScreenStack.CurrentScreen).Mods.Value.Any());
|
||||
@ -186,6 +202,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
openSkinEditor();
|
||||
AddStep("select autoplay", () => Game.SelectedMods.Value = new Mod[] { new OsuModAutoplay() });
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
switchToGameplayScene();
|
||||
|
||||
AddAssert("no mod selected", () => !((Player)Game.ScreenStack.CurrentScreen).Mods.Value.Any());
|
||||
@ -198,6 +217,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
openSkinEditor();
|
||||
AddStep("select cinema", () => Game.SelectedMods.Value = new Mod[] { new OsuModCinema() });
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
switchToGameplayScene();
|
||||
|
||||
AddAssert("no mod selected", () => !((Player)Game.ScreenStack.CurrentScreen).Mods.Value.Any());
|
||||
@ -240,6 +262,43 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("editor sidebars not empty", () => skinEditor.ChildrenOfType<EditorSidebar>().SelectMany(sidebar => sidebar.Children).Count(), () => Is.GreaterThan(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOpenSkinEditorGameplaySceneOnBeatmapWithNoObjects()
|
||||
{
|
||||
AddStep("set dummy beatmap", () => Game.Beatmap.SetDefault());
|
||||
advanceToSongSelect();
|
||||
|
||||
AddStep("create empty beatmap", () => Game.BeatmapManager.CreateNew(new OsuRuleset().RulesetInfo, new GuestUser()));
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
openSkinEditor();
|
||||
switchToGameplayScene();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOpenSkinEditorGameplaySceneWhenDummyBeatmapActive()
|
||||
{
|
||||
AddStep("set dummy beatmap", () => Game.Beatmap.SetDefault());
|
||||
|
||||
openSkinEditor();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOpenSkinEditorGameplaySceneWhenDifferentRulesetActive()
|
||||
{
|
||||
BeatmapSetInfo beatmapSet = null!;
|
||||
|
||||
AddStep("import beatmap", () => beatmapSet = BeatmapImportHelper.LoadQuickOszIntoOsu(Game).GetResultSafely());
|
||||
AddStep("select mania difficulty", () =>
|
||||
{
|
||||
var beatmap = beatmapSet.Beatmaps.First(b => b.Ruleset.OnlineID == 3);
|
||||
Game.Beatmap.Value = Game.BeatmapManager.GetWorkingBeatmap(beatmap);
|
||||
});
|
||||
|
||||
openSkinEditor();
|
||||
switchToGameplayScene();
|
||||
}
|
||||
|
||||
private void advanceToSongSelect()
|
||||
{
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
@ -266,9 +325,6 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
private void switchToGameplayScene()
|
||||
{
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
AddStep("Click gameplay scene button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(skinEditor.ChildrenOfType<SkinEditorSceneLibrary.SceneButton>().First(b => b.Text.ToString() == "Gameplay"));
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
@ -56,92 +54,76 @@ namespace osu.Game.Tests.Visual.Online
|
||||
textContainer.Clear();
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestLinksGeneral()
|
||||
[TestCase("test!")]
|
||||
[TestCase("dev.ppy.sh!")]
|
||||
[TestCase("https://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("http://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("forgothttps://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("forgothttp://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("00:12:345 - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase("00:12:345 (1,2) - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase($"{OsuGameBase.OSU_PROTOCOL}edit/00:12:345 - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase($"{OsuGameBase.OSU_PROTOCOL}edit/00:12:345 (1,2) - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase($"{OsuGameBase.OSU_PROTOCOL}00:12:345 - not an editor timestamp", LinkAction.External)]
|
||||
[TestCase("Wiki link for tasty [[Performance Points]]", LinkAction.OpenWiki)]
|
||||
[TestCase("(osu forums)[https://dev.ppy.sh/forum] (old link format)", LinkAction.External)]
|
||||
[TestCase("[https://dev.ppy.sh/home New site] (new link format)", LinkAction.External)]
|
||||
[TestCase("[osu forums](https://dev.ppy.sh/forum) (new link format 2)", LinkAction.External)]
|
||||
[TestCase("[https://dev.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", LinkAction.External)]
|
||||
[TestCase("Let's (try)[https://dev.ppy.sh/home] [https://dev.ppy.sh/b/252238 multiple links] https://dev.ppy.sh/home", LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External)]
|
||||
[TestCase("[https://dev.ppy.sh/home New link format with escaped [and \\[ paired] braces]", LinkAction.External)]
|
||||
[TestCase("[Markdown link format with escaped [and \\[ paired] braces](https://dev.ppy.sh/home)", LinkAction.External)]
|
||||
[TestCase("(Old link format with escaped (and \\( paired) parentheses)[https://dev.ppy.sh/home] and [[also a rogue wiki link]]", LinkAction.External, LinkAction.OpenWiki)]
|
||||
[TestCase("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present).")] // note that there's 0 links here (they get removed if a channel is not found)
|
||||
[TestCase("Join my multiplayer game osump://12346.", LinkAction.JoinMultiplayerMatch)]
|
||||
[TestCase("Join my multiplayer gameosump://12346.", LinkAction.JoinMultiplayerMatch)]
|
||||
[TestCase("Join my [multiplayer game](osump://12346).", LinkAction.JoinMultiplayerMatch)]
|
||||
[TestCase($"Join my [#english]({OsuGameBase.OSU_PROTOCOL}chan/#english).", LinkAction.OpenChannel)]
|
||||
[TestCase($"Join my {OsuGameBase.OSU_PROTOCOL}chan/#english.", LinkAction.OpenChannel)]
|
||||
[TestCase($"Join my{OsuGameBase.OSU_PROTOCOL}chan/#english.", LinkAction.OpenChannel)]
|
||||
[TestCase("Join my #english or #japanese channels.", LinkAction.OpenChannel, LinkAction.OpenChannel)]
|
||||
[TestCase("Join my #english or #nonexistent #hashtag channels.", LinkAction.OpenChannel)]
|
||||
[TestCase("Hello world\uD83D\uDE12(<--This is an emoji). There are more:\uD83D\uDE10\uD83D\uDE00,\uD83D\uDE20")]
|
||||
public void TestLinksGeneral(string text, params LinkAction[] actions)
|
||||
{
|
||||
int messageIndex = 0;
|
||||
addMessageWithChecks(text, expectedActions: actions);
|
||||
}
|
||||
|
||||
addMessageWithChecks("test!");
|
||||
addMessageWithChecks("dev.ppy.sh!");
|
||||
addMessageWithChecks("https://dev.ppy.sh!", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("http://dev.ppy.sh!", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("forgothttps://dev.ppy.sh!", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("forgothttp://dev.ppy.sh!", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("00:12:345 (1,2) - Test?", 1, expectedActions: LinkAction.OpenEditorTimestamp);
|
||||
addMessageWithChecks("Wiki link for tasty [[Performance Points]]", 1, expectedActions: LinkAction.OpenWiki);
|
||||
addMessageWithChecks("(osu forums)[https://dev.ppy.sh/forum] (old link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home New site] (new link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[osu forums](https://dev.ppy.sh/forum) (new link format 2)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("is now listening to [https://dev.ppy.sh/s/93523 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmapSet);
|
||||
addMessageWithChecks("is now playing [https://dev.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmap);
|
||||
addMessageWithChecks("Let's (try)[https://dev.ppy.sh/home] [https://dev.ppy.sh/b/252238 multiple links] https://dev.ppy.sh/home", 3,
|
||||
expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External });
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home New link format with escaped [and \\[ paired] braces]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://dev.ppy.sh/home)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("(Old link format with escaped (and \\( paired) parentheses)[https://dev.ppy.sh/home] and [[also a rogue wiki link]]", 2,
|
||||
expectedActions: new[] { LinkAction.External, LinkAction.OpenWiki });
|
||||
// note that there's 0 links here (they get removed if a channel is not found)
|
||||
addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present).");
|
||||
addMessageWithChecks("I am important!", 0, false, true);
|
||||
addMessageWithChecks("feels important", 0, true, true);
|
||||
addMessageWithChecks("likes to post this [https://dev.ppy.sh/home link].", 1, true, true, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("Join my multiplayer game osump://12346.", 1, expectedActions: LinkAction.JoinMultiplayerMatch);
|
||||
addMessageWithChecks("Join my multiplayer gameosump://12346.", 1, expectedActions: LinkAction.JoinMultiplayerMatch);
|
||||
addMessageWithChecks("Join my [multiplayer game](osump://12346).", 1, expectedActions: LinkAction.JoinMultiplayerMatch);
|
||||
addMessageWithChecks($"Join my [#english]({OsuGameBase.OSU_PROTOCOL}chan/#english).", 1, expectedActions: LinkAction.OpenChannel);
|
||||
addMessageWithChecks($"Join my {OsuGameBase.OSU_PROTOCOL}chan/#english.", 1, expectedActions: LinkAction.OpenChannel);
|
||||
addMessageWithChecks($"Join my{OsuGameBase.OSU_PROTOCOL}chan/#english.", 1, expectedActions: LinkAction.OpenChannel);
|
||||
addMessageWithChecks("Join my #english or #japanese channels.", 2, expectedActions: new[] { LinkAction.OpenChannel, LinkAction.OpenChannel });
|
||||
addMessageWithChecks("Join my #english or #nonexistent #hashtag channels.", 1, expectedActions: LinkAction.OpenChannel);
|
||||
addMessageWithChecks("Hello world\uD83D\uDE12(<--This is an emoji). There are more:\uD83D\uDE10\uD83D\uDE00,\uD83D\uDE20");
|
||||
[TestCase("is now listening to [https://dev.ppy.sh/s/93523 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmapSet)]
|
||||
[TestCase("is now playing [https://dev.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmap)]
|
||||
[TestCase("I am important!", false, true)]
|
||||
[TestCase("feels important", true, true)]
|
||||
[TestCase("likes to post this [https://dev.ppy.sh/home link].", true, true, LinkAction.External)]
|
||||
public void TestActionAndImportantLinks(string text, bool isAction, bool isImportant, params LinkAction[] expectedActions)
|
||||
{
|
||||
addMessageWithChecks(text, isAction, isImportant, expectedActions);
|
||||
}
|
||||
|
||||
void addMessageWithChecks(string text, int linkAmount = 0, bool isAction = false, bool isImportant = false, params LinkAction[] expectedActions)
|
||||
private void addMessageWithChecks(string text, bool isAction = false, bool isImportant = false, params LinkAction[] expectedActions)
|
||||
{
|
||||
ChatLine newLine = null!;
|
||||
|
||||
AddStep("add message", () =>
|
||||
{
|
||||
ChatLine newLine = null;
|
||||
int index = messageIndex++;
|
||||
newLine = new ChatLine(new DummyMessage(text, isAction, isImportant));
|
||||
textContainer.Add(newLine);
|
||||
});
|
||||
|
||||
AddStep("add message", () =>
|
||||
{
|
||||
newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index));
|
||||
textContainer.Add(newLine);
|
||||
});
|
||||
AddAssert("msg has the right action", () => newLine.Message.Links.Select(l => l.Action), () => Is.EqualTo(expectedActions));
|
||||
AddAssert($"msg shows {expectedActions.Length} link(s)", isShowingLinks);
|
||||
|
||||
AddAssert($"msg #{index} has {linkAmount} link(s)", () => newLine.Message.Links.Count == linkAmount);
|
||||
AddAssert($"msg #{index} has the right action", hasExpectedActions);
|
||||
//AddAssert($"msg #{index} is " + (isAction ? "italic" : "not italic"), () => newLine.ContentFlow.Any() && isAction == isItalic());
|
||||
AddAssert($"msg #{index} shows {linkAmount} link(s)", isShowingLinks);
|
||||
bool isShowingLinks()
|
||||
{
|
||||
bool hasBackground = !string.IsNullOrEmpty(newLine.Message.Sender.Colour);
|
||||
|
||||
bool hasExpectedActions()
|
||||
{
|
||||
var expectedActionsList = expectedActions.ToList();
|
||||
Color4 textColour = isAction && hasBackground ? Color4Extensions.FromHex(newLine.Message.Sender.Colour) : Color4.White;
|
||||
|
||||
if (expectedActionsList.Count != newLine.Message.Links.Count)
|
||||
return false;
|
||||
var linkCompilers = newLine.DrawableContentFlow.Where(d => d is DrawableLinkCompiler).ToList();
|
||||
var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts);
|
||||
|
||||
for (int i = 0; i < newLine.Message.Links.Count; i++)
|
||||
{
|
||||
var action = newLine.Message.Links[i].Action;
|
||||
if (action != expectedActions[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool isItalic() => newLine.ContentFlow.Where(d => d is OsuSpriteText).Cast<OsuSpriteText>().All(sprite => sprite.Font.Italics);
|
||||
|
||||
bool isShowingLinks()
|
||||
{
|
||||
bool hasBackground = !string.IsNullOrEmpty(newLine.Message.Sender.Colour);
|
||||
|
||||
Color4 textColour = isAction && hasBackground ? Color4Extensions.FromHex(newLine.Message.Sender.Colour) : Color4.White;
|
||||
|
||||
var linkCompilers = newLine.DrawableContentFlow.Where(d => d is DrawableLinkCompiler).ToList();
|
||||
var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts);
|
||||
|
||||
return linkSprites.All(d => d.Colour == linkColour)
|
||||
&& newLine.DrawableContentFlow.Except(linkSprites.Concat(linkCompilers)).All(d => d.Colour == textColour);
|
||||
}
|
||||
return linkSprites.All(d => d.Colour == linkColour)
|
||||
&& newLine.DrawableContentFlow.Except(linkSprites.Concat(linkCompilers)).All(d => d.Colour == textColour)
|
||||
&& linkCompilers.Count == expectedActions.Length;
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +137,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
addEchoWithWait("[https://dev.ppy.sh/forum let's try multiple words too!]");
|
||||
addEchoWithWait("(long loading times! clickable while loading?)[https://dev.ppy.sh/home]", null, 5000);
|
||||
|
||||
void addEchoWithWait(string text, string completeText = null, double delay = 250)
|
||||
void addEchoWithWait(string text, string? completeText = null, double delay = 250)
|
||||
{
|
||||
int index = messageIndex++;
|
||||
|
||||
@ -184,21 +166,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
private static long messageCounter;
|
||||
|
||||
internal static readonly APIUser TEST_SENDER_BACKGROUND = new APIUser
|
||||
{
|
||||
Username = @"i-am-important",
|
||||
Id = 42,
|
||||
Colour = "#250cc9",
|
||||
};
|
||||
|
||||
internal static readonly APIUser TEST_SENDER = new APIUser
|
||||
{
|
||||
Username = @"Somebody",
|
||||
Id = 1,
|
||||
};
|
||||
|
||||
public new DateTimeOffset Timestamp = DateTimeOffset.Now;
|
||||
|
||||
public DummyMessage(string text, bool isAction = false, bool isImportant = false, int number = 0)
|
||||
: base(messageCounter++)
|
||||
{
|
||||
|
@ -12,6 +12,7 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Online;
|
||||
using osu.Game.Users;
|
||||
@ -47,9 +48,16 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
foreach (var link in links)
|
||||
{
|
||||
string displayText = text.Substring(link.Index, link.Length);
|
||||
|
||||
if (previousLinkEnd > link.Index)
|
||||
{
|
||||
Logger.Log($@"Link ""{link.Url}"" with text ""{displayText}"" overlaps previous link, ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
AddText(text[previousLinkEnd..link.Index]);
|
||||
|
||||
string displayText = text.Substring(link.Index, link.Length);
|
||||
object linkArgument = link.Argument;
|
||||
string tooltip = displayText == link.Url ? null : link.Url;
|
||||
|
||||
|
@ -179,21 +179,11 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
public static LocalisableString ClickToSelectTrack => new TranslatableString(getKey(@"click_to_select_track"), @"Click to select a track");
|
||||
|
||||
/// <summary>
|
||||
/// "Click to replace the track"
|
||||
/// </summary>
|
||||
public static LocalisableString ClickToReplaceTrack => new TranslatableString(getKey(@"click_to_replace_track"), @"Click to replace the track");
|
||||
|
||||
/// <summary>
|
||||
/// "Click to select a background image"
|
||||
/// </summary>
|
||||
public static LocalisableString ClickToSelectBackground => new TranslatableString(getKey(@"click_to_select_background"), @"Click to select a background image");
|
||||
|
||||
/// <summary>
|
||||
/// "Click to replace the background image"
|
||||
/// </summary>
|
||||
public static LocalisableString ClickToReplaceBackground => new TranslatableString(getKey(@"click_to_replace_background"), @"Click to replace the background image");
|
||||
|
||||
/// <summary>
|
||||
/// "Ruleset ({0})"
|
||||
/// </summary>
|
||||
|
@ -85,8 +85,8 @@ namespace osu.Game.Online.Chat
|
||||
if (escapeChars != null)
|
||||
displayText = escapeChars.Aggregate(displayText, (current, c) => current.Replace($"\\{c}", c.ToString()));
|
||||
|
||||
// Check for encapsulated links
|
||||
if (result.Links.Find(l => (l.Index <= index && l.Index + l.Length >= index + m.Length) || (index <= l.Index && index + m.Length >= l.Index + l.Length)) == null)
|
||||
// Check for overlapping links
|
||||
if (!result.Links.Exists(l => l.Overlaps(index, m.Length)))
|
||||
{
|
||||
result.Text = result.Text.Remove(index, m.Length).Insert(index, displayText);
|
||||
|
||||
@ -364,7 +364,9 @@ namespace osu.Game.Online.Chat
|
||||
Argument = argument;
|
||||
}
|
||||
|
||||
public bool Overlaps(Link otherLink) => Index < otherLink.Index + otherLink.Length && otherLink.Index < Index + Length;
|
||||
public bool Overlaps(Link otherLink) => Overlaps(otherLink.Index, otherLink.Length);
|
||||
|
||||
public bool Overlaps(int otherIndex, int otherLength) => Index < otherIndex + otherLength && otherIndex < Index + Length;
|
||||
|
||||
public int CompareTo(Link? otherLink) => Index > otherLink?.Index ? 1 : -1;
|
||||
}
|
||||
|
@ -183,9 +183,7 @@ namespace osu.Game.Overlays
|
||||
// new results may contain beatmaps from a previous page,
|
||||
// this is dodgy but matches web behaviour for now.
|
||||
// see: https://github.com/ppy/osu-web/issues/9270
|
||||
// todo: replace custom equality compraer with ExceptBy in net6.0
|
||||
// newCards = newCards.ExceptBy(foundContent.Select(c => c.BeatmapSet.OnlineID), c => c.BeatmapSet.OnlineID);
|
||||
newCards = newCards.Except(foundContent, BeatmapCardEqualityComparer.Default);
|
||||
newCards = newCards.ExceptBy(foundContent.Select(c => c.BeatmapSet.OnlineID), c => c.BeatmapSet.OnlineID);
|
||||
|
||||
panelLoadTask = LoadComponentsAsync(newCards, loaded =>
|
||||
{
|
||||
@ -378,21 +376,5 @@ namespace osu.Game.Overlays
|
||||
if (shouldShowMore)
|
||||
filterControl.FetchNextPage();
|
||||
}
|
||||
|
||||
private class BeatmapCardEqualityComparer : IEqualityComparer<BeatmapCard>
|
||||
{
|
||||
public static BeatmapCardEqualityComparer Default { get; } = new BeatmapCardEqualityComparer();
|
||||
|
||||
public bool Equals(BeatmapCard x, BeatmapCard y)
|
||||
{
|
||||
if (ReferenceEquals(x, y)) return true;
|
||||
if (ReferenceEquals(x, null)) return false;
|
||||
if (ReferenceEquals(y, null)) return false;
|
||||
|
||||
return x.BeatmapSet.Equals(y.BeatmapSet);
|
||||
}
|
||||
|
||||
public int GetHashCode(BeatmapCard obj) => obj.BeatmapSet.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Chat
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Icon = HexaconsIcons.Social,
|
||||
Icon = HexaconsIcons.Messaging,
|
||||
Size = new Vector2(24),
|
||||
},
|
||||
// Placeholder text
|
||||
|
@ -17,7 +17,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens;
|
||||
@ -26,6 +25,7 @@ using osu.Game.Screens.Edit.Components;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Users;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
|
||||
@ -55,9 +55,6 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
[Resolved]
|
||||
private MusicController music { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private Bindable<IReadOnlyList<Mod>> mods { get; set; } = null!;
|
||||
|
||||
@ -139,6 +136,12 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
{
|
||||
performer?.PerformFromScreen(screen =>
|
||||
{
|
||||
if (beatmap.Value is DummyWorkingBeatmap)
|
||||
{
|
||||
// presume we don't have anything good to play and just bail.
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're playing the intro, switch away to another beatmap.
|
||||
if (beatmap.Value.BeatmapSetInfo.Protected)
|
||||
{
|
||||
@ -150,7 +153,7 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
if (screen is Player)
|
||||
return;
|
||||
|
||||
var replayGeneratingMod = ruleset.Value.CreateInstance().GetAutoplayMod();
|
||||
var replayGeneratingMod = beatmap.Value.BeatmapInfo.Ruleset.CreateInstance().GetAutoplayMod();
|
||||
|
||||
IReadOnlyList<Mod> usableMods = mods.Value;
|
||||
|
||||
@ -285,6 +288,8 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
|
||||
private partial class EndlessPlayer : ReplayPlayer
|
||||
{
|
||||
protected override UserActivity? InitialActivity => null;
|
||||
|
||||
public EndlessPlayer(Func<IBeatmap, IReadOnlyList<Mod>, Score> createScore)
|
||||
: base(createScore, new PlayerConfiguration
|
||||
{
|
||||
@ -294,10 +299,21 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
{
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
if (!LoadedBeatmapSuccessfully)
|
||||
Scheduler.AddDelayed(this.Exit, 3000);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!LoadedBeatmapSuccessfully)
|
||||
return;
|
||||
|
||||
if (GameplayState.HasPassed)
|
||||
GameplayClockContainer.Seek(0);
|
||||
}
|
||||
|
@ -146,13 +146,8 @@ namespace osu.Game.Screens.Edit.Setup
|
||||
|
||||
private void updatePlaceholderText()
|
||||
{
|
||||
audioTrackChooser.Text = audioTrackChooser.Current.Value == null
|
||||
? EditorSetupStrings.ClickToSelectTrack
|
||||
: EditorSetupStrings.ClickToReplaceTrack;
|
||||
|
||||
backgroundChooser.Text = backgroundChooser.Current.Value == null
|
||||
? EditorSetupStrings.ClickToSelectBackground
|
||||
: EditorSetupStrings.ClickToReplaceBackground;
|
||||
audioTrackChooser.Text = audioTrackChooser.Current.Value?.Name ?? EditorSetupStrings.ClickToSelectTrack;
|
||||
backgroundChooser.Text = backgroundChooser.Current.Value?.Name ?? EditorSetupStrings.ClickToSelectBackground;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Realm" Version="11.5.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2023.1127.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2023.1201.1" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2023.1127.0" />
|
||||
<PackageReference Include="Sentry" Version="3.40.0" />
|
||||
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
||||
|
@ -23,6 +23,6 @@
|
||||
<RuntimeIdentifier>iossimulator-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2023.1127.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2023.1201.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
Loading…
Reference in New Issue
Block a user