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

Merge branch 'master' into add-spinner-bonus-score

This commit is contained in:
Dean Herbert 2020-07-23 23:05:04 +09:00 committed by GitHub
commit 0050f6348f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 276 additions and 204 deletions

View File

@ -52,6 +52,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.714.1" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2020.722.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -35,18 +35,15 @@ namespace osu.Game.Rulesets.Catch.Replays
} }
} }
public override List<IInput> GetPendingInputs() public override void CollectPendingInputs(List<IInput> inputs)
{ {
if (!Position.HasValue) return new List<IInput>(); if (!Position.HasValue) return;
return new List<IInput> inputs.Add(new CatchReplayState
{ {
new CatchReplayState PressedActions = CurrentFrame?.Actions ?? new List<CatchAction>(),
{ CatcherX = Position.Value
PressedActions = CurrentFrame?.Actions ?? new List<CatchAction>(), });
CatcherX = Position.Value
},
};
} }
public class CatchReplayState : ReplayState<CatchAction> public class CatchReplayState : ReplayState<CatchAction>

View File

@ -18,6 +18,9 @@ namespace osu.Game.Rulesets.Mania.Replays
protected override bool IsImportant(ManiaReplayFrame frame) => frame.Actions.Any(); protected override bool IsImportant(ManiaReplayFrame frame) => frame.Actions.Any();
public override List<IInput> GetPendingInputs() => new List<IInput> { new ReplayState<ManiaAction> { PressedActions = CurrentFrame?.Actions ?? new List<ManiaAction>() } }; public override void CollectPendingInputs(List<IInput> inputs)
{
inputs.Add(new ReplayState<ManiaAction> { PressedActions = CurrentFrame?.Actions ?? new List<ManiaAction>() });
}
} }
} }

View File

@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Osu.Tests
const double time_slider = 1500; const double time_slider = 1500;
const double time_circle = 1510; const double time_circle = 1510;
Vector2 positionCircle = Vector2.Zero; Vector2 positionCircle = Vector2.Zero;
Vector2 positionSlider = new Vector2(80); Vector2 positionSlider = new Vector2(30);
var hitObjects = new List<OsuHitObject> var hitObjects = new List<OsuHitObject>
{ {

View File

@ -2,6 +2,7 @@
// 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;
using System.Linq;
using osuTK; using osuTK;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -11,6 +12,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Rulesets.Osu.Skinning;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Game.Skinning; using osu.Game.Skinning;
@ -81,6 +83,42 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
foreach (var drawableHitObject in NestedHitObjects) foreach (var drawableHitObject in NestedHitObjects)
drawableHitObject.AccentColour.Value = colour.NewValue; drawableHitObject.AccentColour.Value = colour.NewValue;
}, true); }, true);
Tracking.BindValueChanged(updateSlidingSample);
}
private SkinnableSound slidingSample;
protected override void LoadSamples()
{
base.LoadSamples();
slidingSample?.Expire();
slidingSample = null;
var firstSample = HitObject.Samples.FirstOrDefault();
if (firstSample != null)
{
var clone = HitObject.SampleControlPoint.ApplyTo(firstSample);
clone.Name = "sliderslide";
AddInternal(slidingSample = new SkinnableSound(clone)
{
Looping = true
});
}
}
private void updateSlidingSample(ValueChangedEvent<bool> tracking)
{
// note that samples will not start playing if exiting a seek operation in the middle of a slider.
// may be something we want to address at a later point, but not so easy to make happen right now
// (SkinnableSound would need to expose whether the sample is already playing and this logic would need to run in Update).
if (tracking.NewValue && ShouldPlaySamples)
slidingSample?.Play();
else
slidingSample?.Stop();
} }
protected override void AddNestedHitObject(DrawableHitObject hitObject) protected override void AddNestedHitObject(DrawableHitObject hitObject)
@ -156,6 +194,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Tracking.Value = Ball.Tracking; Tracking.Value = Ball.Tracking;
if (Tracking.Value && slidingSample != null)
// keep the sliding sample playing at the current tracking position
slidingSample.Balance.Value = CalculateSamplePlaybackBalance(Ball.X / OsuPlayfield.BASE_SIZE.X);
double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
Ball.UpdateProgress(completionProgress); Ball.UpdateProgress(completionProgress);

View File

@ -23,6 +23,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private readonly Drawable scaleContainer; private readonly Drawable scaleContainer;
public override bool DisplayResult => false;
public DrawableSliderRepeat(SliderRepeat sliderRepeat, DrawableSlider drawableSlider) public DrawableSliderRepeat(SliderRepeat sliderRepeat, DrawableSlider drawableSlider)
: base(sliderRepeat) : base(sliderRepeat)
{ {

View File

@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
private readonly Slider slider; private readonly Slider slider;
private readonly Drawable followCircle; private readonly Drawable followCircle;
private readonly DrawableSlider drawableSlider; private readonly DrawableSlider drawableSlider;
private readonly CircularContainer ball; private readonly Drawable ball;
public SliderBall(Slider slider, DrawableSlider drawableSlider = null) public SliderBall(Slider slider, DrawableSlider drawableSlider = null)
{ {
@ -54,19 +54,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
Alpha = 0, Alpha = 0,
Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderFollowCircle), _ => new DefaultFollowCircle()), Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderFollowCircle), _ => new DefaultFollowCircle()),
}, },
ball = new CircularContainer ball = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBall), _ => new DefaultSliderBall())
{ {
Masking = true,
RelativeSizeAxes = Axes.Both,
Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Alpha = 1, Origin = Anchor.Centre,
Child = new Container },
{
RelativeSizeAxes = Axes.Both,
Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBall), _ => new DefaultSliderBall()),
}
}
}; };
} }
@ -187,12 +179,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
return; return;
Position = newPos; Position = newPos;
Rotation = -90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI); ball.Rotation = -90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI);
lastPosition = newPos; lastPosition = newPos;
} }
private class FollowCircleContainer : Container private class FollowCircleContainer : CircularContainer
{ {
public override bool HandlePositionalInput => true; public override bool HandlePositionalInput => true;
} }

View File

@ -36,19 +36,10 @@ namespace osu.Game.Rulesets.Osu.Replays
} }
} }
public override List<IInput> GetPendingInputs() public override void CollectPendingInputs(List<IInput> inputs)
{ {
return new List<IInput> inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(Position ?? Vector2.Zero) });
{ inputs.Add(new ReplayState<OsuAction> { PressedActions = CurrentFrame?.Actions ?? new List<OsuAction>() });
new MousePositionAbsoluteInput
{
Position = GamefieldToScreenSpace(Position ?? Vector2.Zero)
},
new ReplayState<OsuAction>
{
PressedActions = CurrentFrame?.Actions ?? new List<OsuAction>()
}
};
} }
} }
} }

View File

@ -15,6 +15,9 @@ namespace osu.Game.Rulesets.Osu.Skinning
{ {
private readonly Drawable animationContent; private readonly Drawable animationContent;
private Sprite layerNd;
private Sprite layerSpec;
public LegacySliderBall(Drawable animationContent) public LegacySliderBall(Drawable animationContent)
{ {
this.animationContent = animationContent; this.animationContent = animationContent;
@ -29,18 +32,37 @@ namespace osu.Game.Rulesets.Osu.Skinning
InternalChildren = new[] InternalChildren = new[]
{ {
new Sprite layerNd = new Sprite
{ {
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = skin.GetTexture("sliderb-nd"), Texture = skin.GetTexture("sliderb-nd"),
Colour = new Color4(5, 5, 5, 255), Colour = new Color4(5, 5, 5, 255),
}, },
animationContent, animationContent.With(d =>
new Sprite
{ {
d.Anchor = Anchor.Centre;
d.Origin = Anchor.Centre;
}),
layerSpec = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = skin.GetTexture("sliderb-spec"), Texture = skin.GetTexture("sliderb-spec"),
Blending = BlendingParameters.Additive, Blending = BlendingParameters.Additive,
}, },
}; };
} }
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
//undo rotation on layers which should not be rotated.
float appliedRotation = Parent.Rotation;
layerNd.Rotation = -appliedRotation;
layerSpec.Rotation = -appliedRotation;
}
} }
} }

View File

@ -18,6 +18,9 @@ namespace osu.Game.Rulesets.Taiko.Replays
protected override bool IsImportant(TaikoReplayFrame frame) => frame.Actions.Any(); protected override bool IsImportant(TaikoReplayFrame frame) => frame.Actions.Any();
public override List<IInput> GetPendingInputs() => new List<IInput> { new ReplayState<TaikoAction> { PressedActions = CurrentFrame?.Actions ?? new List<TaikoAction>() } }; public override void CollectPendingInputs(List<IInput> inputs)
{
inputs.Add(new ReplayState<TaikoAction> { PressedActions = CurrentFrame?.Actions ?? new List<TaikoAction>() });
}
} }
} }

View File

@ -173,19 +173,10 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
} }
public override List<IInput> GetPendingInputs() public override void CollectPendingInputs(List<IInput> inputs)
{ {
return new List<IInput> inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) });
{ inputs.Add(new ReplayState<TestAction> { PressedActions = CurrentFrame?.Actions ?? new List<TestAction>() });
new MousePositionAbsoluteInput
{
Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero)
},
new ReplayState<TestAction>
{
PressedActions = CurrentFrame?.Actions ?? new List<TestAction>()
}
};
} }
} }

View File

@ -113,19 +113,10 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
} }
public override List<IInput> GetPendingInputs() public override void CollectPendingInputs(List<IInput> inputs)
{ {
return new List<IInput> inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) });
{ inputs.Add(new ReplayState<TestAction> { PressedActions = CurrentFrame?.Actions ?? new List<TestAction>() });
new MousePositionAbsoluteInput
{
Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero)
},
new ReplayState<TestAction>
{
PressedActions = CurrentFrame?.Actions ?? new List<TestAction>()
}
};
} }
} }

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -65,11 +64,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void bindHandler(double delay = 0) private void bindHandler(double delay = 0)
{ {
var roomScores = new List<RoomScore>(); var roomScores = new List<MultiplayerScore>();
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
roomScores.Add(new RoomScore roomScores.Add(new MultiplayerScore
{ {
ID = i, ID = i,
Accuracy = 0.9 - 0.01 * i, Accuracy = 0.9 - 0.01 * i,

View File

@ -30,12 +30,6 @@ namespace osu.Game.Tests.Visual.Online
Add(selector = new SpotlightSelector()); Add(selector = new SpotlightSelector());
} }
[Test]
public void TestVisibility()
{
AddStep("Toggle Visibility", selector.ToggleVisibility);
}
[Test] [Test]
public void TestLocalSpotlights() public void TestLocalSpotlights()
{ {

View File

@ -36,11 +36,11 @@ namespace osu.Game.Tests.Visual.UserInterface
} }
}); });
addHeader("Orange OverlayHeader (no background)", new TestNoBackgroundHeader(), OverlayColourScheme.Orange); addHeader("Orange OverlayHeader (no background, 100 padding)", new TestNoBackgroundHeader(), OverlayColourScheme.Orange);
addHeader("Blue OverlayHeader", new TestNoControlHeader(), OverlayColourScheme.Blue); addHeader("Blue OverlayHeader (default 50 padding)", new TestNoControlHeader(), OverlayColourScheme.Blue);
addHeader("Green TabControlOverlayHeader (string) with ruleset selector", new TestStringTabControlHeader(), OverlayColourScheme.Green); addHeader("Green TabControlOverlayHeader (string) with ruleset selector", new TestStringTabControlHeader(), OverlayColourScheme.Green);
addHeader("Pink TabControlOverlayHeader (enum)", new TestEnumTabControlHeader(), OverlayColourScheme.Pink); addHeader("Pink TabControlOverlayHeader (enum, 30 padding)", new TestEnumTabControlHeader(), OverlayColourScheme.Pink);
addHeader("Red BreadcrumbControlOverlayHeader (no background)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red); addHeader("Red BreadcrumbControlOverlayHeader (no background, 10 padding)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red);
} }
private void addHeader(string name, OverlayHeader header, OverlayColourScheme colourScheme) private void addHeader(string name, OverlayHeader header, OverlayColourScheme colourScheme)
@ -86,6 +86,11 @@ namespace osu.Game.Tests.Visual.UserInterface
private class TestNoBackgroundHeader : OverlayHeader private class TestNoBackgroundHeader : OverlayHeader
{ {
protected override OverlayTitle CreateTitle() => new TestTitle(); protected override OverlayTitle CreateTitle() => new TestTitle();
public TestNoBackgroundHeader()
{
ContentSidePadding = 100;
}
} }
private class TestNoControlHeader : OverlayHeader private class TestNoControlHeader : OverlayHeader
@ -112,6 +117,11 @@ namespace osu.Game.Tests.Visual.UserInterface
private class TestEnumTabControlHeader : TabControlOverlayHeader<TestEnum> private class TestEnumTabControlHeader : TabControlOverlayHeader<TestEnum>
{ {
public TestEnumTabControlHeader()
{
ContentSidePadding = 30;
}
protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/rankings"); protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/rankings");
protected override OverlayTitle CreateTitle() => new TestTitle(); protected override OverlayTitle CreateTitle() => new TestTitle();
@ -130,6 +140,8 @@ namespace osu.Game.Tests.Visual.UserInterface
public TestBreadcrumbControlHeader() public TestBreadcrumbControlHeader()
{ {
ContentSidePadding = 10;
TabControl.AddItem("tab1"); TabControl.AddItem("tab1");
TabControl.AddItem("tab2"); TabControl.AddItem("tab2");
TabControl.Current.Value = "tab2"; TabControl.Current.Value = "tab2";

View File

@ -2,9 +2,8 @@
// 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 Newtonsoft.Json; using Newtonsoft.Json;
using osu.Game.Online.Multiplayer;
namespace osu.Game.Online.API.Requests.Responses namespace osu.Game.Online.Multiplayer
{ {
public class APICreatedRoom : Room public class APICreatedRoom : Room
{ {

View File

@ -6,7 +6,7 @@ using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets; using osu.Game.Rulesets;
namespace osu.Game.Online.API namespace osu.Game.Online.Multiplayer
{ {
public class APIPlaylistBeatmap : APIBeatmap public class APIPlaylistBeatmap : APIBeatmap
{ {

View File

@ -3,7 +3,7 @@
using Newtonsoft.Json; using Newtonsoft.Json;
namespace osu.Game.Online.API.Requests.Responses namespace osu.Game.Online.Multiplayer
{ {
public class APIScoreToken public class APIScoreToken
{ {

View File

@ -4,10 +4,9 @@
using System.Net.Http; using System.Net.Http;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Framework.IO.Network; using osu.Framework.IO.Network;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.Multiplayer
{ {
public class CreateRoomRequest : APIRequest<APICreatedRoom> public class CreateRoomRequest : APIRequest<APICreatedRoom>
{ {

View File

@ -3,9 +3,9 @@
using System.Net.Http; using System.Net.Http;
using osu.Framework.IO.Network; using osu.Framework.IO.Network;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.Multiplayer
{ {
public class CreateRoomScoreRequest : APIRequest<APIScoreToken> public class CreateRoomScoreRequest : APIRequest<APIScoreToken>
{ {

View File

@ -3,8 +3,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Game.Online.API;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.Multiplayer
{ {
public class GetRoomPlaylistScoresRequest : APIRequest<RoomPlaylistScores> public class GetRoomPlaylistScoresRequest : APIRequest<RoomPlaylistScores>
{ {
@ -23,6 +24,6 @@ namespace osu.Game.Online.API.Requests
public class RoomPlaylistScores public class RoomPlaylistScores
{ {
[JsonProperty("scores")] [JsonProperty("scores")]
public List<RoomScore> Scores { get; set; } public List<MultiplayerScore> Scores { get; set; }
} }
} }

View File

@ -1,9 +1,9 @@
// 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 osu.Game.Online.Multiplayer; using osu.Game.Online.API;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.Multiplayer
{ {
public class GetRoomRequest : APIRequest<Room> public class GetRoomRequest : APIRequest<Room>
{ {

View File

@ -2,9 +2,10 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.Multiplayer
{ {
public class GetRoomScoresRequest : APIRequest<List<APIUserScoreAggregate>> public class GetRoomScoresRequest : APIRequest<List<APIUserScoreAggregate>>
{ {

View File

@ -4,10 +4,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using Humanizer; using Humanizer;
using osu.Framework.IO.Network; using osu.Framework.IO.Network;
using osu.Game.Online.Multiplayer; using osu.Game.Online.API;
using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Screens.Multi.Lounge.Components;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.Multiplayer
{ {
public class GetRoomsRequest : APIRequest<List<Room>> public class GetRoomsRequest : APIRequest<List<Room>>
{ {

View File

@ -3,9 +3,9 @@
using System.Net.Http; using System.Net.Http;
using osu.Framework.IO.Network; using osu.Framework.IO.Network;
using osu.Game.Online.Multiplayer; using osu.Game.Online.API;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.Multiplayer
{ {
public class JoinRoomRequest : APIRequest public class JoinRoomRequest : APIRequest
{ {

View File

@ -6,15 +6,15 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using osu.Game.Online.Multiplayer; using osu.Game.Online.API;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Online.API namespace osu.Game.Online.Multiplayer
{ {
public class RoomScore public class MultiplayerScore
{ {
[JsonProperty("id")] [JsonProperty("id")]
public int ID { get; set; } public int ID { get; set; }

View File

@ -3,9 +3,9 @@
using System.Net.Http; using System.Net.Http;
using osu.Framework.IO.Network; using osu.Framework.IO.Network;
using osu.Game.Online.Multiplayer; using osu.Game.Online.API;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.Multiplayer
{ {
public class PartRoomRequest : APIRequest public class PartRoomRequest : APIRequest
{ {

View File

@ -4,11 +4,12 @@
using System.Net.Http; using System.Net.Http;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Framework.IO.Network; using osu.Framework.IO.Network;
using osu.Game.Online.API;
using osu.Game.Scoring; using osu.Game.Scoring;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.Multiplayer
{ {
public class SubmitRoomScoreRequest : APIRequest<RoomScore> public class SubmitRoomScoreRequest : APIRequest<MultiplayerScore>
{ {
private readonly int scoreId; private readonly int scoreId;
private readonly int roomId; private readonly int roomId;

View File

@ -12,9 +12,26 @@ namespace osu.Game.Overlays
{ {
public abstract class OverlayHeader : Container public abstract class OverlayHeader : Container
{ {
public const int CONTENT_X_MARGIN = 50; private float contentSidePadding;
/// <summary>
/// Horizontal padding of the header content.
/// </summary>
protected float ContentSidePadding
{
get => contentSidePadding;
set
{
contentSidePadding = value;
content.Padding = new MarginPadding
{
Horizontal = value
};
}
}
private readonly Box titleBackground; private readonly Box titleBackground;
private readonly Container content;
protected readonly FillFlowContainer HeaderInfo; protected readonly FillFlowContainer HeaderInfo;
@ -50,14 +67,10 @@ namespace osu.Game.Overlays
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = Color4.Gray, Colour = Color4.Gray,
}, },
new Container content = new Container
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Padding = new MarginPadding
{
Horizontal = CONTENT_X_MARGIN,
},
Children = new[] Children = new[]
{ {
CreateTitle().With(title => CreateTitle().With(title =>
@ -79,6 +92,8 @@ namespace osu.Game.Overlays
CreateContent() CreateContent()
} }
}); });
ContentSidePadding = 50;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -23,6 +23,8 @@ namespace osu.Game.Overlays.Profile
public ProfileHeader() public ProfileHeader()
{ {
ContentSidePadding = UserProfileOverlay.CONTENT_X_MARGIN;
User.ValueChanged += e => updateDisplay(e.NewValue); User.ValueChanged += e => updateDisplay(e.NewValue);
TabControl.AddItem("info"); TabControl.AddItem("info");

View File

@ -18,10 +18,8 @@ using osu.Game.Online.API.Requests;
namespace osu.Game.Overlays.Rankings namespace osu.Game.Overlays.Rankings
{ {
public class SpotlightSelector : VisibilityContainer, IHasCurrentValue<APISpotlight> public class SpotlightSelector : CompositeDrawable, IHasCurrentValue<APISpotlight>
{ {
private const int duration = 300;
private readonly BindableWithCurrent<APISpotlight> current = new BindableWithCurrent<APISpotlight>(); private readonly BindableWithCurrent<APISpotlight> current = new BindableWithCurrent<APISpotlight>();
public readonly Bindable<RankingsSortCriteria> Sort = new Bindable<RankingsSortCriteria>(); public readonly Bindable<RankingsSortCriteria> Sort = new Bindable<RankingsSortCriteria>();
@ -37,10 +35,7 @@ namespace osu.Game.Overlays.Rankings
set => dropdown.Items = value; set => dropdown.Items = value;
} }
protected override bool StartHidden => true;
private readonly Box background; private readonly Box background;
private readonly Container content;
private readonly SpotlightsDropdown dropdown; private readonly SpotlightsDropdown dropdown;
private readonly InfoColumn startDateColumn; private readonly InfoColumn startDateColumn;
private readonly InfoColumn endDateColumn; private readonly InfoColumn endDateColumn;
@ -51,73 +46,68 @@ namespace osu.Game.Overlays.Rankings
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
Add(content = new Container InternalChildren = new Drawable[]
{ {
RelativeSizeAxes = Axes.X, background = new Box
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{ {
background = new Box RelativeSizeAxes = Axes.Both,
{ },
RelativeSizeAxes = Axes.Both, new Container
}, {
new Container RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN },
Child = new FillFlowContainer
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN }, Direction = FillDirection.Vertical,
Child = new FillFlowContainer Children = new Drawable[]
{ {
RelativeSizeAxes = Axes.X, new Container
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{ {
new Container Margin = new MarginPadding { Vertical = 20 },
{ RelativeSizeAxes = Axes.X,
Margin = new MarginPadding { Vertical = 20 }, Height = 40,
RelativeSizeAxes = Axes.X, Depth = -float.MaxValue,
Height = 40, Child = dropdown = new SpotlightsDropdown
Depth = -float.MaxValue,
Child = dropdown = new SpotlightsDropdown
{
RelativeSizeAxes = Axes.X,
Current = Current
}
},
new Container
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, Current = Current
Children = new Drawable[] }
},
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
new FillFlowContainer
{ {
new FillFlowContainer AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(10, 0),
Margin = new MarginPadding { Bottom = 5 },
Children = new Drawable[]
{ {
AutoSizeAxes = Axes.Both, startDateColumn = new InfoColumn(@"Start Date"),
Direction = FillDirection.Horizontal, endDateColumn = new InfoColumn(@"End Date"),
Spacing = new Vector2(10, 0), mapCountColumn = new InfoColumn(@"Map Count"),
Margin = new MarginPadding { Bottom = 5 }, participantsColumn = new InfoColumn(@"Participants")
Children = new Drawable[]
{
startDateColumn = new InfoColumn(@"Start Date"),
endDateColumn = new InfoColumn(@"End Date"),
mapCountColumn = new InfoColumn(@"Map Count"),
participantsColumn = new InfoColumn(@"Participants")
}
},
new RankingsSortTabControl
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Current = Sort
} }
},
new RankingsSortTabControl
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Current = Sort
} }
} }
} }
} }
} }
} }
}); };
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -134,10 +124,6 @@ namespace osu.Game.Overlays.Rankings
participantsColumn.Value = response.Spotlight.Participants?.ToString("N0"); participantsColumn.Value = response.Spotlight.Participants?.ToString("N0");
} }
protected override void PopIn() => content.FadeIn(duration, Easing.OutQuint);
protected override void PopOut() => content.FadeOut(duration, Easing.OutQuint);
private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd"); private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd");
private class InfoColumn : FillFlowContainer private class InfoColumn : FillFlowContainer

View File

@ -81,8 +81,6 @@ namespace osu.Game.Overlays.Rankings
{ {
base.LoadComplete(); base.LoadComplete();
selector.Show();
selectedSpotlight.BindValueChanged(_ => onSpotlightChanged()); selectedSpotlight.BindValueChanged(_ => onSpotlightChanged());
sort.BindValueChanged(_ => onSpotlightChanged()); sort.BindValueChanged(_ => onSpotlightChanged());
Ruleset.BindValueChanged(onRulesetChanged); Ruleset.BindValueChanged(onRulesetChanged);

View File

@ -22,6 +22,7 @@ namespace osu.Game.Overlays
protected OsuTabControl<T> TabControl; protected OsuTabControl<T> TabControl;
private readonly Box controlBackground; private readonly Box controlBackground;
private readonly Container tabControlContainer;
private readonly BindableWithCurrent<T> current = new BindableWithCurrent<T>(); private readonly BindableWithCurrent<T> current = new BindableWithCurrent<T>();
public Bindable<T> Current public Bindable<T> Current
@ -30,6 +31,16 @@ namespace osu.Game.Overlays
set => current.Current = value; set => current.Current = value;
} }
protected new float ContentSidePadding
{
get => base.ContentSidePadding;
set
{
base.ContentSidePadding = value;
tabControlContainer.Padding = new MarginPadding { Horizontal = value };
}
}
protected TabControlOverlayHeader() protected TabControlOverlayHeader()
{ {
HeaderInfo.Add(new Container HeaderInfo.Add(new Container
@ -42,11 +53,16 @@ namespace osu.Game.Overlays
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}, },
TabControl = CreateTabControl().With(control => tabControlContainer = new Container
{ {
control.Margin = new MarginPadding { Left = CONTENT_X_MARGIN }; RelativeSizeAxes = Axes.X,
control.Current = Current; AutoSizeAxes = Axes.Y,
}) Padding = new MarginPadding { Horizontal = ContentSidePadding },
Child = TabControl = CreateTabControl().With(control =>
{
control.Current = Current;
})
}
} }
}); });
} }

View File

@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
if (Result == null) if (Result == null)
throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}.");
loadSamples(); LoadSamples();
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -145,14 +145,14 @@ namespace osu.Game.Rulesets.Objects.Drawables
} }
samplesBindable = HitObject.SamplesBindable.GetBoundCopy(); samplesBindable = HitObject.SamplesBindable.GetBoundCopy();
samplesBindable.CollectionChanged += (_, __) => loadSamples(); samplesBindable.CollectionChanged += (_, __) => LoadSamples();
apply(HitObject); apply(HitObject);
updateState(ArmedState.Idle, true); updateState(ArmedState.Idle, true);
} }
private void loadSamples() protected virtual void LoadSamples()
{ {
if (Samples != null) if (Samples != null)
{ {
@ -353,17 +353,32 @@ namespace osu.Game.Rulesets.Objects.Drawables
[Resolved(canBeNull: true)] [Resolved(canBeNull: true)]
private GameplayClock gameplayClock { get; set; } private GameplayClock gameplayClock { get; set; }
/// <summary>
/// Calculate the position to be used for sample playback at a specified X position (0..1).
/// </summary>
/// <param name="position">The lookup X position. Generally should be <see cref="SamplePlaybackPosition"/>.</param>
/// <returns></returns>
protected double CalculateSamplePlaybackBalance(double position)
{
const float balance_adjust_amount = 0.4f;
return balance_adjust_amount * (userPositionalHitSounds.Value ? position - 0.5f : 0);
}
/// <summary>
/// Whether samples should currently be playing. Will be false during seek operations.
/// </summary>
protected bool ShouldPlaySamples => gameplayClock?.IsSeeking != true;
/// <summary> /// <summary>
/// Plays all the hit sounds for this <see cref="DrawableHitObject"/>. /// Plays all the hit sounds for this <see cref="DrawableHitObject"/>.
/// This is invoked automatically when this <see cref="DrawableHitObject"/> is hit. /// This is invoked automatically when this <see cref="DrawableHitObject"/> is hit.
/// </summary> /// </summary>
public virtual void PlaySamples() public virtual void PlaySamples()
{ {
const float balance_adjust_amount = 0.4f; if (Samples != null && ShouldPlaySamples)
if (Samples != null && gameplayClock?.IsSeeking != true)
{ {
Samples.Balance.Value = balance_adjust_amount * (userPositionalHitSounds.Value ? SamplePlaybackPosition - 0.5f : 0); Samples.Balance.Value = CalculateSamplePlaybackBalance(SamplePlaybackPosition);
Samples.Play(); Samples.Play();
} }
} }

View File

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Input.StateChanges;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Replays; using osu.Game.Replays;
@ -69,8 +68,6 @@ namespace osu.Game.Rulesets.Replays
return true; return true;
} }
public override List<IInput> GetPendingInputs() => new List<IInput>();
private const double sixty_frame_time = 1000.0 / 60; private const double sixty_frame_time = 1000.0 / 60;
protected virtual double AllowedImportantTimeSpan => sixty_frame_time * 1.2; protected virtual double AllowedImportantTimeSpan => sixty_frame_time * 1.2;

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Leaderboards; using osu.Game.Online.Leaderboards;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;

View File

@ -10,7 +10,6 @@ using osu.Framework.Bindables;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Scoring; using osu.Game.Scoring;

View File

@ -9,7 +9,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;

View File

@ -14,7 +14,6 @@ using osu.Framework.Logging;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online; using osu.Game.Online;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Screens.Multi.Lounge.Components;

View File

@ -13,6 +13,7 @@ using osu.Framework.Input.Events;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Ranking.Contracted; using osu.Game.Screens.Ranking.Contracted;
using osu.Game.Screens.Ranking.Expanded; using osu.Game.Screens.Ranking.Expanded;
using osu.Game.Users;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -142,7 +143,16 @@ namespace osu.Game.Screens.Ranking
CornerRadius = 20, CornerRadius = 20,
CornerExponent = 2.5f, CornerExponent = 2.5f,
Masking = true, Masking = true,
Child = middleLayerBackground = new Box { RelativeSizeAxes = Axes.Both } Children = new[]
{
middleLayerBackground = new Box { RelativeSizeAxes = Axes.Both },
new UserCoverBackground
{
RelativeSizeAxes = Axes.Both,
User = Score.User,
Colour = ColourInfo.GradientVertical(Color4.White.Opacity(0.5f), Color4Extensions.FromHex("#444").Opacity(0))
},
}
}, },
middleLayerContentContainer = new Container { RelativeSizeAxes = Axes.Both } middleLayerContentContainer = new Container { RelativeSizeAxes = Axes.Both }
} }
@ -155,18 +165,10 @@ namespace osu.Game.Screens.Ranking
{ {
base.LoadComplete(); base.LoadComplete();
if (state == PanelState.Expanded)
{
topLayerBackground.FadeColour(expanded_top_layer_colour);
middleLayerBackground.FadeColour(expanded_middle_layer_colour);
}
else
{
topLayerBackground.FadeColour(contracted_top_layer_colour);
middleLayerBackground.FadeColour(contracted_middle_layer_colour);
}
updateState(); updateState();
topLayerBackground.FinishTransforms(false, nameof(Colour));
middleLayerBackground.FinishTransforms(false, nameof(Colour));
} }
private PanelState state = PanelState.Contracted; private PanelState state = PanelState.Contracted;

View File

@ -98,6 +98,8 @@ namespace osu.Game.Skinning
protected override void SkinChanged(ISkinSource skin, bool allowFallback) protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{ {
bool wasPlaying = samplesContainer.Any(s => s.Playing);
var channels = hitSamples.Select(s => var channels = hitSamples.Select(s =>
{ {
var ch = skin.GetSample(s); var ch = skin.GetSample(s);
@ -121,6 +123,9 @@ namespace osu.Game.Skinning
}).Where(c => c != null); }).Where(c => c != null);
samplesContainer.ChildrenEnumerable = channels.Select(c => new DrawableSample(c)); samplesContainer.ChildrenEnumerable = channels.Select(c => new DrawableSample(c));
if (wasPlaying)
Play();
} }
} }
} }

View File

@ -24,7 +24,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2020.714.1" /> <PackageReference Include="ppy.osu.Framework" Version="2020.722.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
<PackageReference Include="Sentry" Version="2.1.4" /> <PackageReference Include="Sentry" Version="2.1.4" />
<PackageReference Include="SharpCompress" Version="0.25.1" /> <PackageReference Include="SharpCompress" Version="0.25.1" />

View File

@ -70,7 +70,7 @@
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.714.1" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2020.722.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
</ItemGroup> </ItemGroup>
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. --> <!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
@ -80,7 +80,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2020.714.1" /> <PackageReference Include="ppy.osu.Framework" Version="2020.722.0" />
<PackageReference Include="SharpCompress" Version="0.25.1" /> <PackageReference Include="SharpCompress" Version="0.25.1" />
<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" />