mirror of
https://github.com/osukey/osukey.git
synced 2025-06-08 21:07:59 +09:00
Merge branch 'master' into long-standard
This commit is contained in:
commit
57b8495c7a
@ -51,8 +51,8 @@
|
|||||||
<Reference Include="Java.Interop" />
|
<Reference Include="Java.Interop" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1103.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1113.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.1110.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.1113.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||||
|
@ -248,6 +248,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slider.Path.ExpectedDistance.Value = null;
|
||||||
piece.ControlPoint.Type = type;
|
piece.ControlPoint.Type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
{
|
{
|
||||||
switch (nested)
|
switch (nested)
|
||||||
{
|
{
|
||||||
|
//Freezing the SliderTicks doesnt play well with snaking sliders
|
||||||
|
case SliderTick:
|
||||||
//SliderRepeat wont layer correctly if preempt is changed.
|
//SliderRepeat wont layer correctly if preempt is changed.
|
||||||
case SliderRepeat:
|
case SliderRepeat:
|
||||||
break;
|
break;
|
||||||
|
@ -49,7 +49,6 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
private const float max_rotation = 0.25f;
|
private const float max_rotation = 0.25f;
|
||||||
|
|
||||||
public IShader? TextureShader { get; private set; }
|
public IShader? TextureShader { get; private set; }
|
||||||
public IShader? RoundedTextureShader { get; private set; }
|
|
||||||
|
|
||||||
protected Texture? Texture { get; set; }
|
protected Texture? Texture { get; set; }
|
||||||
|
|
||||||
@ -69,7 +68,6 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ShaderManager shaders)
|
private void load(ShaderManager shaders)
|
||||||
{
|
{
|
||||||
RoundedTextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED);
|
|
||||||
TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE);
|
TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,18 +245,16 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
texture ??= renderer.WhitePixel;
|
texture ??= renderer.WhitePixel;
|
||||||
RectangleF textureRect = texture.GetTextureRect();
|
RectangleF textureRect = texture.GetTextureRect();
|
||||||
|
|
||||||
var shader = GetAppropriateShader(renderer);
|
|
||||||
|
|
||||||
renderer.SetBlend(BlendingParameters.Additive);
|
renderer.SetBlend(BlendingParameters.Additive);
|
||||||
renderer.PushLocalMatrix(DrawInfo.Matrix);
|
renderer.PushLocalMatrix(DrawInfo.Matrix);
|
||||||
|
|
||||||
shader.Bind();
|
TextureShader.Bind();
|
||||||
texture.Bind();
|
texture.Bind();
|
||||||
|
|
||||||
for (int i = 0; i < points.Count; i++)
|
for (int i = 0; i < points.Count; i++)
|
||||||
drawPointQuad(points[i], textureRect, i + firstVisiblePointIndex);
|
drawPointQuad(points[i], textureRect, i + firstVisiblePointIndex);
|
||||||
|
|
||||||
shader.Unbind();
|
TextureShader.Unbind();
|
||||||
renderer.PopLocalMatrix();
|
renderer.PopLocalMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
|
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.Tests.Skinning
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestSceneDrawableSwell : TaikoSkinnableTestScene
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestHits()
|
||||||
|
{
|
||||||
|
AddStep("Centre hit", () => SetContents(_ => new DrawableSwell(createHitAtCurrentTime())
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Swell createHitAtCurrentTime()
|
||||||
|
{
|
||||||
|
var hit = new Swell
|
||||||
|
{
|
||||||
|
StartTime = Time.Current + 3000,
|
||||||
|
EndTime = Time.Current + 6000,
|
||||||
|
};
|
||||||
|
|
||||||
|
hit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||||
|
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ using osu.Framework.Graphics.Shapes;
|
|||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Skinning.Argon
|
namespace osu.Game.Rulesets.Taiko.Skinning.Argon
|
||||||
@ -81,12 +82,15 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon
|
|||||||
updateStateTransforms(drawableHitObject, drawableHitObject.State.Value);
|
updateStateTransforms(drawableHitObject, drawableHitObject.State.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
|
private void updateStateTransforms(DrawableHitObject h, ArmedState state)
|
||||||
{
|
{
|
||||||
|
if (h.HitObject is not Hit)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case ArmedState.Hit:
|
case ArmedState.Hit:
|
||||||
using (BeginAbsoluteSequence(drawableHitObject.HitStateUpdateTime))
|
using (BeginAbsoluteSequence(h.HitStateUpdateTime))
|
||||||
{
|
{
|
||||||
flash.FadeTo(0.9f).FadeOut(500, Easing.OutQuint);
|
flash.FadeTo(0.9f).FadeOut(500, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.Skinning.Argon
|
||||||
|
{
|
||||||
|
public class ArgonSwellCirclePiece : ArgonCirclePiece
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
AccentColour = ColourInfo.GradientVertical(
|
||||||
|
new Color4(240, 201, 0, 255),
|
||||||
|
new Color4(167, 139, 0, 255)
|
||||||
|
);
|
||||||
|
|
||||||
|
AddInternal(new SpriteIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Icon = FontAwesome.Solid.Asterisk,
|
||||||
|
Size = new Vector2(ICON_SIZE),
|
||||||
|
Scale = new Vector2(0.8f, 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -60,6 +60,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon
|
|||||||
case TaikoSkinComponents.TaikoExplosionMiss:
|
case TaikoSkinComponents.TaikoExplosionMiss:
|
||||||
case TaikoSkinComponents.TaikoExplosionOk:
|
case TaikoSkinComponents.TaikoExplosionOk:
|
||||||
return new ArgonHitExplosion(taikoComponent.Component);
|
return new ArgonHitExplosion(taikoComponent.Component);
|
||||||
|
|
||||||
|
case TaikoSkinComponents.Swell:
|
||||||
|
return new ArgonSwellCirclePiece();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -153,12 +153,15 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default
|
|||||||
updateStateTransforms(drawableHitObject, drawableHitObject.State.Value);
|
updateStateTransforms(drawableHitObject, drawableHitObject.State.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
|
private void updateStateTransforms(DrawableHitObject h, ArmedState state)
|
||||||
{
|
{
|
||||||
|
if (h.HitObject is not Hit)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case ArmedState.Hit:
|
case ArmedState.Hit:
|
||||||
using (BeginAbsoluteSequence(drawableHitObject.HitStateUpdateTime))
|
using (BeginAbsoluteSequence(h.HitStateUpdateTime))
|
||||||
flashBox.FadeTo(0.9f).FadeOut(300);
|
flashBox.FadeTo(0.9f).FadeOut(300);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ namespace osu.Game.Tests.Chat
|
|||||||
private ChannelManager channelManager;
|
private ChannelManager channelManager;
|
||||||
private int currentMessageId;
|
private int currentMessageId;
|
||||||
private List<Message> sentMessages;
|
private List<Message> sentMessages;
|
||||||
|
private List<int> silencedUserIds;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup() => Schedule(() =>
|
public void Setup() => Schedule(() =>
|
||||||
@ -39,6 +40,7 @@ namespace osu.Game.Tests.Chat
|
|||||||
{
|
{
|
||||||
currentMessageId = 0;
|
currentMessageId = 0;
|
||||||
sentMessages = new List<Message>();
|
sentMessages = new List<Message>();
|
||||||
|
silencedUserIds = new List<int>();
|
||||||
|
|
||||||
((DummyAPIAccess)API).HandleRequest = req =>
|
((DummyAPIAccess)API).HandleRequest = req =>
|
||||||
{
|
{
|
||||||
@ -56,6 +58,11 @@ namespace osu.Game.Tests.Chat
|
|||||||
handleMarkChannelAsReadRequest(markRead);
|
handleMarkChannelAsReadRequest(markRead);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case ChatAckRequest ack:
|
||||||
|
ack.TriggerSuccess(new ChatAckResponse { Silences = silencedUserIds.Select(u => new ChatSilence { UserId = u }).ToList() });
|
||||||
|
silencedUserIds.Clear();
|
||||||
|
return true;
|
||||||
|
|
||||||
case GetUpdatesRequest updatesRequest:
|
case GetUpdatesRequest updatesRequest:
|
||||||
updatesRequest.TriggerSuccess(new GetUpdatesResponse
|
updatesRequest.TriggerSuccess(new GetUpdatesResponse
|
||||||
{
|
{
|
||||||
@ -115,6 +122,28 @@ namespace osu.Game.Tests.Chat
|
|||||||
AddAssert("channel's last read ID is set to the latest message", () => channel.LastReadId == sentMessages.Last().Id);
|
AddAssert("channel's last read ID is set to the latest message", () => channel.LastReadId == sentMessages.Last().Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSilencedUsersAreRemoved()
|
||||||
|
{
|
||||||
|
Channel channel = null;
|
||||||
|
|
||||||
|
AddStep("join channel and select it", () =>
|
||||||
|
{
|
||||||
|
channelManager.JoinChannel(channel = createChannel(1, ChannelType.Public));
|
||||||
|
channelManager.CurrentChannel.Value = channel;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("post message", () => channelManager.PostMessage("Definitely something bad"));
|
||||||
|
|
||||||
|
AddStep("mark user as silenced and send ack request", () =>
|
||||||
|
{
|
||||||
|
silencedUserIds.Add(API.LocalUser.Value.OnlineID);
|
||||||
|
channelManager.SendAck();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("channel has no more messages", () => channel.Messages, () => Is.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
private void handlePostMessageRequest(PostMessageRequest request)
|
private void handlePostMessageRequest(PostMessageRequest request)
|
||||||
{
|
{
|
||||||
var message = new Message(++currentMessageId)
|
var message = new Message(++currentMessageId)
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
// 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 osu.Game.Graphics.Backgrounds;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Background
|
||||||
|
{
|
||||||
|
public class TestSceneTrianglesBackground : OsuTestScene
|
||||||
|
{
|
||||||
|
private readonly Triangles triangles;
|
||||||
|
|
||||||
|
public TestSceneTrianglesBackground()
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Black
|
||||||
|
},
|
||||||
|
triangles = new Triangles
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
ColourLight = Color4.White,
|
||||||
|
ColourDark = Color4.Gray
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
AddSliderStep("Triangle scale", 0f, 10f, 1f, s => triangles.TriangleScale = s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -163,10 +163,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
AddUntilStep("wait for bars to disappear", () => !this.ChildrenOfType<BarHitErrorMeter.JudgementLine>().Any());
|
AddUntilStep("wait for bars to disappear", () => !this.ChildrenOfType<BarHitErrorMeter.JudgementLine>().Any());
|
||||||
AddUntilStep("ensure max circles not exceeded", () =>
|
AddUntilStep("ensure max circles not exceeded", () =>
|
||||||
{
|
this.ChildrenOfType<ColourHitErrorMeter>().First().ChildrenOfType<ColourHitErrorMeter.HitErrorShape>().Count(), () => Is.LessThanOrEqualTo(max_displayed_judgements));
|
||||||
return this.ChildrenOfType<ColourHitErrorMeter>()
|
|
||||||
.All(m => m.ChildrenOfType<ColourHitErrorMeter.HitErrorShape>().Count() <= max_displayed_judgements);
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep("show displays", () =>
|
AddStep("show displays", () =>
|
||||||
{
|
{
|
||||||
|
@ -436,6 +436,8 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
{
|
{
|
||||||
AddUntilStep("Wait for toolbar to load", () => Game.Toolbar.IsLoaded);
|
AddUntilStep("Wait for toolbar to load", () => Game.Toolbar.IsLoaded);
|
||||||
|
|
||||||
|
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||||
|
|
||||||
TestPlaySongSelect songSelect = null;
|
TestPlaySongSelect songSelect = null;
|
||||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||||
|
|
||||||
|
@ -40,8 +40,10 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
private ChannelManager channelManager;
|
private ChannelManager channelManager;
|
||||||
|
|
||||||
private readonly APIUser testUser = new APIUser { Username = "test user", Id = 5071479 };
|
private readonly APIUser testUser = new APIUser { Username = "test user", Id = 5071479 };
|
||||||
|
private readonly APIUser testUser1 = new APIUser { Username = "test user", Id = 5071480 };
|
||||||
|
|
||||||
private Channel[] testChannels;
|
private Channel[] testChannels;
|
||||||
|
private Message[] initialMessages;
|
||||||
|
|
||||||
private Channel testChannel1 => testChannels[0];
|
private Channel testChannel1 => testChannels[0];
|
||||||
private Channel testChannel2 => testChannels[1];
|
private Channel testChannel2 => testChannels[1];
|
||||||
@ -49,10 +51,14 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuConfigManager config { get; set; } = null!;
|
private OsuConfigManager config { get; set; } = null!;
|
||||||
|
|
||||||
|
private int currentMessageId;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
|
currentMessageId = 0;
|
||||||
testChannels = Enumerable.Range(1, 10).Select(createPublicChannel).ToArray();
|
testChannels = Enumerable.Range(1, 10).Select(createPublicChannel).ToArray();
|
||||||
|
initialMessages = testChannels.SelectMany(createChannelMessages).ToArray();
|
||||||
|
|
||||||
Child = new DependencyProvidingContainer
|
Child = new DependencyProvidingContainer
|
||||||
{
|
{
|
||||||
@ -99,7 +105,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GetMessagesRequest getMessages:
|
case GetMessagesRequest getMessages:
|
||||||
getMessages.TriggerSuccess(createChannelMessages(getMessages.Channel));
|
getMessages.TriggerSuccess(initialMessages.ToList());
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GetUserRequest getUser:
|
case GetUserRequest getUser:
|
||||||
@ -495,6 +501,35 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
waitForChannel1Visible();
|
waitForChannel1Visible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestRemoveMessages()
|
||||||
|
{
|
||||||
|
AddStep("Show overlay with channel", () =>
|
||||||
|
{
|
||||||
|
chatOverlay.Show();
|
||||||
|
channelManager.CurrentChannel.Value = channelManager.JoinChannel(testChannel1);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Overlay is visible", () => chatOverlay.State.Value == Visibility.Visible);
|
||||||
|
waitForChannel1Visible();
|
||||||
|
|
||||||
|
AddStep("Send message from another user", () =>
|
||||||
|
{
|
||||||
|
testChannel1.AddNewMessages(new Message
|
||||||
|
{
|
||||||
|
ChannelId = testChannel1.Id,
|
||||||
|
Content = "Message from another user",
|
||||||
|
Timestamp = DateTimeOffset.Now,
|
||||||
|
Sender = testUser1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Remove messages from other user", () =>
|
||||||
|
{
|
||||||
|
testChannel1.RemoveMessagesFromUser(testUser.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void joinTestChannel(int i)
|
private void joinTestChannel(int i)
|
||||||
{
|
{
|
||||||
AddStep($"Join test channel {i}", () => channelManager.JoinChannel(testChannels[i]));
|
AddStep($"Join test channel {i}", () => channelManager.JoinChannel(testChannels[i]));
|
||||||
@ -546,7 +581,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
private List<Message> createChannelMessages(Channel channel)
|
private List<Message> createChannelMessages(Channel channel)
|
||||||
{
|
{
|
||||||
var message = new Message
|
var message = new Message(currentMessageId++)
|
||||||
{
|
{
|
||||||
ChannelId = channel.Id,
|
ChannelId = channel.Id,
|
||||||
Content = $"Hello, this is a message in {channel.Name}",
|
Content = $"Hello, this is a message in {channel.Name}",
|
||||||
|
@ -1055,6 +1055,18 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
AddUntilStep("mod overlay hidden", () => songSelect!.ModSelect.State.Value == Visibility.Hidden);
|
AddUntilStep("mod overlay hidden", () => songSelect!.ModSelect.State.Value == Visibility.Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBeatmapOptionsDisabled()
|
||||||
|
{
|
||||||
|
createSongSelect();
|
||||||
|
|
||||||
|
addRulesetImportStep(0);
|
||||||
|
|
||||||
|
AddAssert("options enabled", () => songSelect.ChildrenOfType<FooterButtonOptions>().Single().Enabled.Value);
|
||||||
|
AddStep("delete all beatmaps", () => manager.Delete());
|
||||||
|
AddAssert("options disabled", () => !songSelect.ChildrenOfType<FooterButtonOptions>().Single().Enabled.Value);
|
||||||
|
}
|
||||||
|
|
||||||
private void waitForInitialSelection()
|
private void waitForInitialSelection()
|
||||||
{
|
{
|
||||||
AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault);
|
AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault);
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
@ -43,6 +45,12 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
InputManager.MoveMouseTo(Vector2.Zero);
|
InputManager.MoveMouseTo(Vector2.Zero);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestState()
|
||||||
|
{
|
||||||
|
AddRepeatStep("toggle options state", () => this.ChildrenOfType<FooterButton>().Last().Enabled.Toggle(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestFooterRandom()
|
public void TestFooterRandom()
|
||||||
{
|
{
|
||||||
|
@ -59,6 +59,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
return base.OnScroll(e);
|
return base.OnScroll(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool OnClick(ClickEvent e) => true;
|
||||||
|
|
||||||
private class ExpandedContentScrollbar : OsuScrollbar
|
private class ExpandedContentScrollbar : OsuScrollbar
|
||||||
{
|
{
|
||||||
public ExpandedContentScrollbar(Direction scrollDir)
|
public ExpandedContentScrollbar(Direction scrollDir)
|
||||||
|
@ -8,7 +8,7 @@ namespace osu.Game.Configuration
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A settings provider which generally sources from <see cref="OsuConfigManager"/> (global user settings)
|
/// A settings provider which generally sources from <see cref="OsuConfigManager"/> (global user settings)
|
||||||
/// but can allow overriding settings by caching more locally. For instance, in the editor.
|
/// but can allow overriding settings by caching more locally. For instance, in the editor compose screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// More settings can be moved into this interface as required.
|
/// More settings can be moved into this interface as required.
|
||||||
|
@ -17,6 +17,7 @@ using System.Collections.Generic;
|
|||||||
using osu.Framework.Graphics.Rendering;
|
using osu.Framework.Graphics.Rendering;
|
||||||
using osu.Framework.Graphics.Rendering.Vertices;
|
using osu.Framework.Graphics.Rendering.Vertices;
|
||||||
using osu.Framework.Lists;
|
using osu.Framework.Lists;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Backgrounds
|
namespace osu.Game.Graphics.Backgrounds
|
||||||
{
|
{
|
||||||
@ -25,6 +26,11 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
private const float triangle_size = 100;
|
private const float triangle_size = 100;
|
||||||
private const float base_velocity = 50;
|
private const float base_velocity = 50;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sqrt(3) / 2
|
||||||
|
/// </summary>
|
||||||
|
private const float equilateral_triangle_ratio = 0.866f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How many screen-space pixels are smoothed over.
|
/// How many screen-space pixels are smoothed over.
|
||||||
/// Same behavior as Sprite's EdgeSmoothness.
|
/// Same behavior as Sprite's EdgeSmoothness.
|
||||||
@ -69,7 +75,13 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual float SpawnRatio => 1;
|
protected virtual float SpawnRatio => 1;
|
||||||
|
|
||||||
private float triangleScale = 1;
|
private readonly BindableFloat triangleScale = new BindableFloat(1f);
|
||||||
|
|
||||||
|
public float TriangleScale
|
||||||
|
{
|
||||||
|
get => triangleScale.Value;
|
||||||
|
set => triangleScale.Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether we should drop-off alpha values of triangles more quickly to improve
|
/// Whether we should drop-off alpha values of triangles more quickly to improve
|
||||||
@ -103,30 +115,13 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
private void load(IRenderer renderer, ShaderManager shaders)
|
private void load(IRenderer renderer, ShaderManager shaders)
|
||||||
{
|
{
|
||||||
texture = renderer.WhitePixel;
|
texture = renderer.WhitePixel;
|
||||||
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED);
|
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
addTriangles(true);
|
triangleScale.BindValueChanged(_ => Reset(), true);
|
||||||
}
|
|
||||||
|
|
||||||
public float TriangleScale
|
|
||||||
{
|
|
||||||
get => triangleScale;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
float change = value / triangleScale;
|
|
||||||
triangleScale = value;
|
|
||||||
|
|
||||||
for (int i = 0; i < parts.Count; i++)
|
|
||||||
{
|
|
||||||
TriangleParticle newParticle = parts[i];
|
|
||||||
newParticle.Scale *= change;
|
|
||||||
parts[i] = newParticle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
@ -147,7 +142,7 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
// Since position is relative, the velocity needs to scale inversely with DrawHeight.
|
// Since position is relative, the velocity needs to scale inversely with DrawHeight.
|
||||||
// Since we will later multiply by the scale of individual triangles we normalize by
|
// Since we will later multiply by the scale of individual triangles we normalize by
|
||||||
// dividing by triangleScale.
|
// dividing by triangleScale.
|
||||||
float movedDistance = -elapsedSeconds * Velocity * base_velocity / (DrawHeight * triangleScale);
|
float movedDistance = -elapsedSeconds * Velocity * base_velocity / (DrawHeight * TriangleScale);
|
||||||
|
|
||||||
for (int i = 0; i < parts.Count; i++)
|
for (int i = 0; i < parts.Count; i++)
|
||||||
{
|
{
|
||||||
@ -159,7 +154,7 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
|
|
||||||
parts[i] = newParticle;
|
parts[i] = newParticle;
|
||||||
|
|
||||||
float bottomPos = parts[i].Position.Y + triangle_size * parts[i].Scale * 0.866f / DrawHeight;
|
float bottomPos = parts[i].Position.Y + triangle_size * parts[i].Scale * equilateral_triangle_ratio / DrawHeight;
|
||||||
if (bottomPos < 0)
|
if (bottomPos < 0)
|
||||||
parts.RemoveAt(i);
|
parts.RemoveAt(i);
|
||||||
}
|
}
|
||||||
@ -185,9 +180,11 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
// Limited by the maximum size of QuadVertexBuffer for safety.
|
// Limited by the maximum size of QuadVertexBuffer for safety.
|
||||||
const int max_triangles = ushort.MaxValue / (IRenderer.VERTICES_PER_QUAD + 2);
|
const int max_triangles = ushort.MaxValue / (IRenderer.VERTICES_PER_QUAD + 2);
|
||||||
|
|
||||||
AimCount = (int)Math.Min(max_triangles, (DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio));
|
AimCount = (int)Math.Min(max_triangles, DrawWidth * DrawHeight * 0.002f / (TriangleScale * TriangleScale) * SpawnRatio);
|
||||||
|
|
||||||
for (int i = 0; i < AimCount - parts.Count; i++)
|
int currentCount = parts.Count;
|
||||||
|
|
||||||
|
for (int i = 0; i < AimCount - currentCount; i++)
|
||||||
parts.Add(createTriangle(randomY));
|
parts.Add(createTriangle(randomY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,13 +192,27 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
{
|
{
|
||||||
TriangleParticle particle = CreateTriangle();
|
TriangleParticle particle = CreateTriangle();
|
||||||
|
|
||||||
particle.Position = new Vector2(nextRandom(), randomY ? nextRandom() : 1);
|
particle.Position = getRandomPosition(randomY, particle.Scale);
|
||||||
particle.ColourShade = nextRandom();
|
particle.ColourShade = nextRandom();
|
||||||
particle.Colour = CreateTriangleShade(particle.ColourShade);
|
particle.Colour = CreateTriangleShade(particle.ColourShade);
|
||||||
|
|
||||||
return particle;
|
return particle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Vector2 getRandomPosition(bool randomY, float scale)
|
||||||
|
{
|
||||||
|
float y = 1;
|
||||||
|
|
||||||
|
if (randomY)
|
||||||
|
{
|
||||||
|
// since triangles are drawn from the top - allow them to be positioned a bit above the screen
|
||||||
|
float maxOffset = triangle_size * scale * equilateral_triangle_ratio / DrawHeight;
|
||||||
|
y = Interpolation.ValueAt(nextRandom(), -maxOffset, 1f, 0f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Vector2(nextRandom(), y);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a triangle particle with a random scale.
|
/// Creates a triangle particle with a random scale.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -214,7 +225,7 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
float u1 = 1 - nextRandom(); //uniform(0,1] random floats
|
float u1 = 1 - nextRandom(); //uniform(0,1] random floats
|
||||||
float u2 = 1 - nextRandom();
|
float u2 = 1 - nextRandom();
|
||||||
float randStdNormal = (float)(Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2)); // random normal(0,1)
|
float randStdNormal = (float)(Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2)); // random normal(0,1)
|
||||||
float scale = Math.Max(triangleScale * (mean + std_dev * randStdNormal), 0.1f); // random normal(mean,stdDev^2)
|
float scale = Math.Max(TriangleScale * (mean + std_dev * randStdNormal), 0.1f); // random normal(mean,stdDev^2)
|
||||||
|
|
||||||
return new TriangleParticle { Scale = scale };
|
return new TriangleParticle { Scale = scale };
|
||||||
}
|
}
|
||||||
@ -284,7 +295,7 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
|
|
||||||
foreach (TriangleParticle particle in parts)
|
foreach (TriangleParticle particle in parts)
|
||||||
{
|
{
|
||||||
var offset = triangle_size * new Vector2(particle.Scale * 0.5f, particle.Scale * 0.866f);
|
var offset = triangle_size * new Vector2(particle.Scale * 0.5f, particle.Scale * equilateral_triangle_ratio);
|
||||||
|
|
||||||
var triangle = new Triangle(
|
var triangle = new Triangle(
|
||||||
Vector2Extensions.Transform(particle.Position * size, DrawInfo.Matrix),
|
Vector2Extensions.Transform(particle.Position * size, DrawInfo.Matrix),
|
||||||
|
@ -17,7 +17,6 @@ namespace osu.Game.Graphics.Sprites
|
|||||||
private void load(ShaderManager shaders)
|
private void load(ShaderManager shaders)
|
||||||
{
|
{
|
||||||
TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, @"LogoAnimation");
|
TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, @"LogoAnimation");
|
||||||
RoundedTextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, @"LogoAnimation"); // Masking isn't supported for now
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private float animationProgress;
|
private float animationProgress;
|
||||||
@ -58,7 +57,7 @@ namespace osu.Game.Graphics.Sprites
|
|||||||
|
|
||||||
protected override void Blit(IRenderer renderer)
|
protected override void Blit(IRenderer renderer)
|
||||||
{
|
{
|
||||||
GetAppropriateShader(renderer).GetUniform<float>("progress").UpdateValue(ref progress);
|
TextureShader.GetUniform<float>("progress").UpdateValue(ref progress);
|
||||||
|
|
||||||
base.Blit(renderer);
|
base.Blit(renderer);
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,30 @@ using osu.Game.Online.API.Requests.Responses;
|
|||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.API.Requests
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A request which should be sent occasionally while interested in chat and online state.
|
||||||
|
///
|
||||||
|
/// This will:
|
||||||
|
/// - Mark the user as "online" (for 10 minutes since the last invocation).
|
||||||
|
/// - Return any silences since the last invocation (if either <see cref="SinceMessageId"/> or <see cref="SinceSilenceId"/> is not null).
|
||||||
|
///
|
||||||
|
/// For silence handling, a <see cref="SinceMessageId"/> should be provided as soon as a message is received by the client.
|
||||||
|
/// From that point forward, <see cref="SinceSilenceId"/> should be preferred after the first <see cref="ChatSilence"/>
|
||||||
|
/// arrives in a response from the ack request. Specifying both parameters will prioritise the latter.
|
||||||
|
/// </summary>
|
||||||
public class ChatAckRequest : APIRequest<ChatAckResponse>
|
public class ChatAckRequest : APIRequest<ChatAckResponse>
|
||||||
{
|
{
|
||||||
|
public long? SinceMessageId;
|
||||||
|
public uint? SinceSilenceId;
|
||||||
|
|
||||||
protected override WebRequest CreateWebRequest()
|
protected override WebRequest CreateWebRequest()
|
||||||
{
|
{
|
||||||
var req = base.CreateWebRequest();
|
var req = base.CreateWebRequest();
|
||||||
req.Method = HttpMethod.Post;
|
req.Method = HttpMethod.Post;
|
||||||
|
if (SinceMessageId != null)
|
||||||
|
req.AddParameter(@"since", SinceMessageId.ToString());
|
||||||
|
if (SinceSilenceId != null)
|
||||||
|
req.AddParameter(@"history_since", SinceSilenceId.Value.ToString());
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,6 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
public uint Id { get; set; }
|
public uint Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("user_id")]
|
[JsonProperty("user_id")]
|
||||||
public uint UserId { get; set; }
|
public int UserId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +157,20 @@ namespace osu.Game.Online.Chat
|
|||||||
NewMessagesArrived?.Invoke(messages);
|
NewMessagesArrived?.Invoke(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RemoveMessagesFromUser(int userId)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Messages.Count; i++)
|
||||||
|
{
|
||||||
|
var message = Messages[i];
|
||||||
|
|
||||||
|
if (message.SenderId == userId)
|
||||||
|
{
|
||||||
|
Messages.RemoveAt(i--);
|
||||||
|
MessageRemoved?.Invoke(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Replace or remove a message from the channel.
|
/// Replace or remove a message from the channel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -74,6 +74,9 @@ namespace osu.Game.Online.Chat
|
|||||||
private bool channelsInitialised;
|
private bool channelsInitialised;
|
||||||
private ScheduledDelegate scheduledAck;
|
private ScheduledDelegate scheduledAck;
|
||||||
|
|
||||||
|
private long? lastSilenceMessageId;
|
||||||
|
private uint? lastSilenceId;
|
||||||
|
|
||||||
public ChannelManager(IAPIProvider api)
|
public ChannelManager(IAPIProvider api)
|
||||||
{
|
{
|
||||||
this.api = api;
|
this.api = api;
|
||||||
@ -105,28 +108,7 @@ namespace osu.Game.Online.Chat
|
|||||||
connector.Start();
|
connector.Start();
|
||||||
|
|
||||||
apiState.BindTo(api.State);
|
apiState.BindTo(api.State);
|
||||||
apiState.BindValueChanged(_ => performChatAckRequest(), true);
|
apiState.BindValueChanged(_ => SendAck(), true);
|
||||||
}
|
|
||||||
|
|
||||||
private void performChatAckRequest()
|
|
||||||
{
|
|
||||||
if (apiState.Value != APIState.Online)
|
|
||||||
return;
|
|
||||||
|
|
||||||
scheduledAck?.Cancel();
|
|
||||||
|
|
||||||
var req = new ChatAckRequest();
|
|
||||||
req.Success += _ => scheduleNextRequest();
|
|
||||||
req.Failure += _ => scheduleNextRequest();
|
|
||||||
api.Queue(req);
|
|
||||||
|
|
||||||
// Todo: Handle silences.
|
|
||||||
|
|
||||||
void scheduleNextRequest()
|
|
||||||
{
|
|
||||||
scheduledAck?.Cancel();
|
|
||||||
scheduledAck = Scheduler.AddDelayed(performChatAckRequest, 60000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -349,6 +331,8 @@ namespace osu.Game.Online.Chat
|
|||||||
|
|
||||||
foreach (var group in messages.GroupBy(m => m.ChannelId))
|
foreach (var group in messages.GroupBy(m => m.ChannelId))
|
||||||
channels.Find(c => c.Id == group.Key)?.AddNewMessages(group.ToArray());
|
channels.Find(c => c.Id == group.Key)?.AddNewMessages(group.ToArray());
|
||||||
|
|
||||||
|
lastSilenceMessageId ??= messages.LastOrDefault()?.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeChannels()
|
private void initializeChannels()
|
||||||
@ -398,6 +382,44 @@ namespace osu.Game.Online.Chat
|
|||||||
api.Queue(fetchInitialMsgReq);
|
api.Queue(fetchInitialMsgReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends an acknowledgement request to the API.
|
||||||
|
/// This marks the user as online to receive messages from public channels, while also returning a list of silenced users.
|
||||||
|
/// It needs to be called at least once every 10 minutes to remain visibly marked as online.
|
||||||
|
/// </summary>
|
||||||
|
public void SendAck()
|
||||||
|
{
|
||||||
|
if (apiState.Value != APIState.Online)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var req = new ChatAckRequest
|
||||||
|
{
|
||||||
|
SinceMessageId = lastSilenceMessageId,
|
||||||
|
SinceSilenceId = lastSilenceId
|
||||||
|
};
|
||||||
|
|
||||||
|
req.Failure += _ => scheduleNextRequest();
|
||||||
|
req.Success += ack =>
|
||||||
|
{
|
||||||
|
foreach (var silence in ack.Silences)
|
||||||
|
{
|
||||||
|
foreach (var channel in JoinedChannels)
|
||||||
|
channel.RemoveMessagesFromUser(silence.UserId);
|
||||||
|
lastSilenceId = Math.Max(lastSilenceId ?? 0, silence.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduleNextRequest();
|
||||||
|
};
|
||||||
|
|
||||||
|
api.Queue(req);
|
||||||
|
|
||||||
|
void scheduleNextRequest()
|
||||||
|
{
|
||||||
|
scheduledAck?.Cancel();
|
||||||
|
scheduledAck = Scheduler.AddDelayed(SendAck, 60000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Find an existing channel instance for the provided channel. Lookup is performed basd on ID.
|
/// Find an existing channel instance for the provided channel. Lookup is performed basd on ID.
|
||||||
/// The provided channel may be used if an existing instance is not found.
|
/// The provided channel may be used if an existing instance is not found.
|
||||||
|
@ -72,7 +72,6 @@ namespace osu.Game.Online.Notifications.WebSocket
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Log($"{GetType().ReadableName()} handling event: {message.Event}");
|
|
||||||
await onMessageReceivedAsync(message);
|
await onMessageReceivedAsync(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,11 +41,8 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
private IBindable<APIUser> apiUser;
|
private IBindable<APIUser> apiUser;
|
||||||
|
|
||||||
private Drawable currentContent;
|
|
||||||
private Container panelTarget;
|
private Container panelTarget;
|
||||||
private FillFlowContainer<BeatmapCard> foundContent;
|
private FillFlowContainer<BeatmapCard> foundContent;
|
||||||
private NotFoundDrawable notFoundContent;
|
|
||||||
private SupporterRequiredDrawable supporterRequiredContent;
|
|
||||||
private BeatmapListingFilterControl filterControl;
|
private BeatmapListingFilterControl filterControl;
|
||||||
|
|
||||||
public BeatmapListingOverlay()
|
public BeatmapListingOverlay()
|
||||||
@ -86,11 +83,6 @@ namespace osu.Game.Overlays
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Padding = new MarginPadding { Horizontal = 20 },
|
Padding = new MarginPadding { Horizontal = 20 },
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
notFoundContent = new NotFoundDrawable(),
|
|
||||||
supporterRequiredContent = new SupporterRequiredDrawable(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -107,7 +99,7 @@ namespace osu.Game.Overlays
|
|||||||
apiUser.BindValueChanged(_ => Schedule(() =>
|
apiUser.BindValueChanged(_ => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (api.IsLoggedIn)
|
if (api.IsLoggedIn)
|
||||||
addContentToResultsArea(Drawable.Empty());
|
replaceResultsAreaContent(Drawable.Empty());
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,8 +147,8 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
if (searchResult.Type == BeatmapListingFilterControl.SearchResultType.SupporterOnlyFilters)
|
if (searchResult.Type == BeatmapListingFilterControl.SearchResultType.SupporterOnlyFilters)
|
||||||
{
|
{
|
||||||
supporterRequiredContent.UpdateText(searchResult.SupporterOnlyFiltersUsed);
|
var supporterOnly = new SupporterRequiredDrawable(searchResult.SupporterOnlyFiltersUsed);
|
||||||
addContentToResultsArea(supporterRequiredContent);
|
replaceResultsAreaContent(supporterOnly);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,13 +159,13 @@ namespace osu.Game.Overlays
|
|||||||
//No matches case
|
//No matches case
|
||||||
if (!newCards.Any())
|
if (!newCards.Any())
|
||||||
{
|
{
|
||||||
addContentToResultsArea(notFoundContent);
|
replaceResultsAreaContent(new NotFoundDrawable());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var content = createCardContainerFor(newCards);
|
var content = createCardContainerFor(newCards);
|
||||||
|
|
||||||
panelLoadTask = LoadComponentAsync(foundContent = content, addContentToResultsArea, (cancellationToken = new CancellationTokenSource()).Token);
|
panelLoadTask = LoadComponentAsync(foundContent = content, replaceResultsAreaContent, (cancellationToken = new CancellationTokenSource()).Token);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -221,36 +213,16 @@ namespace osu.Game.Overlays
|
|||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addContentToResultsArea(Drawable content)
|
private void replaceResultsAreaContent(Drawable content)
|
||||||
{
|
{
|
||||||
Loading.Hide();
|
Loading.Hide();
|
||||||
lastFetchDisplayedTime = Time.Current;
|
lastFetchDisplayedTime = Time.Current;
|
||||||
|
|
||||||
if (content == currentContent)
|
panelTarget.Child = content;
|
||||||
return;
|
|
||||||
|
|
||||||
var lastContent = currentContent;
|
|
||||||
|
|
||||||
if (lastContent != null)
|
|
||||||
{
|
|
||||||
lastContent.FadeOut();
|
|
||||||
if (!isPlaceholderContent(lastContent))
|
|
||||||
lastContent.Expire();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!content.IsAlive)
|
|
||||||
panelTarget.Add(content);
|
|
||||||
|
|
||||||
content.FadeInFromZero();
|
content.FadeInFromZero();
|
||||||
currentContent = content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether <paramref name="drawable"/> is a static placeholder reused multiple times by this overlay.
|
|
||||||
/// </summary>
|
|
||||||
private bool isPlaceholderContent(Drawable drawable)
|
|
||||||
=> drawable == notFoundContent || drawable == supporterRequiredContent;
|
|
||||||
|
|
||||||
private void onCardSizeChanged()
|
private void onCardSizeChanged()
|
||||||
{
|
{
|
||||||
if (foundContent?.IsAlive != true || !foundContent.Any())
|
if (foundContent?.IsAlive != true || !foundContent.Any())
|
||||||
@ -287,7 +259,7 @@ namespace osu.Game.Overlays
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
AddInternal(new FillFlowContainer
|
AddInternal(new FillFlowContainer
|
||||||
{
|
{
|
||||||
@ -324,15 +296,19 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
private LinkFlowContainer supporterRequiredText;
|
private LinkFlowContainer supporterRequiredText;
|
||||||
|
|
||||||
public SupporterRequiredDrawable()
|
private readonly List<LocalisableString> filtersUsed;
|
||||||
|
|
||||||
|
public SupporterRequiredDrawable(List<LocalisableString> filtersUsed)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Height = 225;
|
Height = 225;
|
||||||
Alpha = 0;
|
Alpha = 0;
|
||||||
|
|
||||||
|
this.filtersUsed = filtersUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
AddInternal(new FillFlowContainer
|
AddInternal(new FillFlowContainer
|
||||||
{
|
{
|
||||||
@ -360,14 +336,9 @@ namespace osu.Game.Overlays
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateText(List<LocalisableString> filters)
|
|
||||||
{
|
|
||||||
supporterRequiredText.Clear();
|
|
||||||
|
|
||||||
supporterRequiredText.AddText(
|
supporterRequiredText.AddText(
|
||||||
BeatmapsStrings.ListingSearchSupporterFilterQuoteDefault(string.Join(" and ", filters), "").ToString(),
|
BeatmapsStrings.ListingSearchSupporterFilterQuoteDefault(string.Join(" and ", filtersUsed), "").ToString(),
|
||||||
t =>
|
t =>
|
||||||
{
|
{
|
||||||
t.Font = OsuFont.GetFont(size: 16);
|
t.Font = OsuFont.GetFont(size: 16);
|
||||||
|
@ -119,22 +119,17 @@ namespace osu.Game.Overlays.Dashboard.Home.News
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(GameHost host)
|
private void load(GameHost host)
|
||||||
{
|
{
|
||||||
NewsPostBackground bg;
|
Child = new DelayedLoadUnloadWrapper(() => new NewsPostBackground(post.FirstImage)
|
||||||
|
|
||||||
Child = new DelayedLoadWrapper(bg = new NewsPostBackground(post.FirstImage)
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fill,
|
FillMode = FillMode.Fill,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Alpha = 0
|
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
};
|
};
|
||||||
|
|
||||||
bg.OnLoadComplete += d => d.FadeIn(250, Easing.In);
|
|
||||||
|
|
||||||
TooltipText = "view in browser";
|
TooltipText = "view in browser";
|
||||||
Action = () => host.OpenUrlExternally("https://osu.ppy.sh/home/news/" + post.Slug);
|
Action = () => host.OpenUrlExternally("https://osu.ppy.sh/home/news/" + post.Slug);
|
||||||
|
|
||||||
|
@ -49,7 +49,6 @@ namespace osu.Game.Overlays.News
|
|||||||
Action = () => host.OpenUrlExternally("https://osu.ppy.sh/home/news/" + post.Slug);
|
Action = () => host.OpenUrlExternally("https://osu.ppy.sh/home/news/" + post.Slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
NewsPostBackground bg;
|
|
||||||
AddRange(new Drawable[]
|
AddRange(new Drawable[]
|
||||||
{
|
{
|
||||||
background = new Box
|
background = new Box
|
||||||
@ -71,14 +70,14 @@ namespace osu.Game.Overlays.News
|
|||||||
CornerRadius = 6,
|
CornerRadius = 6,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new DelayedLoadWrapper(bg = new NewsPostBackground(post.FirstImage)
|
new DelayedLoadUnloadWrapper(() => new NewsPostBackground(post.FirstImage)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fill,
|
FillMode = FillMode.Fill,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Alpha = 0
|
Alpha = 0
|
||||||
})
|
}, timeBeforeUnload: 5000)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
},
|
},
|
||||||
@ -116,8 +115,6 @@ namespace osu.Game.Overlays.News
|
|||||||
IdleColour = colourProvider.Background4;
|
IdleColour = colourProvider.Background4;
|
||||||
HoverColour = colourProvider.Background3;
|
HoverColour = colourProvider.Background3;
|
||||||
|
|
||||||
bg.OnLoadComplete += d => d.FadeIn(250, Easing.In);
|
|
||||||
|
|
||||||
main.AddParagraph(post.Title, t => t.Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold));
|
main.AddParagraph(post.Title, t => t.Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold));
|
||||||
main.AddParagraph(post.Preview, t => t.Font = OsuFont.GetFont(size: 12)); // Should use sans-serif font
|
main.AddParagraph(post.Preview, t => t.Font = OsuFont.GetFont(size: 12)); // Should use sans-serif font
|
||||||
main.AddParagraph("by ", t => t.Font = OsuFont.GetFont(size: 12));
|
main.AddParagraph("by ", t => t.Font = OsuFont.GetFont(size: 12));
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
|
|
||||||
@ -25,6 +26,12 @@ namespace osu.Game.Overlays.News
|
|||||||
Texture = store.Get(createUrl(sourceUrl));
|
Texture = store.Get(createUrl(sourceUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
this.FadeInFromZero(500, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
private string createUrl(string source)
|
private string createUrl(string source)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(source))
|
if (string.IsNullOrEmpty(source))
|
||||||
|
@ -100,7 +100,7 @@ namespace osu.Game.Overlays
|
|||||||
},
|
},
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
background = new Background(),
|
background = Empty(),
|
||||||
title = new OsuSpriteText
|
title = new OsuSpriteText
|
||||||
{
|
{
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
@ -413,7 +413,7 @@ namespace osu.Game.Overlays
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4");
|
sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4");
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Overlays
|
|||||||
Height = 80;
|
Height = 80;
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
InternalChild = new Background(textureName);
|
InternalChild = new DelayedLoadWrapper(() => new Background(textureName));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Background : Sprite
|
private class Background : Sprite
|
||||||
@ -36,10 +36,16 @@ namespace osu.Game.Overlays
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
Texture = textures.Get(textureName);
|
Texture = textures.Get(textureName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
this.FadeInFromZero(500, Easing.OutQuint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Localisation;
|
using osu.Game.Localisation;
|
||||||
@ -13,6 +15,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
{
|
{
|
||||||
protected override LocalisableString Header => BindingSettingsStrings.ShortcutAndGameplayBindings;
|
protected override LocalisableString Header => BindingSettingsStrings.ShortcutAndGameplayBindings;
|
||||||
|
|
||||||
|
public override IEnumerable<LocalisableString> FilterTerms => base.FilterTerms.Concat(new LocalisableString[] { "keybindings" });
|
||||||
|
|
||||||
public BindingSettings(KeyBindingPanel keyConfig)
|
public BindingSettings(KeyBindingPanel keyConfig)
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
|
@ -111,9 +111,10 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows || RuntimeInfo.OS == RuntimeInfo.Platform.Linux)
|
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows || RuntimeInfo.OS == RuntimeInfo.Platform.Linux)
|
||||||
{
|
{
|
||||||
t.NewLine();
|
t.NewLine();
|
||||||
var formattedSource = MessageFormatter.FormatText(localisation.GetLocalisedBindableString(TabletSettingsStrings.NoTabletDetectedDescription(RuntimeInfo.OS == RuntimeInfo.Platform.Windows
|
var formattedSource = MessageFormatter.FormatText(localisation.GetLocalisedBindableString(TabletSettingsStrings.NoTabletDetectedDescription(
|
||||||
? @"https://opentabletdriver.net/Wiki/FAQ/Windows"
|
RuntimeInfo.OS == RuntimeInfo.Platform.Windows
|
||||||
: @"https://opentabletdriver.net/Wiki/FAQ/Linux")).Value);
|
? @"https://opentabletdriver.net/Wiki/FAQ/Windows"
|
||||||
|
: @"https://opentabletdriver.net/Wiki/FAQ/Linux")).Value);
|
||||||
t.AddLinks(formattedSource.Text, formattedSource.Links);
|
t.AddLinks(formattedSource.Text, formattedSource.Links);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@ -274,6 +275,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
sizeY.Default = sizeY.MaxValue = tab.Size.Y;
|
sizeY.Default = sizeY.MaxValue = tab.Size.Y;
|
||||||
|
|
||||||
areaSize.Default = new Vector2(sizeX.Default, sizeY.Default);
|
areaSize.Default = new Vector2(sizeX.Default, sizeY.Default);
|
||||||
|
areaOffset.Default = new Vector2(offsetX.Default, offsetY.Default);
|
||||||
}), true);
|
}), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
@ -22,8 +20,6 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
|
|
||||||
public override LocalisableString Header => InputSettingsStrings.InputSectionHeader;
|
public override LocalisableString Header => InputSettingsStrings.InputSectionHeader;
|
||||||
|
|
||||||
public override IEnumerable<LocalisableString> FilterTerms => base.FilterTerms.Concat(new LocalisableString[] { "keybindings" });
|
|
||||||
|
|
||||||
public override Drawable CreateIcon() => new SpriteIcon
|
public override Drawable CreateIcon() => new SpriteIcon
|
||||||
{
|
{
|
||||||
Icon = FontAwesome.Solid.Keyboard
|
Icon = FontAwesome.Solid.Keyboard
|
||||||
|
@ -115,7 +115,11 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
public Sample Get(string name) => primary.Get(name) ?? fallback.Get(name);
|
public Sample Get(string name) => primary.Get(name) ?? fallback.Get(name);
|
||||||
|
|
||||||
public Task<Sample> GetAsync(string name, CancellationToken cancellationToken = default) => primary.GetAsync(name, cancellationToken) ?? fallback.GetAsync(name, cancellationToken);
|
public async Task<Sample> GetAsync(string name, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return await primary.GetAsync(name, cancellationToken).ConfigureAwait(false)
|
||||||
|
?? await fallback.GetAsync(name, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
public Stream GetStream(string name) => primary.GetStream(name) ?? fallback.GetStream(name);
|
public Stream GetStream(string name) => primary.GetStream(name) ?? fallback.GetStream(name);
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Extensions;
|
using osu.Game.Extensions;
|
||||||
using osu.Game.IO.Serialization;
|
using osu.Game.IO.Serialization;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -19,7 +20,7 @@ using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Compose
|
namespace osu.Game.Screens.Edit.Compose
|
||||||
{
|
{
|
||||||
public class ComposeScreen : EditorScreenWithTimeline
|
public class ComposeScreen : EditorScreenWithTimeline, IGameplaySettings
|
||||||
{
|
{
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private GameHost host { get; set; }
|
private GameHost host { get; set; }
|
||||||
@ -27,6 +28,9 @@ namespace osu.Game.Screens.Edit.Compose
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private EditorClock clock { get; set; }
|
private EditorClock clock { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IGameplaySettings globalGameplaySettings { get; set; }
|
||||||
|
|
||||||
private Bindable<string> clipboard { get; set; }
|
private Bindable<string> clipboard { get; set; }
|
||||||
|
|
||||||
private HitObjectComposer composer;
|
private HitObjectComposer composer;
|
||||||
@ -157,5 +161,12 @@ namespace osu.Game.Screens.Edit.Compose
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
// Combo colour normalisation should not be applied in the editor.
|
||||||
|
// Note this doesn't affect editor test mode.
|
||||||
|
IBindable<float> IGameplaySettings.ComboColourNormalisationAmount => new Bindable<float>();
|
||||||
|
|
||||||
|
// Arguable.
|
||||||
|
IBindable<float> IGameplaySettings.PositionalHitsoundsLevel => globalGameplaySettings.PositionalHitsoundsLevel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,8 +58,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
{
|
{
|
||||||
[Cached(typeof(IBeatSnapProvider))]
|
[Cached(typeof(IBeatSnapProvider))]
|
||||||
[Cached]
|
[Cached]
|
||||||
public class Editor : ScreenWithBeatmapBackground, IKeyBindingHandler<GlobalAction>, IKeyBindingHandler<PlatformAction>, IBeatSnapProvider, ISamplePlaybackDisabler, IBeatSyncProvider,
|
public class Editor : ScreenWithBeatmapBackground, IKeyBindingHandler<GlobalAction>, IKeyBindingHandler<PlatformAction>, IBeatSnapProvider, ISamplePlaybackDisabler, IBeatSyncProvider
|
||||||
IGameplaySettings
|
|
||||||
{
|
{
|
||||||
public override float BackgroundParallaxAmount => 0.1f;
|
public override float BackgroundParallaxAmount => 0.1f;
|
||||||
|
|
||||||
@ -99,9 +98,6 @@ namespace osu.Game.Screens.Edit
|
|||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private INotificationOverlay notifications { get; set; }
|
private INotificationOverlay notifications { get; set; }
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private IGameplaySettings globalGameplaySettings { get; set; }
|
|
||||||
|
|
||||||
public readonly Bindable<EditorScreenMode> Mode = new Bindable<EditorScreenMode>();
|
public readonly Bindable<EditorScreenMode> Mode = new Bindable<EditorScreenMode>();
|
||||||
|
|
||||||
public IBindable<bool> SamplePlaybackDisabled => samplePlaybackDisabled;
|
public IBindable<bool> SamplePlaybackDisabled => samplePlaybackDisabled;
|
||||||
@ -1045,11 +1041,5 @@ namespace osu.Game.Screens.Edit
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combo colour normalisation should not be applied in the editor.
|
|
||||||
IBindable<float> IGameplaySettings.ComboColourNormalisationAmount => new Bindable<float>();
|
|
||||||
|
|
||||||
// Arguable.
|
|
||||||
IBindable<float> IGameplaySettings.PositionalHitsoundsLevel => globalGameplaySettings.PositionalHitsoundsLevel;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
using System.Linq;
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -17,7 +16,7 @@ namespace osu.Game.Screens.Edit.GameplayTest
|
|||||||
private readonly EditorState editorState;
|
private readonly EditorState editorState;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private MusicController musicController { get; set; }
|
private MusicController musicController { get; set; } = null!;
|
||||||
|
|
||||||
public EditorPlayer(Editor editor)
|
public EditorPlayer(Editor editor)
|
||||||
: base(new PlayerConfiguration { ShowResults = false })
|
: base(new PlayerConfiguration { ShowResults = false })
|
||||||
@ -29,7 +28,12 @@ namespace osu.Game.Screens.Edit.GameplayTest
|
|||||||
protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart)
|
protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart)
|
||||||
{
|
{
|
||||||
var masterGameplayClockContainer = new MasterGameplayClockContainer(beatmap, gameplayStart);
|
var masterGameplayClockContainer = new MasterGameplayClockContainer(beatmap, gameplayStart);
|
||||||
masterGameplayClockContainer.Reset(editorState.Time);
|
|
||||||
|
// Only reset the time to the current point if the editor is later than the normal start time (and the first object).
|
||||||
|
// This allows more sane test playing from the start of the beatmap (ie. correctly adding lead-in time).
|
||||||
|
if (editorState.Time > gameplayStart && editorState.Time > DrawableRuleset.Objects.FirstOrDefault()?.StartTime)
|
||||||
|
masterGameplayClockContainer.Reset(editorState.Time);
|
||||||
|
|
||||||
return masterGameplayClockContainer;
|
return masterGameplayClockContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,13 +125,11 @@ namespace osu.Game.Screens
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ShaderManager manager)
|
private void load(ShaderManager manager)
|
||||||
{
|
{
|
||||||
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED));
|
|
||||||
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.BLUR));
|
|
||||||
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE));
|
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE));
|
||||||
|
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.BLUR));
|
||||||
|
|
||||||
loadTargets.Add(manager.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE));
|
loadTargets.Add(manager.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE));
|
||||||
|
|
||||||
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE_ROUNDED));
|
|
||||||
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE));
|
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,8 +224,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
{
|
{
|
||||||
rulesetsScale.ScaleTo(0.8f, 1000);
|
rulesetsScale.ScaleTo(0.8f, 1000);
|
||||||
rulesets.FadeIn().ScaleTo(1).TransformSpacingTo(new Vector2(200, 0));
|
rulesets.FadeIn().ScaleTo(1).TransformSpacingTo(new Vector2(200, 0));
|
||||||
welcomeText.FadeOut();
|
welcomeText.FadeOut().Expire();
|
||||||
triangles.FadeOut();
|
triangles.FadeOut().Expire();
|
||||||
}
|
}
|
||||||
|
|
||||||
using (BeginDelayedSequence(rulesets_2))
|
using (BeginDelayedSequence(rulesets_2))
|
||||||
@ -307,7 +307,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
|
@ -89,7 +89,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
private void load(IRenderer renderer, ShaderManager shaders)
|
private void load(IRenderer renderer, ShaderManager shaders)
|
||||||
{
|
{
|
||||||
texture = renderer.WhitePixel;
|
texture = renderer.WhitePixel;
|
||||||
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED);
|
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly float[] temporalAmplitudes = new float[ChannelAmplitudes.AMPLITUDES_SIZE];
|
private readonly float[] temporalAmplitudes = new float[ChannelAmplitudes.AMPLITUDES_SIZE];
|
||||||
|
@ -1,8 +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.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -11,6 +9,7 @@ using osu.Framework.Extensions.Color4Extensions;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Colour;
|
using osu.Framework.Graphics.Colour;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
@ -23,10 +22,9 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
||||||
{
|
{
|
||||||
|
[Cached]
|
||||||
public class BarHitErrorMeter : HitErrorMeter
|
public class BarHitErrorMeter : HitErrorMeter
|
||||||
{
|
{
|
||||||
private const int judgement_line_width = 14;
|
|
||||||
|
|
||||||
[SettingSource("Judgement line thickness", "How thick the individual lines should be.")]
|
[SettingSource("Judgement line thickness", "How thick the individual lines should be.")]
|
||||||
public BindableNumber<float> JudgementLineThickness { get; } = new BindableNumber<float>(4)
|
public BindableNumber<float> JudgementLineThickness { get; } = new BindableNumber<float>(4)
|
||||||
{
|
{
|
||||||
@ -44,28 +42,33 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
[SettingSource("Label style", "How to show early/late extremities")]
|
[SettingSource("Label style", "How to show early/late extremities")]
|
||||||
public Bindable<LabelStyles> LabelStyle { get; } = new Bindable<LabelStyles>(LabelStyles.Icons);
|
public Bindable<LabelStyles> LabelStyle { get; } = new Bindable<LabelStyles>(LabelStyles.Icons);
|
||||||
|
|
||||||
private SpriteIcon arrow;
|
private const int judgement_line_width = 14;
|
||||||
private UprightAspectMaintainingContainer labelEarly;
|
|
||||||
private UprightAspectMaintainingContainer labelLate;
|
|
||||||
|
|
||||||
private Container colourBarsEarly;
|
private const int max_concurrent_judgements = 50;
|
||||||
private Container colourBarsLate;
|
|
||||||
|
|
||||||
private Container judgementsContainer;
|
private const int centre_marker_size = 8;
|
||||||
|
|
||||||
private double maxHitWindow;
|
private double maxHitWindow;
|
||||||
|
|
||||||
private double floatingAverage;
|
private double floatingAverage;
|
||||||
private Container colourBars;
|
|
||||||
private Container arrowContainer;
|
|
||||||
|
|
||||||
private (HitResult result, double length)[] hitWindows;
|
private readonly DrawablePool<JudgementLine> judgementLinePool = new DrawablePool<JudgementLine>(50);
|
||||||
|
|
||||||
private const int max_concurrent_judgements = 50;
|
private SpriteIcon arrow = null!;
|
||||||
|
private UprightAspectMaintainingContainer labelEarly = null!;
|
||||||
|
private UprightAspectMaintainingContainer labelLate = null!;
|
||||||
|
|
||||||
private Drawable[] centreMarkerDrawables;
|
private Container colourBarsEarly = null!;
|
||||||
|
private Container colourBarsLate = null!;
|
||||||
|
|
||||||
private const int centre_marker_size = 8;
|
private Container judgementsContainer = null!;
|
||||||
|
|
||||||
|
private Container colourBars = null!;
|
||||||
|
private Container arrowContainer = null!;
|
||||||
|
|
||||||
|
private (HitResult result, double length)[] hitWindows = null!;
|
||||||
|
|
||||||
|
private Drawable[]? centreMarkerDrawables;
|
||||||
|
|
||||||
public BarHitErrorMeter()
|
public BarHitErrorMeter()
|
||||||
{
|
{
|
||||||
@ -88,6 +91,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
Margin = new MarginPadding(2),
|
Margin = new MarginPadding(2),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
|
judgementLinePool,
|
||||||
colourBars = new Container
|
colourBars = new Container
|
||||||
{
|
{
|
||||||
Name = "colour axis",
|
Name = "colour axis",
|
||||||
@ -403,11 +407,12 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
judgementsContainer.Add(new JudgementLine
|
judgementLinePool.Get(drawableJudgement =>
|
||||||
{
|
{
|
||||||
JudgementLineThickness = { BindTarget = JudgementLineThickness },
|
drawableJudgement.Y = getRelativeJudgementPosition(judgement.TimeOffset);
|
||||||
Y = getRelativeJudgementPosition(judgement.TimeOffset),
|
drawableJudgement.Colour = GetColourForHitResult(judgement.Type);
|
||||||
Colour = GetColourForHitResult(judgement.Type),
|
|
||||||
|
judgementsContainer.Add(drawableJudgement);
|
||||||
});
|
});
|
||||||
|
|
||||||
arrow.MoveToY(
|
arrow.MoveToY(
|
||||||
@ -417,10 +422,13 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
|
|
||||||
private float getRelativeJudgementPosition(double value) => Math.Clamp((float)((value / maxHitWindow) + 1) / 2, 0, 1);
|
private float getRelativeJudgementPosition(double value) => Math.Clamp((float)((value / maxHitWindow) + 1) / 2, 0, 1);
|
||||||
|
|
||||||
internal class JudgementLine : CompositeDrawable
|
internal class JudgementLine : PoolableDrawable
|
||||||
{
|
{
|
||||||
public readonly BindableNumber<float> JudgementLineThickness = new BindableFloat();
|
public readonly BindableNumber<float> JudgementLineThickness = new BindableFloat();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private BarHitErrorMeter barHitErrorMeter { get; set; } = null!;
|
||||||
|
|
||||||
public JudgementLine()
|
public JudgementLine()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
@ -439,16 +447,22 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
JudgementLineThickness.BindTo(barHitErrorMeter.JudgementLineThickness);
|
||||||
|
JudgementLineThickness.BindValueChanged(thickness => Height = thickness.NewValue, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PrepareForUse()
|
||||||
|
{
|
||||||
|
base.PrepareForUse();
|
||||||
|
|
||||||
const int judgement_fade_in_duration = 100;
|
const int judgement_fade_in_duration = 100;
|
||||||
const int judgement_fade_out_duration = 5000;
|
const int judgement_fade_out_duration = 5000;
|
||||||
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
Alpha = 0;
|
Alpha = 0;
|
||||||
Width = 0;
|
Width = 0;
|
||||||
|
|
||||||
JudgementLineThickness.BindValueChanged(thickness => Height = thickness.NewValue, true);
|
|
||||||
|
|
||||||
this
|
this
|
||||||
.FadeTo(0.6f, judgement_fade_in_duration, Easing.OutQuint)
|
.FadeTo(0.6f, judgement_fade_in_duration, Easing.OutQuint)
|
||||||
.ResizeWidthTo(1, judgement_fade_in_duration, Easing.OutQuint)
|
.ResizeWidthTo(1, judgement_fade_in_duration, Easing.OutQuint)
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
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.Pooling;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
@ -15,6 +17,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
||||||
{
|
{
|
||||||
|
[Cached]
|
||||||
public class ColourHitErrorMeter : HitErrorMeter
|
public class ColourHitErrorMeter : HitErrorMeter
|
||||||
{
|
{
|
||||||
private const int animation_duration = 200;
|
private const int animation_duration = 200;
|
||||||
@ -82,7 +85,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
JudgementCount.BindValueChanged(count =>
|
JudgementCount.BindValueChanged(_ =>
|
||||||
{
|
{
|
||||||
removeExtraJudgements();
|
removeExtraJudgements();
|
||||||
updateMetrics();
|
updateMetrics();
|
||||||
@ -91,14 +94,17 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
JudgementSpacing.BindValueChanged(_ => updateMetrics(), true);
|
JudgementSpacing.BindValueChanged(_ => updateMetrics(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly DrawablePool<HitErrorShape> judgementLinePool = new DrawablePool<HitErrorShape>(50);
|
||||||
|
|
||||||
public void Push(Color4 colour)
|
public void Push(Color4 colour)
|
||||||
{
|
{
|
||||||
Add(new HitErrorShape(colour, drawable_judgement_size)
|
judgementLinePool.Get(shape =>
|
||||||
{
|
{
|
||||||
Shape = { BindTarget = JudgementShape },
|
shape.Colour = colour;
|
||||||
});
|
Add(shape);
|
||||||
|
|
||||||
removeExtraJudgements();
|
removeExtraJudgements();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeExtraJudgements()
|
private void removeExtraJudgements()
|
||||||
@ -116,32 +122,32 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HitErrorShape : Container
|
public class HitErrorShape : PoolableDrawable
|
||||||
{
|
{
|
||||||
public bool IsRemoved { get; private set; }
|
public bool IsRemoved { get; private set; }
|
||||||
|
|
||||||
public readonly Bindable<ShapeStyle> Shape = new Bindable<ShapeStyle>();
|
public readonly Bindable<ShapeStyle> Shape = new Bindable<ShapeStyle>();
|
||||||
|
|
||||||
private readonly Color4 colour;
|
[Resolved]
|
||||||
|
private ColourHitErrorMeter hitErrorMeter { get; set; } = null!;
|
||||||
|
|
||||||
private Container content = null!;
|
private Container content = null!;
|
||||||
|
|
||||||
public HitErrorShape(Color4 colour, int size)
|
public HitErrorShape()
|
||||||
{
|
{
|
||||||
this.colour = colour;
|
Size = new Vector2(drawable_judgement_size);
|
||||||
Size = new Vector2(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
Child = content = new Container
|
InternalChild = content = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = colour
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Shape.BindTo(hitErrorMeter.JudgementShape);
|
||||||
Shape.BindValueChanged(shape =>
|
Shape.BindValueChanged(shape =>
|
||||||
{
|
{
|
||||||
switch (shape.NewValue)
|
switch (shape.NewValue)
|
||||||
@ -155,17 +161,32 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
content.FadeInFromZero(animation_duration, Easing.OutQuint);
|
protected override void PrepareForUse()
|
||||||
content.MoveToY(-DrawSize.Y);
|
{
|
||||||
content.MoveToY(0, animation_duration, Easing.OutQuint);
|
base.PrepareForUse();
|
||||||
|
|
||||||
|
this.FadeInFromZero(animation_duration, Easing.OutQuint)
|
||||||
|
// On pool re-use, start flow animation from (0,0).
|
||||||
|
.MoveTo(Vector2.Zero);
|
||||||
|
|
||||||
|
content.MoveToY(-DrawSize.Y)
|
||||||
|
.MoveToY(0, animation_duration, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void FreeAfterUse()
|
||||||
|
{
|
||||||
|
base.FreeAfterUse();
|
||||||
|
IsRemoved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove()
|
public void Remove()
|
||||||
{
|
{
|
||||||
IsRemoved = true;
|
IsRemoved = true;
|
||||||
|
|
||||||
this.FadeOut(animation_duration, Easing.OutQuint).Expire();
|
this.FadeOut(animation_duration, Easing.OutQuint)
|
||||||
|
.Expire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,18 @@ namespace osu.Game.Screens.Select
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateModeLight() => modeLight.FadeColour(buttons.FirstOrDefault(b => b.IsHovered)?.SelectedColour ?? Color4.Transparent, TRANSITION_LENGTH, Easing.OutQuint);
|
private void updateModeLight()
|
||||||
|
{
|
||||||
|
var selectedButton = buttons.FirstOrDefault(b => b.Enabled.Value && b.IsHovered);
|
||||||
|
|
||||||
|
if (selectedButton != null)
|
||||||
|
{
|
||||||
|
modeLight.FadeIn(TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
|
modeLight.FadeColour(selectedButton.SelectedColour, TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
modeLight.FadeOut(TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
public Footer()
|
public Footer()
|
||||||
{
|
{
|
||||||
@ -78,6 +89,7 @@ namespace osu.Game.Screens.Select
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 3,
|
Height = 3,
|
||||||
Position = new Vector2(0, -3),
|
Position = new Vector2(0, -3),
|
||||||
|
Colour = Color4.Black,
|
||||||
},
|
},
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
|
@ -120,10 +120,18 @@ namespace osu.Game.Screens.Select
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
Enabled.BindValueChanged(_ => updateDisplay(), true);
|
||||||
|
}
|
||||||
|
|
||||||
public Action Hovered;
|
public Action Hovered;
|
||||||
public Action HoverLost;
|
public Action HoverLost;
|
||||||
public GlobalAction? Hotkey;
|
public GlobalAction? Hotkey;
|
||||||
|
|
||||||
|
private bool mouseDown;
|
||||||
|
|
||||||
protected override void UpdateAfterChildren()
|
protected override void UpdateAfterChildren()
|
||||||
{
|
{
|
||||||
base.UpdateAfterChildren();
|
base.UpdateAfterChildren();
|
||||||
@ -140,32 +148,38 @@ namespace osu.Game.Screens.Select
|
|||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
{
|
{
|
||||||
Hovered?.Invoke();
|
Hovered?.Invoke();
|
||||||
light.ScaleTo(new Vector2(1, 2), Footer.TRANSITION_LENGTH, Easing.OutQuint);
|
updateDisplay();
|
||||||
light.FadeColour(SelectedColour, Footer.TRANSITION_LENGTH, Easing.OutQuint);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
{
|
{
|
||||||
HoverLost?.Invoke();
|
HoverLost?.Invoke();
|
||||||
light.ScaleTo(new Vector2(1, 1), Footer.TRANSITION_LENGTH, Easing.OutQuint);
|
updateDisplay();
|
||||||
light.FadeColour(DeselectedColour, Footer.TRANSITION_LENGTH, Easing.OutQuint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
{
|
{
|
||||||
box.FadeTo(0.3f, Footer.TRANSITION_LENGTH * 2, Easing.OutQuint);
|
if (!Enabled.Value)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
mouseDown = true;
|
||||||
|
updateDisplay();
|
||||||
return base.OnMouseDown(e);
|
return base.OnMouseDown(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMouseUp(MouseUpEvent e)
|
protected override void OnMouseUp(MouseUpEvent e)
|
||||||
{
|
{
|
||||||
box.FadeOut(Footer.TRANSITION_LENGTH, Easing.OutQuint);
|
mouseDown = false;
|
||||||
|
updateDisplay();
|
||||||
base.OnMouseUp(e);
|
base.OnMouseUp(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnClick(ClickEvent e)
|
||||||
{
|
{
|
||||||
|
if (!Enabled.Value)
|
||||||
|
return true;
|
||||||
|
|
||||||
box.ClearTransforms();
|
box.ClearTransforms();
|
||||||
box.Alpha = 1;
|
box.Alpha = 1;
|
||||||
box.FadeOut(Footer.TRANSITION_LENGTH * 3, Easing.OutQuint);
|
box.FadeOut(Footer.TRANSITION_LENGTH * 3, Easing.OutQuint);
|
||||||
@ -184,5 +198,20 @@ namespace osu.Game.Screens.Select
|
|||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnReleased(KeyBindingReleaseEvent<GlobalAction> e) { }
|
public virtual void OnReleased(KeyBindingReleaseEvent<GlobalAction> e) { }
|
||||||
|
|
||||||
|
private void updateDisplay()
|
||||||
|
{
|
||||||
|
this.FadeTo(Enabled.Value ? 1 : 0.25f, Footer.TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
|
|
||||||
|
light.ScaleTo(Enabled.Value && IsHovered ? new Vector2(1, 2) : new Vector2(1), Footer.TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
|
light.FadeColour(Enabled.Value && IsHovered ? SelectedColour : DeselectedColour, Footer.TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
|
|
||||||
|
box.FadeTo(Enabled.Value & mouseDown ? 0.3f : 0f, Footer.TRANSITION_LENGTH * 2, Easing.OutQuint);
|
||||||
|
|
||||||
|
if (Enabled.Value && IsHovered)
|
||||||
|
Hovered?.Invoke();
|
||||||
|
else
|
||||||
|
HoverLost?.Invoke();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,8 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
protected BeatmapDetailArea BeatmapDetails { get; private set; }
|
protected BeatmapDetailArea BeatmapDetails { get; private set; }
|
||||||
|
|
||||||
|
private FooterButtonOptions beatmapOptionsButton;
|
||||||
|
|
||||||
private readonly Bindable<RulesetInfo> decoupledRuleset = new Bindable<RulesetInfo>();
|
private readonly Bindable<RulesetInfo> decoupledRuleset = new Bindable<RulesetInfo>();
|
||||||
|
|
||||||
private double audioFeedbackLastPlaybackTime;
|
private double audioFeedbackLastPlaybackTime;
|
||||||
@ -314,7 +316,7 @@ namespace osu.Game.Screens.Select
|
|||||||
NextRandom = () => Carousel.SelectNextRandom(),
|
NextRandom = () => Carousel.SelectNextRandom(),
|
||||||
PreviousRandom = Carousel.SelectPreviousRandom
|
PreviousRandom = Carousel.SelectPreviousRandom
|
||||||
}, null),
|
}, null),
|
||||||
(new FooterButtonOptions(), BeatmapOptions)
|
(beatmapOptionsButton = new FooterButtonOptions(), BeatmapOptions)
|
||||||
};
|
};
|
||||||
|
|
||||||
protected virtual ModSelectOverlay CreateModSelectOverlay() => new SoloModSelectOverlay();
|
protected virtual ModSelectOverlay CreateModSelectOverlay() => new SoloModSelectOverlay();
|
||||||
@ -739,6 +741,16 @@ namespace osu.Game.Screens.Select
|
|||||||
beatmapInfoWedge.Beatmap = beatmap;
|
beatmapInfoWedge.Beatmap = beatmap;
|
||||||
|
|
||||||
BeatmapDetails.Beatmap = beatmap;
|
BeatmapDetails.Beatmap = beatmap;
|
||||||
|
|
||||||
|
bool beatmapSelected = beatmap is not DummyWorkingBeatmap;
|
||||||
|
|
||||||
|
if (beatmapSelected)
|
||||||
|
beatmapOptionsButton.Enabled.Value = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
beatmapOptionsButton.Enabled.Value = false;
|
||||||
|
BeatmapOptions.Hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly WeakReference<ITrack> lastTrack = new WeakReference<ITrack>(null);
|
private readonly WeakReference<ITrack> lastTrack = new WeakReference<ITrack>(null);
|
||||||
|
@ -82,21 +82,14 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
||||||
{
|
{
|
||||||
|
// Temporary until default skin has a valid hit lighting.
|
||||||
|
if ((lookup as SkinnableSprite.SpriteComponentLookup)?.LookupName == @"lighting") return Drawable.Empty();
|
||||||
|
|
||||||
if (base.GetDrawableComponent(lookup) is Drawable c)
|
if (base.GetDrawableComponent(lookup) is Drawable c)
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
switch (lookup)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
case SkinnableSprite.SpriteComponentLookup spriteLookup:
|
|
||||||
switch (spriteLookup.LookupName)
|
|
||||||
{
|
|
||||||
// Temporary until default skin has a valid hit lighting.
|
|
||||||
case @"lighting":
|
|
||||||
return Drawable.Empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GlobalSkinComponentLookup globalLookup:
|
case GlobalSkinComponentLookup globalLookup:
|
||||||
switch (globalLookup.Lookup)
|
switch (globalLookup.Lookup)
|
||||||
{
|
{
|
||||||
|
@ -396,9 +396,6 @@ namespace osu.Game.Skinning
|
|||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
case SkinnableSprite.SpriteComponentLookup sprite:
|
|
||||||
return this.GetAnimation(sprite.LookupName, false, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -158,6 +158,10 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
switch (lookup)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
|
// This fallback is important for user skins which use SkinnableSprites.
|
||||||
|
case SkinnableSprite.SpriteComponentLookup sprite:
|
||||||
|
return this.GetAnimation(sprite.LookupName, false, false);
|
||||||
|
|
||||||
case GlobalSkinComponentLookup target:
|
case GlobalSkinComponentLookup target:
|
||||||
if (!DrawableComponentInfo.TryGetValue(target.Lookup, out var skinnableInfo))
|
if (!DrawableComponentInfo.TryGetValue(target.Lookup, out var skinnableInfo))
|
||||||
return null;
|
return null;
|
||||||
|
@ -60,21 +60,14 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
||||||
{
|
{
|
||||||
|
// Temporary until default skin has a valid hit lighting.
|
||||||
|
if ((lookup as SkinnableSprite.SpriteComponentLookup)?.LookupName == @"lighting") return Drawable.Empty();
|
||||||
|
|
||||||
if (base.GetDrawableComponent(lookup) is Drawable c)
|
if (base.GetDrawableComponent(lookup) is Drawable c)
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
switch (lookup)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
case SkinnableSprite.SpriteComponentLookup spriteLookup:
|
|
||||||
switch (spriteLookup.LookupName)
|
|
||||||
{
|
|
||||||
// Temporary until default skin has a valid hit lighting.
|
|
||||||
case @"lighting":
|
|
||||||
return Drawable.Empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GlobalSkinComponentLookup target:
|
case GlobalSkinComponentLookup target:
|
||||||
switch (target.Lookup)
|
switch (target.Lookup)
|
||||||
{
|
{
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Realm" Version="10.18.0" />
|
<PackageReference Include="Realm" Version="10.18.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2022.1110.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2022.1113.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1103.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1113.0" />
|
||||||
<PackageReference Include="Sentry" Version="3.23.1" />
|
<PackageReference Include="Sentry" Version="3.23.1" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.32.2" />
|
<PackageReference Include="SharpCompress" Version="0.32.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
|
@ -61,8 +61,8 @@
|
|||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1103.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1113.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.1110.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.1113.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) -->
|
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@ -82,7 +82,7 @@
|
|||||||
<PackageReference Include="DiffPlex" Version="1.7.1" />
|
<PackageReference Include="DiffPlex" Version="1.7.1" />
|
||||||
<PackageReference Include="Humanizer" Version="2.14.1" />
|
<PackageReference Include="Humanizer" Version="2.14.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2022.1110.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2022.1113.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.32.2" />
|
<PackageReference Include="SharpCompress" Version="0.32.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user