1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-25 02:42:54 +08:00
osu-lazer/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs

191 lines
6.7 KiB
C#
Raw Normal View History

2019-03-19 16:39:53 +08:00
// 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.
2022-06-17 15:37:17 +08:00
#nullable disable
2019-03-19 16:39:53 +08:00
using osu.Framework.Allocation;
using osu.Framework.Bindables;
2019-03-19 16:39:53 +08:00
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
2019-04-09 15:27:10 +08:00
using osu.Framework.Graphics.Effects;
2019-03-19 16:39:53 +08:00
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Rulesets.Osu.Skinning;
using osu.Game.Screens.Play;
2019-03-19 16:39:53 +08:00
using osu.Game.Skinning;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Rulesets.Osu.UI.Cursor
{
2022-11-24 13:32:20 +08:00
public partial class OsuCursor : SkinReloadableDrawable
2019-03-19 16:39:53 +08:00
{
2023-11-07 09:52:48 +08:00
public const float SIZE = 28;
2019-07-25 15:17:02 +08:00
2019-03-19 16:39:53 +08:00
private bool cursorExpand;
2019-12-10 19:45:06 +08:00
private SkinnableDrawable cursorSprite;
private Container cursorScaleContainer = null!;
2019-12-10 19:45:06 +08:00
private SkinnableCursor skinnableCursor => (SkinnableCursor)cursorSprite.Drawable;
2019-03-19 16:39:53 +08:00
public IBindable<float> CursorScale => cursorScale;
private readonly Bindable<float> cursorScale = new BindableFloat(1);
private Bindable<float> userCursorScale = null!;
private Bindable<bool> autoCursorScale = null!;
[Resolved(canBeNull: true)]
private GameplayState state { get; set; }
[Resolved]
private OsuConfigManager config { get; set; }
2019-03-19 16:39:53 +08:00
public OsuCursor()
{
Origin = Anchor.Centre;
2019-07-25 15:17:02 +08:00
2023-11-07 09:52:48 +08:00
Size = new Vector2(SIZE);
2019-03-19 16:39:53 +08:00
}
[BackgroundDependencyLoader]
private void load()
2019-03-19 16:39:53 +08:00
{
InternalChild = CreateCursorContent();
userCursorScale = config.GetBindable<float>(OsuSetting.GameplayCursorSize);
userCursorScale.ValueChanged += _ => cursorScale.Value = CalculateCursorScale();
autoCursorScale = config.GetBindable<bool>(OsuSetting.AutoCursorSize);
autoCursorScale.ValueChanged += _ => cursorScale.Value = CalculateCursorScale();
cursorScale.BindValueChanged(e => cursorScaleContainer.Scale = new Vector2(e.NewValue), true);
2019-03-19 16:39:53 +08:00
}
protected override void LoadComplete()
{
base.LoadComplete();
cursorScale.Value = CalculateCursorScale();
}
protected virtual Drawable CreateCursorContent() => cursorScaleContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Child = cursorSprite = new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling)
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
},
};
protected virtual float CalculateCursorScale()
{
float scale = userCursorScale.Value;
if (autoCursorScale.Value && state != null)
{
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
scale *= GetScaleForCircleSize(state.Beatmap.Difficulty.CircleSize);
}
return scale;
}
protected override void SkinChanged(ISkinSource skin)
{
cursorExpand = skin.GetConfig<OsuSkinConfiguration, bool>(OsuSkinConfiguration.CursorExpand)?.Value ?? true;
}
2019-03-19 16:39:53 +08:00
public void Expand()
{
if (!cursorExpand) return;
skinnableCursor.Expand();
2019-03-19 16:39:53 +08:00
}
public void Contract() => skinnableCursor.Contract();
2019-07-25 15:17:02 +08:00
2023-11-07 20:08:49 +08:00
/// <summary>
/// Get the scale applicable to the ActiveCursor based on a beatmap's circle size.
/// </summary>
public static float GetScaleForCircleSize(float circleSize) =>
1f - 0.7f * (1f + circleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY;
private partial class DefaultCursor : SkinnableCursor
2019-07-25 15:17:02 +08:00
{
public DefaultCursor()
{
RelativeSizeAxes = Axes.Both;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
2019-12-10 20:40:10 +08:00
InternalChildren = new[]
2019-07-25 15:17:02 +08:00
{
ExpandTarget = new CircularContainer
2019-07-25 15:17:02 +08:00
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
2019-07-25 15:17:02 +08:00
RelativeSizeAxes = Axes.Both,
Masking = true,
2023-11-07 09:52:48 +08:00
BorderThickness = SIZE / 6,
2019-07-25 15:17:02 +08:00
BorderColour = Color4.White,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Pink.Opacity(0.5f),
Radius = 5,
},
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true,
},
new CircularContainer
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Masking = true,
2023-11-07 09:52:48 +08:00
BorderThickness = SIZE / 3,
2019-07-25 15:17:02 +08:00
BorderColour = Color4.White.Opacity(0.5f),
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true,
},
},
},
},
},
new Circle
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Scale = new Vector2(0.14f),
Colour = new Color4(34, 93, 204, 255),
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Glow,
Radius = 8,
Colour = Color4.White,
},
},
2019-07-25 15:17:02 +08:00
};
}
}
2019-03-19 16:39:53 +08:00
}
}