1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 18:07:23 +08:00

Merge branch 'master' into move-cache-logic-to-base-impl

This commit is contained in:
Dean Herbert 2020-11-06 16:56:35 +09:00
commit 9bb32f0914
16 changed files with 196 additions and 113 deletions

View File

@ -20,8 +20,8 @@ namespace osu.Game.Rulesets.Osu.Tests
private TestDrawableSpinner drawableSpinner;
[TestCase(false)]
[TestCase(true)]
[TestCase(false)]
public void TestVariousSpinners(bool autoplay)
{
string term = autoplay ? "Hit" : "Miss";

View File

@ -19,26 +19,37 @@ namespace osu.Game.Rulesets.Osu.Skinning
/// Legacy skinned spinner with two main spinning layers, one fixed overlay and one final spinning overlay.
/// No background layer.
/// </summary>
public class LegacyNewStyleSpinner : CompositeDrawable
public class LegacyNewStyleSpinner : LegacySpinner
{
private Sprite glow;
private Sprite discBottom;
private Sprite discTop;
private Sprite spinningMiddle;
private Sprite fixedMiddle;
private DrawableSpinner drawableSpinner;
private readonly Color4 glowColour = new Color4(3, 151, 255, 255);
private const float final_scale = 0.625f;
private Container scaleContainer;
[BackgroundDependencyLoader]
private void load(ISkinSource source, DrawableHitObject drawableObject)
private void load(ISkinSource source)
{
drawableSpinner = (DrawableSpinner)drawableObject;
Scale = new Vector2(final_scale);
InternalChildren = new Drawable[]
AddInternal(scaleContainer = new Container
{
Scale = new Vector2(SPRITE_SCALE),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
glow = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = source.GetTexture("spinner-glow"),
Blending = BlendingParameters.Additive,
Colour = glowColour,
},
discBottom = new Sprite
{
Anchor = Anchor.Centre,
@ -63,22 +74,17 @@ namespace osu.Game.Rulesets.Osu.Skinning
Origin = Anchor.Centre,
Texture = source.GetTexture("spinner-middle2")
}
};
}
});
}
protected override void LoadComplete()
protected override void UpdateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
{
base.LoadComplete();
base.UpdateStateTransforms(drawableHitObject, state);
drawableSpinner.ApplyCustomUpdateState += updateStateTransforms;
updateStateTransforms(drawableSpinner, drawableSpinner.State.Value);
}
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
switch (drawableHitObject)
{
if (!(drawableHitObject is DrawableSpinner d))
return;
case DrawableSpinner d:
Spinner spinner = d.HitObject;
using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimePreempt, true))
@ -94,23 +100,32 @@ namespace osu.Game.Rulesets.Osu.Skinning
using (BeginDelayedSequence(spinner.TimePreempt, true))
fixedMiddle.FadeColour(Color4.Red, spinner.Duration);
}
if (state == ArmedState.Hit)
{
using (BeginAbsoluteSequence(d.HitStateUpdateTime))
glow.FadeOut(300);
}
break;
case DrawableSpinnerBonusTick _:
if (state == ArmedState.Hit)
glow.FlashColour(Color4.White, 200);
break;
}
}
protected override void Update()
{
base.Update();
spinningMiddle.Rotation = discTop.Rotation = drawableSpinner.RotationTracker.Rotation;
spinningMiddle.Rotation = discTop.Rotation = DrawableSpinner.RotationTracker.Rotation;
discBottom.Rotation = discTop.Rotation / 3;
Scale = new Vector2(final_scale * (0.8f + (float)Interpolation.ApplyEasing(Easing.Out, drawableSpinner.Progress) * 0.2f));
}
glow.Alpha = DrawableSpinner.Progress;
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (drawableSpinner != null)
drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms;
scaleContainer.Scale = new Vector2(SPRITE_SCALE * (0.8f + (float)Interpolation.ApplyEasing(Easing.Out, DrawableSpinner.Progress) * 0.2f));
}
}
}

View File

@ -18,28 +18,22 @@ namespace osu.Game.Rulesets.Osu.Skinning
/// <summary>
/// Legacy skinned spinner with one main spinning layer and a background layer.
/// </summary>
public class LegacyOldStyleSpinner : CompositeDrawable
public class LegacyOldStyleSpinner : LegacySpinner
{
private DrawableSpinner drawableSpinner;
private Sprite disc;
private Sprite metreSprite;
private Container metre;
private bool spinnerBlink;
private const float sprite_scale = 1 / 1.6f;
private const float final_metre_height = 692 * sprite_scale;
private const float final_metre_height = 692 * SPRITE_SCALE;
[BackgroundDependencyLoader]
private void load(ISkinSource source, DrawableHitObject drawableObject)
private void load(ISkinSource source)
{
spinnerBlink = source.GetConfig<OsuSkinConfiguration, bool>(OsuSkinConfiguration.SpinnerNoBlink)?.Value != true;
drawableSpinner = (DrawableSpinner)drawableObject;
RelativeSizeAxes = Axes.Both;
InternalChild = new Container
AddInternal(new Container
{
// the old-style spinner relied heavily on absolute screen-space coordinate values.
// wrap everything in a container simulating absolute coords to preserve alignment
@ -55,14 +49,14 @@ namespace osu.Game.Rulesets.Osu.Skinning
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = source.GetTexture("spinner-background"),
Scale = new Vector2(sprite_scale)
Scale = new Vector2(SPRITE_SCALE)
},
disc = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = source.GetTexture("spinner-circle"),
Scale = new Vector2(sprite_scale)
Scale = new Vector2(SPRITE_SCALE)
},
metre = new Container
{
@ -78,23 +72,17 @@ namespace osu.Game.Rulesets.Osu.Skinning
Texture = source.GetTexture("spinner-metre"),
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft,
Scale = new Vector2(0.625f)
Scale = new Vector2(SPRITE_SCALE)
}
}
}
};
});
}
protected override void LoadComplete()
protected override void UpdateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
{
base.LoadComplete();
base.UpdateStateTransforms(drawableHitObject, state);
drawableSpinner.ApplyCustomUpdateState += updateStateTransforms;
updateStateTransforms(drawableSpinner, drawableSpinner.State.Value);
}
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
{
if (!(drawableHitObject is DrawableSpinner d))
return;
@ -110,11 +98,11 @@ namespace osu.Game.Rulesets.Osu.Skinning
protected override void Update()
{
base.Update();
disc.Rotation = drawableSpinner.RotationTracker.Rotation;
disc.Rotation = DrawableSpinner.RotationTracker.Rotation;
// careful: need to call this exactly once for all calculations in a frame
// as the function has a random factor in it
var metreHeight = getMetreHeight(drawableSpinner.Progress);
var metreHeight = getMetreHeight(DrawableSpinner.Progress);
// hack to make the metre blink up from below than down from above.
// move down the container to be able to apply masking for the metre,
@ -140,13 +128,5 @@ namespace osu.Game.Rulesets.Osu.Skinning
return (float)barCount / total_bars * final_metre_height;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (drawableSpinner != null)
drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms;
}
}
}

View File

@ -0,0 +1,84 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Rulesets.Osu.Skinning
{
public abstract class LegacySpinner : CompositeDrawable
{
protected const float SPRITE_SCALE = 0.625f;
protected DrawableSpinner DrawableSpinner { get; private set; }
private Sprite spin;
[BackgroundDependencyLoader]
private void load(DrawableHitObject drawableHitObject, ISkinSource source)
{
RelativeSizeAxes = Axes.Both;
DrawableSpinner = (DrawableSpinner)drawableHitObject;
AddRangeInternal(new[]
{
spin = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Depth = float.MinValue,
Texture = source.GetTexture("spinner-spin"),
Scale = new Vector2(SPRITE_SCALE),
Y = 120 - 45 // offset temporarily to avoid overlapping default spin counter
},
});
}
protected override void LoadComplete()
{
base.LoadComplete();
DrawableSpinner.ApplyCustomUpdateState += UpdateStateTransforms;
UpdateStateTransforms(DrawableSpinner, DrawableSpinner.State.Value);
}
protected virtual void UpdateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
{
switch (drawableHitObject)
{
case DrawableSpinner d:
double fadeOutLength = Math.Min(400, d.HitObject.Duration);
using (BeginAbsoluteSequence(drawableHitObject.HitStateUpdateTime - fadeOutLength, true))
spin.FadeOutFromOne(fadeOutLength);
break;
case DrawableSpinnerTick d:
if (state == ArmedState.Hit)
{
using (BeginAbsoluteSequence(d.HitStateUpdateTime, true))
spin.FadeOut(300);
}
break;
}
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (DrawableSpinner != null)
DrawableSpinner.ApplyCustomUpdateState -= UpdateStateTransforms;
}
}
}

View File

@ -250,7 +250,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public void EndPlay(int beatmapId)
{
((ISpectatorClient)this).UserFinishedPlaying((int)StreamingUser.Id, new SpectatorState
((ISpectatorClient)this).UserFinishedPlaying(StreamingUser.Id, new SpectatorState
{
BeatmapID = beatmapId,
RulesetID = 0,
@ -273,7 +273,7 @@ namespace osu.Game.Tests.Visual.Gameplay
}
var bundle = new FrameDataBundle(frames);
((ISpectatorClient)this).UserSentFrames((int)StreamingUser.Id, bundle);
((ISpectatorClient)this).UserSentFrames(StreamingUser.Id, bundle);
if (!sentState)
sendState(beatmapId);
@ -293,7 +293,7 @@ namespace osu.Game.Tests.Visual.Gameplay
private void sendState(int beatmapId)
{
sentState = true;
((ISpectatorClient)this).UserBeganPlaying((int)StreamingUser.Id, new SpectatorState
((ISpectatorClient)this).UserBeganPlaying(StreamingUser.Id, new SpectatorState
{
BeatmapID = beatmapId,
RulesetID = 0,

View File

@ -277,7 +277,7 @@ namespace osu.Game.Tournament.Screens.Editors
userId.Value = user.Id.ToString();
userId.BindValueChanged(idString =>
{
long.TryParse(idString.NewValue, out var parsed);
int.TryParse(idString.NewValue, out var parsed);
user.Id = parsed;

View File

@ -61,7 +61,7 @@ namespace osu.Game.Online.API.Requests.Responses
private int[] ratings { get; set; }
[JsonProperty(@"user_id")]
private long creatorId
private int creatorId
{
set => Author.Id = value;
}

View File

@ -20,7 +20,7 @@ namespace osu.Game.Online.API.Requests.Responses
public string OsuUsername { get; set; }
[JsonProperty("user_id")]
public long? UserId { get; set; }
public int? UserId { get; set; }
[JsonProperty("user_url")]
public string UserUrl { get; set; }

View File

@ -22,7 +22,7 @@ namespace osu.Game.Online.Chat
public readonly ObservableCollection<User> Users = new ObservableCollection<User>();
[JsonProperty(@"users")]
private long[] userIds
private int[] userIds
{
set
{

View File

@ -278,7 +278,7 @@ namespace osu.Game
break;
case LinkAction.OpenUserProfile:
if (long.TryParse(link.Argument, out long userId))
if (int.TryParse(link.Argument, out int userId))
ShowUser(userId);
break;
@ -321,7 +321,7 @@ namespace osu.Game
/// Show a user's profile as an overlay.
/// </summary>
/// <param name="userId">The user to display.</param>
public void ShowUser(long userId) => waitForReady(() => userProfile, _ => userProfile.ShowUser(userId));
public void ShowUser(int userId) => waitForReady(() => userProfile, _ => userProfile.ShowUser(userId));
/// <summary>
/// Show a beatmap's set as an overlay, displaying the given beatmap.

View File

@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Dashboard
var request = new GetUserRequest(u);
request.Success += user => Schedule(() =>
{
if (playingUsers.Contains((int)user.Id))
if (playingUsers.Contains(user.Id))
userFlow.Add(createUserPanel(user));
});
api.Queue(request);

View File

@ -33,7 +33,7 @@ namespace osu.Game.Overlays
{
}
public void ShowUser(long userId) => ShowUser(new User { Id = userId });
public void ShowUser(int userId) => ShowUser(new User { Id = userId });
public void ShowUser(User user, bool fetchOnline = true)
{

View File

@ -546,7 +546,11 @@ namespace osu.Game.Rulesets.Objects.Drawables
// Ensure that the judgement is given a valid time offset, because this may not get set by the caller
var endTime = HitObject.GetEndTime();
Result.TimeOffset = Math.Min(HitObject.HitWindows.WindowFor(HitResult.Miss), Time.Current - endTime);
Result.TimeOffset = Time.Current - endTime;
double missWindow = HitObject.HitWindows.WindowFor(HitResult.Miss);
if (missWindow > 0)
Result.TimeOffset = Math.Min(Result.TimeOffset, missWindow);
if (Result.HasResult)
updateState(Result.IsHit ? ArmedState.Hit : ArmedState.Miss);

View File

@ -123,7 +123,7 @@ namespace osu.Game.Scoring
[JsonIgnore]
[Column("UserID")]
public long? UserID
public int? UserID
{
get => User?.Id ?? 1;
set

View File

@ -182,7 +182,7 @@ namespace osu.Game.Screens.Play
spectatorStreaming.OnUserFinishedPlaying += userFinishedPlaying;
spectatorStreaming.OnNewFrames += userSentFrames;
spectatorStreaming.WatchUser((int)targetUser.Id);
spectatorStreaming.WatchUser(targetUser.Id);
managerUpdated = beatmaps.ItemUpdated.GetBoundCopy();
managerUpdated.BindValueChanged(beatmapUpdated);
@ -353,7 +353,7 @@ namespace osu.Game.Screens.Play
spectatorStreaming.OnUserFinishedPlaying -= userFinishedPlaying;
spectatorStreaming.OnNewFrames -= userSentFrames;
spectatorStreaming.StopWatchingUser((int)targetUser.Id);
spectatorStreaming.StopWatchingUser(targetUser.Id);
}
managerUpdated?.UnbindAll();

View File

@ -12,7 +12,7 @@ namespace osu.Game.Users
public class User : IEquatable<User>
{
[JsonProperty(@"id")]
public long Id = 1;
public int Id = 1;
[JsonProperty(@"join_date")]
public DateTimeOffset JoinDate;