1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 04:13:00 +08:00

Merge remote-tracking branch 'refs/remotes/ppy/master' into rankings-scope-selector

This commit is contained in:
Andrei Zavatski 2019-09-10 16:33:08 +03:00
commit 6c2db8e4b0
27 changed files with 274 additions and 167 deletions

View File

@ -63,6 +63,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.904.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.904.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2019.905.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2019.909.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -3,6 +3,7 @@
using System.Linq; using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Replays;
@ -12,6 +13,7 @@ using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Mania.Tests namespace osu.Game.Rulesets.Mania.Tests
{ {
[TestFixture] [TestFixture]
[HeadlessTest]
public class TestSceneAutoGeneration : OsuTestScene public class TestSceneAutoGeneration : OsuTestScene
{ {
[Test] [Test]

View File

@ -1,4 +1,4 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System; using System;
@ -11,6 +11,7 @@ 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.Graphics; using osu.Game.Graphics;
@ -40,6 +41,7 @@ namespace osu.Game.Rulesets.Mania.Tests
{ {
Child = new FillFlowContainer Child = new FillFlowContainer
{ {
Clock = new FramedClock(new ManualClock()),
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
@ -62,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Tests
private Drawable createNoteDisplay(ScrollingDirection direction, int identifier, out DrawableNote hitObject) 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()); note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
return new ScrollingTestContainer(direction) return new ScrollingTestContainer(direction)
@ -77,7 +79,7 @@ namespace osu.Game.Rulesets.Mania.Tests
private Drawable createHoldNoteDisplay(ScrollingDirection direction, int identifier, out DrawableHoldNote hitObject) 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()); note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
return new ScrollingTestContainer(direction) return new ScrollingTestContainer(direction)
@ -133,7 +135,7 @@ namespace osu.Game.Rulesets.Mania.Tests
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Width = 1.25f, Width = 1.25f,
Colour = Color4.Black.Opacity(0.5f) Colour = Color4.Green.Opacity(0.5f)
}, },
content = new Container { RelativeSizeAxes = Axes.Both } content = new Container { RelativeSizeAxes = Axes.Both }
} }

View File

@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
using osuTK; using osuTK;
@ -114,8 +115,7 @@ namespace osu.Game.Rulesets.Mania.Tests
var obj = new BarLine var obj = new BarLine
{ {
StartTime = Time.Current + 2000, StartTime = Time.Current + 2000,
ControlPoint = new TimingControlPoint(), Major = major,
BeatIndex = major ? 0 : 1
}; };
obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());

View File

@ -1,21 +0,0 @@
// 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 osu.Game.Beatmaps.ControlPoints;
namespace osu.Game.Rulesets.Mania.Objects
{
public class BarLine : ManiaHitObject
{
/// <summary>
/// The control point which this bar line is part of.
/// </summary>
public TimingControlPoint ControlPoint;
/// <summary>
/// The index of the beat which this bar line represents within the control point.
/// This is a "major" bar line if <see cref="BeatIndex"/> % <see cref="TimingControlPoint.TimeSignature"/> == 0.
/// </summary>
public int BeatIndex;
}
}

View File

@ -4,6 +4,7 @@
using osuTK; using osuTK;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osuTK.Graphics; using osuTK.Graphics;
@ -13,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
/// Visualises a <see cref="BarLine"/>. Although this derives DrawableManiaHitObject, /// Visualises a <see cref="BarLine"/>. Although this derives DrawableManiaHitObject,
/// this does not handle input/sound like a normal hit object. /// this does not handle input/sound like a normal hit object.
/// </summary> /// </summary>
public class DrawableBarLine : DrawableManiaHitObject<BarLine> public class DrawableBarLine : DrawableHitObject<BarLine>
{ {
/// <summary> /// <summary>
/// Height of major bar line triangles. /// Height of major bar line triangles.
@ -40,9 +41,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Colour = new Color4(255, 204, 33, 255), Colour = new Color4(255, 204, 33, 255),
}); });
bool isMajor = barLine.BeatIndex % (int)barLine.ControlPoint.TimeSignature == 0; if (barLine.Major)
if (isMajor)
{ {
AddInternal(new EquilateralTriangle 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; Alpha = 0.2f;
} }

View File

@ -2,14 +2,11 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Replays; using osu.Game.Replays;
using osu.Game.Rulesets.Mania.Beatmaps; 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.Replays;
using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
@ -45,33 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI
public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods) public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods) : base(ruleset, beatmap, mods)
{ {
// Generate the bar lines BarLines = new BarLineGenerator(Beatmap).BarLines;
double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue;
var timingPoints = Beatmap.ControlPointInfo.TimingPoints;
var barLines = new List<BarLine>();
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;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
using osuTK; using osuTK;

View File

@ -12,6 +12,7 @@ using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Objects;
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.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;

View File

@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
return null; return null;
case OsuSkinComponents.HitCircleText: case OsuSkinComponents.HitCircleText:
var font = GetConfig<OsuSkinConfiguration, string>(OsuSkinConfiguration.HitCircleFont)?.Value ?? "default"; var font = GetConfig<OsuSkinConfiguration, string>(OsuSkinConfiguration.HitCirclePrefix)?.Value ?? "default";
var overlap = GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? 0; var overlap = GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? 0;
return !hasFont(font) return !hasFont(font)

View File

@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
{ {
public enum OsuSkinConfiguration public enum OsuSkinConfiguration
{ {
HitCircleFont, HitCirclePrefix,
HitCircleOverlap, HitCircleOverlap,
SliderBorderSize, SliderBorderSize,
SliderPathRadius, SliderPathRadius,

View File

@ -1,9 +0,0 @@
// 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.
namespace osu.Game.Rulesets.Taiko.Objects
{
public class BarLine : TaikoHitObject
{
}
}

View File

@ -3,6 +3,7 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
using osuTK; using osuTK;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
/// <summary> /// <summary>
/// A line that scrolls alongside hit objects in the playfield and visualises control points. /// A line that scrolls alongside hit objects in the playfield and visualises control points.
/// </summary> /// </summary>
public class DrawableBarLine : DrawableHitObject<TaikoHitObject> public class DrawableBarLine : DrawableHitObject<HitObject>
{ {
/// <summary> /// <summary>
/// The width of the line tracker. /// The width of the line tracker.

View File

@ -5,6 +5,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osuTK; using osuTK;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {

View File

@ -5,19 +5,18 @@ using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Rulesets.Taiko.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Rulesets.Taiko.Replays;
using System.Linq;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Replays; using osu.Game.Replays;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
@ -38,49 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
loadBarLines(); new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar)));
}
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++;
}
} }
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this);

View File

@ -0,0 +1,108 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.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<Type> 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<ChatLine>
{
protected override int Compare(Drawable x, Drawable y)
{
var xC = (ChatLine)x;
var yC = (ChatLine)y;
return xC.Message.CompareTo(yC.Message);
}
}
}
}

View File

@ -9,6 +9,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Screens.Select; using osu.Game.Screens.Select;
using osu.Game.Tests.Beatmaps;
using osuTK; using osuTK;
namespace osu.Game.Tests.Visual.SongSelect namespace osu.Game.Tests.Visual.SongSelect
@ -30,14 +31,14 @@ namespace osu.Game.Tests.Visual.SongSelect
Size = new Vector2(550f, 450f), Size = new Vector2(550f, 450f),
}); });
AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{ {
BeatmapSetInfo = BeatmapInfo =
{
BeatmapSet = new BeatmapSetInfo
{ {
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
}, },
BeatmapInfo =
{
Version = "All Metrics", Version = "All Metrics",
Metadata = new BeatmapMetadata Metadata = new BeatmapMetadata
{ {
@ -58,17 +59,16 @@ namespace osu.Game.Tests.Visual.SongSelect
Retries = Enumerable.Range(-2, 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 = BeatmapInfo =
{
BeatmapSet = new BeatmapSetInfo
{ {
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
}, },
BeatmapInfo =
{
Version = "All Metrics", Version = "All Metrics",
Metadata = new BeatmapMetadata Metadata = new BeatmapMetadata
{ {
@ -88,16 +88,16 @@ namespace osu.Game.Tests.Visual.SongSelect
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), 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 = BeatmapInfo =
{
BeatmapSet = new BeatmapSetInfo
{ {
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
}, },
BeatmapInfo =
{
Version = "Only Ratings", Version = "Only Ratings",
Metadata = new BeatmapMetadata Metadata = new BeatmapMetadata
{ {
@ -113,9 +113,9 @@ namespace osu.Game.Tests.Visual.SongSelect
}, },
StarDifficulty = 4.8f StarDifficulty = 4.8f
} }
}); }));
AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) AddStep("fails+retries", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{ {
BeatmapInfo = BeatmapInfo =
{ {
@ -139,9 +139,9 @@ namespace osu.Game.Tests.Visual.SongSelect
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), 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 = BeatmapInfo =
{ {
@ -160,7 +160,7 @@ namespace osu.Game.Tests.Visual.SongSelect
}, },
StarDifficulty = 1.97f, StarDifficulty = 1.97f,
} }
}); }));
AddStep("null beatmap", () => detailsArea.Beatmap = null); AddStep("null beatmap", () => detailsArea.Beatmap = null);
} }

View File

@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter)); AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter));
AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn)); AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn));
AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable)); AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable));
AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected));
foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus))) foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus)))
AddStep($"{status} beatmap", () => showBeatmapWithStatus(status)); AddStep($"{status} beatmap", () => showBeatmapWithStatus(status));
} }

View File

@ -133,6 +133,10 @@ namespace osu.Game.Online.Leaderboards
}); });
break; break;
case PlaceholderState.NoneSelected:
replacePlaceholder(new MessagePlaceholder(@"Please select a beatmap!"));
break;
case PlaceholderState.Unavailable: case PlaceholderState.Unavailable:
replacePlaceholder(new MessagePlaceholder(@"Leaderboards are not available for this beatmap!")); replacePlaceholder(new MessagePlaceholder(@"Leaderboards are not available for this beatmap!"));
break; break;

View File

@ -9,6 +9,7 @@ namespace osu.Game.Online.Leaderboards
Retrieving, Retrieving,
NetworkFailure, NetworkFailure,
Unavailable, Unavailable,
NoneSelected,
NoScores, NoScores,
NotLoggedIn, NotLoggedIn,
NotSupporter, NotSupporter,

View File

@ -31,6 +31,8 @@ namespace osu.Game.Overlays.Chat
protected virtual float MessagePadding => default_message_padding; protected virtual float MessagePadding => default_message_padding;
private const float timestamp_padding = 65;
private const float default_horizontal_padding = 15; private const float default_horizontal_padding = 15;
protected virtual float HorizontalPadding => default_horizontal_padding; protected virtual float HorizontalPadding => default_horizontal_padding;
@ -87,7 +89,12 @@ namespace osu.Game.Overlays.Chat
{ {
Shadow = false, Shadow = false,
Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], 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) if (hasBackground)
@ -142,6 +149,7 @@ namespace osu.Game.Overlays.Chat
new MessageSender(message.Sender) new MessageSender(message.Sender)
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = timestamp_padding },
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Child = effectedUsername, Child = effectedUsername,

View File

@ -0,0 +1,16 @@
// 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.
namespace osu.Game.Rulesets.Objects
{
/// <summary>
/// A hit object representing the end of a bar.
/// </summary>
public class BarLine : HitObject
{
/// <summary>
/// Whether this barline is a prominent beat (based on time signature of beatmap).
/// </summary>
public bool Major;
}
}

View File

@ -0,0 +1,58 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.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
{
/// <summary>
/// The generated bar lines.
/// </summary>
public readonly List<BarLine> BarLines = new List<BarLine>();
/// <summary>
/// Constructs and generates bar lines for provided beatmap.
/// </summary>
/// <param name="beatmap">The beatmap to generate bar lines for.</param>
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
});
}
}
}
}
}

View File

@ -27,8 +27,8 @@ namespace osu.Game.Screens.Select
set set
{ {
beatmap = value; beatmap = value;
Leaderboard.Beatmap = beatmap?.BeatmapInfo;
Details.Beatmap = beatmap?.BeatmapInfo; Details.Beatmap = beatmap?.BeatmapInfo;
Leaderboard.Beatmap = beatmap is DummyWorkingBeatmap ? null : beatmap?.BeatmapInfo;
} }
} }

View File

@ -83,6 +83,12 @@ namespace osu.Game.Screens.Select.Leaderboards
protected override APIRequest FetchScores(Action<IEnumerable<ScoreInfo>> scoresCallback) protected override APIRequest FetchScores(Action<IEnumerable<ScoreInfo>> scoresCallback)
{ {
if (Beatmap == null)
{
PlaceholderState = PlaceholderState.NoneSelected;
return null;
}
if (Scope == BeatmapLeaderboardScope.Local) if (Scope == BeatmapLeaderboardScope.Local)
{ {
var scores = scoreManager var scores = scoreManager
@ -113,7 +119,7 @@ namespace osu.Game.Screens.Select.Leaderboards
return null; return null;
} }
if (Beatmap?.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending) if (Beatmap.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending)
{ {
PlaceholderState = PlaceholderState.Unavailable; PlaceholderState = PlaceholderState.Unavailable;
return null; return null;

View File

@ -26,7 +26,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.904.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.904.0" />
<PackageReference Include="ppy.osu.Framework" Version="2019.905.0" /> <PackageReference Include="ppy.osu.Framework" Version="2019.909.0" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />

View File

@ -118,8 +118,8 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.904.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.904.0" />
<PackageReference Include="ppy.osu.Framework" Version="2019.905.0" /> <PackageReference Include="ppy.osu.Framework" Version="2019.909.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.905.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2019.909.0" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />
<PackageReference Include="NUnit" Version="3.11.0" /> <PackageReference Include="NUnit" Version="3.11.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />