Merge branch 'master' into editor-context-menu-on-select

This commit is contained in:
Dean Herbert
2021-11-04 15:59:06 +09:00
507 changed files with 4943 additions and 2961 deletions

View File

@ -92,7 +92,7 @@ namespace osu.Game.Screens.Edit
{
int beat = index % beatDivisor;
foreach (var divisor in BindableBeatDivisor.VALID_DIVISORS)
foreach (int divisor in BindableBeatDivisor.VALID_DIVISORS)
{
if ((beat * divisor) % beatDivisor == 0)
return divisor;

View File

@ -205,7 +205,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
[BackgroundDependencyLoader]
private void load()
{
foreach (var t in availableDivisors)
foreach (int t in availableDivisors)
{
AddInternal(new Tick
{
@ -287,7 +287,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void handleMouseInput(Vector2 screenSpaceMousePosition)
{
// copied from SliderBar so we can do custom spacing logic.
var xPosition = (ToLocalSpace(screenSpaceMousePosition).X - RangePadding) / UsableWidth;
float xPosition = (ToLocalSpace(screenSpaceMousePosition).X - RangePadding) / UsableWidth;
CurrentNumber.Value = availableDivisors.OrderBy(d => Math.Abs(getMappedPosition(d) - xPosition)).First();
OnUserChange(Current.Value);

View File

@ -58,13 +58,13 @@ namespace osu.Game.Screens.Edit.Compose.Components
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var o in args.NewItems)
foreach (object o in args.NewItems)
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Select();
break;
case NotifyCollectionChangedAction.Remove:
foreach (var o in args.OldItems)
foreach (object o in args.OldItems)
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Deselect();
break;
@ -477,7 +477,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
if (snapProvider != null)
{
// check for positional snap for every object in selection (for things like object-object snapping)
for (var i = 0; i < movementBlueprintOriginalPositions.Length; i++)
for (int i = 0; i < movementBlueprintOriginalPositions.Length; i++)
{
Vector2 originalPosition = movementBlueprintOriginalPositions[i];
var testPosition = originalPosition + distanceTravelled;

View File

@ -132,8 +132,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected ColourInfo GetColourForIndexFromPlacement(int placementIndex)
{
var timingPoint = beatmap.ControlPointInfo.TimingPointAt(StartTime);
var beatLength = timingPoint.BeatLength / beatDivisor.Value;
var beatIndex = (int)Math.Round((StartTime - timingPoint.Time) / beatLength);
double beatLength = timingPoint.BeatLength / beatDivisor.Value;
int beatIndex = (int)Math.Round((StartTime - timingPoint.Time) / beatLength);
var colour = BindableBeatDivisor.GetColourFor(BindableBeatDivisor.GetDivisorForBeatIndex(beatIndex + placementIndex + 1, beatDivisor.Value), Colours);

View File

@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// </summary>
private void createStateBindables()
{
foreach (var sampleName in HitSampleInfo.AllAdditions)
foreach (string sampleName in HitSampleInfo.AllAdditions)
{
var bindable = new Bindable<TernaryState>
{
@ -102,7 +102,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
SelectionNewComboState.Value = GetStateFromSelection(SelectedItems.OfType<IHasComboInformation>(), h => h.NewCombo);
foreach (var (sampleName, bindable) in SelectionSampleStates)
foreach ((string sampleName, var bindable) in SelectionSampleStates)
{
bindable.Value = GetStateFromSelection(SelectedItems, h => h.Samples.Any(s => s.Name == sampleName));
}

View File

@ -176,7 +176,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
if (timeline != null)
{
var timelineQuad = timeline.ScreenSpaceDrawQuad;
var mouseX = e.ScreenSpaceMousePosition.X;
float mouseX = e.ScreenSpaceMousePosition.X;
// scroll if in a drag and dragging outside visible extents
if (mouseX > timelineQuad.TopRight.X)

View File

@ -397,7 +397,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
if (hitObject.DifficultyControlPoint == DifficultyControlPoint.DEFAULT)
hitObject.DifficultyControlPoint = new DifficultyControlPoint();
var newVelocity = hitObject.DifficultyControlPoint.SliderVelocity * (repeatHitObject.Duration / proposedDuration);
double newVelocity = hitObject.DifficultyControlPoint.SliderVelocity * (repeatHitObject.Duration / proposedDuration);
if (Precision.AlmostEquals(newVelocity, hitObject.DifficultyControlPoint.SliderVelocity))
return;
@ -408,8 +408,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
else
{
// find the number of repeats which can fit in the requested time.
var lengthOfOneRepeat = repeatHitObject.Duration / (repeatHitObject.RepeatCount + 1);
var proposedCount = Math.Max(0, (int)Math.Round(proposedDuration / lengthOfOneRepeat) - 1);
double lengthOfOneRepeat = repeatHitObject.Duration / (repeatHitObject.RepeatCount + 1);
int proposedCount = Math.Max(0, (int)Math.Round(proposedDuration / lengthOfOneRepeat) - 1);
if (proposedCount == repeatHitObject.RepeatCount)
return;
@ -421,7 +421,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
break;
case IHasDuration endTimeHitObject:
var snappedTime = Math.Max(hitObject.StartTime, beatSnapProvider.SnapTime(time));
double snappedTime = Math.Max(hitObject.StartTime, beatSnapProvider.SnapTime(time));
if (endTimeHitObject.EndTime == snappedTime || Precision.AlmostEquals(snappedTime, hitObject.StartTime, beatmap.GetBeatLengthAtTime(snappedTime)))
return;

View File

@ -104,10 +104,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
nextMinTick = null;
nextMaxTick = null;
for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++)
for (int i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++)
{
var point = beatmap.ControlPointInfo.TimingPoints[i];
var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length;
double until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length;
int beat = 0;
@ -127,7 +127,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
int indexInBar = beat % ((int)point.TimeSignature * beatDivisor.Value);
var divisor = BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value);
int divisor = BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value);
var colour = BindableBeatDivisor.GetColourFor(divisor, colours);
// even though "bar lines" take up the full vertical space, we render them in two pieces because it allows for less anchor/origin churn.

View File

@ -301,7 +301,7 @@ namespace osu.Game.Screens.Edit
editorBeatmap.SelectedHitObjects.BindCollectionChanged((_, __) =>
{
var hasObjects = editorBeatmap.SelectedHitObjects.Count > 0;
bool hasObjects = editorBeatmap.SelectedHitObjects.Count > 0;
cutMenuItem.Action.Disabled = !hasObjects;
copyMenuItem.Action.Disabled = !hasObjects;

View File

@ -183,7 +183,7 @@ namespace osu.Game.Screens.Edit
public void Add(HitObject hitObject)
{
// Preserve existing sorting order in the beatmap
var insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime);
int insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime);
Insert(insertionIndex + 1, hitObject);
}
@ -332,7 +332,7 @@ namespace osu.Game.Screens.Edit
// For now we'll remove and re-add the hitobject. This is not optimal and can be improved if required.
mutableHitObjects.Remove(hitObject);
var insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime);
int insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime);
mutableHitObjects.Insert(insertionIndex + 1, hitObject);
Update(hitObject);

View File

@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
new LegacyBeatmapEncoder(editorBeatmap, editorBeatmap.BeatmapSkin).Encode(sw);
var newState = stream.ToArray();
byte[] newState = stream.ToArray();
// if the previous state is binary equal we don't need to push a new one, unless this is the initial state.
if (savedStates.Count > 0 && newState.SequenceEqual(savedStates[currentState])) return;

View File

@ -82,7 +82,7 @@ namespace osu.Game.Screens.Edit
if (toAdd.Count > 0)
{
IBeatmap newBeatmap = readBeatmap(newState);
foreach (var i in toAdd)
foreach (int i in toAdd)
editorBeatmap.Insert(i, newBeatmap.HitObjects[i]);
}

View File

@ -68,7 +68,7 @@ namespace osu.Game.Screens.Edit.Timing
if (!isNew)
return;
if (double.TryParse(sender.Text, out var newTime))
if (double.TryParse(sender.Text, out double newTime))
{
changeSelectedGroupTime(newTime);
}

View File

@ -6,6 +6,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Localisation;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Overlays.Settings;
@ -16,7 +17,7 @@ namespace osu.Game.Screens.Edit.Timing
{
private readonly SettingsSlider<T> slider;
public SliderWithTextBoxInput(string labelText)
public SliderWithTextBoxInput(LocalisableString labelText)
{
LabelledTextBox textbox;

View File

@ -37,7 +37,7 @@ namespace osu.Game.Screens.Menu
private readonly Bindable<User> currentUser = new Bindable<User>();
private FillFlowContainer fill;
private readonly List<Drawable> expendableText = new List<Drawable>();
private readonly List<ITextPart> expendableText = new List<ITextPart>();
public Disclaimer(OsuScreen nextScreen = null)
{
@ -97,7 +97,7 @@ namespace osu.Game.Screens.Menu
textFlow.AddText("this is osu!", t => t.Font = t.Font.With(Typeface.Torus, 30, FontWeight.Regular));
expendableText.AddRange(textFlow.AddText("lazer", t =>
expendableText.Add(textFlow.AddText("lazer", t =>
{
t.Font = t.Font.With(Typeface.Torus, 30, FontWeight.Regular);
t.Colour = colours.PinkLight;
@ -114,7 +114,7 @@ namespace osu.Game.Screens.Menu
t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.SemiBold);
t.Colour = colours.Pink;
});
expendableText.AddRange(textFlow.AddText(" coming to osu!", formatRegular));
expendableText.Add(textFlow.AddText(" coming to osu!", formatRegular));
textFlow.AddText(".", formatRegular);
textFlow.NewParagraph();
@ -152,7 +152,7 @@ namespace osu.Game.Screens.Menu
t.Font = t.Font.With(size: 20);
t.Origin = Anchor.Centre;
t.Colour = colours.Pink;
}).First();
}).Drawables.First();
if (IsLoaded)
animateHeart();
@ -193,7 +193,7 @@ namespace osu.Game.Screens.Menu
using (BeginDelayedSequence(520 + 160))
{
fill.MoveToOffset(new Vector2(0, 15), 160, Easing.OutQuart);
Schedule(() => expendableText.ForEach(t =>
Schedule(() => expendableText.SelectMany(t => t.Drawables).ForEach(t =>
{
t.FadeOut(100);
t.ScaleTo(new Vector2(0, 1), 100, Easing.OutQuart);

View File

@ -211,7 +211,7 @@ namespace osu.Game.Screens.Menu
else
{
const int quick_appear = 350;
var initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0;
int initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0;
logo.MoveTo(new Vector2(0.5f), initialMovementTime, Easing.OutQuint);

View File

@ -272,7 +272,7 @@ namespace osu.Game.Screens.Menu
lastBeatIndex = beatIndex;
var beatLength = timingPoint.BeatLength;
double beatLength = timingPoint.BeatLength;
float amplitudeAdjust = Math.Min(1, 0.4f + amplitudes.Maximum);
@ -337,7 +337,7 @@ namespace osu.Game.Screens.Menu
if (musicController.CurrentTrack.IsRunning)
{
var maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentTrack.CurrentAmplitudes.Maximum : 0;
float maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentTrack.CurrentAmplitudes.Maximum : 0;
logoAmplitudeContainer.Scale = new Vector2((float)Interpolation.Damp(logoAmplitudeContainer.Scale.X, 1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 0.9f, Time.Elapsed));
if (maxAmplitude > velocity_adjust_cutoff)

View File

@ -7,7 +7,6 @@ using osu.Framework.Graphics;
using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.Chat;
namespace osu.Game.Screens.OnlinePlay.Components
@ -69,24 +68,14 @@ namespace osu.Game.Screens.OnlinePlay.Components
}
else
{
textFlow.AddLink(new[]
{
new OsuSpriteText
{
Text = new RomanisableString(beatmap.Value.Metadata.ArtistUnicode, beatmap.Value.Metadata.Artist),
Font = OsuFont.GetFont(size: TextSize),
},
new OsuSpriteText
{
Text = " - ",
Font = OsuFont.GetFont(size: TextSize),
},
new OsuSpriteText
{
Text = new RomanisableString(beatmap.Value.Metadata.TitleUnicode, beatmap.Value.Metadata.Title),
Font = OsuFont.GetFont(size: TextSize),
}
}, LinkAction.OpenBeatmap, beatmap.Value.OnlineID.ToString(), "Open beatmap");
var metadataInfo = beatmap.Value.Metadata;
string artistUnicode = string.IsNullOrEmpty(metadataInfo.ArtistUnicode) ? metadataInfo.Artist : metadataInfo.ArtistUnicode;
string titleUnicode = string.IsNullOrEmpty(metadataInfo.TitleUnicode) ? metadataInfo.Title : metadataInfo.TitleUnicode;
var title = new RomanisableString($"{artistUnicode} - {titleUnicode}".Trim(), $"{metadataInfo.Artist} - {metadataInfo.Title}".Trim());
textFlow.AddLink(title, LinkAction.OpenBeatmap, beatmap.Value.OnlineID.ToString(), "Open beatmap");
}
}
}

View File

@ -95,7 +95,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
public override bool OnExiting(IScreen next)
{
var result = base.OnExiting(next);
bool result = base.OnExiting(next);
this.MoveToX(0);
return result;
}

View File

@ -3,13 +3,15 @@
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Localisation;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osu.Game.Online.Rooms;
namespace osu.Game.Screens.OnlinePlay.Components
{
public abstract class ReadyButton : TriangleButton
public abstract class ReadyButton : TriangleButton, IHasTooltip
{
public new readonly BindableBool Enabled = new BindableBool();
@ -24,6 +26,18 @@ namespace osu.Game.Screens.OnlinePlay.Components
Enabled.BindValueChanged(_ => updateState(), true);
}
private void updateState() => base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value;
private void updateState() =>
base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value;
public virtual LocalisableString TooltipText
{
get
{
if (Enabled.Value)
return string.Empty;
return "Beatmap not downloaded";
}
}
}
}

View File

@ -14,6 +14,9 @@ namespace osu.Game.Screens.OnlinePlay.Components
{
private OsuSpriteText attemptDisplay;
[Resolved]
private OsuColour colours { get; set; }
public RoomLocalUserInfo()
{
AutoSizeAxes = Axes.Both;
@ -54,6 +57,9 @@ namespace osu.Game.Screens.OnlinePlay.Components
{
int remaining = MaxAttempts.Value.Value - UserScore.Value.PlaylistItemAttempts.Sum(a => a.Attempts);
attemptDisplay.Text += $" ({remaining} remaining)";
if (remaining == 0)
attemptDisplay.Colour = colours.RedLight;
}
}
else

View File

@ -105,13 +105,12 @@ namespace osu.Game.Screens.OnlinePlay
private void refresh()
{
difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value, requiredMods) { Size = new Vector2(32) };
difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(32) };
beatmapText.Clear();
beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineBeatmapID.ToString(), null, text =>
{
text.Truncate = true;
text.RelativeSizeAxes = Axes.X;
});
authorText.Clear();
@ -182,8 +181,11 @@ namespace osu.Game.Screens.OnlinePlay
{
beatmapText = new LinkFlowContainer(fontParameters)
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
// workaround to ensure only the first line of text shows, emulating truncation (but without ellipsis at the end).
// TODO: remove when text/link flow can support truncation with ellipsis natively.
Height = OsuFont.DEFAULT_FONT_SIZE,
Masking = true
},
new FillFlowContainer
{
@ -248,10 +250,7 @@ namespace osu.Game.Screens.OnlinePlay
protected virtual IEnumerable<Drawable> CreateButtons() =>
new Drawable[]
{
new PlaylistDownloadButton(Item)
{
Size = new Vector2(50, 30)
},
new PlaylistDownloadButton(Item),
new PlaylistRemoveButton
{
Size = new Vector2(30, 30),
@ -282,28 +281,33 @@ namespace osu.Game.Screens.OnlinePlay
return true;
}
private class PlaylistDownloadButton : BeatmapPanelDownloadButton
private sealed class PlaylistDownloadButton : BeatmapPanelDownloadButton
{
private readonly PlaylistItem playlistItem;
[Resolved]
private BeatmapManager beatmapManager { get; set; }
public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks;
// required for download tracking, as this button hides itself. can probably be removed with a bit of consideration.
public override bool IsPresent => true;
private const float width = 50;
public PlaylistDownloadButton(PlaylistItem playlistItem)
: base(playlistItem.Beatmap.Value.BeatmapSet)
{
this.playlistItem = playlistItem;
Size = new Vector2(width, 30);
Alpha = 0;
}
protected override void LoadComplete()
{
base.LoadComplete();
State.BindValueChanged(stateChanged, true);
FinishTransforms(true);
// base implementation calls FinishTransforms, so should be run after the above state update.
base.LoadComplete();
}
private void stateChanged(ValueChangedEvent<DownloadState> state)
@ -315,12 +319,16 @@ namespace osu.Game.Screens.OnlinePlay
if (beatmapManager.QueryBeatmap(b => b.MD5Hash == playlistItem.Beatmap.Value.MD5Hash) == null)
State.Value = DownloadState.NotDownloaded;
else
this.FadeTo(0, 500);
{
this.FadeTo(0, 500)
.ResizeWidthTo(0, 500, Easing.OutQuint);
}
break;
default:
this.FadeTo(1, 500);
this.ResizeWidthTo(width, 500, Easing.OutQuint)
.FadeTo(1, 500);
break;
}
}
@ -333,13 +341,14 @@ namespace osu.Game.Screens.OnlinePlay
public PanelBackground()
{
UpdateableBeatmapBackgroundSprite backgroundSprite;
InternalChildren = new Drawable[]
{
new UpdateableBeatmapBackgroundSprite
backgroundSprite = new UpdateableBeatmapBackgroundSprite
{
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fill,
Beatmap = { BindTarget = Beatmap }
},
new FillFlowContainer
{
@ -374,6 +383,10 @@ namespace osu.Game.Screens.OnlinePlay
}
}
};
// manual binding required as playlists don't expose IBeatmapInfo currently.
// may be removed in the future if this changes.
Beatmap.BindValueChanged(beatmap => backgroundSprite.Beatmap.Value = beatmap.NewValue);
}
}
}

View File

@ -353,7 +353,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
})
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
// workaround to ensure only the first line of text shows, emulating truncation (but without ellipsis at the end).
// TODO: remove when text/link flow can support truncation with ellipsis natively.
Height = 16,
Masking = true
}
}
}
@ -385,7 +388,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
creationParameters: s =>
{
s.Truncate = true;
s.RelativeSizeAxes = Axes.X;
});
}
}

View File

@ -4,6 +4,7 @@
using System.Collections.Specialized;
using Humanizer;
using osu.Framework.Allocation;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
@ -46,7 +47,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
private void updateCount(object sender, NotifyCollectionChangedEventArgs e)
{
count.Clear();
count.AddText(Playlist.Count.ToString(), s => s.Font = s.Font.With(weight: FontWeight.Bold));
count.AddText(Playlist.Count.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold));
count.AddText(" ");
count.AddText("Beatmap".ToQuantity(Playlist.Count, ShowQuantityAs.None));
}

View File

@ -65,9 +65,9 @@ namespace osu.Game.Screens.OnlinePlay.Match
private IBindable<WeakReference<BeatmapSetInfo>> managerUpdated;
[Cached]
protected OnlinePlayBeatmapAvailabilityTracker BeatmapAvailabilityTracker { get; private set; }
private OnlinePlayBeatmapAvailabilityTracker beatmapAvailabilityTracker { get; set; }
protected IBindable<BeatmapAvailability> BeatmapAvailability => BeatmapAvailabilityTracker.Availability;
protected IBindable<BeatmapAvailability> BeatmapAvailability => beatmapAvailabilityTracker.Availability;
public readonly Room Room;
private readonly bool allowEdit;
@ -88,7 +88,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
Padding = new MarginPadding { Top = Header.HEIGHT };
BeatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
beatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
{
SelectedItem = { BindTarget = SelectedItem }
};
@ -103,7 +103,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
InternalChildren = new Drawable[]
{
BeatmapAvailabilityTracker,
beatmapAvailabilityTracker,
new GridContainer
{
RelativeSizeAxes = Axes.Both,

View File

@ -186,7 +186,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
var ruleset = rulesets.GetRuleset(Room.Settings.RulesetID).CreateInstance();
var currentModeRank = User.User?.RulesetsStatistics?.GetValueOrDefault(ruleset.ShortName)?.GlobalRank;
int? currentModeRank = User.User?.RulesetsStatistics?.GetValueOrDefault(ruleset.ShortName)?.GlobalRank;
userRankText.Text = currentModeRank != null ? $"#{currentModeRank.Value:N0}" : string.Empty;
userStateDisplay.UpdateStatus(User.State, User.BeatmapAvailability);

View File

@ -180,11 +180,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
{
// Seek the master clock to the gameplay time.
// This is chosen as the first available frame in the players' replays, which matches the seek by each individual SpectatorPlayer.
var startTime = instances.Where(i => i.Score != null)
.SelectMany(i => i.Score.Replay.Frames)
.Select(f => f.Time)
.DefaultIfEmpty(0)
.Min();
double startTime = instances.Where(i => i.Score != null)
.SelectMany(i => i.Score.Replay.Frames)
.Select(f => f.Time)
.DefaultIfEmpty(0)
.Min();
masterClockContainer.Seek(startTime);
masterClockContainer.Start();

View File

@ -2,8 +2,10 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Online.Rooms;
@ -16,6 +18,12 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
[Resolved(typeof(Room), nameof(Room.EndDate))]
private Bindable<DateTimeOffset?> endDate { get; set; }
[Resolved(typeof(Room), nameof(Room.MaxAttempts))]
private Bindable<int?> maxAttempts { get; set; }
[Resolved(typeof(Room), nameof(Room.UserScore))]
private Bindable<PlaylistAggregateScore> userScore { get; set; }
[Resolved]
private IBindable<WorkingBeatmap> gameBeatmap { get; set; }
@ -32,11 +40,49 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
Triangles.ColourLight = colours.GreenLight;
}
private bool hasRemainingAttempts = true;
protected override void LoadComplete()
{
base.LoadComplete();
userScore.BindValueChanged(aggregate =>
{
if (maxAttempts.Value == null)
return;
int remaining = maxAttempts.Value.Value - aggregate.NewValue.PlaylistItemAttempts.Sum(a => a.Attempts);
hasRemainingAttempts = remaining > 0;
});
}
protected override void Update()
{
base.Update();
Enabled.Value = endDate.Value != null && DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate.Value;
Enabled.Value = hasRemainingAttempts && enoughTimeLeft;
}
public override LocalisableString TooltipText
{
get
{
if (Enabled.Value)
return string.Empty;
if (!enoughTimeLeft)
return "No time left!";
if (!hasRemainingAttempts)
return "Attempts exhausted!";
return base.TooltipText;
}
}
private bool enoughTimeLeft =>
// This should probably consider the length of the currently selected item, rather than a constant 30 seconds.
endDate.Value != null && DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate.Value;
}
}

View File

@ -37,6 +37,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
private MatchLeaderboard leaderboard;
private SelectionPollingComponent selectionPollingComponent;
private FillFlowContainer progressSection;
public PlaylistsRoomSubScreen(Room room)
: base(room, false) // Editing is temporarily not allowed.
{
@ -67,6 +69,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
Schedule(() => SelectedItem.Value = Room.Playlist.FirstOrDefault());
}
}, true);
Room.MaxAttempts.BindValueChanged(attempts => progressSection.Alpha = Room.MaxAttempts.Value != null ? 1 : 0, true);
}
protected override Drawable CreateMainContent() => new GridContainer
@ -153,6 +157,22 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
},
},
new Drawable[]
{
progressSection = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Alpha = 0,
Margin = new MarginPadding { Bottom = 10 },
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new OverlinedHeader("Progress"),
new RoomLocalUserInfo(),
}
},
},
new Drawable[]
{
new OverlinedHeader("Leaderboard")
},
@ -162,6 +182,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
},
RowDimensions = new[]
{
new Dimension(GridSizeMode.AutoSize),
new Dimension(GridSizeMode.AutoSize),
new Dimension(GridSizeMode.AutoSize),
new Dimension(),

View File

@ -56,7 +56,7 @@ namespace osu.Game.Screens.Play.Break
private void currentValueChanged(ValueChangedEvent<T> e)
{
var newText = prefix + Format(e.NewValue);
string newText = prefix + Format(e.NewValue);
if (valueText.Text == newText)
return;

View File

@ -51,7 +51,7 @@ namespace osu.Game.Screens.Play
private void updateBreakTime()
{
var time = Clock.CurrentTime;
double time = Clock.CurrentTime;
isBreakTime.Value = breaks?.IsInAny(time) == true
|| time < gameplayStartTime

View File

@ -10,6 +10,7 @@ using ManagedBass.Fx;
using osu.Framework.Allocation;
using osu.Framework.Audio.Sample;
using osu.Framework.Audio.Track;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
@ -83,7 +84,7 @@ namespace osu.Game.Screens.Play
Content,
redFlashLayer = new Box
{
Colour = Color4.Red,
Colour = Color4.Red.Opacity(0.6f),
RelativeSizeAxes = Axes.Both,
Blending = BlendingParameters.Additive,
Depth = float.MinValue,

View File

@ -90,7 +90,7 @@ namespace osu.Game.Screens.Play.HUD
private void updateState()
{
// Don't display ever if the ruleset is not using a draining health display.
var showLayer = HealthProcessor is DrainingHealthProcessor && fadePlayfieldWhenHealthLow.Value && ShowHealth.Value;
bool showLayer = HealthProcessor is DrainingHealthProcessor && fadePlayfieldWhenHealthLow.Value && ShowHealth.Value;
this.FadeTo(showLayer ? 1 : 0, fade_time, Easing.OutQuint);
}

View File

@ -157,11 +157,11 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
// max to avoid div-by-zero.
maxHitWindow = Math.Max(1, windows.First().length);
for (var i = 0; i < windows.Length; i++)
for (int i = 0; i < windows.Length; i++)
{
var (result, length) = windows[i];
(var result, double length) = windows[i];
var hitWindow = (float)(length / maxHitWindow);
float hitWindow = (float)(length / maxHitWindow);
colourBarsEarly.Add(createColourBar(result, hitWindow, i == 0));
colourBarsLate.Add(createColourBar(result, hitWindow, i == 0));

View File

@ -133,7 +133,7 @@ namespace osu.Game.Screens.Play.HUD
var winningBar = Team1Score.Value > Team2Score.Value ? score1Bar : score2Bar;
var losingBar = Team1Score.Value <= Team2Score.Value ? score1Bar : score2Bar;
var diff = Math.Max(Team1Score.Value, Team2Score.Value) - Math.Min(Team1Score.Value, Team2Score.Value);
int diff = Math.Max(Team1Score.Value, Team2Score.Value) - Math.Min(Team1Score.Value, Team2Score.Value);
losingBar.ResizeWidthTo(0, 400, Easing.OutQuint);
winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint);

View File

@ -148,7 +148,7 @@ namespace osu.Game.Screens.Play.HUD
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
foreach (var userId in e.OldItems.OfType<int>())
foreach (int userId in e.OldItems.OfType<int>())
{
spectatorClient.StopWatchingUser(userId);

View File

@ -223,7 +223,7 @@ namespace osu.Game.Screens.Play
onlineBeatmapRequest.Success += res => Schedule(() =>
{
onlineBeatmap = res.ToBeatmapSet(rulesets);
beatmapPanelContainer.Child = new GridBeatmapPanel(onlineBeatmap);
beatmapPanelContainer.Child = new GridBeatmapPanel(res);
checkForAutomaticDownload();
});

View File

@ -24,17 +24,17 @@ namespace osu.Game.Screens.Play
if (!objects.Any())
return;
var firstHit = objects.First().StartTime;
var lastHit = objects.Max(o => o.GetEndTime());
double firstHit = objects.First().StartTime;
double lastHit = objects.Max(o => o.GetEndTime());
if (lastHit == 0)
lastHit = objects.Last().StartTime;
var interval = (lastHit - firstHit + 1) / granularity;
double interval = (lastHit - firstHit + 1) / granularity;
foreach (var h in objects)
{
var endTime = h.GetEndTime();
double endTime = h.GetEndTime();
Debug.Assert(endTime >= h.StartTime);

View File

@ -82,7 +82,7 @@ namespace osu.Game.Screens.Play
{
base.Update();
var time = gameplayClock?.CurrentTime ?? Time.Current;
double time = gameplayClock?.CurrentTime ?? Time.Current;
double songCurrentTime = time - startTime;
int currentPercent = Math.Max(0, Math.Min(100, (int)(songCurrentTime / songLength * 100)));

View File

@ -165,7 +165,7 @@ namespace osu.Game.Screens.Play
return;
}
var max = values.Max();
int max = values.Max();
float step = values.Length / (float)ColumnCount;

View File

@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play
public override bool OnExiting(IScreen next)
{
var exiting = base.OnExiting(next);
bool exiting = base.OnExiting(next);
submitScore(Score.DeepClone());

View File

@ -62,12 +62,12 @@ namespace osu.Game.Screens.Ranking.Expanded
{
var beatmap = score.BeatmapInfo;
var metadata = beatmap.BeatmapSet?.Metadata ?? beatmap.Metadata;
var creator = metadata.Author?.Username;
string creator = metadata.Author?.Username;
var topStatistics = new List<StatisticDisplay>
{
new AccuracyStatistic(score.Accuracy),
new ComboStatistic(score.MaxCombo, !score.Statistics.TryGetValue(HitResult.Miss, out var missCount) || missCount == 0),
new ComboStatistic(score.MaxCombo, !score.Statistics.TryGetValue(HitResult.Miss, out int missCount) || missCount == 0),
new PerformanceStatistic(score),
};

View File

@ -4,6 +4,7 @@
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
@ -12,13 +13,17 @@ using osuTK;
namespace osu.Game.Screens.Ranking
{
public class ReplayDownloadButton : DownloadTrackingComposite<ScoreInfo, ScoreManager>
public class ReplayDownloadButton : CompositeDrawable
{
public Bindable<ScoreInfo> Score => Model;
public readonly Bindable<ScoreInfo> Score = new Bindable<ScoreInfo>();
protected readonly Bindable<DownloadState> State = new Bindable<DownloadState>();
private DownloadButton button;
private ShakeContainer shakeContainer;
private ScoreDownloadTracker downloadTracker;
private ReplayAvailability replayAvailability
{
get
@ -26,7 +31,7 @@ namespace osu.Game.Screens.Ranking
if (State.Value == DownloadState.LocallyAvailable)
return ReplayAvailability.Local;
if (!string.IsNullOrEmpty(Model.Value?.Hash))
if (!string.IsNullOrEmpty(Score.Value?.Hash))
return ReplayAvailability.Online;
return ReplayAvailability.NotAvailable;
@ -34,8 +39,8 @@ namespace osu.Game.Screens.Ranking
}
public ReplayDownloadButton(ScoreInfo score)
: base(score)
{
Score.Value = score;
Size = new Vector2(50, 30);
}
@ -56,11 +61,11 @@ namespace osu.Game.Screens.Ranking
switch (State.Value)
{
case DownloadState.LocallyAvailable:
game?.PresentScore(Model.Value, ScorePresentType.Gameplay);
game?.PresentScore(Score.Value, ScorePresentType.Gameplay);
break;
case DownloadState.NotDownloaded:
scores.Download(Model.Value, false);
scores.Download(Score.Value, false);
break;
case DownloadState.Importing:
@ -70,17 +75,25 @@ namespace osu.Game.Screens.Ranking
}
};
State.BindValueChanged(state =>
Score.BindValueChanged(score =>
{
button.State.Value = state.NewValue;
downloadTracker?.RemoveAndDisposeImmediately();
if (score.NewValue != null)
{
AddInternal(downloadTracker = new ScoreDownloadTracker(score.NewValue)
{
State = { BindTarget = State }
});
}
button.Enabled.Value = replayAvailability != ReplayAvailability.NotAvailable;
updateTooltip();
}, true);
Model.BindValueChanged(_ =>
State.BindValueChanged(state =>
{
button.Enabled.Value = replayAvailability != ReplayAvailability.NotAvailable;
button.State.Value = state.NewValue;
updateTooltip();
}, true);
}

View File

@ -287,7 +287,7 @@ namespace osu.Game.Screens.Ranking
detachedPanelContainer.Add(expandedPanel);
// Move into its original location in the local container first, then to the final location.
var origLocation = detachedPanelContainer.ToLocalSpace(screenSpacePos).X;
float origLocation = detachedPanelContainer.ToLocalSpace(screenSpacePos).X;
expandedPanel.MoveToX(origLocation)
.Then()
.MoveToX(StatisticsPanel.SIDE_PADDING, 150, Easing.OutQuint);

View File

@ -31,7 +31,7 @@ namespace osu.Game.Screens.Ranking
return null;
getScoreRequest = new GetScoresRequest(Score.BeatmapInfo, Score.Ruleset);
getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineScoreID != Score.OnlineScoreID).Select(s => s.CreateScoreInfo(rulesets)));
getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineID != Score.OnlineScoreID).Select(s => s.CreateScoreInfo(rulesets, Beatmap.Value.BeatmapInfo)));
return getScoreRequest;
}

View File

@ -20,8 +20,8 @@ namespace osu.Game.Screens.Ranking.Statistics
public UnstableRate(IEnumerable<HitEvent> hitEvents)
: base("Unstable Rate")
{
var timeOffsets = hitEvents.Where(e => !(e.HitObject.HitWindows is HitWindows.EmptyHitWindows) && e.Result.IsHit())
.Select(ev => ev.TimeOffset).ToArray();
double[] timeOffsets = hitEvents.Where(e => !(e.HitObject.HitWindows is HitWindows.EmptyHitWindows) && e.Result.IsHit())
.Select(ev => ev.TimeOffset).ToArray();
Value = 10 * standardDeviation(timeOffsets);
}
@ -30,8 +30,8 @@ namespace osu.Game.Screens.Ranking.Statistics
if (timeOffsets.Length == 0)
return double.NaN;
var mean = timeOffsets.Average();
var squares = timeOffsets.Select(offset => Math.Pow(offset - mean, 2)).Sum();
double mean = timeOffsets.Average();
double squares = timeOffsets.Select(offset => Math.Pow(offset - mean, 2)).Sum();
return Math.Sqrt(squares / timeOffsets.Length);
}

View File

@ -57,7 +57,7 @@ namespace osu.Game.Screens.Select
beatmapInfo = value;
failTimes = beatmapInfo?.OnlineInfo?.FailTimes;
ratings = beatmapInfo?.BeatmapSet?.Ratings;
ratings = beatmapInfo?.BeatmapSet?.OnlineInfo?.Ratings;
Scheduler.AddOnce(updateStatistics);
}
@ -182,7 +182,7 @@ namespace osu.Game.Screens.Select
source.Text = BeatmapInfo?.Metadata?.Source;
tags.Text = BeatmapInfo?.Metadata?.Tags;
// metrics may have been previously fetched
// failTimes may have been previously fetched
if (ratings != null && failTimes != null)
{
updateMetrics();
@ -233,7 +233,7 @@ namespace osu.Game.Screens.Select
private void updateMetrics()
{
var hasMetrics = (failTimes?.Retries?.Any() ?? false) || (failTimes?.Fails?.Any() ?? false);
bool hasMetrics = (failTimes?.Retries?.Any() ?? false) || (failTimes?.Fails?.Any() ?? false);
if (ratings?.Any() ?? false)
{

View File

@ -188,8 +188,8 @@ namespace osu.Game.Screens.Select
RelativeSizeAxes = Axes.Both;
titleBinding = localisation.GetLocalisedString(new RomanisableString(metadata.TitleUnicode, metadata.Title));
artistBinding = localisation.GetLocalisedString(new RomanisableString(metadata.ArtistUnicode, metadata.Artist));
titleBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.TitleUnicode, metadata.Title));
artistBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.ArtistUnicode, metadata.Artist));
const float top_height = 0.7f;

View File

@ -57,9 +57,9 @@ namespace osu.Game.Screens.Select.Carousel
if (match)
{
var terms = BeatmapInfo.GetSearchableTerms();
string[] terms = BeatmapInfo.GetSearchableTerms();
foreach (var criteriaTerm in criteria.SearchTerms)
foreach (string criteriaTerm in criteria.SearchTerms)
match &= terms.Any(term => term.Contains(criteriaTerm, StringComparison.InvariantCultureIgnoreCase));
// if a match wasn't found via text matching of terms, do a second catch-all check matching against online IDs.
@ -89,7 +89,7 @@ namespace osu.Game.Screens.Select.Carousel
{
default:
case SortMode.Difficulty:
var ruleset = BeatmapInfo.RulesetID.CompareTo(otherBeatmap.BeatmapInfo.RulesetID);
int ruleset = BeatmapInfo.RulesetID.CompareTo(otherBeatmap.BeatmapInfo.RulesetID);
if (ruleset != 0) return ruleset;
return BeatmapInfo.StarDifficulty.CompareTo(otherBeatmap.BeatmapInfo.StarDifficulty);

View File

@ -69,7 +69,7 @@ namespace osu.Game.Screens.Select.Carousel
return string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.OrdinalIgnoreCase);
case SortMode.Author:
return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.OrdinalIgnoreCase);
return string.Compare(BeatmapSet.Metadata.Author?.Username, otherSet.BeatmapSet.Metadata.Author?.Username, StringComparison.OrdinalIgnoreCase);
case SortMode.Source:
return string.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source, StringComparison.OrdinalIgnoreCase);
@ -95,8 +95,8 @@ namespace osu.Game.Screens.Select.Carousel
private int compareUsingAggregateMax(CarouselBeatmapSet other, Func<BeatmapInfo, double> func)
{
var ourBeatmaps = ValidBeatmaps.Any();
var otherBeatmaps = other.ValidBeatmaps.Any();
bool ourBeatmaps = ValidBeatmaps.Any();
bool otherBeatmaps = other.ValidBeatmaps.Any();
if (!ourBeatmaps && !otherBeatmaps) return 0;
if (!ourBeatmaps) return -1;

View File

@ -142,7 +142,7 @@ namespace osu.Game.Screens.Select.Carousel
},
new OsuSpriteText
{
Text = $"{(beatmapInfo.Metadata ?? beatmapInfo.BeatmapSet.Metadata).Author.Username}",
Text = $"{(beatmapInfo.Metadata ?? beatmapInfo.BeatmapSet.Metadata).Author?.Username ?? string.Empty}",
Font = OsuFont.GetFont(italics: true),
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft

View File

@ -241,7 +241,7 @@ namespace osu.Game.Screens.Select.Carousel
TernaryState state;
var countExisting = beatmapSet.Beatmaps.Count(b => collection.Beatmaps.Contains(b));
int countExisting = beatmapSet.Beatmaps.Count(b => collection.Beatmaps.Contains(b));
if (countExisting == beatmapSet.Beatmaps.Count)
state = TernaryState.True;

View File

@ -38,9 +38,9 @@ namespace osu.Game.Screens.Select.Details
protected readonly StatisticRow FirstValue, HpDrain, Accuracy, ApproachRate;
private readonly StatisticRow starDifficulty;
private BeatmapInfo beatmapInfo;
private IBeatmapInfo beatmapInfo;
public BeatmapInfo BeatmapInfo
public IBeatmapInfo BeatmapInfo
{
get => beatmapInfo;
set
@ -94,9 +94,6 @@ namespace osu.Game.Screens.Select.Details
modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue);
modSettingChangeTracker.SettingChanged += m =>
{
if (!(m is IApplicableToDifficulty))
return;
debouncedStatisticsUpdate?.Cancel();
debouncedStatisticsUpdate = Scheduler.AddDelayed(updateStatistics, 100);
};
@ -106,7 +103,7 @@ namespace osu.Game.Screens.Select.Details
private void updateStatistics()
{
IBeatmapDifficultyInfo baseDifficulty = BeatmapInfo?.BaseDifficulty;
IBeatmapDifficultyInfo baseDifficulty = BeatmapInfo?.Difficulty;
BeatmapDifficulty adjustedDifficulty = null;
if (baseDifficulty != null && mods.Value.Any(m => m is IApplicableToDifficulty))
@ -117,7 +114,7 @@ namespace osu.Game.Screens.Select.Details
mod.ApplyToDifficulty(adjustedDifficulty);
}
switch (BeatmapInfo?.Ruleset?.ID ?? 0)
switch (BeatmapInfo?.Ruleset.OnlineID)
{
case 3:
// Account for mania differences locally for now

View File

@ -27,9 +27,9 @@ namespace osu.Game.Screens.Select.Details
failTimes = value;
var retries = FailTimes?.Retries ?? Array.Empty<int>();
var fails = FailTimes?.Fails ?? Array.Empty<int>();
var retriesAndFails = sumRetriesAndFails(retries, fails);
int[] retries = FailTimes?.Retries ?? Array.Empty<int>();
int[] fails = FailTimes?.Fails ?? Array.Empty<int>();
int[] retriesAndFails = sumRetriesAndFails(retries, fails);
float maxValue = retriesAndFails.Any() ? retriesAndFails.Max() : 0;
failGraph.MaxValue = maxValue;
@ -42,7 +42,7 @@ namespace osu.Game.Screens.Select.Details
private int[] sumRetriesAndFails(int[] retries, int[] fails)
{
var result = new int[Math.Max(retries.Length, fails.Length)];
int[] result = new int[Math.Max(retries.Length, fails.Length)];
for (int i = 0; i < retries.Length; ++i)
result[i] = retries[i];

View File

@ -45,8 +45,8 @@ namespace osu.Game.Screens.Select.Details
{
var usableRange = Ratings.Skip(1).Take(rating_range); // adjust for API returning weird empty data at 0.
var negativeCount = usableRange.Take(rating_range / 2).Sum();
var totalCount = usableRange.Sum();
int negativeCount = usableRange.Take(rating_range / 2).Sum();
int totalCount = usableRange.Sum();
negativeRatings.Text = negativeCount.ToLocalisableString(@"N0");
positiveRatings.Text = (totalCount - negativeCount).ToLocalisableString(@"N0");

View File

@ -39,7 +39,7 @@ namespace osu.Game.Screens.Select
{
Debug.Assert(ruleset.Value.ID != null);
var query = searchTextBox.Text;
string query = searchTextBox.Text;
var criteria = new FilterCriteria
{

View File

@ -22,9 +22,9 @@ namespace osu.Game.Screens.Select
{
foreach (Match match in query_syntax_regex.Matches(query))
{
var key = match.Groups["key"].Value.ToLower();
string key = match.Groups["key"].Value.ToLower();
var op = parseOperator(match.Groups["op"].Value);
var value = match.Groups["value"].Value;
string value = match.Groups["value"].Value;
if (tryParseKeywordCriteria(criteria, key, value, op))
query = query.Replace(match.ToString(), "");
@ -310,10 +310,10 @@ namespace osu.Game.Screens.Select
private static bool tryUpdateLengthRange(FilterCriteria criteria, Operator op, string val)
{
if (!tryParseDoubleWithPoint(val.TrimEnd('m', 's', 'h'), out var length))
if (!tryParseDoubleWithPoint(val.TrimEnd('m', 's', 'h'), out double length))
return false;
var scale = getLengthScale(val);
int scale = getLengthScale(val);
return tryUpdateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0);
}
}

View File

@ -192,14 +192,14 @@ namespace osu.Game.Screens.Select.Leaderboards
req.Success += r =>
{
scoreManager.OrderByTotalScoreAsync(r.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToArray(), loadCancellationSource.Token)
scoreManager.OrderByTotalScoreAsync(r.Scores.Select(s => s.CreateScoreInfo(rulesets, BeatmapInfo)).ToArray(), loadCancellationSource.Token)
.ContinueWith(ordered => Schedule(() =>
{
if (loadCancellationSource.IsCancellationRequested)
return;
scoresCallback?.Invoke(ordered.Result);
TopScore = r.UserScore?.CreateScoreInfo(rulesets);
TopScore = r.UserScore?.CreateScoreInfo(rulesets, BeatmapInfo);
}), TaskContinuationOptions.OnlyOnRanToCompletion);
};

View File

@ -76,7 +76,7 @@ namespace osu.Game.Screens.Spectate
managerUpdated = beatmaps.ItemUpdated.GetBoundCopy();
managerUpdated.BindValueChanged(beatmapUpdated);
foreach (var (id, _) in userMap)
foreach ((int id, var _) in userMap)
spectatorClient.WatchUser(id);
}));
}
@ -86,7 +86,7 @@ namespace osu.Game.Screens.Spectate
if (!e.NewValue.TryGetTarget(out var beatmapSet))
return;
foreach (var (userId, _) in userMap)
foreach ((int userId, var _) in userMap)
{
if (!playingUserStates.TryGetValue(userId, out var userState))
continue;
@ -101,20 +101,20 @@ namespace osu.Game.Screens.Spectate
switch (e.Action)
{
case NotifyDictionaryChangedAction.Add:
foreach (var (userId, state) in e.NewItems.AsNonNull())
foreach ((int userId, var state) in e.NewItems.AsNonNull())
onUserStateAdded(userId, state);
break;
case NotifyDictionaryChangedAction.Remove:
foreach (var (userId, _) in e.OldItems.AsNonNull())
foreach ((int userId, var _) in e.OldItems.AsNonNull())
onUserStateRemoved(userId);
break;
case NotifyDictionaryChangedAction.Replace:
foreach (var (userId, _) in e.OldItems.AsNonNull())
foreach ((int userId, var _) in e.OldItems.AsNonNull())
onUserStateRemoved(userId);
foreach (var (userId, state) in e.NewItems.AsNonNull())
foreach ((int userId, var state) in e.NewItems.AsNonNull())
onUserStateAdded(userId, state);
break;
}
@ -219,7 +219,7 @@ namespace osu.Game.Screens.Spectate
if (spectatorClient != null)
{
foreach (var (userId, _) in userMap)
foreach ((int userId, var _) in userMap)
spectatorClient.StopWatchingUser(userId);
}