1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-21 03:02:54 +08:00

Merge branch 'master' into samah-ios

This commit is contained in:
Shane Woolcock 2019-01-08 17:09:26 +10:30
commit a267a1a085
37 changed files with 137 additions and 167 deletions

View File

@ -2,7 +2,6 @@
// 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 System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Framework; using osu.Framework;
@ -77,10 +76,10 @@ namespace osu.Desktop.Updater
switch (RuntimeInfo.OS) switch (RuntimeInfo.OS)
{ {
case RuntimeInfo.Platform.Windows: case RuntimeInfo.Platform.Windows:
bestAsset = release.Assets?.FirstOrDefault(f => f.Name.EndsWith(".exe")); bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".exe"));
break; break;
case RuntimeInfo.Platform.MacOsx: case RuntimeInfo.Platform.MacOsx:
bestAsset = release.Assets?.FirstOrDefault(f => f.Name.EndsWith(".app.zip")); bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".app.zip"));
break; break;
} }

View File

@ -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 osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
@ -23,60 +24,70 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
var osuBeatmap = (Beatmap<OsuHitObject>)Beatmap; var osuBeatmap = (Beatmap<OsuHitObject>)Beatmap;
// Reset stacking if (osuBeatmap.HitObjects.Count > 0)
foreach (var h in osuBeatmap.HitObjects) {
h.StackHeight = 0; // Reset stacking
foreach (var h in osuBeatmap.HitObjects)
h.StackHeight = 0;
if (Beatmap.BeatmapInfo.BeatmapVersion >= 6) if (Beatmap.BeatmapInfo.BeatmapVersion >= 6)
applyStacking(osuBeatmap); applyStacking(osuBeatmap, 0, osuBeatmap.HitObjects.Count - 1);
else else
applyStackingOld(osuBeatmap); applyStackingOld(osuBeatmap);
}
} }
private void applyStacking(Beatmap<OsuHitObject> beatmap) private void applyStacking(Beatmap<OsuHitObject> beatmap, int startIndex, int endIndex)
{ {
// Extend the end index to include objects they are stacked on if (startIndex > endIndex) throw new ArgumentOutOfRangeException(nameof(startIndex), $"{nameof(startIndex)} cannot be greater than {nameof(endIndex)}.");
int extendedEndIndex = beatmap.HitObjects.Count - 1; if (startIndex < 0) throw new ArgumentOutOfRangeException(nameof(startIndex), $"{nameof(startIndex)} cannot be less than 0.");
for (int i = beatmap.HitObjects.Count - 1; i >= 0; i--) if (endIndex < 0) throw new ArgumentOutOfRangeException(nameof(endIndex), $"{nameof(endIndex)} cannot be less than 0.");
int extendedEndIndex = endIndex;
if (endIndex < beatmap.HitObjects.Count - 1)
{ {
int stackBaseIndex = i; // Extend the end index to include objects they are stacked on
for (int n = stackBaseIndex + 1; n < beatmap.HitObjects.Count; n++) for (int i = endIndex; i >= startIndex; i--)
{ {
OsuHitObject stackBaseObject = beatmap.HitObjects[stackBaseIndex]; int stackBaseIndex = i;
if (stackBaseObject is Spinner) break; for (int n = stackBaseIndex + 1; n < beatmap.HitObjects.Count; n++)
OsuHitObject objectN = beatmap.HitObjects[n];
if (objectN is Spinner)
continue;
double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime;
double stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo.StackLeniency;
if (objectN.StartTime - endTime > stackThreshold)
//We are no longer within stacking range of the next object.
break;
if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance ||
stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)
{ {
stackBaseIndex = n; OsuHitObject stackBaseObject = beatmap.HitObjects[stackBaseIndex];
if (stackBaseObject is Spinner) break;
// HitObjects after the specified update range haven't been reset yet OsuHitObject objectN = beatmap.HitObjects[n];
objectN.StackHeight = 0; if (objectN is Spinner)
continue;
double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime;
double stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo.StackLeniency;
if (objectN.StartTime - endTime > stackThreshold)
//We are no longer within stacking range of the next object.
break;
if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance
|| stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)
{
stackBaseIndex = n;
// HitObjects after the specified update range haven't been reset yet
objectN.StackHeight = 0;
}
} }
}
if (stackBaseIndex > extendedEndIndex) if (stackBaseIndex > extendedEndIndex)
{ {
extendedEndIndex = stackBaseIndex; extendedEndIndex = stackBaseIndex;
if (extendedEndIndex == beatmap.HitObjects.Count - 1) if (extendedEndIndex == beatmap.HitObjects.Count - 1)
break; break;
}
} }
} }
//Reverse pass for stack calculation. //Reverse pass for stack calculation.
int extendedStartIndex = 0; int extendedStartIndex = startIndex;
for (int i = extendedEndIndex; i > 0; i--) for (int i = extendedEndIndex; i > startIndex; i--)
{ {
int n = i; int n = i;
/* We should check every note which has not yet got a stack. /* We should check every note which has not yet got a stack.
@ -155,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
/* We have hit the first slider in a possible stack. /* We have hit the first slider in a possible stack.
* From this point on, we ALWAYS stack positive regardless. * From this point on, we ALWAYS stack positive regardless.
*/ */
while (--n >= 0) while (--n >= startIndex)
{ {
OsuHitObject objectN = beatmap.HitObjects[n]; OsuHitObject objectN = beatmap.HitObjects[n];
if (objectN is Spinner) continue; if (objectN is Spinner) continue;

View File

@ -7,6 +7,7 @@ using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using System.Linq; using System.Linq;
using osu.Framework.Caching;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -26,8 +27,11 @@ namespace osu.Game.Rulesets.Osu.Objects
public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity; public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity;
public double Duration => EndTime - StartTime; public double Duration => EndTime - StartTime;
private Cached<Vector2> endPositionCache;
public override Vector2 EndPosition => endPositionCache.IsValid ? endPositionCache.Value : endPositionCache.Value = Position + this.CurvePositionAt(1);
public Vector2 StackedPositionAt(double t) => StackedPosition + this.CurvePositionAt(t); public Vector2 StackedPositionAt(double t) => StackedPosition + this.CurvePositionAt(t);
public override Vector2 EndPosition => Position + this.CurvePositionAt(1);
public override int ComboIndex public override int ComboIndex
{ {
@ -56,7 +60,11 @@ namespace osu.Game.Rulesets.Osu.Objects
public SliderPath Path public SliderPath Path
{ {
get => PathBindable.Value; get => PathBindable.Value;
set => PathBindable.Value = value; set
{
PathBindable.Value = value;
endPositionCache.Invalidate();
}
} }
public double Distance => Path.Distance; public double Distance => Path.Distance;
@ -73,6 +81,8 @@ namespace osu.Game.Rulesets.Osu.Objects
if (TailCircle != null) if (TailCircle != null)
TailCircle.Position = EndPosition; TailCircle.Position = EndPosition;
endPositionCache.Invalidate();
} }
} }
@ -92,7 +102,17 @@ namespace osu.Game.Rulesets.Osu.Objects
public List<List<SampleInfo>> NodeSamples { get; set; } = new List<List<SampleInfo>>(); public List<List<SampleInfo>> NodeSamples { get; set; } = new List<List<SampleInfo>>();
public int RepeatCount { get; set; } private int repeatCount;
public int RepeatCount
{
get => repeatCount;
set
{
repeatCount = value;
endPositionCache.Invalidate();
}
}
/// <summary> /// <summary>
/// The length of one span of this <see cref="Slider"/>. /// The length of one span of this <see cref="Slider"/>.
@ -169,7 +189,11 @@ namespace osu.Game.Rulesets.Osu.Objects
private void createTicks() private void createTicks()
{ {
var length = Path.Distance; // A very lenient maximum length of a slider for ticks to be generated.
// This exists for edge cases such as /b/1573664 where the beatmap has been edited by the user, and should never be reached in normal usage.
const double max_length = 100000;
var length = Math.Min(max_length, Path.Distance);
var tickDistance = MathHelper.Clamp(TickDistance, 0, length); var tickDistance = MathHelper.Clamp(TickDistance, 0, length);
if (tickDistance == 0) return; if (tickDistance == 0) return;
@ -191,7 +215,7 @@ namespace osu.Game.Rulesets.Osu.Objects
var distanceProgress = d / length; var distanceProgress = d / length;
var timeProgress = reversed ? 1 - distanceProgress : distanceProgress; var timeProgress = reversed ? 1 - distanceProgress : distanceProgress;
var firstSample = Samples.FirstOrDefault(s => s.Name == SampleInfo.HIT_NORMAL) var firstSample = Samples.Find(s => s.Name == SampleInfo.HIT_NORMAL)
?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933)
var sampleList = new List<SampleInfo>(); var sampleList = new List<SampleInfo>();

View File

@ -135,7 +135,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
if (userTriggered) if (userTriggered)
{ {
var nextTick = ticks.FirstOrDefault(j => !j.IsHit); var nextTick = ticks.Find(j => !j.IsHit);
nextTick?.TriggerResult(HitResult.Great); nextTick?.TriggerResult(HitResult.Great);

View File

@ -148,7 +148,7 @@ namespace osu.Game.Tests.Visual
private bool selectedBeatmapVisible() private bool selectedBeatmapVisible()
{ {
var currentlySelected = carousel.Items.FirstOrDefault(s => s.Item is CarouselBeatmap && s.Item.State == CarouselItemState.Selected); var currentlySelected = carousel.Items.Find(s => s.Item is CarouselBeatmap && s.Item.State == CarouselItemState.Selected);
if (currentlySelected == null) if (currentlySelected == null)
return true; return true;
return currentlySelected.Item.Visible; return currentlySelected.Item.Visible;

View File

@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual
linkColour = colours.Blue; linkColour = colours.Blue;
var chatManager = new ChannelManager(); var chatManager = new ChannelManager();
BindableCollection<Channel> availableChannels = (BindableCollection<Channel>)chatManager.AvailableChannels; BindableList<Channel> availableChannels = (BindableList<Channel>)chatManager.AvailableChannels;
availableChannels.Add(new Channel { Name = "#english"}); availableChannels.Add(new Channel { Name = "#english"});
availableChannels.Add(new Channel { Name = "#japanese" }); availableChannels.Add(new Channel { Name = "#japanese" });
Dependencies.Cache(chatManager); Dependencies.Cache(chatManager);

View File

@ -73,8 +73,8 @@ namespace osu.Game.Tests.Visual
{ {
public event Action RoomsUpdated; public event Action RoomsUpdated;
public readonly BindableCollection<Room> Rooms = new BindableCollection<Room>(); public readonly BindableList<Room> Rooms = new BindableList<Room>();
IBindableCollection<Room> IRoomManager.Rooms => Rooms; IBindableList<Room> IRoomManager.Rooms => Rooms;
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) => Rooms.Add(room); public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) => Rooms.Add(room);

View File

@ -138,7 +138,7 @@ namespace osu.Game.Tests.Visual
public event Action RoomsUpdated; public event Action RoomsUpdated;
public IBindableCollection<Room> Rooms { get; } = null; public IBindableList<Room> Rooms { get; } = null;
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
{ {

View File

@ -49,7 +49,6 @@ namespace osu.Game.Tests.Visual
manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count}"; }; manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count}"; };
setState(Visibility.Visible); setState(Visibility.Visible);
AddStep(@"simple #1", sendHelloNotification); AddStep(@"simple #1", sendHelloNotification);
AddStep(@"simple #2", sendAmazingNotification); AddStep(@"simple #2", sendAmazingNotification);
@ -75,7 +74,6 @@ namespace osu.Game.Tests.Visual
checkProgressingCount(0); checkProgressingCount(0);
setState(Visibility.Visible); setState(Visibility.Visible);
//AddStep(@"barrage", () => sendBarrage()); //AddStep(@"barrage", () => sendBarrage());
@ -111,7 +109,7 @@ namespace osu.Game.Tests.Visual
if (progressingNotifications.Count(n => n.State == ProgressNotificationState.Active) < 3) if (progressingNotifications.Count(n => n.State == ProgressNotificationState.Active) < 3)
{ {
var p = progressingNotifications.FirstOrDefault(n => n.State == ProgressNotificationState.Queued); var p = progressingNotifications.Find(n => n.State == ProgressNotificationState.Queued);
if (p != null) if (p != null)
p.State = ProgressNotificationState.Active; p.State = ProgressNotificationState.Active;
} }

View File

@ -5,7 +5,6 @@ using System.ComponentModel;
using System.Linq; using System.Linq;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
@ -23,7 +22,7 @@ namespace osu.Game.Tests.Visual
// Reset the mods // Reset the mods
Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Where(m => !(m is ModAutoplay)); Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Where(m => !(m is ModAutoplay));
return new ReplayPlayer(new Score { Replay = dummyRulesetContainer.Replay }); return new ReplayPlayer(dummyRulesetContainer.ReplayScore);
} }
} }
} }

View File

@ -36,7 +36,7 @@ namespace osu.Game.Beatmaps
public string Hash { get; set; } public string Hash { get; set; }
public string StoryboardFile => Files?.FirstOrDefault(f => f.Filename.EndsWith(".osb"))?.Filename; public string StoryboardFile => Files?.Find(f => f.Filename.EndsWith(".osb"))?.Filename;
public List<BeatmapSetFileInfo> Files { get; set; } public List<BeatmapSetFileInfo> Files { get; set; }

View File

@ -151,7 +151,7 @@ namespace osu.Game.Beatmaps
public bool WaveformLoaded => waveform.IsResultAvailable; public bool WaveformLoaded => waveform.IsResultAvailable;
public Waveform Waveform => waveform.Value; public Waveform Waveform => waveform.Value;
protected virtual Waveform GetWaveform() => new Waveform(); protected virtual Waveform GetWaveform() => new Waveform(null);
private readonly RecyclableLazy<Waveform> waveform; private readonly RecyclableLazy<Waveform> waveform;
public bool StoryboardLoaded => storyboard.IsResultAvailable; public bool StoryboardLoaded => storyboard.IsResultAvailable;

View File

@ -2,7 +2,6 @@
// 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.Configuration; using osu.Framework.Configuration;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -43,7 +42,7 @@ namespace osu.Game.Configuration
{ {
base.AddBindable(lookup, bindable); base.AddBindable(lookup, bindable);
var setting = databasedSettings.FirstOrDefault(s => (int)s.Key == (int)(object)lookup); var setting = databasedSettings.Find(s => (int)s.Key == (int)(object)lookup);
if (setting != null) if (setting != null)
{ {
bindable.Parse(setting.Value); bindable.Parse(setting.Value);

View File

@ -29,8 +29,8 @@ namespace osu.Game.Online.Chat
@"#lobby" @"#lobby"
}; };
private readonly BindableCollection<Channel> availableChannels = new BindableCollection<Channel>(); private readonly BindableList<Channel> availableChannels = new BindableList<Channel>();
private readonly BindableCollection<Channel> joinedChannels = new BindableCollection<Channel>(); private readonly BindableList<Channel> joinedChannels = new BindableList<Channel>();
/// <summary> /// <summary>
/// The currently opened channel /// The currently opened channel
@ -40,12 +40,12 @@ namespace osu.Game.Online.Chat
/// <summary> /// <summary>
/// The Channels the player has joined /// The Channels the player has joined
/// </summary> /// </summary>
public IBindableCollection<Channel> JoinedChannels => joinedChannels; public IBindableList<Channel> JoinedChannels => joinedChannels;
/// <summary> /// <summary>
/// The channels available for the player to join /// The channels available for the player to join
/// </summary> /// </summary>
public IBindableCollection<Channel> AvailableChannels => availableChannels; public IBindableList<Channel> AvailableChannels => availableChannels;
private IAPIProvider api; private IAPIProvider api;

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -30,6 +31,7 @@ namespace osu.Game.Online.Leaderboards
private readonly LoadingAnimation loading; private readonly LoadingAnimation loading;
private ScheduledDelegate showScoresDelegate; private ScheduledDelegate showScoresDelegate;
private CancellationTokenSource showScoresCancellationSource;
private bool scoresLoadedOnce; private bool scoresLoadedOnce;
@ -49,6 +51,10 @@ namespace osu.Game.Online.Leaderboards
loading.Hide(); loading.Hide();
// schedule because we may not be loaded yet (LoadComponentAsync complains).
showScoresDelegate?.Cancel();
showScoresCancellationSource?.Cancel();
if (scores == null || !scores.Any()) if (scores == null || !scores.Any())
return; return;
@ -58,8 +64,6 @@ namespace osu.Game.Online.Leaderboards
scrollFlow = CreateScoreFlow(); scrollFlow = CreateScoreFlow();
scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1));
// schedule because we may not be loaded yet (LoadComponentAsync complains).
showScoresDelegate?.Cancel();
if (!IsLoaded) if (!IsLoaded)
showScoresDelegate = Schedule(showScores); showScoresDelegate = Schedule(showScores);
else else
@ -77,7 +81,7 @@ namespace osu.Game.Online.Leaderboards
} }
scrollContainer.ScrollTo(0f, false); scrollContainer.ScrollTo(0f, false);
}); }, (showScoresCancellationSource = new CancellationTokenSource()).Token);
} }
} }

View File

@ -37,10 +37,10 @@ namespace osu.Game.Online.Multiplayer
public RulesetInfo Ruleset { get; set; } public RulesetInfo Ruleset { get; set; }
[JsonIgnore] [JsonIgnore]
public readonly BindableCollection<Mod> AllowedMods = new BindableCollection<Mod>(); public readonly BindableList<Mod> AllowedMods = new BindableList<Mod>();
[JsonIgnore] [JsonIgnore]
public readonly BindableCollection<Mod> RequiredMods = new BindableCollection<Mod>(); public readonly BindableList<Mod> RequiredMods = new BindableList<Mod>();
[JsonProperty("beatmap")] [JsonProperty("beatmap")]
private APIBeatmap apiBeatmap { get; set; } private APIBeatmap apiBeatmap { get; set; }

View File

@ -24,7 +24,7 @@ namespace osu.Game.Online.Multiplayer
public Bindable<User> Host { get; private set; } = new Bindable<User>(); public Bindable<User> Host { get; private set; } = new Bindable<User>();
[JsonProperty("playlist")] [JsonProperty("playlist")]
public BindableCollection<PlaylistItem> Playlist { get; set; } = new BindableCollection<PlaylistItem>(); public BindableList<PlaylistItem> Playlist { get; set; } = new BindableList<PlaylistItem>();
[JsonProperty("channel_id")] [JsonProperty("channel_id")]
public Bindable<int> ChannelId { get; private set; } = new Bindable<int>(); public Bindable<int> ChannelId { get; private set; } = new Bindable<int>();

View File

@ -222,7 +222,7 @@ namespace osu.Game
var databasedSet = BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID); var databasedSet = BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID);
// Use first beatmap available for current ruleset, else switch ruleset. // Use first beatmap available for current ruleset, else switch ruleset.
var first = databasedSet.Beatmaps.FirstOrDefault(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First(); var first = databasedSet.Beatmaps.Find(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First();
ruleset.Value = first.Ruleset; ruleset.Value = first.Ruleset;
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first);

View File

@ -396,11 +396,11 @@ namespace osu.Game.Overlays.Profile
infoTextLeft.NewLine(); infoTextLeft.NewLine();
infoTextLeft.AddText("Last seen ", lightText); infoTextLeft.AddText("Last seen ", lightText);
infoTextLeft.AddText(new DrawableDate(user.LastVisit.Value), boldItalic); infoTextLeft.AddText(new DrawableDate(user.LastVisit.Value), boldItalic);
infoTextLeft.NewParagraph();
} }
if (user.PlayStyle?.Length > 0) if (user.PlayStyle?.Length > 0)
{ {
infoTextLeft.NewParagraph();
infoTextLeft.AddText("Plays with ", lightText); infoTextLeft.AddText("Plays with ", lightText);
infoTextLeft.AddText(string.Join(", ", user.PlayStyle), boldItalic); infoTextLeft.AddText(string.Join(", ", user.PlayStyle), boldItalic);
} }

View File

@ -16,9 +16,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
{ {
protected override string Header => "Layout"; protected override string Header => "Layout";
private FillFlowContainer letterboxSettings;
private Bindable<bool> letterboxing;
private Bindable<Size> sizeFullscreen; private Bindable<Size> sizeFullscreen;
private OsuGameBase game; private OsuGameBase game;
@ -32,7 +29,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
{ {
this.game = game; this.game = game;
letterboxing = config.GetBindable<bool>(FrameworkSetting.Letterboxing);
sizeFullscreen = config.GetBindable<Size>(FrameworkSetting.SizeFullscreen); sizeFullscreen = config.GetBindable<Size>(FrameworkSetting.SizeFullscreen);
Container resolutionSettingsContainer; Container resolutionSettingsContainer;
@ -49,36 +45,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y AutoSizeAxes = Axes.Y
}, },
new SettingsCheckbox
{
LabelText = "Letterboxing",
Bindable = letterboxing,
},
letterboxSettings = new FillFlowContainer
{
Direction = FillDirection.Vertical,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
AutoSizeDuration = transition_duration,
AutoSizeEasing = Easing.OutQuint,
Masking = true,
Children = new Drawable[]
{
new SettingsSlider<double>
{
LabelText = "Horizontal position",
Bindable = config.GetBindable<double>(FrameworkSetting.LetterboxPositionX),
KeyboardStep = 0.01f
},
new SettingsSlider<double>
{
LabelText = "Vertical position",
Bindable = config.GetBindable<double>(FrameworkSetting.LetterboxPositionY),
KeyboardStep = 0.01f
},
}
},
}; };
var resolutions = getResolutions(); var resolutions = getResolutions();
@ -104,15 +70,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
resolutionDropdown.Hide(); resolutionDropdown.Hide();
}, true); }, true);
} }
letterboxing.BindValueChanged(isVisible =>
{
letterboxSettings.ClearTransforms();
letterboxSettings.AutoSizeAxes = isVisible ? Axes.Y : Axes.None;
if (!isVisible)
letterboxSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint);
}, true);
} }
private IReadOnlyList<Size> getResolutions() private IReadOnlyList<Size> getResolutions()

View File

@ -1,20 +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 osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Graphics;
namespace osu.Game.Overlays.Settings
{
public class SettingsLabel : SettingsItem<string>
{
protected override Drawable CreateControl() => null;
[BackgroundDependencyLoader]
private void load(OsuColour colour)
{
Colour = colour.Gray6;
}
}
}

View File

@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mods
public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0;
public virtual void ApplyToRulesetContainer(RulesetContainer<T> rulesetContainer) => rulesetContainer.SetReplay(CreateReplayScore(rulesetContainer.Beatmap)?.Replay); public virtual void ApplyToRulesetContainer(RulesetContainer<T> rulesetContainer) => rulesetContainer.SetReplayScore(CreateReplayScore(rulesetContainer.Beatmap));
} }
public abstract class ModAutoplay : Mod, IApplicableFailOverride public abstract class ModAutoplay : Mod, IApplicableFailOverride

View File

@ -22,6 +22,7 @@ using osu.Game.Overlays;
using osu.Game.Replays; using osu.Game.Replays;
using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Configuration;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.UI namespace osu.Game.Rulesets.UI
{ {
@ -130,7 +131,7 @@ namespace osu.Game.Rulesets.UI
protected virtual ReplayInputHandler CreateReplayInputHandler(Replay replay) => null; protected virtual ReplayInputHandler CreateReplayInputHandler(Replay replay) => null;
public Replay Replay { get; private set; } public Score ReplayScore { get; private set; }
/// <summary> /// <summary>
/// Whether the game is paused. Used to block user input. /// Whether the game is paused. Used to block user input.
@ -140,14 +141,14 @@ namespace osu.Game.Rulesets.UI
/// <summary> /// <summary>
/// Sets a replay to be used, overriding local input. /// Sets a replay to be used, overriding local input.
/// </summary> /// </summary>
/// <param name="replay">The replay, null for local input.</param> /// <param name="replayScore">The replay, null for local input.</param>
public virtual void SetReplay(Replay replay) public virtual void SetReplayScore(Score replayScore)
{ {
if (ReplayInputManager == null) if (ReplayInputManager == null)
throw new InvalidOperationException($"A {nameof(KeyBindingInputManager)} which supports replay loading is not available"); throw new InvalidOperationException($"A {nameof(KeyBindingInputManager)} which supports replay loading is not available");
Replay = replay; ReplayScore = replayScore;
ReplayInputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null; ReplayInputManager.ReplayInputHandler = replayScore != null ? CreateReplayInputHandler(replayScore.Replay) : null;
HasReplayLoaded.Value = ReplayInputManager.ReplayInputHandler != null; HasReplayLoaded.Value = ReplayInputManager.ReplayInputHandler != null;
} }
@ -302,9 +303,9 @@ namespace osu.Game.Rulesets.UI
mod.ReadFromConfig(config); mod.ReadFromConfig(config);
} }
public override void SetReplay(Replay replay) public override void SetReplayScore(Score replayScore)
{ {
base.SetReplay(replay); base.SetReplayScore(replayScore);
if (ReplayInputManager?.ReplayInputHandler != null) if (ReplayInputManager?.ReplayInputHandler != null)
ReplayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace; ReplayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace;

View File

@ -31,7 +31,7 @@ namespace osu.Game.Scoring
[Column(TypeName="DECIMAL(1,4)")] [Column(TypeName="DECIMAL(1,4)")]
public double Accuracy { get; set; } public double Accuracy { get; set; }
[JsonIgnore] [JsonProperty(@"pp")]
public double? PP { get; set; } public double? PP { get; set; }
[JsonProperty("max_combo")] [JsonProperty("max_combo")]

View File

@ -57,7 +57,7 @@ namespace osu.Game.Screens.Edit
// Depending on beatSnapLength, we may snap to a beat that is beyond timingPoint's end time, but we want to instead snap to // 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 // the next timing point's start time
var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time); var nextTimingPoint = ControlPointInfo.TimingPoints.Find(t => t.Time > timingPoint.Time);
if (position > nextTimingPoint?.Time) if (position > nextTimingPoint?.Time)
position = nextTimingPoint.Time; position = nextTimingPoint.Time;
@ -123,7 +123,7 @@ namespace osu.Game.Screens.Edit
if (seekTime < timingPoint.Time && timingPoint != ControlPointInfo.TimingPoints.First()) if (seekTime < timingPoint.Time && timingPoint != ControlPointInfo.TimingPoints.First())
seekTime = timingPoint.Time; seekTime = timingPoint.Time;
var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time); var nextTimingPoint = ControlPointInfo.TimingPoints.Find(t => t.Time > timingPoint.Time);
if (seekTime > nextTimingPoint?.Time) if (seekTime > nextTimingPoint?.Time)
seekTime = nextTimingPoint.Time; seekTime = nextTimingPoint.Time;

View File

@ -18,7 +18,7 @@ namespace osu.Game.Screens.Multi
/// <summary> /// <summary>
/// All the active <see cref="Room"/>s. /// All the active <see cref="Room"/>s.
/// </summary> /// </summary>
IBindableCollection<Room> Rooms { get; } IBindableList<Room> Rooms { get; }
/// <summary> /// <summary>
/// Creates a new <see cref="Room"/>. /// Creates a new <see cref="Room"/>.

View File

@ -22,7 +22,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
private readonly Bindable<Room> selectedRoom = new Bindable<Room>(); private readonly Bindable<Room> selectedRoom = new Bindable<Room>();
public IBindable<Room> SelectedRoom => selectedRoom; public IBindable<Room> SelectedRoom => selectedRoom;
private readonly IBindableCollection<Room> rooms = new BindableCollection<Room>(); private readonly IBindableList<Room> rooms = new BindableList<Room>();
private readonly FillFlowContainer<DrawableRoom> roomFlow; private readonly FillFlowContainer<DrawableRoom> roomFlow;
public IReadOnlyList<DrawableRoom> Rooms => roomFlow; public IReadOnlyList<DrawableRoom> Rooms => roomFlow;

View File

@ -165,8 +165,8 @@ namespace osu.Game.Screens.Multi.Match.Components
TimeSpan.FromHours(12), TimeSpan.FromHours(12),
//TimeSpan.FromHours(16), //TimeSpan.FromHours(16),
TimeSpan.FromHours(24), TimeSpan.FromHours(24),
//TimeSpan.FromDays(3), TimeSpan.FromDays(3),
//TimeSpan.FromDays(7) TimeSpan.FromDays(7)
} }
} }
}, },

View File

@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi
public readonly Bindable<User> Host = new Bindable<User>(); public readonly Bindable<User> Host = new Bindable<User>();
public readonly Bindable<RoomStatus> Status = new Bindable<RoomStatus>(); public readonly Bindable<RoomStatus> Status = new Bindable<RoomStatus>();
public readonly Bindable<GameType> Type = new Bindable<GameType>(); public readonly Bindable<GameType> Type = new Bindable<GameType>();
public readonly BindableCollection<PlaylistItem> Playlist = new BindableCollection<PlaylistItem>(); public readonly BindableList<PlaylistItem> Playlist = new BindableList<PlaylistItem>();
public readonly Bindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>(); public readonly Bindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>();
public readonly Bindable<int> ParticipantCount = new Bindable<int>(); public readonly Bindable<int> ParticipantCount = new Bindable<int>();
public readonly Bindable<int?> MaxParticipants = new Bindable<int?>(); public readonly Bindable<int?> MaxParticipants = new Bindable<int?>();

View File

@ -21,8 +21,8 @@ namespace osu.Game.Screens.Multi
{ {
public event Action RoomsUpdated; public event Action RoomsUpdated;
private readonly BindableCollection<Room> rooms = new BindableCollection<Room>(); private readonly BindableList<Room> rooms = new BindableList<Room>();
public IBindableCollection<Room> Rooms => rooms; public IBindableList<Room> Rooms => rooms;
private Room currentRoom; private Room currentRoom;

View File

@ -285,7 +285,7 @@ namespace osu.Game.Screens.Play
if (!IsCurrentScreen) return; if (!IsCurrentScreen) return;
var score = CreateScore(); var score = CreateScore();
if (RulesetContainer.Replay == null) if (RulesetContainer.ReplayScore == null)
scoreManager.Import(score, true); scoreManager.Import(score, true);
Push(CreateResults(score)); Push(CreateResults(score));
@ -297,7 +297,7 @@ namespace osu.Game.Screens.Play
protected virtual ScoreInfo CreateScore() protected virtual ScoreInfo CreateScore()
{ {
var score = new ScoreInfo var score = RulesetContainer.ReplayScore?.ScoreInfo ?? new ScoreInfo
{ {
Beatmap = Beatmap.Value.BeatmapInfo, Beatmap = Beatmap.Value.BeatmapInfo,
Ruleset = ruleset, Ruleset = ruleset,

View File

@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
RulesetContainer.SetReplay(score.Replay); RulesetContainer.SetReplayScore(score);
} }
protected override ScoreInfo CreateScore() => score.ScoreInfo; protected override ScoreInfo CreateScore() => score.ScoreInfo;

View File

@ -327,7 +327,7 @@ namespace osu.Game.Screens.Tournament
continue; continue;
// ReSharper disable once AccessToModifiedClosure // ReSharper disable once AccessToModifiedClosure
DrawingsTeam teamToAdd = allTeams.FirstOrDefault(t => t.FullName == line); DrawingsTeam teamToAdd = allTeams.Find(t => t.FullName == line);
if (teamToAdd == null) if (teamToAdd == null)
continue; continue;

View File

@ -102,7 +102,7 @@ namespace osu.Game.Skinning
string lastPiece = filename.Split('/').Last(); string lastPiece = filename.Split('/').Last();
var file = source.Files.FirstOrDefault(f => var file = source.Files.Find(f =>
string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), lastPiece, StringComparison.InvariantCultureIgnoreCase)); string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), lastPiece, StringComparison.InvariantCultureIgnoreCase));
return file?.FileInfo.StoragePath; return file?.FileInfo.StoragePath;
} }

View File

@ -6,7 +6,6 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Animations;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using System.Linq;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
namespace osu.Game.Storyboards.Drawables namespace osu.Game.Storyboards.Drawables
@ -71,7 +70,7 @@ namespace osu.Game.Storyboards.Drawables
{ {
var framePath = basePath.Replace(".", frame + "."); var framePath = basePath.Replace(".", frame + ".");
var path = beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename.ToLowerInvariant() == framePath)?.FileInfo.StoragePath; var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.ToLowerInvariant() == framePath)?.FileInfo.StoragePath;
if (path == null) if (path == null)
continue; continue;

View File

@ -6,7 +6,6 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using System.Linq;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
namespace osu.Game.Storyboards.Drawables namespace osu.Game.Storyboards.Drawables
@ -66,7 +65,7 @@ namespace osu.Game.Storyboards.Drawables
private void load(IBindableBeatmap beatmap, TextureStore textureStore) private void load(IBindableBeatmap beatmap, TextureStore textureStore)
{ {
var spritePath = Sprite.Path.ToLowerInvariant(); var spritePath = Sprite.Path.ToLowerInvariant();
var path = beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename.ToLowerInvariant() == spritePath)?.FileInfo.StoragePath; var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.ToLowerInvariant() == spritePath)?.FileInfo.StoragePath;
if (path == null) if (path == null)
return; return;

View File

@ -18,7 +18,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="ppy.osu.Framework" Version="2018.1226.0" /> <PackageReference Include="ppy.osu.Framework" Version="2019.107.0" />
<PackageReference Include="SharpCompress" Version="0.22.0" /> <PackageReference Include="SharpCompress" Version="0.22.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" />