mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 23:24:04 +09:00
Merge branch 'master' into legacy-sprite-text-fonts
This commit is contained in:
@ -17,10 +17,10 @@ namespace osu.Game.Rulesets.Osu.Configuration
|
||||
protected override void InitialiseDefaults()
|
||||
{
|
||||
base.InitialiseDefaults();
|
||||
Set(OsuRulesetSetting.SnakingInSliders, true);
|
||||
Set(OsuRulesetSetting.SnakingOutSliders, true);
|
||||
Set(OsuRulesetSetting.ShowCursorTrail, true);
|
||||
Set(OsuRulesetSetting.PlayfieldBorderStyle, PlayfieldBorderStyle.None);
|
||||
SetDefault(OsuRulesetSetting.SnakingInSliders, true);
|
||||
SetDefault(OsuRulesetSetting.SnakingOutSliders, true);
|
||||
SetDefault(OsuRulesetSetting.ShowCursorTrail, true);
|
||||
SetDefault(OsuRulesetSetting.PlayfieldBorderStyle, PlayfieldBorderStyle.None);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,11 +7,13 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osuTK;
|
||||
@ -23,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
/// <summary>
|
||||
/// A visualisation of a single <see cref="PathControlPoint"/> in a <see cref="Slider"/>.
|
||||
/// </summary>
|
||||
public class PathControlPointPiece : BlueprintPiece<Slider>
|
||||
public class PathControlPointPiece : BlueprintPiece<Slider>, IHasTooltip
|
||||
{
|
||||
public Action<PathControlPointPiece, MouseButtonEvent> RequestSelection;
|
||||
|
||||
@ -195,7 +197,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
|
||||
markerRing.Alpha = IsSelected.Value ? 1 : 0;
|
||||
|
||||
Color4 colour = ControlPoint.Type.Value != null ? colours.Red : colours.Yellow;
|
||||
Color4 colour = getColourFromNodeType();
|
||||
|
||||
if (IsHovered || IsSelected.Value)
|
||||
colour = colour.Lighten(1);
|
||||
@ -203,5 +205,28 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
marker.Colour = colour;
|
||||
marker.Scale = new Vector2(slider.Scale);
|
||||
}
|
||||
|
||||
private Color4 getColourFromNodeType()
|
||||
{
|
||||
if (!(ControlPoint.Type.Value is PathType pathType))
|
||||
return colours.Yellow;
|
||||
|
||||
switch (pathType)
|
||||
{
|
||||
case PathType.Catmull:
|
||||
return colours.Seafoam;
|
||||
|
||||
case PathType.Bezier:
|
||||
return colours.Pink;
|
||||
|
||||
case PathType.PerfectCurve:
|
||||
return colours.PurpleDark;
|
||||
|
||||
default:
|
||||
return colours.Red;
|
||||
}
|
||||
}
|
||||
|
||||
public string TooltipText => ControlPoint.Type.Value.ToString() ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@ -28,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
protected SliderBodyPiece BodyPiece { get; private set; }
|
||||
protected SliderCircleSelectionBlueprint HeadBlueprint { get; private set; }
|
||||
protected SliderCircleSelectionBlueprint TailBlueprint { get; private set; }
|
||||
|
||||
[CanBeNull]
|
||||
protected PathControlPointVisualiser ControlPointVisualiser { get; private set; }
|
||||
|
||||
private readonly DrawableSlider slider;
|
||||
@ -114,6 +117,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
|
||||
// throw away frame buffers on deselection.
|
||||
ControlPointVisualiser?.Expire();
|
||||
ControlPointVisualiser = null;
|
||||
|
||||
BodyPiece.RecyclePath();
|
||||
}
|
||||
|
||||
|
@ -164,28 +164,29 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
ApproachCircle.Expire(true);
|
||||
}
|
||||
|
||||
protected override void UpdateStartTimeStateTransforms()
|
||||
{
|
||||
base.UpdateStartTimeStateTransforms();
|
||||
|
||||
ApproachCircle.FadeOut(50);
|
||||
}
|
||||
|
||||
protected override void UpdateHitStateTransforms(ArmedState state)
|
||||
{
|
||||
Debug.Assert(HitObject.HitWindows != null);
|
||||
|
||||
// todo: temporary / arbitrary, used for lifetime optimisation.
|
||||
this.Delay(800).FadeOut();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Idle:
|
||||
this.Delay(HitObject.TimePreempt).FadeOut(500);
|
||||
HitArea.HitAction = null;
|
||||
break;
|
||||
|
||||
case ArmedState.Miss:
|
||||
ApproachCircle.FadeOut(50);
|
||||
this.FadeOut(100);
|
||||
break;
|
||||
|
||||
case ArmedState.Hit:
|
||||
ApproachCircle.FadeOut(50);
|
||||
|
||||
// todo: temporary / arbitrary
|
||||
this.Delay(800).FadeOut();
|
||||
break;
|
||||
}
|
||||
|
||||
Expire();
|
||||
|
@ -33,12 +33,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
public SpinnerSpmCounter SpmCounter { get; private set; }
|
||||
|
||||
private Container<DrawableSpinnerTick> ticks;
|
||||
private SpinnerBonusDisplay bonusDisplay;
|
||||
private PausableSkinnableSound spinningSample;
|
||||
|
||||
private Bindable<bool> isSpinning;
|
||||
private bool spinnerFrequencyModulate;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of bonus score gained from spinning after the required number of spins, for display purposes.
|
||||
/// </summary>
|
||||
public IBindable<double> GainedBonus => gainedBonus;
|
||||
|
||||
private readonly Bindable<double> gainedBonus = new Bindable<double>();
|
||||
|
||||
private const double fade_out_duration = 160;
|
||||
|
||||
public DrawableSpinner()
|
||||
: this(null)
|
||||
{
|
||||
@ -65,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SpinnerBody), _ => new DefaultSpinnerDisc()),
|
||||
new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SpinnerBody), _ => new DefaultSpinner()),
|
||||
RotationTracker = new SpinnerRotationTracker(this)
|
||||
}
|
||||
},
|
||||
@ -76,12 +84,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
Y = 120,
|
||||
Alpha = 0
|
||||
},
|
||||
bonusDisplay = new SpinnerBonusDisplay
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Y = -120,
|
||||
},
|
||||
spinningSample = new PausableSkinnableSound
|
||||
{
|
||||
Volume = { Value = 0 },
|
||||
@ -131,12 +133,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
if (tracking.NewValue)
|
||||
{
|
||||
if (!spinningSample.IsPlaying)
|
||||
spinningSample?.Play();
|
||||
spinningSample?.VolumeTo(1, 300);
|
||||
spinningSample.Play();
|
||||
|
||||
spinningSample.VolumeTo(1, 300);
|
||||
}
|
||||
else
|
||||
{
|
||||
spinningSample?.VolumeTo(0, 300).OnComplete(_ => spinningSample.Stop());
|
||||
spinningSample.VolumeTo(0, fade_out_duration);
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,7 +176,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
base.UpdateHitStateTransforms(state);
|
||||
|
||||
this.FadeOut(160).Expire();
|
||||
this.FadeOut(fade_out_duration).OnComplete(_ =>
|
||||
{
|
||||
// looping sample should be stopped here as it is safer than running in the OnComplete
|
||||
// of the volume transition above.
|
||||
spinningSample.Stop();
|
||||
});
|
||||
|
||||
Expire();
|
||||
|
||||
// skin change does a rewind of transforms, which will stop the spinning sound from playing if it's currently in playback.
|
||||
isSpinning?.TriggerChange();
|
||||
@ -288,6 +298,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
private void fadeInCounter() => SpmCounter.FadeIn(HitObject.TimeFadeIn);
|
||||
|
||||
private static readonly int score_per_tick = new SpinnerBonusTick.OsuSpinnerBonusTickJudgement().MaxNumericResult;
|
||||
|
||||
private int wholeSpins;
|
||||
|
||||
private void updateBonusScore()
|
||||
@ -312,8 +324,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
if (tick != null)
|
||||
{
|
||||
tick.TriggerResult(true);
|
||||
|
||||
if (tick is DrawableSpinnerBonusTick)
|
||||
bonusDisplay.SetBonusCount(spins - HitObject.SpinsRequired);
|
||||
gainedBonus.Value = score_per_tick * (spins - HitObject.SpinsRequired);
|
||||
}
|
||||
|
||||
wholeSpins++;
|
||||
|
@ -18,6 +18,6 @@ namespace osu.Game.Rulesets.Osu
|
||||
SliderFollowCircle,
|
||||
SliderBall,
|
||||
SliderBody,
|
||||
SpinnerBody
|
||||
SpinnerBody,
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,18 @@
|
||||
{
|
||||
"Mappings": [{
|
||||
"StartTime": 114993,
|
||||
"Objects": [{
|
||||
"StartTime": 114993,
|
||||
"EndTime": 114993,
|
||||
"X": 493,
|
||||
"Y": 92
|
||||
}, {
|
||||
"StartTime": 115290,
|
||||
"EndTime": 115290,
|
||||
"X": 451.659241,
|
||||
"Y": 267.188
|
||||
}]
|
||||
}, {
|
||||
"StartTime": 118858.0,
|
||||
"Objects": [{
|
||||
"StartTime": 118858.0,
|
||||
|
@ -9,7 +9,9 @@ SliderMultiplier:1.87
|
||||
SliderTickRate:1
|
||||
|
||||
[TimingPoints]
|
||||
49051,230.769230769231,4,2,1,15,1,0
|
||||
114000,346.820809248555,4,2,1,71,1,0
|
||||
118000,230.769230769231,4,2,1,15,1,0
|
||||
|
||||
[HitObjects]
|
||||
493,92,114993,2,0,P|472:181|442:308,1,180,12|0,0:0|0:0,0:0:0:0:
|
||||
219,215,118858,2,0,P|224:170|244:-10,1,187,8|2,0:0|0:0,0:0:0:0:
|
||||
|
68
osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs
Normal file
68
osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Globalization;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Skinning.Default
|
||||
{
|
||||
public class DefaultSpinner : CompositeDrawable
|
||||
{
|
||||
private DrawableSpinner drawableSpinner;
|
||||
|
||||
private OsuSpriteText bonusCounter;
|
||||
|
||||
public DefaultSpinner()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(DrawableHitObject drawableHitObject)
|
||||
{
|
||||
drawableSpinner = (DrawableSpinner)drawableHitObject;
|
||||
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new DefaultSpinnerDisc
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
bonusCounter = new OsuSpriteText
|
||||
{
|
||||
Alpha = 0,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.Numeric.With(size: 24),
|
||||
Y = -120,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private IBindable<double> gainedBonus;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
gainedBonus = drawableSpinner.GainedBonus.GetBoundCopy();
|
||||
gainedBonus.BindValueChanged(bonus =>
|
||||
{
|
||||
bonusCounter.Text = bonus.NewValue.ToString(NumberFormatInfo.InvariantInfo);
|
||||
bonusCounter.FadeOutFromOne(1500);
|
||||
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(1f, 1000, Easing.OutQuint);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -40,14 +40,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default
|
||||
|
||||
public DefaultSpinnerDisc()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
// we are slightly bigger than our parent, to clip the top and bottom of the circle
|
||||
// this should probably be revisited when scaled spinners are a thing.
|
||||
Scale = new Vector2(initial_scale);
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -74,10 +74,11 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default
|
||||
|
||||
private void updateState(DrawableHitObject drawableObject, ArmedState state)
|
||||
{
|
||||
using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime, true))
|
||||
{
|
||||
using (BeginAbsoluteSequence(drawableObject.StateUpdateTime))
|
||||
glow.FadeOut(400);
|
||||
|
||||
using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Hit:
|
||||
|
@ -1,47 +0,0 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Skinning.Default
|
||||
{
|
||||
/// <summary>
|
||||
/// Shows incremental bonus score achieved for a spinner.
|
||||
/// </summary>
|
||||
public class SpinnerBonusDisplay : CompositeDrawable
|
||||
{
|
||||
private static readonly int score_per_tick = new SpinnerBonusTick().CreateJudgement().MaxNumericResult;
|
||||
|
||||
private readonly OsuSpriteText bonusCounter;
|
||||
|
||||
public SpinnerBonusDisplay()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
InternalChild = bonusCounter = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.Numeric.With(size: 24),
|
||||
Alpha = 0,
|
||||
};
|
||||
}
|
||||
|
||||
private int displayedCount;
|
||||
|
||||
public void SetBonusCount(int count)
|
||||
{
|
||||
if (displayedCount == count)
|
||||
return;
|
||||
|
||||
displayedCount = count;
|
||||
bonusCounter.Text = $"{score_per_tick * count}";
|
||||
bonusCounter.FadeOutFromOne(1500);
|
||||
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(1f, 1000, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@ -32,6 +33,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
private Sprite spin;
|
||||
private Sprite clear;
|
||||
|
||||
private LegacySpriteText bonusCounter;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(DrawableHitObject drawableHitObject, ISkinSource source)
|
||||
{
|
||||
@ -45,36 +48,67 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
|
||||
DrawableSpinner = (DrawableSpinner)drawableHitObject;
|
||||
|
||||
AddRangeInternal(new[]
|
||||
Container overlayContainer;
|
||||
|
||||
AddInternal(overlayContainer = new Container
|
||||
{
|
||||
spin = new Sprite
|
||||
Depth = float.MinValue,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
Depth = float.MinValue,
|
||||
Texture = source.GetTexture("spinner-spin"),
|
||||
Scale = new Vector2(SPRITE_SCALE),
|
||||
Y = SPINNER_TOP_OFFSET + 335,
|
||||
},
|
||||
clear = new Sprite
|
||||
{
|
||||
Alpha = 0,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
Depth = float.MinValue,
|
||||
Texture = source.GetTexture("spinner-clear"),
|
||||
Scale = new Vector2(SPRITE_SCALE),
|
||||
Y = SPINNER_TOP_OFFSET + 115,
|
||||
},
|
||||
spin = new Sprite
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = source.GetTexture("spinner-spin"),
|
||||
Scale = new Vector2(SPRITE_SCALE),
|
||||
Y = SPINNER_TOP_OFFSET + 335,
|
||||
},
|
||||
clear = new Sprite
|
||||
{
|
||||
Alpha = 0,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = source.GetTexture("spinner-clear"),
|
||||
Scale = new Vector2(SPRITE_SCALE),
|
||||
Y = SPINNER_TOP_OFFSET + 115,
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
bonusCounter = (source.GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreText)) as LegacySpriteText)?.With(c =>
|
||||
{
|
||||
c.Alpha = 0f;
|
||||
c.Anchor = Anchor.TopCentre;
|
||||
c.Origin = Anchor.Centre;
|
||||
c.Font = c.Font.With(fixedWidth: false);
|
||||
c.Scale = new Vector2(SPRITE_SCALE);
|
||||
c.Y = SPINNER_TOP_OFFSET + 299;
|
||||
});
|
||||
|
||||
if (bonusCounter != null)
|
||||
overlayContainer.Add(bonusCounter);
|
||||
}
|
||||
|
||||
private IBindable<double> gainedBonus;
|
||||
|
||||
private readonly Bindable<bool> completed = new Bindable<bool>();
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
if (bonusCounter != null)
|
||||
{
|
||||
gainedBonus = DrawableSpinner.GainedBonus.GetBoundCopy();
|
||||
gainedBonus.BindValueChanged(bonus =>
|
||||
{
|
||||
bonusCounter.Text = bonus.NewValue.ToString(NumberFormatInfo.InvariantInfo);
|
||||
bonusCounter.FadeOutFromOne(800, Easing.Out);
|
||||
bonusCounter.ScaleTo(SPRITE_SCALE * 2f).Then().ScaleTo(SPRITE_SCALE * 1.28f, 800, Easing.Out);
|
||||
});
|
||||
}
|
||||
|
||||
completed.BindValueChanged(onCompletedChanged, true);
|
||||
|
||||
DrawableSpinner.ApplyCustomUpdateState += UpdateStateTransforms;
|
||||
|
Reference in New Issue
Block a user