diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index c1a4c1981f..05cb42d853 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -160,9 +160,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.SkinChanged(skin, allowFallback); - Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? Body.AccentColour; - Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Body.BorderColour; - Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Ball.AccentColour; + Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? SliderBody.DEFAULT_BORDER_SIZE; + Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour; + Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White; + Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour; } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 2f5c326bda..25e1aebd18 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -14,6 +14,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public abstract class SliderBody : CompositeDrawable { + public const float DEFAULT_BORDER_SIZE = 1; + private readonly SliderPath path; protected Path Path => path; @@ -64,6 +66,23 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } + /// + /// Used to size the path border. + /// + public float BorderSize + { + get => path.BorderSize; + set + { + if (path.BorderSize == value) + return; + + path.BorderSize = value; + + container.ForceRedraw(); + } + } + public Quad PathDrawQuad => container.ScreenSpaceDrawQuad; protected SliderBody() @@ -92,6 +111,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private class SliderPath : SmoothPath { + private const float border_max_size = 8f; + private const float border_min_size = 0f; + private const float border_portion = 0.128f; private const float gradient_portion = 1 - border_portion; @@ -130,12 +152,33 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } + private float borderSize = DEFAULT_BORDER_SIZE; + + public float BorderSize + { + get => borderSize; + set + { + if (borderSize == value) + return; + + if (value < border_min_size || value > border_max_size) + return; + + borderSize = value; + + InvalidateTexture(); + } + } + + private float calculatedBorderPortion => BorderSize * border_portion; + protected override Color4 ColourAt(float position) { - if (position <= border_portion) + if (calculatedBorderPortion != 0f && position <= calculatedBorderPortion) return BorderColour; - position -= border_portion; + position -= calculatedBorderPortion; return new Color4(AccentColour.R, AccentColour.G, AccentColour.B, (opacity_at_edge - (opacity_at_edge - opacity_at_centre) * position / gradient_portion) * AccentColour.A); } } diff --git a/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs b/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs index fdc3d5394f..356ede0d57 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs @@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep("remove all channels", () => { var first = channelTabControl.Items.First(); - if (first.Name == "+") + if (first is ChannelSelectorTabItem.ChannelSelectorTabChannel) return true; channelTabControl.RemoveChannel(first); diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 8c6422afe3..2efc9f4968 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -10,6 +10,7 @@ using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Overlays.Chat.Tabs; using osu.Game.Users; namespace osu.Game.Online.Chat @@ -84,7 +85,11 @@ namespace osu.Game.Online.Chat ?? new Channel(user); } - private void currentChannelChanged(ValueChangedEvent e) => JoinChannel(e.NewValue); + private void currentChannelChanged(ValueChangedEvent e) + { + if (!(e.NewValue is ChannelSelectorTabItem.ChannelSelectorTabChannel)) + JoinChannel(e.NewValue); + } /// /// Ensure we run post actions in sequence, once at a time. diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index c26ecfd86f..7386bffb1a 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -13,8 +13,8 @@ namespace osu.Game.Overlays.Chat.Tabs public override bool IsSwitchable => false; - public ChannelSelectorTabItem(Channel value) - : base(value) + public ChannelSelectorTabItem() + : base(new ChannelSelectorTabChannel()) { Depth = float.MaxValue; Width = 45; @@ -31,5 +31,13 @@ namespace osu.Game.Overlays.Chat.Tabs BackgroundInactive = colour.Gray2; BackgroundActive = colour.Gray3; } + + public class ChannelSelectorTabChannel : Channel + { + public ChannelSelectorTabChannel() + { + Name = "+"; + } + } } } diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 67d9356b76..fafcb0a72d 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Chat.Tabs Margin = new MarginPadding(10), }); - AddTabItem(selectorTab = new ChannelSelectorTabItem(new Channel { Name = "+" })); + AddTabItem(selectorTab = new ChannelSelectorTabItem()); ChannelSelectorActive.BindTo(selectorTab.Active); } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 221fd35576..eb95fabe02 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -199,6 +199,9 @@ namespace osu.Game.Overlays return; } + if (e.NewValue is ChannelSelectorTabItem.ChannelSelectorTabChannel) + return; + textbox.Current.Disabled = e.NewValue.ReadOnly; if (channelTabControl.Current.Value != e.NewValue) @@ -268,7 +271,7 @@ namespace osu.Game.Overlays private void selectTab(int index) { var channel = channelTabControl.Items.Skip(index).FirstOrDefault(); - if (channel != null && channel.Name != "+") + if (channel != null && !(channel is ChannelSelectorTabItem.ChannelSelectorTabChannel)) channelTabControl.Current.Value = channel; } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index cf42a70640..ce94ca9c7d 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -8,6 +8,7 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.TypeExtensions; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; @@ -99,7 +100,7 @@ namespace osu.Game.Rulesets.Scoring /// /// The default conditions for failing. /// - protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue; + protected virtual bool DefaultFailCondition => Precision.AlmostBigger(Health.MinValue, Health.Value); protected ScoreProcessor() { diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 09f7e09961..ecb112955c 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -34,6 +34,10 @@ namespace osu.Game.Skinning case @"CursorExpand": skin.CursorExpand = pair.Value != "0"; break; + + case @"SliderBorderSize": + skin.SliderBorderSize = Parsing.ParseFloat(pair.Value); + break; } break; diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 82faec4e9d..043622f8ce 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -25,6 +25,8 @@ namespace osu.Game.Skinning public int HitCircleOverlap { get; set; } + public float? SliderBorderSize { get; set; } + public bool? CursorExpand { get; set; } = true; } }