diff --git a/osu.Android.props b/osu.Android.props index 896b10133d..f76297c197 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index 20ac5eaa39..f260357df5 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -3,6 +3,7 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Testing; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; @@ -12,6 +13,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] + [HeadlessTest] public class TestSceneAutoGeneration : OsuTestScene { [Test] diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 031abb08e2..8dae5e6d84 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -11,6 +11,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; @@ -40,6 +41,7 @@ namespace osu.Game.Rulesets.Mania.Tests { Child = new FillFlowContainer { + Clock = new FramedClock(new ManualClock()), Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, @@ -62,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createNoteDisplay(ScrollingDirection direction, int identifier, out DrawableNote hitObject) { - var note = new Note { StartTime = 999999999 }; + var note = new Note { StartTime = 0 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) @@ -77,7 +79,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createHoldNoteDisplay(ScrollingDirection direction, int identifier, out DrawableHoldNote hitObject) { - var note = new HoldNote { StartTime = 999999999, Duration = 5000 }; + var note = new HoldNote { StartTime = 0, Duration = 5000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) @@ -133,7 +135,7 @@ namespace osu.Game.Rulesets.Mania.Tests Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Both, Width = 1.25f, - Colour = Color4.Black.Opacity(0.5f) + Colour = Color4.Green.Opacity(0.5f) }, content = new Container { RelativeSizeAxes = Axes.Both } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index 395e6daf0a..e7fd601abe 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; using osuTK; @@ -114,8 +115,7 @@ namespace osu.Game.Rulesets.Mania.Tests var obj = new BarLine { StartTime = Time.Current + 2000, - ControlPoint = new TimingControlPoint(), - BeatIndex = major ? 0 : 1 + Major = major, }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs deleted file mode 100644 index 4c644a8f09..0000000000 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Beatmaps.ControlPoints; - -namespace osu.Game.Rulesets.Mania.Objects -{ - public class BarLine : ManiaHitObject - { - /// - /// The control point which this bar line is part of. - /// - public TimingControlPoint ControlPoint; - - /// - /// The index of the beat which this bar line represents within the control point. - /// This is a "major" bar line if % == 0. - /// - public int BeatIndex; - } -} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index e9c352c97e..862af8d15b 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -4,6 +4,7 @@ using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK.Graphics; @@ -13,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// Visualises a . Although this derives DrawableManiaHitObject, /// this does not handle input/sound like a normal hit object. /// - public class DrawableBarLine : DrawableManiaHitObject + public class DrawableBarLine : DrawableHitObject { /// /// Height of major bar line triangles. @@ -40,9 +41,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Colour = new Color4(255, 204, 33, 255), }); - bool isMajor = barLine.BeatIndex % (int)barLine.ControlPoint.TimeSignature == 0; - - if (isMajor) + if (barLine.Major) { AddInternal(new EquilateralTriangle { @@ -65,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }); } - if (!isMajor && barLine.BeatIndex % 2 == 1) + if (!barLine.Major) Alpha = 0.2f; } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index f26526fe70..29863fba2e 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -2,14 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input; -using osu.Framework.MathUtils; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Handlers; using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; @@ -19,8 +16,8 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; @@ -45,33 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { - // Generate the bar lines - double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; - - var timingPoints = Beatmap.ControlPointInfo.TimingPoints; - var barLines = new List(); - - for (int i = 0; i < timingPoints.Count; i++) - { - TimingControlPoint point = timingPoints[i]; - - // Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object - double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - point.BeatLength : lastObjectTime + point.BeatLength * (int)point.TimeSignature; - - int index = 0; - - for (double t = timingPoints[i].Time; Precision.DefinitelyBigger(endTime, t); t += point.BeatLength, index++) - { - barLines.Add(new BarLine - { - StartTime = t, - ControlPoint = point, - BeatIndex = index - }); - } - } - - BarLines = barLines; + BarLines = new BarLineGenerator(Beatmap).BarLines; } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 5ab07416a6..12faa499ad 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osuTK; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index a28de7ea58..98a4b7d0b6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 5957b81d7e..6b6a08ed21 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; case OsuSkinComponents.HitCircleText: - var font = GetConfig(OsuSkinConfiguration.HitCircleFont)?.Value ?? "default"; + var font = GetConfig(OsuSkinConfiguration.HitCirclePrefix)?.Value ?? "default"; var overlap = GetConfig(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? 0; return !hasFont(font) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs index a6b87150ae..e7b686d27d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs @@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Osu.Skinning { public enum OsuSkinConfiguration { - HitCircleFont, + HitCirclePrefix, HitCircleOverlap, SliderBorderSize, SliderPathRadius, diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs deleted file mode 100644 index a07012fd71..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Rulesets.Taiko.Objects -{ - public class BarLine : TaikoHitObject - { - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index bf89f7e15b..1a5a797f28 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; using osuTK; using osu.Game.Rulesets.Objects.Drawables; @@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. /// - public class DrawableBarLine : DrawableHitObject + public class DrawableBarLine : DrawableHitObject { /// /// The width of the line tracker. diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs index 4d3a1a3f8a..f5b75a781b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index b03bea578e..5caa9e4626 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -5,19 +5,18 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Taiko.Replays; -using System.Linq; using osu.Framework.Input; using osu.Game.Configuration; using osu.Game.Input.Handlers; using osu.Game.Replays; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI @@ -38,49 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI [BackgroundDependencyLoader] private void load() { - loadBarLines(); - } - - private void loadBarLines() - { - TaikoHitObject lastObject = Beatmap.HitObjects[Beatmap.HitObjects.Count - 1]; - double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime); - - var timingPoints = Beatmap.ControlPointInfo.TimingPoints.ToList(); - - if (timingPoints.Count == 0) - return; - - int currentIndex = 0; - int currentBeat = 0; - double time = timingPoints[currentIndex].Time; - - while (time <= lastHitTime) - { - int nextIndex = currentIndex + 1; - - if (nextIndex < timingPoints.Count && time > timingPoints[nextIndex].Time) - { - currentIndex = nextIndex; - time = timingPoints[currentIndex].Time; - currentBeat = 0; - } - - var currentPoint = timingPoints[currentIndex]; - - var barLine = new BarLine - { - StartTime = time, - }; - - barLine.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty); - - bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0; - Playfield.Add(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); - - time += currentPoint.BeatLength * (int)currentPoint.TimeSignature; - currentBeat++; - } + new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar))); } public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs new file mode 100644 index 0000000000..4773e84a5e --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs @@ -0,0 +1,108 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Chat; +using osu.Game.Overlays.Chat; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneChatLineTruncation : OsuTestScene + { + private readonly TestChatLineContainer textContainer; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ChatLine), + typeof(Message), + typeof(LinkFlowContainer), + typeof(MessageFormatter) + }; + + public TestSceneChatLineTruncation() + { + Add(textContainer = new TestChatLineContainer + { + Padding = new MarginPadding { Left = 20, Right = 20 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }); + } + + [BackgroundDependencyLoader] + private void load() + { + testFormatting(); + } + + private void clear() => AddStep("clear messages", textContainer.Clear); + + private void addMessageWithChecks(string text, bool isAction = false, bool isImportant = false, string username = null) + { + int index = textContainer.Count + 1; + var newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index, username)); + textContainer.Add(newLine); + } + + private void testFormatting() + { + for (int a = 0; a < 25; a++) + addMessageWithChecks($"Wide {a} character username.", username: new string('w', a)); + addMessageWithChecks("Short name with spaces.", username: "sho rt name"); + addMessageWithChecks("Long name with spaces.", username: "long name with s p a c e s"); + } + + private class DummyMessage : Message + { + private static long messageCounter; + + internal static readonly User TEST_SENDER_BACKGROUND = new User + { + Username = @"i-am-important", + Id = 42, + Colour = "#250cc9", + }; + + internal static readonly User TEST_SENDER = new User + { + Username = @"Somebody", + Id = 1, + }; + + public new DateTimeOffset Timestamp = DateTimeOffset.Now; + + public DummyMessage(string text, bool isAction = false, bool isImportant = false, int number = 0, string username = null) + : base(messageCounter++) + { + Content = text; + IsAction = isAction; + Sender = new User + { + Username = username ?? $"user {number}", + Id = number, + Colour = isImportant ? "#250cc9" : null, + }; + } + } + + private class TestChatLineContainer : FillFlowContainer + { + protected override int Compare(Drawable x, Drawable y) + { + var xC = (ChatLine)x; + var yC = (ChatLine)y; + + return xC.Message.CompareTo(yC.Message); + } + } + } +} diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index 7b97a27732..ed9e01a67e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Screens.Select; +using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Tests.Visual.SongSelect @@ -30,45 +31,44 @@ namespace osu.Game.Tests.Visual.SongSelect Size = new Vector2(550f, 450f), }); - AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap + { + BeatmapInfo = { - BeatmapSetInfo = + BeatmapSet = new BeatmapSetInfo { Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } }, - BeatmapInfo = + Version = "All Metrics", + Metadata = new BeatmapMetadata { - Version = "All Metrics", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has all the metrics", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 7, - DrainRate = 1, - OverallDifficulty = 5.7f, - ApproachRate = 3.5f, - }, - StarDifficulty = 5.3f, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } + Source = "osu!lazer", + Tags = "this beatmap has all the metrics", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + }, + StarDifficulty = 5.3f, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, } - ); + })); - AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("all except source", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { - BeatmapSetInfo = - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, BeatmapInfo = { + BeatmapSet = new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, Version = "All Metrics", Metadata = new BeatmapMetadata { @@ -88,16 +88,16 @@ namespace osu.Game.Tests.Visual.SongSelect Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, } - }); + })); - AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("ratings", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { - BeatmapSetInfo = - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, BeatmapInfo = { + BeatmapSet = new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, Version = "Only Ratings", Metadata = new BeatmapMetadata { @@ -113,9 +113,9 @@ namespace osu.Game.Tests.Visual.SongSelect }, StarDifficulty = 4.8f } - }); + })); - AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("fails+retries", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = { @@ -139,9 +139,9 @@ namespace osu.Game.Tests.Visual.SongSelect Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, } - }); + })); - AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("null metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = { @@ -160,7 +160,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, StarDifficulty = 1.97f, } - }); + })); AddStep("null beatmap", () => detailsArea.Beatmap = null); } diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index 8e358a77db..186f27a8b2 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter)); AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn)); AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable)); + AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected)); foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus))) AddStep($"{status} beatmap", () => showBeatmapWithStatus(status)); } diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 98f15599fc..147556b78b 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -133,6 +133,10 @@ namespace osu.Game.Online.Leaderboards }); break; + case PlaceholderState.NoneSelected: + replacePlaceholder(new MessagePlaceholder(@"Please select a beatmap!")); + break; + case PlaceholderState.Unavailable: replacePlaceholder(new MessagePlaceholder(@"Leaderboards are not available for this beatmap!")); break; diff --git a/osu.Game/Online/Leaderboards/PlaceholderState.cs b/osu.Game/Online/Leaderboards/PlaceholderState.cs index 930e1df484..297241fa73 100644 --- a/osu.Game/Online/Leaderboards/PlaceholderState.cs +++ b/osu.Game/Online/Leaderboards/PlaceholderState.cs @@ -9,6 +9,7 @@ namespace osu.Game.Online.Leaderboards Retrieving, NetworkFailure, Unavailable, + NoneSelected, NoScores, NotLoggedIn, NotSupporter, diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 2576b38ec8..7596231a3d 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -31,6 +31,8 @@ namespace osu.Game.Overlays.Chat protected virtual float MessagePadding => default_message_padding; + private const float timestamp_padding = 65; + private const float default_horizontal_padding = 15; protected virtual float HorizontalPadding => default_horizontal_padding; @@ -87,7 +89,12 @@ namespace osu.Game.Overlays.Chat { Shadow = false, Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], - Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true) + Truncate = true, + EllipsisString = "… :", + Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + MaxWidth = default_message_padding - timestamp_padding }; if (hasBackground) @@ -142,6 +149,7 @@ namespace osu.Game.Overlays.Chat new MessageSender(message.Sender) { AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = timestamp_padding }, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, Child = effectedUsername, diff --git a/osu.Game/Rulesets/Objects/BarLine.cs b/osu.Game/Rulesets/Objects/BarLine.cs new file mode 100644 index 0000000000..a5c716e127 --- /dev/null +++ b/osu.Game/Rulesets/Objects/BarLine.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Objects +{ + /// + /// A hit object representing the end of a bar. + /// + public class BarLine : HitObject + { + /// + /// Whether this barline is a prominent beat (based on time signature of beatmap). + /// + public bool Major; + } +} diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs new file mode 100644 index 0000000000..ce571d7b17 --- /dev/null +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.MathUtils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects +{ + public class BarLineGenerator + { + /// + /// The generated bar lines. + /// + public readonly List BarLines = new List(); + + /// + /// Constructs and generates bar lines for provided beatmap. + /// + /// The beatmap to generate bar lines for. + public BarLineGenerator(IBeatmap beatmap) + { + if (beatmap.HitObjects.Count == 0) + return; + + HitObject lastObject = beatmap.HitObjects.Last(); + double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime); + + var timingPoints = beatmap.ControlPointInfo.TimingPoints; + + if (timingPoints.Count == 0) + return; + + for (int i = 0; i < timingPoints.Count; i++) + { + TimingControlPoint currentTimingPoint = timingPoints[i]; + int currentBeat = 0; + + // Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object + double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - currentTimingPoint.BeatLength : lastHitTime + currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature; + + double barLength = currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature; + + for (double t = currentTimingPoint.Time; Precision.DefinitelyBigger(endTime, t); t += barLength, currentBeat++) + { + BarLines.Add(new BarLine + { + StartTime = t, + Major = currentBeat % (int)currentTimingPoint.TimeSignature == 0 + }); + } + } + } + } +} diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index b66a2ffe0f..5348de68d6 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -27,8 +27,8 @@ namespace osu.Game.Screens.Select set { beatmap = value; - Leaderboard.Beatmap = beatmap?.BeatmapInfo; Details.Beatmap = beatmap?.BeatmapInfo; + Leaderboard.Beatmap = beatmap is DummyWorkingBeatmap ? null : beatmap?.BeatmapInfo; } } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index cb45c00f66..33f040755e 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -83,6 +83,12 @@ namespace osu.Game.Screens.Select.Leaderboards protected override APIRequest FetchScores(Action> scoresCallback) { + if (Beatmap == null) + { + PlaceholderState = PlaceholderState.NoneSelected; + return null; + } + if (Scope == BeatmapLeaderboardScope.Local) { var scores = scoreManager @@ -113,7 +119,7 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } - if (Beatmap?.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending) + if (Beatmap.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending) { PlaceholderState = PlaceholderState.Unavailable; return null; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5f2aad24dc..791d2fe285 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5027a4ef8c..0560c45edf 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + +