1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-28 09:37:23 +08:00

Merge remote-tracking branch 'Joehuu/master' into requests-limit-usage

This commit is contained in:
smoogipoo 2019-07-19 15:33:18 +09:00
commit 2a66cf36d5
28 changed files with 202 additions and 86 deletions

View File

@ -63,6 +63,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2019.711.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2019.717.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Osu.Tests
protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; protected override string ResourceAssembly => "osu.Game.Rulesets.Osu";
[TestCase(6.931145117263422, "diffcalc-test")] [TestCase(6.931145117263422, "diffcalc-test")]
[TestCase(1.0736587013228804d, "zero-length-sliders")]
public void Test(double expected, string name) public void Test(double expected, string name)
=> base.Test(expected, name); => base.Test(expected, name);

View File

@ -29,6 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
ShakeDuration = 30, ShakeDuration = 30,
RelativeSizeAxes = Axes.Both RelativeSizeAxes = Axes.Both
}); });
Alpha = 0; Alpha = 0;
} }
@ -38,6 +39,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren); protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren);
protected override bool RemoveInternal(Drawable drawable) => shakeContainer.Remove(drawable); protected override bool RemoveInternal(Drawable drawable) => shakeContainer.Remove(drawable);
protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt;
protected sealed override void UpdateState(ArmedState state) protected sealed override void UpdateState(ArmedState state)
{ {
double transformTime = HitObject.StartTime - HitObject.TimePreempt; double transformTime = HitObject.StartTime - HitObject.TimePreempt;

View File

@ -156,6 +156,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
} }
} }
public override void OnKilled()
{
base.OnKilled();
Body.RecyclePath();
}
protected override void SkinChanged(ISkinSource skin, bool allowFallback) protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{ {
base.SkinChanged(skin, allowFallback); base.SkinChanged(skin, allowFallback);

View File

@ -13,7 +13,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
public const float DEFAULT_BORDER_SIZE = 1; public const float DEFAULT_BORDER_SIZE = 1;
private readonly SliderPath path; private SliderPath path;
protected Path Path => path; protected Path Path => path;
public float PathRadius public float PathRadius
@ -77,6 +78,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
InternalChild = path = new SliderPath(); InternalChild = path = new SliderPath();
} }
/// <summary>
/// Initialises a new <see cref="SliderPath"/>, releasing all resources retained by the old one.
/// </summary>
public void RecyclePath()
{
InternalChild = path = new SliderPath
{
Position = path.Position,
PathRadius = path.PathRadius,
AccentColour = path.AccentColour,
BorderColour = path.BorderColour,
BorderSize = path.BorderSize,
Vertices = path.Vertices
};
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => path.ReceivePositionalInputAt(screenSpacePos); public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => path.ReceivePositionalInputAt(screenSpacePos);
/// <summary> /// <summary>

View File

@ -0,0 +1,28 @@
osu file format v14
[Difficulty]
HPDrainRate:3
CircleSize:3
OverallDifficulty:3
ApproachRate:4.5
SliderMultiplier:0.799999999999999
SliderTickRate:1
[TimingPoints]
800,260.869565217391,3,2,10,60,1,0
[HitObjects]
// Linear
78,193,2365,2,0,L|330:193,1,0
78,193,3669,2,0,L|330:193,1,0
78,193,4973,2,0,L|330:193,1,0
// Perfect-curve
151,206,6278,2,0,P|293:75|345:204,1,0
151,206,8104,2,0,P|293:75|345:204,1,0
151,206,9930,2,0,P|293:75|345:204,1,0
// Bezier
76,191,11756,2,0,B|176:59|358:340|438:190,1,0
76,191,13582,2,0,B|176:59|358:340|438:190,1,0
76,191,15408,2,0,B|176:59|358:340|438:190,1,0

View File

@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private readonly TrailPart[] parts = new TrailPart[max_sprites]; private readonly TrailPart[] parts = new TrailPart[max_sprites];
private Vector2 size; private Vector2 size;
private readonly VertexBatch<TexturedTrailVertex> vertexBatch = new QuadBatch<TexturedTrailVertex>(max_sprites, 1); private readonly TrailBatch vertexBatch = new TrailBatch(max_sprites, 1);
public TrailDrawNode(CursorTrail source) public TrailDrawNode(CursorTrail source)
: base(source) : base(source)
@ -196,21 +196,16 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
for (int i = 0; i < parts.Length; ++i) for (int i = 0; i < parts.Length; ++i)
{ {
vertexBatch.DrawTime = parts[i].Time;
Vector2 pos = parts[i].Position; Vector2 pos = parts[i].Position;
float localTime = parts[i].Time;
DrawQuad( DrawQuad(
texture, texture,
new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y),
DrawColourInfo.Colour, DrawColourInfo.Colour,
null, null,
v => vertexBatch.Add(new TexturedTrailVertex vertexBatch.AddAction);
{
Position = v.Position,
TexturePosition = v.TexturePosition,
Time = localTime + 1,
Colour = v.Colour,
}));
} }
shader.Unbind(); shader.Unbind();
@ -222,6 +217,25 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
vertexBatch.Dispose(); vertexBatch.Dispose();
} }
// Todo: This shouldn't exist, but is currently used to reduce allocations by caching variable-capturing closures.
private class TrailBatch : QuadBatch<TexturedTrailVertex>
{
public new readonly Action<TexturedVertex2D> AddAction;
public float DrawTime;
public TrailBatch(int size, int maxBuffers)
: base(size, maxBuffers)
{
AddAction = v => Add(new TexturedTrailVertex
{
Position = v.Position,
TexturePosition = v.TexturePosition,
Time = DrawTime + 1,
Colour = v.Colour,
});
}
}
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]

View File

@ -12,6 +12,7 @@ using osu.Game.Rulesets.UI;
using System.Linq; using System.Linq;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Rulesets.Osu.UI.Cursor;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.UI namespace osu.Game.Rulesets.Osu.UI
{ {
@ -39,7 +40,13 @@ namespace osu.Game.Rulesets.Osu.UI
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Depth = 1, Depth = 1,
}, },
HitObjectContainer, // Todo: This should not exist, but currently helps to reduce LOH allocations due to unbinding skin source events on judgement disposal
// Todo: Remove when hitobjects are properly pooled
new LocalSkinOverrideContainer(null)
{
RelativeSizeAxes = Axes.Both,
Child = HitObjectContainer,
},
approachCircles = new ApproachCircleProxyContainer approachCircles = new ApproachCircleProxyContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,

View File

@ -16,7 +16,7 @@ namespace osu.Game.Graphics.Backgrounds
/// </summary> /// </summary>
public class Background : CompositeDrawable public class Background : CompositeDrawable
{ {
public Sprite Sprite; public readonly Sprite Sprite;
private readonly string textureName; private readonly string textureName;
@ -51,7 +51,7 @@ namespace osu.Game.Graphics.Backgrounds
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns> /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
public void BlurTo(Vector2 newBlurSigma, double duration = 0, Easing easing = Easing.None) public void BlurTo(Vector2 newBlurSigma, double duration = 0, Easing easing = Easing.None)
{ {
if (bufferedContainer == null) if (bufferedContainer == null && newBlurSigma != Vector2.Zero)
{ {
RemoveInternal(Sprite); RemoveInternal(Sprite);
@ -63,7 +63,7 @@ namespace osu.Game.Graphics.Backgrounds
}); });
} }
bufferedContainer.BlurTo(newBlurSigma, duration, easing); bufferedContainer?.BlurTo(newBlurSigma, duration, easing);
} }
} }
} }

View File

@ -51,7 +51,6 @@ namespace osu.Game.Online.Leaderboards
loading.Hide(); loading.Hide();
// schedule because we may not be loaded yet (LoadComponentAsync complains).
showScoresDelegate?.Cancel(); showScoresDelegate?.Cancel();
showScoresCancellationSource?.Cancel(); showScoresCancellationSource?.Cancel();
@ -61,28 +60,22 @@ namespace osu.Game.Online.Leaderboards
// ensure placeholder is hidden when displaying scores // ensure placeholder is hidden when displaying scores
PlaceholderState = PlaceholderState.Successful; PlaceholderState = PlaceholderState.Successful;
scrollFlow = CreateScoreFlow(); var sf = CreateScoreFlow();
scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); sf.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1));
if (!IsLoaded) // schedule because we may not be loaded yet (LoadComponentAsync complains).
showScoresDelegate = Schedule(showScores); showScoresDelegate = Schedule(() => LoadComponentAsync(sf, _ =>
else
showScores();
void showScores() => LoadComponentAsync(scrollFlow, _ =>
{ {
scrollContainer.Add(scrollFlow); scrollContainer.Add(scrollFlow = sf);
int i = 0; int i = 0;
foreach (var s in scrollFlow.Children) foreach (var s in scrollFlow.Children)
{
using (s.BeginDelayedSequence(i++ * 50, true)) using (s.BeginDelayedSequence(i++ * 50, true))
s.Show(); s.Show();
}
scrollContainer.ScrollTo(0f, false); scrollContainer.ScrollTo(0f, false);
}, (showScoresCancellationSource = new CancellationTokenSource()).Token); }, (showScoresCancellationSource = new CancellationTokenSource()).Token));
} }
} }

View File

@ -62,7 +62,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
}, },
} }
}, },
avatar = new UpdateableAvatar(hideImmediately: true) avatar = new UpdateableAvatar
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
@ -99,7 +99,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold)
}, },
flag = new UpdateableFlag(hideImmediately: true) flag = new UpdateableFlag
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,

View File

@ -26,8 +26,13 @@ namespace osu.Game.Overlays.Direct
TabContainer.Masking = false; TabContainer.Masking = false;
TabContainer.Spacing = new Vector2(10, 0); TabContainer.Spacing = new Vector2(10, 0);
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
}
Current.DisabledChanged += value => SelectedTab.FadeColour(value ? Color4.DarkGray : Color4.White, 200, Easing.OutQuint); protected override void LoadComplete()
{
base.LoadComplete();
Current.BindDisabledChanged(value => SelectedTab.FadeColour(value ? Color4.DarkGray : Color4.White, 200, Easing.OutQuint), true);
} }
protected override TabItem<RulesetInfo> CreateTabItem(RulesetInfo value) => new DirectRulesetTabItem(value); protected override TabItem<RulesetInfo> CreateTabItem(RulesetInfo value) => new DirectRulesetTabItem(value);

View File

@ -7,7 +7,6 @@ using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Extensions.TypeExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -179,6 +178,39 @@ namespace osu.Game.Rulesets.Objects.Drawables
UpdateResult(false); UpdateResult(false);
} }
private double? lifetimeStart;
public override double LifetimeStart
{
get => lifetimeStart ?? (HitObject.StartTime - InitialLifetimeOffset);
set
{
base.LifetimeStart = value;
lifetimeStart = value;
}
}
/// <summary>
/// A safe offset prior to the start time of <see cref="HitObject"/> at which this <see cref="DrawableHitObject"/> may begin displaying contents.
/// By default, <see cref="DrawableHitObject"/>s are assumed to display their contents within 10 seconds prior to the start time of <see cref="HitObject"/>.
/// </summary>
/// <remarks>
/// This is only used as an optimisation to delay the initial update of this <see cref="DrawableHitObject"/> and may be tuned more aggressively if required.
/// A more accurate <see cref="LifetimeStart"/> should be set inside <see cref="UpdateState"/> for an <see cref="ArmedState.Idle"/> state.
/// </remarks>
protected virtual double InitialLifetimeOffset => 10000;
/// <summary>
/// Will be called at least once after this <see cref="DrawableHitObject"/> has become not alive.
/// </summary>
public virtual void OnKilled()
{
foreach (var nested in NestedHitObjects)
nested.OnKilled();
UpdateResult(false);
}
protected virtual void AddNested(DrawableHitObject h) protected virtual void AddNested(DrawableHitObject h)
{ {
h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r);
@ -223,16 +255,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
OnNewResult?.Invoke(this, Result); OnNewResult?.Invoke(this, Result);
} }
/// <summary>
/// Will called at least once after the <see cref="Drawable.LifetimeEnd"/> of this <see cref="DrawableHitObject"/> has been passed.
/// </summary>
internal void OnLifetimeEnd()
{
foreach (var nested in NestedHitObjects)
nested.OnLifetimeEnd();
UpdateResult(false);
}
/// <summary> /// <summary>
/// Processes this <see cref="DrawableHitObject"/>, checking if a scoring result has occurred. /// Processes this <see cref="DrawableHitObject"/>, checking if a scoring result has occurred.
/// </summary> /// </summary>

View File

@ -37,7 +37,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
}; };
} }
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples) protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
List<List<HitSampleInfo>> nodeSamples)
{ {
newCombo |= forceNewCombo; newCombo |= forceNewCombo;
comboOffset += extraComboOffset; comboOffset += extraComboOffset;

View File

@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
else if (type.HasFlag(ConvertHitObjectType.Slider)) else if (type.HasFlag(ConvertHitObjectType.Slider))
{ {
PathType pathType = PathType.Catmull; PathType pathType = PathType.Catmull;
double length = 0; double? length = null;
string[] pointSplit = split[5].Split('|'); string[] pointSplit = split[5].Split('|');
@ -130,7 +130,11 @@ namespace osu.Game.Rulesets.Objects.Legacy
repeatCount = Math.Max(0, repeatCount - 1); repeatCount = Math.Max(0, repeatCount - 1);
if (split.Length > 7) if (split.Length > 7)
{
length = Math.Max(0, Parsing.ParseDouble(split[7])); length = Math.Max(0, Parsing.ParseDouble(split[7]));
if (length == 0)
length = null;
}
if (split.Length > 10) if (split.Length > 10)
readCustomSampleBanks(split[10], bankInfo); readCustomSampleBanks(split[10], bankInfo);
@ -291,7 +295,8 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// <param name="repeatCount">The slider repeat count.</param> /// <param name="repeatCount">The slider repeat count.</param>
/// <param name="nodeSamples">The samples to be played when the slider nodes are hit. This includes the head and tail of the slider.</param> /// <param name="nodeSamples">The samples to be played when the slider nodes are hit. This includes the head and tail of the slider.</param>
/// <returns>The hit object.</returns> /// <returns>The hit object.</returns>
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples); protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
List<List<HitSampleInfo>> nodeSamples);
/// <summary> /// <summary>
/// Creates a legacy Spinner-type hit object. /// Creates a legacy Spinner-type hit object.

View File

@ -26,7 +26,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
}; };
} }
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples) protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
List<List<HitSampleInfo>> nodeSamples)
{ {
return new ConvertSlider return new ConvertSlider
{ {

View File

@ -1,7 +1,6 @@
// 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 osuTK; using osuTK;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic; using System.Collections.Generic;
@ -38,7 +37,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
}; };
} }
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples) protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
List<List<HitSampleInfo>> nodeSamples)
{ {
newCombo |= forceNewCombo; newCombo |= forceNewCombo;
comboOffset += extraComboOffset; comboOffset += extraComboOffset;
@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
Position = position, Position = position,
NewCombo = FirstObject || newCombo, NewCombo = FirstObject || newCombo,
ComboOffset = comboOffset, ComboOffset = comboOffset,
Path = new SliderPath(pathType, controlPoints, Math.Max(0, length)), Path = new SliderPath(pathType, controlPoints, length),
NodeSamples = nodeSamples, NodeSamples = nodeSamples,
RepeatCount = repeatCount RepeatCount = repeatCount
}; };

View File

@ -23,7 +23,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
return new ConvertHit(); return new ConvertHit();
} }
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples) protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
List<List<HitSampleInfo>> nodeSamples)
{ {
return new ConvertSlider return new ConvertSlider
{ {

View File

@ -34,8 +34,14 @@ namespace osu.Game.Rulesets.UI
protected override void OnChildLifetimeBoundaryCrossed(LifetimeBoundaryCrossedEvent e) protected override void OnChildLifetimeBoundaryCrossed(LifetimeBoundaryCrossedEvent e)
{ {
if (e.Kind == LifetimeBoundaryKind.End && e.Direction == LifetimeBoundaryCrossingDirection.Forward && e.Child is DrawableHitObject hitObject) if (!(e.Child is DrawableHitObject hitObject))
hitObject.OnLifetimeEnd(); return;
if ((e.Kind == LifetimeBoundaryKind.End && e.Direction == LifetimeBoundaryCrossingDirection.Forward)
|| (e.Kind == LifetimeBoundaryKind.Start && e.Direction == LifetimeBoundaryCrossingDirection.Backward))
{
hitObject.OnKilled();
}
} }
} }
} }

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;
@ -168,6 +168,12 @@ namespace osu.Game.Screens.Backgrounds
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
{ {
userBlurLevel = config.GetBindable<double>(OsuSetting.BlurLevel); userBlurLevel = config.GetBindable<double>(OsuSetting.BlurLevel);
}
protected override void LoadComplete()
{
base.LoadComplete();
userBlurLevel.ValueChanged += _ => UpdateVisuals(); userBlurLevel.ValueChanged += _ => UpdateVisuals();
BlurAmount.ValueChanged += _ => UpdateVisuals(); BlurAmount.ValueChanged += _ => UpdateVisuals();
} }

View File

@ -256,9 +256,12 @@ namespace osu.Game.Screens.Ranking
} }
}; };
foreach (var t in CreateResultPages()) var pages = CreateResultPages();
modeChangeButtons.AddItem(t);
modeChangeButtons.Current.Value = modeChangeButtons.Items.FirstOrDefault(); foreach (var p in pages)
modeChangeButtons.AddItem(p);
modeChangeButtons.Current.Value = pages.FirstOrDefault();
modeChangeButtons.Current.BindValueChanged(page => modeChangeButtons.Current.BindValueChanged(page =>
{ {

View File

@ -9,18 +9,25 @@ using osu.Game.Rulesets.Mods;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics; using osu.Game.Graphics;
using osuTK; using osuTK;
using osuTK.Input; using osuTK.Input;
namespace osu.Game.Screens.Select namespace osu.Game.Screens.Select
{ {
public class FooterButtonMods : FooterButton public class FooterButtonMods : FooterButton, IHasCurrentValue<IReadOnlyList<Mod>>
{ {
public FooterButtonMods(Bindable<IReadOnlyList<Mod>> mods) public Bindable<IReadOnlyList<Mod>> Current
{ {
FooterModDisplay modDisplay; get => modDisplay.Current;
set => modDisplay.Current = value;
}
private readonly FooterModDisplay modDisplay;
public FooterButtonMods()
{
Add(new Container Add(new Container
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
@ -33,9 +40,6 @@ namespace osu.Game.Screens.Select
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Left = 70 } Margin = new MarginPadding { Left = 70 }
}); });
if (mods != null)
modDisplay.Current = mods;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -221,11 +221,9 @@ namespace osu.Game.Screens.Select
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores)
{ {
mods.BindTo(Mods);
if (Footer != null) if (Footer != null)
{ {
Footer.AddButton(new FooterButtonMods(mods), ModSelect); Footer.AddButton(new FooterButtonMods { Current = mods }, ModSelect);
Footer.AddButton(new FooterButtonRandom { Action = triggerRandom }); Footer.AddButton(new FooterButtonRandom { Action = triggerRandom });
Footer.AddButton(new FooterButtonOptions(), BeatmapOptions); Footer.AddButton(new FooterButtonOptions(), BeatmapOptions);
@ -253,7 +251,7 @@ namespace osu.Game.Screens.Select
Schedule(() => Schedule(() =>
{ {
// if we have no beatmaps but osu-stable is found, let's prompt the user to import. // if we have no beatmaps but osu-stable is found, let's prompt the user to import.
if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) if (!beatmaps.GetAllUsableBeatmapSetsEnumerable().Any() && beatmaps.StableInstallationAvailable)
dialogOverlay.Push(new ImportFromStablePopup(() => dialogOverlay.Push(new ImportFromStablePopup(() =>
{ {
Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion); Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion);
@ -263,6 +261,13 @@ namespace osu.Game.Screens.Select
} }
} }
protected override void LoadComplete()
{
base.LoadComplete();
mods.BindTo(Mods);
}
private DependencyContainer dependencies; private DependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)

View File

@ -34,7 +34,7 @@ namespace osu.Game.Skinning
public Drawable GetDrawableComponent(string componentName) public Drawable GetDrawableComponent(string componentName)
{ {
Drawable sourceDrawable; Drawable sourceDrawable;
if (beatmapSkins.Value && (sourceDrawable = skin.GetDrawableComponent(componentName)) != null) if (beatmapSkins.Value && (sourceDrawable = skin?.GetDrawableComponent(componentName)) != null)
return sourceDrawable; return sourceDrawable;
return fallbackSource?.GetDrawableComponent(componentName); return fallbackSource?.GetDrawableComponent(componentName);
@ -43,7 +43,7 @@ namespace osu.Game.Skinning
public Texture GetTexture(string componentName) public Texture GetTexture(string componentName)
{ {
Texture sourceTexture; Texture sourceTexture;
if (beatmapSkins.Value && (sourceTexture = skin.GetTexture(componentName)) != null) if (beatmapSkins.Value && (sourceTexture = skin?.GetTexture(componentName)) != null)
return sourceTexture; return sourceTexture;
return fallbackSource.GetTexture(componentName); return fallbackSource.GetTexture(componentName);
@ -52,7 +52,7 @@ namespace osu.Game.Skinning
public SampleChannel GetSample(string sampleName) public SampleChannel GetSample(string sampleName)
{ {
SampleChannel sourceChannel; SampleChannel sourceChannel;
if (beatmapHitsounds.Value && (sourceChannel = skin.GetSample(sampleName)) != null) if (beatmapHitsounds.Value && (sourceChannel = skin?.GetSample(sampleName)) != null)
return sourceChannel; return sourceChannel;
return fallbackSource?.GetSample(sampleName); return fallbackSource?.GetSample(sampleName);

View File

@ -5,7 +5,6 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Transforms;
namespace osu.Game.Users.Drawables namespace osu.Game.Users.Drawables
{ {
@ -38,8 +37,6 @@ namespace osu.Game.Users.Drawables
set => base.EdgeEffect = value; set => base.EdgeEffect = value;
} }
protected override bool TransformImmediately { get; }
/// <summary> /// <summary>
/// Whether to show a default guest representation on null user (as opposed to nothing). /// Whether to show a default guest representation on null user (as opposed to nothing).
/// </summary> /// </summary>
@ -50,14 +47,11 @@ namespace osu.Game.Users.Drawables
/// </summary> /// </summary>
public readonly BindableBool OpenOnClick = new BindableBool(true); public readonly BindableBool OpenOnClick = new BindableBool(true);
public UpdateableAvatar(User user = null, bool hideImmediately = false) public UpdateableAvatar(User user = null)
{ {
TransformImmediately = hideImmediately;
User = user; User = user;
} }
protected override TransformSequence<Drawable> ApplyHideTransforms(Drawable drawable) => TransformImmediately ? drawable?.FadeOut() : base.ApplyHideTransforms(drawable);
protected override Drawable CreateDrawable(User user) protected override Drawable CreateDrawable(User user)
{ {
if (user == null && !ShowGuestOnNull) if (user == null && !ShowGuestOnNull)

View File

@ -3,7 +3,6 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Transforms;
namespace osu.Game.Users.Drawables namespace osu.Game.Users.Drawables
{ {
@ -15,21 +14,16 @@ namespace osu.Game.Users.Drawables
set => Model = value; set => Model = value;
} }
protected override bool TransformImmediately { get; }
/// <summary> /// <summary>
/// Whether to show a place holder on null country. /// Whether to show a place holder on null country.
/// </summary> /// </summary>
public bool ShowPlaceholderOnNull = true; public bool ShowPlaceholderOnNull = true;
public UpdateableFlag(Country country = null, bool hideImmediately = false) public UpdateableFlag(Country country = null)
{ {
TransformImmediately = hideImmediately;
Country = country; Country = country;
} }
protected override TransformSequence<Drawable> ApplyHideTransforms(Drawable drawable) => TransformImmediately ? drawable?.FadeOut() : base.ApplyHideTransforms(drawable);
protected override Drawable CreateDrawable(Country country) protected override Drawable CreateDrawable(Country country)
{ {
if (country == null && !ShowPlaceholderOnNull) if (country == null && !ShowPlaceholderOnNull)

View File

@ -15,7 +15,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.4" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
<PackageReference Include="ppy.osu.Framework" Version="2019.711.0" /> <PackageReference Include="ppy.osu.Framework" Version="2019.717.1" />
<PackageReference Include="SharpCompress" Version="0.23.0" /> <PackageReference Include="SharpCompress" Version="0.23.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

@ -105,8 +105,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.702.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
<PackageReference Include="ppy.osu.Framework" Version="2019.711.0" /> <PackageReference Include="ppy.osu.Framework" Version="2019.717.1" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.711.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2019.717.1" />
<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" />