mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 15:16:38 +09:00
Merge branch 'master' into dev
This commit is contained in:
@ -3,8 +3,8 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
@ -23,19 +23,19 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
{
|
||||
Name = @"Circle Count",
|
||||
Content = circles.ToString(),
|
||||
Icon = FontAwesome.fa_circle_o
|
||||
Icon = FontAwesome.Regular.Circle
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Slider Count",
|
||||
Content = sliders.ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
Icon = FontAwesome.Regular.Circle
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Spinner Count",
|
||||
Content = spinners.ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
Icon = FontAwesome.Regular.Circle
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -44,12 +44,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
if (endIndex < 0) throw new ArgumentOutOfRangeException(nameof(endIndex), $"{nameof(endIndex)} cannot be less than 0.");
|
||||
|
||||
int extendedEndIndex = endIndex;
|
||||
|
||||
if (endIndex < beatmap.HitObjects.Count - 1)
|
||||
{
|
||||
// Extend the end index to include objects they are stacked on
|
||||
for (int i = endIndex; i >= startIndex; i--)
|
||||
{
|
||||
int stackBaseIndex = i;
|
||||
|
||||
for (int n = stackBaseIndex + 1; n < beatmap.HitObjects.Count; n++)
|
||||
{
|
||||
OsuHitObject stackBaseObject = beatmap.HitObjects[stackBaseIndex];
|
||||
@ -87,6 +89,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
|
||||
//Reverse pass for stack calculation.
|
||||
int extendedStartIndex = startIndex;
|
||||
|
||||
for (int i = extendedEndIndex; i > startIndex; i--)
|
||||
{
|
||||
int n = i;
|
||||
@ -138,6 +141,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
if (objectN is Slider && Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
||||
{
|
||||
int offset = objectI.StackHeight - objectN.StackHeight + 1;
|
||||
|
||||
for (int j = n + 1; j <= i; j++)
|
||||
{
|
||||
//For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above).
|
||||
|
@ -16,15 +16,16 @@ namespace osu.Game.Rulesets.Osu.Configuration
|
||||
protected override void InitialiseDefaults()
|
||||
{
|
||||
base.InitialiseDefaults();
|
||||
|
||||
Set(OsuRulesetSetting.SnakingInSliders, true);
|
||||
Set(OsuRulesetSetting.SnakingOutSliders, true);
|
||||
Set(OsuRulesetSetting.ShowCursorTrail, true);
|
||||
}
|
||||
}
|
||||
|
||||
public enum OsuRulesetSetting
|
||||
{
|
||||
SnakingInSliders,
|
||||
SnakingOutSliders
|
||||
SnakingOutSliders,
|
||||
ShowCursorTrail
|
||||
}
|
||||
}
|
||||
|
@ -109,6 +109,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f);
|
||||
|
||||
double approachRateFactor = 1.0f;
|
||||
|
||||
if (Attributes.ApproachRate > 10.33f)
|
||||
approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f);
|
||||
else if (Attributes.ApproachRate < 8.0f)
|
||||
|
@ -56,6 +56,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
{
|
||||
// We will scale distances by this factor, so we can assume a uniform CircleSize among beatmaps.
|
||||
float scalingFactor = normalized_radius / (float)BaseObject.Radius;
|
||||
|
||||
if (BaseObject.Radius < 30)
|
||||
{
|
||||
float smallCircleBonus = Math.Min(30 - (float)BaseObject.Radius, 5) / 50;
|
||||
|
@ -42,9 +42,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
speedBonus = 1 + Math.Pow((min_speed_bonus - deltaTime) / speed_balancing_factor, 2);
|
||||
|
||||
double angleBonus = 1.0;
|
||||
|
||||
if (osuCurrent.Angle != null && osuCurrent.Angle.Value < angle_bonus_begin)
|
||||
{
|
||||
angleBonus = 1 + Math.Pow(Math.Sin(1.5 * (angle_bonus_begin - osuCurrent.Angle.Value)), 2) / 3.57;
|
||||
|
||||
if (osuCurrent.Angle.Value < pi_over_2)
|
||||
{
|
||||
angleBonus = 1.28;
|
||||
|
@ -37,6 +37,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
case SliderPosition.Start:
|
||||
Position = slider.StackedPosition + slider.Path.PositionAt(0);
|
||||
break;
|
||||
|
||||
case SliderPosition.End:
|
||||
Position = slider.StackedPosition + slider.Path.PositionAt(1);
|
||||
break;
|
||||
|
@ -62,6 +62,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
case PlacementState.Initial:
|
||||
HitObject.Position = e.MousePosition;
|
||||
return true;
|
||||
|
||||
case PlacementState.Body:
|
||||
cursor = e.MousePosition - HitObject.Position;
|
||||
return true;
|
||||
@ -77,6 +78,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
case PlacementState.Initial:
|
||||
beginCurve();
|
||||
break;
|
||||
|
||||
case PlacementState.Body:
|
||||
switch (e.Button)
|
||||
{
|
||||
|
29
osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs
Normal file
29
osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs
Normal file
@ -0,0 +1,29 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
public class DrawableOsuEditRuleset : DrawableOsuRuleset
|
||||
{
|
||||
public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuPlayfieldNoCursor();
|
||||
|
||||
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer { Size = Vector2.One };
|
||||
|
||||
private class OsuPlayfieldNoCursor : OsuPlayfield
|
||||
{
|
||||
protected override GameplayCursorContainer CreateCursor() => null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +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.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
public class OsuEditRulesetContainer : OsuRulesetContainer
|
||||
{
|
||||
public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuPlayfieldNoCursor { Size = Vector2.One };
|
||||
|
||||
private class OsuPlayfieldNoCursor : OsuPlayfield
|
||||
{
|
||||
public OsuPlayfieldNoCursor()
|
||||
{
|
||||
Cursor?.Expire();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,18 +2,16 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
|
||||
@ -26,8 +24,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
}
|
||||
|
||||
protected override RulesetContainer<OsuHitObject> CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
=> new OsuEditRulesetContainer(ruleset, beatmap);
|
||||
protected override DrawableRuleset<OsuHitObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||
=> new DrawableOsuEditRuleset(ruleset, beatmap, mods);
|
||||
|
||||
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]
|
||||
{
|
||||
@ -38,16 +36,16 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
|
||||
public override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler();
|
||||
|
||||
protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableHitCircle circle:
|
||||
return new HitCircleSelectionBlueprint(circle);
|
||||
|
||||
case DrawableSlider slider:
|
||||
return new SliderSelectionBlueprint(slider);
|
||||
|
||||
case DrawableSpinner spinner:
|
||||
return new SpinnerSelectionBlueprint(spinner);
|
||||
}
|
||||
|
@ -16,13 +16,33 @@ namespace osu.Game.Rulesets.Osu.Judgements
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
|
||||
case HitResult.Meh:
|
||||
return 50;
|
||||
|
||||
case HitResult.Good:
|
||||
return 100;
|
||||
|
||||
case HitResult.Great:
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double HealthIncreaseFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case HitResult.Miss:
|
||||
return -0.02;
|
||||
|
||||
case HitResult.Meh:
|
||||
case HitResult.Good:
|
||||
case HitResult.Great:
|
||||
return 0.01;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Autopilot";
|
||||
public override string Acronym => "AP";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
|
||||
public override IconUsage Icon => OsuIcon.ModAutopilot;
|
||||
public override ModType Type => ModType.Automation;
|
||||
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -8,23 +8,23 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Scoring;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModBlinds : Mod, IApplicableToRulesetContainer<OsuHitObject>, IApplicableToScoreProcessor
|
||||
public class OsuModBlinds : Mod, IApplicableToDrawableRuleset<OsuHitObject>, IApplicableToScoreProcessor
|
||||
{
|
||||
public override string Name => "Blinds";
|
||||
public override string Description => "Play with blinds on your screen.";
|
||||
public override string Acronym => "BL";
|
||||
|
||||
public override FontAwesome Icon => FontAwesome.fa_adjust;
|
||||
public override IconUsage Icon => FontAwesome.Solid.Adjust;
|
||||
public override ModType Type => ModType.DifficultyIncrease;
|
||||
|
||||
public override bool Ranked => false;
|
||||
@ -32,9 +32,9 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
private DrawableOsuBlinds blinds;
|
||||
|
||||
public void ApplyToRulesetContainer(RulesetContainer<OsuHitObject> rulesetContainer)
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<OsuHitObject> drawableRuleset)
|
||||
{
|
||||
rulesetContainer.Overlays.Add(blinds = new DrawableOsuBlinds(rulesetContainer.Playfield.HitObjectContainer, rulesetContainer.Beatmap));
|
||||
drawableRuleset.Overlays.Add(blinds = new DrawableOsuBlinds(drawableRuleset.Playfield.HitObjectContainer, drawableRuleset.Beatmap));
|
||||
}
|
||||
|
||||
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
|
||||
@ -42,6 +42,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
scoreProcessor.Health.ValueChanged += health => { blinds.AnimateClosedness((float)health.NewValue); };
|
||||
}
|
||||
|
||||
public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank;
|
||||
|
||||
/// <summary>
|
||||
/// Element for the Blinds mod drawing 2 black boxes covering the whole screen which resize inside a restricted area with some leniency.
|
||||
/// </summary>
|
||||
|
@ -1,23 +1,37 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModFlashlight : ModFlashlight<OsuHitObject>
|
||||
public class OsuModFlashlight : ModFlashlight<OsuHitObject>, IApplicableToDrawableHitObjects
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
|
||||
private const float default_flashlight_size = 180;
|
||||
|
||||
public override Flashlight CreateFlashlight() => new OsuFlashlight();
|
||||
private OsuFlashlight flashlight;
|
||||
|
||||
public override Flashlight CreateFlashlight() => flashlight = new OsuFlashlight();
|
||||
|
||||
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
|
||||
{
|
||||
foreach (var s in drawables.OfType<DrawableSlider>())
|
||||
{
|
||||
s.Tracking.ValueChanged += flashlight.OnSliderTrackingChange;
|
||||
}
|
||||
}
|
||||
|
||||
private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition
|
||||
{
|
||||
@ -26,6 +40,12 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
FlashlightSize = new Vector2(0, getSizeFor(0));
|
||||
}
|
||||
|
||||
public void OnSliderTrackingChange(ValueChangedEvent<bool> e)
|
||||
{
|
||||
// If a slider is in a tracking state, a further dim should be applied to the (remaining) visible portion of the playfield over a brief duration.
|
||||
this.TransformTo(nameof(FlashlightDim), e.NewValue ? 0.8f : 0.0f, 50);
|
||||
}
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
FlashlightPosition = e.MousePosition;
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
public override string Acronym => "GR";
|
||||
|
||||
public override FontAwesome Icon => FontAwesome.fa_arrows_v;
|
||||
public override IconUsage Icon => FontAwesome.Solid.ArrowsAltV;
|
||||
|
||||
public override ModType Type => ModType.Fun;
|
||||
|
||||
@ -33,6 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
case DrawableSpinner _:
|
||||
continue;
|
||||
|
||||
default:
|
||||
drawable.ApplyCustomUpdateState += ApplyCustomState;
|
||||
break;
|
||||
@ -51,6 +52,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
case DrawableSliderTail _:
|
||||
// special cases we should *not* be scaling.
|
||||
break;
|
||||
|
||||
case DrawableSlider _:
|
||||
case DrawableHitCircle _:
|
||||
{
|
||||
|
@ -59,11 +59,13 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
circle.FadeOut(fadeOutDuration);
|
||||
|
||||
break;
|
||||
|
||||
case DrawableSlider slider:
|
||||
using (slider.BeginAbsoluteSequence(fadeOutStartTime, true))
|
||||
slider.Body.FadeOut(longFadeDuration, Easing.Out);
|
||||
|
||||
break;
|
||||
|
||||
case DrawableSliderTick sliderTick:
|
||||
// slider ticks fade out over up to one second
|
||||
var tickFadeOutDuration = Math.Min(sliderTick.HitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000);
|
||||
@ -72,6 +74,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
sliderTick.FadeOut(tickFadeOutDuration);
|
||||
|
||||
break;
|
||||
|
||||
case DrawableSpinner spinner:
|
||||
// hide elements we don't care about.
|
||||
spinner.Disc.Hide();
|
||||
|
@ -13,7 +13,7 @@ using static osu.Game.Input.Handlers.ReplayInputHandler;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByPlayfield, IApplicableToRulesetContainer<OsuHitObject>
|
||||
public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByPlayfield, IApplicableToDrawableRuleset<OsuHitObject>
|
||||
{
|
||||
public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things.";
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
|
||||
@ -79,10 +79,10 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
state.Apply(osuInputManager.CurrentState, osuInputManager);
|
||||
}
|
||||
|
||||
public void ApplyToRulesetContainer(RulesetContainer<OsuHitObject> rulesetContainer)
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<OsuHitObject> drawableRuleset)
|
||||
{
|
||||
// grab the input manager for future use.
|
||||
osuInputManager = (OsuInputManager)rulesetContainer.KeyBindingInputManager;
|
||||
osuInputManager = (OsuInputManager)drawableRuleset.KeyBindingInputManager;
|
||||
osuInputManager.AllowUserPresses = false;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Spun Out";
|
||||
public override string Acronym => "SO";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
|
||||
public override IconUsage Icon => OsuIcon.ModSpunout;
|
||||
public override ModType Type => ModType.DifficultyReduction;
|
||||
public override string Description => @"Spinners will be automatically completed.";
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override string Name => "Target";
|
||||
public override string Acronym => "TP";
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
|
||||
public override IconUsage Icon => OsuIcon.ModTarget;
|
||||
public override string Description => @"Practice keeping up with the beat of the song.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Transform";
|
||||
public override string Acronym => "TR";
|
||||
public override FontAwesome Icon => FontAwesome.fa_arrows;
|
||||
public override IconUsage Icon => FontAwesome.Solid.ArrowsAlt;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "Everything rotates. EVERYTHING.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -4,7 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Wiggle";
|
||||
public override string Acronym => "WG";
|
||||
public override FontAwesome Icon => FontAwesome.fa_certificate;
|
||||
public override IconUsage Icon => FontAwesome.Solid.Certificate;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "They just won't stay still...";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -6,6 +6,7 @@ using osuTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
|
@ -67,6 +67,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
return;
|
||||
|
||||
OsuHitObject prevHitObject = null;
|
||||
|
||||
foreach (var currHitObject in hitObjects)
|
||||
{
|
||||
if (prevHitObject != null && !currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner))
|
||||
|
@ -124,6 +124,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
}
|
||||
|
||||
var result = HitObject.HitWindows.ResultFor(timeOffset);
|
||||
|
||||
if (result == HitResult.None)
|
||||
{
|
||||
Shake(Math.Abs(timeOffset) - HitObject.HitWindows.HalfWindowFor(HitResult.Miss));
|
||||
@ -158,11 +159,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
// override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early.
|
||||
LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss);
|
||||
break;
|
||||
|
||||
case ArmedState.Miss:
|
||||
ApproachCircle.FadeOut(50);
|
||||
this.FadeOut(100);
|
||||
Expire();
|
||||
break;
|
||||
|
||||
case ArmedState.Hit:
|
||||
ApproachCircle.FadeOut(50);
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osuTK;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Icon = FontAwesome.fa_chevron_right
|
||||
Icon = FontAwesome.Solid.ChevronRight
|
||||
}, restrictSize: false)
|
||||
};
|
||||
}
|
||||
@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (repeatPoint.StartTime <= Time.Current)
|
||||
ApplyResult(r => r.Type = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss);
|
||||
ApplyResult(r => r.Type = drawableSlider.Tracking.Value ? HitResult.Great : HitResult.Miss);
|
||||
}
|
||||
|
||||
protected override void UpdatePreemptState()
|
||||
@ -64,9 +64,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
case ArmedState.Idle:
|
||||
this.Delay(HitObject.TimePreempt).FadeOut();
|
||||
break;
|
||||
|
||||
case ArmedState.Miss:
|
||||
this.FadeOut(animDuration);
|
||||
break;
|
||||
|
||||
case ArmedState.Hit:
|
||||
this.FadeOut(animDuration, Easing.OutQuint)
|
||||
.ScaleTo(Scale * 1.5f, animDuration, Easing.Out);
|
||||
|
@ -130,13 +130,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
public bool Tracking;
|
||||
public readonly Bindable<bool> Tracking = new Bindable<bool>();
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
Tracking = Ball.Tracking;
|
||||
Tracking.Value = Ball.Tracking;
|
||||
|
||||
double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
|
||||
|
||||
@ -160,10 +160,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
base.SkinChanged(skin, allowFallback);
|
||||
|
||||
Body.BorderSize = skin.GetValue<SkinConfiguration, float?>(s => s.SliderBorderSize) ?? Body.BorderSize;
|
||||
Body.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? Body.AccentColour;
|
||||
Body.BorderColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Body.BorderColour;
|
||||
Ball.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Ball.AccentColour;
|
||||
Body.BorderSize = skin.GetValue<SkinConfiguration, float?>(s => s.SliderBorderSize) ?? 1;
|
||||
Body.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour;
|
||||
Body.BorderColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White;
|
||||
Ball.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour;
|
||||
}
|
||||
|
||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||
|
@ -67,10 +67,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
case ArmedState.Idle:
|
||||
this.Delay(HitObject.TimePreempt).FadeOut();
|
||||
break;
|
||||
|
||||
case ArmedState.Miss:
|
||||
this.FadeOut(ANIM_DURATION);
|
||||
this.FadeColour(Color4.Red, ANIM_DURATION / 2);
|
||||
break;
|
||||
|
||||
case ArmedState.Hit:
|
||||
this.FadeOut(ANIM_DURATION, Easing.OutQuint);
|
||||
this.ScaleTo(Scale * 1.5f, ANIM_DURATION, Easing.Out);
|
||||
|
@ -12,6 +12,7 @@ using osu.Game.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
@ -76,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(48),
|
||||
Icon = FontAwesome.fa_asterisk,
|
||||
Icon = FontAwesome.Solid.Asterisk,
|
||||
Shadow = false,
|
||||
},
|
||||
}
|
||||
@ -221,9 +222,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
case ArmedState.Idle:
|
||||
Expire(true);
|
||||
break;
|
||||
|
||||
case ArmedState.Hit:
|
||||
sequence.ScaleTo(Scale * 1.2f, 320, Easing.Out);
|
||||
break;
|
||||
|
||||
case ArmedState.Miss:
|
||||
sequence.ScaleTo(Scale * 0.8f, 320, Easing.In);
|
||||
break;
|
||||
|
@ -4,6 +4,7 @@
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osuTK.Graphics;
|
||||
@ -14,7 +15,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public class SliderBall : CircularContainer, ISliderProgress
|
||||
public class SliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition
|
||||
{
|
||||
private const float width = 128;
|
||||
|
||||
@ -107,18 +108,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
|
||||
private Vector2? lastScreenSpaceMousePosition;
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition;
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition;
|
||||
return base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition;
|
||||
|
@ -4,6 +4,7 @@
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
|
@ -183,6 +183,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
Samples = sampleList
|
||||
});
|
||||
break;
|
||||
|
||||
case SliderEventType.Head:
|
||||
AddNested(HeadCircle = new SliderCircle
|
||||
{
|
||||
@ -194,6 +195,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
ComboIndex = ComboIndex,
|
||||
});
|
||||
break;
|
||||
|
||||
case SliderEventType.LegacyLastTick:
|
||||
// we need to use the LegacyLastTick here for compatibility reasons (difficulty).
|
||||
// it is *okay* to use this because the TailCircle is not used for any meaningful purpose in gameplay.
|
||||
@ -206,6 +208,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
ComboIndex = ComboIndex,
|
||||
});
|
||||
break;
|
||||
|
||||
case SliderEventType.Repeat:
|
||||
AddNested(new RepeatPoint
|
||||
{
|
||||
|
@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Osu.Edit;
|
||||
@ -29,7 +30,7 @@ namespace osu.Game.Rulesets.Osu
|
||||
{
|
||||
public class OsuRuleset : Ruleset
|
||||
{
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new OsuRulesetContainer(this, beatmap);
|
||||
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableOsuRuleset(this, beatmap, mods);
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap);
|
||||
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap);
|
||||
|
||||
@ -103,6 +104,7 @@ namespace osu.Game.Rulesets.Osu
|
||||
new MultiMod(new OsuModHalfTime(), new OsuModDaycore()),
|
||||
new OsuModSpunOut(),
|
||||
};
|
||||
|
||||
case ModType.DifficultyIncrease:
|
||||
return new Mod[]
|
||||
{
|
||||
@ -112,11 +114,13 @@ namespace osu.Game.Rulesets.Osu
|
||||
new OsuModHidden(),
|
||||
new MultiMod(new OsuModFlashlight(), new OsuModBlinds()),
|
||||
};
|
||||
|
||||
case ModType.Conversion:
|
||||
return new Mod[]
|
||||
{
|
||||
new OsuModTarget(),
|
||||
};
|
||||
|
||||
case ModType.Automation:
|
||||
return new Mod[]
|
||||
{
|
||||
@ -124,6 +128,7 @@ namespace osu.Game.Rulesets.Osu
|
||||
new OsuModRelax(),
|
||||
new OsuModAutopilot(),
|
||||
};
|
||||
|
||||
case ModType.Fun:
|
||||
return new Mod[]
|
||||
{
|
||||
@ -132,12 +137,13 @@ namespace osu.Game.Rulesets.Osu
|
||||
new OsuModGrow(),
|
||||
new MultiMod(new ModWindUp<OsuHitObject>(), new ModWindDown<OsuHitObject>()),
|
||||
};
|
||||
|
||||
default:
|
||||
return new Mod[] { };
|
||||
}
|
||||
}
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o };
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetOsu };
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap);
|
||||
|
||||
|
@ -199,6 +199,7 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
|
||||
// Wait until Auto could "see and react" to the next note.
|
||||
double waitTime = h.StartTime - Math.Max(0.0, h.TimePreempt - reactionTime);
|
||||
|
||||
if (waitTime > lastFrame.Time)
|
||||
{
|
||||
lastFrame = new OsuReplayFrame(waitTime, lastFrame.Position) { Actions = lastFrame.Actions };
|
||||
@ -292,7 +293,6 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
{
|
||||
// We add intermediate frames for spinning / following a slider here.
|
||||
case Spinner spinner:
|
||||
{
|
||||
Vector2 difference = startPosition - SPINNER_CENTRE;
|
||||
|
||||
float radius = difference.Length;
|
||||
@ -315,9 +315,8 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
|
||||
endFrame.Position = endPosition;
|
||||
break;
|
||||
}
|
||||
|
||||
case Slider slider:
|
||||
{
|
||||
for (double j = FrameDelay; j < slider.Duration; j += FrameDelay)
|
||||
{
|
||||
Vector2 pos = slider.StackedPositionAt(j / slider.Duration);
|
||||
@ -326,7 +325,6 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
|
||||
AddFrameToReplay(new OsuReplayFrame(slider.EndTime, new Vector2(slider.StackedEndPosition.X, slider.StackedEndPosition.Y), action));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed!
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Input.StateChanges;
|
||||
using osu.Framework.MathUtils;
|
||||
@ -24,10 +25,14 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!HasFrames)
|
||||
var frame = CurrentFrame;
|
||||
|
||||
if (frame == null)
|
||||
return null;
|
||||
|
||||
return Interpolation.ValueAt(CurrentTime, CurrentFrame.Position, NextFrame.Position, CurrentFrame.Time, NextFrame.Time);
|
||||
Debug.Assert(CurrentTime != null);
|
||||
|
||||
return NextFrame != null ? Interpolation.ValueAt(CurrentTime.Value, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time) : frame.Position;
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
},
|
||||
new ReplayState<OsuAction>
|
||||
{
|
||||
PressedActions = CurrentFrame.Actions
|
||||
PressedActions = CurrentFrame?.Actions ?? new List<OsuAction>()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
{
|
||||
internal class OsuScoreProcessor : ScoreProcessor<OsuHitObject>
|
||||
{
|
||||
public OsuScoreProcessor(RulesetContainer<OsuHitObject> rulesetContainer)
|
||||
: base(rulesetContainer)
|
||||
public OsuScoreProcessor(DrawableRuleset<OsuHitObject> drawableRuleset)
|
||||
: base(drawableRuleset)
|
||||
{
|
||||
}
|
||||
|
||||
@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
comboResultCounts.Clear();
|
||||
}
|
||||
|
||||
private const double harshness = 0.01;
|
||||
|
||||
protected override void ApplyResult(JudgementResult result)
|
||||
{
|
||||
base.ApplyResult(result);
|
||||
@ -47,28 +45,29 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
|
||||
if (result.Type != HitResult.None)
|
||||
comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1;
|
||||
}
|
||||
|
||||
protected override double HealthAdjustmentFactorFor(JudgementResult result)
|
||||
{
|
||||
switch (result.Type)
|
||||
{
|
||||
case HitResult.Great:
|
||||
Health.Value += (10.2 - hpDrainRate) * harshness;
|
||||
break;
|
||||
return 10.2 - hpDrainRate;
|
||||
|
||||
case HitResult.Good:
|
||||
Health.Value += (8 - hpDrainRate) * harshness;
|
||||
break;
|
||||
return 8 - hpDrainRate;
|
||||
|
||||
case HitResult.Meh:
|
||||
Health.Value += (4 - hpDrainRate) * harshness;
|
||||
break;
|
||||
return 4 - hpDrainRate;
|
||||
|
||||
/*case HitResult.SliderTick:
|
||||
Health.Value += Math.Max(7 - hpDrainRate, 0) * 0.01;
|
||||
break;*/
|
||||
// case HitResult.SliderTick:
|
||||
// return Math.Max(7 - hpDrainRate, 0) * 0.01;
|
||||
|
||||
case HitResult.Miss:
|
||||
Health.Value -= hpDrainRate * (harshness * 2);
|
||||
break;
|
||||
return hpDrainRate;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,22 +43,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
private readonly InputResampler resampler = new InputResampler();
|
||||
|
||||
protected override DrawNode CreateDrawNode() => new TrailDrawNode();
|
||||
|
||||
protected override void ApplyDrawNode(DrawNode node)
|
||||
{
|
||||
base.ApplyDrawNode(node);
|
||||
|
||||
TrailDrawNode tNode = (TrailDrawNode)node;
|
||||
tNode.Shader = shader;
|
||||
tNode.Texture = texture;
|
||||
tNode.Size = size;
|
||||
tNode.Time = time;
|
||||
|
||||
for (int i = 0; i < parts.Length; ++i)
|
||||
if (parts[i].InvalidationID > tNode.Parts[i].InvalidationID)
|
||||
tNode.Parts[i] = parts[i];
|
||||
}
|
||||
protected override DrawNode CreateDrawNode() => new TrailDrawNode(this);
|
||||
|
||||
public CursorTrail()
|
||||
{
|
||||
@ -167,33 +152,53 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
private class TrailDrawNode : DrawNode
|
||||
{
|
||||
public IShader Shader;
|
||||
public Texture Texture;
|
||||
protected new CursorTrail Source => (CursorTrail)base.Source;
|
||||
|
||||
public float Time;
|
||||
private IShader shader;
|
||||
private Texture texture;
|
||||
|
||||
public readonly TrailPart[] Parts = new TrailPart[max_sprites];
|
||||
public Vector2 Size;
|
||||
private float time;
|
||||
|
||||
private readonly TrailPart[] parts = new TrailPart[max_sprites];
|
||||
private Vector2 size;
|
||||
|
||||
private readonly VertexBuffer<TexturedTrailVertex> vertexBuffer = new QuadVertexBuffer<TexturedTrailVertex>(max_sprites, BufferUsageHint.DynamicDraw);
|
||||
|
||||
public TrailDrawNode()
|
||||
public TrailDrawNode(CursorTrail source)
|
||||
: base(source)
|
||||
{
|
||||
for (int i = 0; i < max_sprites; i++)
|
||||
{
|
||||
Parts[i].InvalidationID = 0;
|
||||
Parts[i].WasUpdated = false;
|
||||
parts[i].InvalidationID = 0;
|
||||
parts[i].WasUpdated = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ApplyState()
|
||||
{
|
||||
base.ApplyState();
|
||||
|
||||
shader = Source.shader;
|
||||
texture = Source.texture;
|
||||
size = Source.size;
|
||||
time = Source.time;
|
||||
|
||||
for (int i = 0; i < Source.parts.Length; ++i)
|
||||
{
|
||||
if (Source.parts[i].InvalidationID > parts[i].InvalidationID)
|
||||
parts[i] = Source.parts[i];
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(Action<TexturedVertex2D> vertexAction)
|
||||
{
|
||||
Shader.GetUniform<float>("g_FadeClock").UpdateValue(ref Time);
|
||||
shader.GetUniform<float>("g_FadeClock").UpdateValue(ref time);
|
||||
|
||||
int updateStart = -1, updateEnd = 0;
|
||||
for (int i = 0; i < Parts.Length; ++i)
|
||||
|
||||
for (int i = 0; i < parts.Length; ++i)
|
||||
{
|
||||
if (Parts[i].WasUpdated)
|
||||
if (parts[i].WasUpdated)
|
||||
{
|
||||
if (updateStart == -1)
|
||||
updateStart = i;
|
||||
@ -202,22 +207,22 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
int start = i * 4;
|
||||
int end = start;
|
||||
|
||||
Vector2 pos = Parts[i].Position;
|
||||
float time = Parts[i].Time;
|
||||
Vector2 pos = parts[i].Position;
|
||||
float localTime = parts[i].Time;
|
||||
|
||||
Texture.DrawQuad(
|
||||
new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y),
|
||||
texture.DrawQuad(
|
||||
new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y),
|
||||
DrawColourInfo.Colour,
|
||||
null,
|
||||
v => vertexBuffer.Vertices[end++] = new TexturedTrailVertex
|
||||
{
|
||||
Position = v.Position,
|
||||
TexturePosition = v.TexturePosition,
|
||||
Time = time + 1,
|
||||
Time = localTime + 1,
|
||||
Colour = v.Colour,
|
||||
});
|
||||
|
||||
Parts[i].WasUpdated = false;
|
||||
parts[i].WasUpdated = false;
|
||||
}
|
||||
else if (updateStart != -1)
|
||||
{
|
||||
@ -232,12 +237,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
base.Draw(vertexAction);
|
||||
|
||||
Shader.Bind();
|
||||
shader.Bind();
|
||||
|
||||
Texture.TextureGL.Bind();
|
||||
texture.TextureGL.Bind();
|
||||
vertexBuffer.Draw();
|
||||
|
||||
Shader.Unbind();
|
||||
shader.Unbind();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
|
@ -1,223 +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.Allocation;
|
||||
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.Bindings;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
{
|
||||
public class GameplayCursorContainer : CursorContainer, IKeyBindingHandler<OsuAction>
|
||||
{
|
||||
protected override Drawable CreateCursor() => new OsuCursor();
|
||||
|
||||
protected override Container<Drawable> Content => fadeContainer;
|
||||
|
||||
private readonly Container<Drawable> fadeContainer;
|
||||
|
||||
public GameplayCursorContainer()
|
||||
{
|
||||
InternalChild = fadeContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new CursorTrail { Depth = 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private int downCount;
|
||||
|
||||
private void updateExpandedState()
|
||||
{
|
||||
if (downCount > 0)
|
||||
(ActiveCursor as OsuCursor)?.Expand();
|
||||
else
|
||||
(ActiveCursor as OsuCursor)?.Contract();
|
||||
}
|
||||
|
||||
public bool OnPressed(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
downCount++;
|
||||
updateExpandedState();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
if (--downCount == 0)
|
||||
updateExpandedState();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool HandlePositionalInput => true; // OverlayContainer will set this false when we go hidden, but we always want to receive input.
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
fadeContainer.FadeTo(1, 300, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(1, 400, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint);
|
||||
}
|
||||
|
||||
public class OsuCursor : SkinReloadableDrawable
|
||||
{
|
||||
private bool cursorExpand;
|
||||
|
||||
private Bindable<double> cursorScale;
|
||||
private Bindable<bool> autoCursorScale;
|
||||
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
private Container expandTarget;
|
||||
private Drawable scaleTarget;
|
||||
|
||||
public OsuCursor()
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
Size = new Vector2(28);
|
||||
}
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
cursorExpand = skin.GetValue<SkinConfiguration, bool>(s => s.CursorExpand ?? true);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config, IBindable<WorkingBeatmap> beatmap)
|
||||
{
|
||||
InternalChild = expandTarget = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Child = scaleTarget = new SkinnableDrawable("cursor", _ => new CircularContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
BorderThickness = Size.X / 6,
|
||||
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,
|
||||
BorderThickness = Size.X / 3,
|
||||
BorderColour = Color4.White.Opacity(0.5f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.1f),
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.White,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}, restrictSize: false)
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
};
|
||||
|
||||
this.beatmap.BindTo(beatmap);
|
||||
this.beatmap.ValueChanged += _ => calculateScale();
|
||||
|
||||
cursorScale = config.GetBindable<double>(OsuSetting.GameplayCursorSize);
|
||||
cursorScale.ValueChanged += _ => calculateScale();
|
||||
|
||||
autoCursorScale = config.GetBindable<bool>(OsuSetting.AutoCursorSize);
|
||||
autoCursorScale.ValueChanged += _ => calculateScale();
|
||||
|
||||
calculateScale();
|
||||
}
|
||||
|
||||
private void calculateScale()
|
||||
{
|
||||
float scale = (float)cursorScale.Value;
|
||||
|
||||
if (autoCursorScale.Value && beatmap.Value != null)
|
||||
{
|
||||
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
|
||||
scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY);
|
||||
}
|
||||
|
||||
scaleTarget.Scale = new Vector2(scale);
|
||||
}
|
||||
|
||||
private const float pressed_scale = 1.2f;
|
||||
private const float released_scale = 1f;
|
||||
|
||||
public void Expand()
|
||||
{
|
||||
if (!cursorExpand) return;
|
||||
|
||||
expandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad);
|
||||
}
|
||||
|
||||
public void Contract() => expandTarget.ScaleTo(released_scale, 100, Easing.OutQuad);
|
||||
}
|
||||
}
|
||||
}
|
149
osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs
Normal file
149
osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs
Normal file
@ -0,0 +1,149 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
{
|
||||
public class OsuCursor : SkinReloadableDrawable
|
||||
{
|
||||
private bool cursorExpand;
|
||||
|
||||
private Bindable<double> cursorScale;
|
||||
private Bindable<bool> autoCursorScale;
|
||||
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
private Container expandTarget;
|
||||
private Drawable scaleTarget;
|
||||
|
||||
public OsuCursor()
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
Size = new Vector2(28);
|
||||
}
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
cursorExpand = skin.GetValue<SkinConfiguration, bool>(s => s.CursorExpand ?? true);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config, IBindable<WorkingBeatmap> beatmap)
|
||||
{
|
||||
InternalChild = expandTarget = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Child = scaleTarget = new SkinnableDrawable("cursor", _ => new CircularContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
BorderThickness = Size.X / 6,
|
||||
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,
|
||||
BorderThickness = Size.X / 3,
|
||||
BorderColour = Color4.White.Opacity(0.5f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.1f),
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.White,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}, restrictSize: false)
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
};
|
||||
|
||||
this.beatmap.BindTo(beatmap);
|
||||
this.beatmap.ValueChanged += _ => calculateScale();
|
||||
|
||||
cursorScale = config.GetBindable<double>(OsuSetting.GameplayCursorSize);
|
||||
cursorScale.ValueChanged += _ => calculateScale();
|
||||
|
||||
autoCursorScale = config.GetBindable<bool>(OsuSetting.AutoCursorSize);
|
||||
autoCursorScale.ValueChanged += _ => calculateScale();
|
||||
|
||||
calculateScale();
|
||||
}
|
||||
|
||||
private void calculateScale()
|
||||
{
|
||||
float scale = (float)cursorScale.Value;
|
||||
|
||||
if (autoCursorScale.Value && beatmap.Value != null)
|
||||
{
|
||||
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
|
||||
scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY);
|
||||
}
|
||||
|
||||
scaleTarget.Scale = new Vector2(scale);
|
||||
}
|
||||
|
||||
private const float pressed_scale = 1.2f;
|
||||
private const float released_scale = 1f;
|
||||
|
||||
public void Expand()
|
||||
{
|
||||
if (!cursorExpand) return;
|
||||
|
||||
expandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad);
|
||||
}
|
||||
|
||||
public void Contract() => expandTarget.ScaleTo(released_scale, 100, Easing.OutQuad);
|
||||
}
|
||||
}
|
98
osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs
Normal file
98
osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs
Normal file
@ -0,0 +1,98 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Osu.Configuration;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
{
|
||||
public class OsuCursorContainer : GameplayCursorContainer, IKeyBindingHandler<OsuAction>
|
||||
{
|
||||
protected override Drawable CreateCursor() => new OsuCursor();
|
||||
|
||||
protected override Container<Drawable> Content => fadeContainer;
|
||||
|
||||
private readonly Container<Drawable> fadeContainer;
|
||||
|
||||
private readonly Bindable<bool> showTrail = new Bindable<bool>(true);
|
||||
|
||||
private readonly CursorTrail cursorTrail;
|
||||
|
||||
public OsuCursorContainer()
|
||||
{
|
||||
InternalChild = fadeContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
cursorTrail = new CursorTrail { Depth = 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuRulesetConfigManager config)
|
||||
{
|
||||
config?.BindWith(OsuRulesetSetting.ShowCursorTrail, showTrail);
|
||||
|
||||
showTrail.BindValueChanged(v => cursorTrail.FadeTo(v.NewValue ? 1 : 0, 200), true);
|
||||
}
|
||||
|
||||
private int downCount;
|
||||
|
||||
private void updateExpandedState()
|
||||
{
|
||||
if (downCount > 0)
|
||||
(ActiveCursor as OsuCursor)?.Expand();
|
||||
else
|
||||
(ActiveCursor as OsuCursor)?.Contract();
|
||||
}
|
||||
|
||||
public bool OnPressed(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
downCount++;
|
||||
updateExpandedState();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
if (--downCount == 0)
|
||||
updateExpandedState();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool HandlePositionalInput => true; // OverlayContainer will set this false when we go hidden, but we always want to receive input.
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
fadeContainer.FadeTo(1, 300, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(1, 400, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,14 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Input.Handlers;
|
||||
using osu.Game.Replays;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Configuration;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
@ -14,15 +17,16 @@ using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.Osu.Scoring;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI
|
||||
{
|
||||
public class OsuRulesetContainer : RulesetContainer<OsuPlayfield, OsuHitObject>
|
||||
public class DrawableOsuRuleset : DrawableRuleset<OsuHitObject>
|
||||
{
|
||||
protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config;
|
||||
|
||||
public OsuRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
public DrawableOsuRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
}
|
||||
|
||||
@ -30,16 +34,22 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuPlayfield();
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo);
|
||||
protected override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo);
|
||||
|
||||
public override DrawableHitObject<OsuHitObject> GetVisualRepresentation(OsuHitObject h)
|
||||
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer();
|
||||
|
||||
protected override ResumeOverlay CreateResumeOverlay() => new OsuResumeOverlay();
|
||||
|
||||
public override DrawableHitObject<OsuHitObject> CreateDrawableRepresentation(OsuHitObject h)
|
||||
{
|
||||
switch (h)
|
||||
{
|
||||
case HitCircle circle:
|
||||
return new DrawableHitCircle(circle);
|
||||
|
||||
case Slider slider:
|
||||
return new DrawableSlider(slider);
|
||||
|
||||
case Spinner spinner:
|
||||
return new DrawableSpinner(spinner);
|
||||
}
|
||||
@ -54,7 +64,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
get
|
||||
{
|
||||
var first = (OsuHitObject)Objects.First();
|
||||
return first.StartTime - first.TimePreempt;
|
||||
return first.StartTime - Math.Max(2000, first.TimePreempt);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Connections;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||
|
||||
@ -24,41 +23,28 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
public static readonly Vector2 BASE_SIZE = new Vector2(512, 384);
|
||||
|
||||
private readonly PlayfieldAdjustmentContainer adjustmentContainer;
|
||||
|
||||
protected override Container CursorTargetContainer => adjustmentContainer;
|
||||
|
||||
protected override CursorContainer CreateCursor() => new GameplayCursorContainer();
|
||||
protected override GameplayCursorContainer CreateCursor() => new OsuCursorContainer();
|
||||
|
||||
public OsuPlayfield()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Size = new Vector2(0.75f);
|
||||
|
||||
InternalChild = adjustmentContainer = new PlayfieldAdjustmentContainer
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
connectionLayer = new FollowPointRenderer
|
||||
{
|
||||
connectionLayer = new FollowPointRenderer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = 2,
|
||||
},
|
||||
judgementLayer = new JudgementContainer<DrawableOsuJudgement>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = 1,
|
||||
},
|
||||
HitObjectContainer,
|
||||
approachCircles = new ApproachCircleProxyContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = -1,
|
||||
},
|
||||
}
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = 2,
|
||||
},
|
||||
judgementLayer = new JudgementContainer<DrawableOsuJudgement>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = 1,
|
||||
},
|
||||
HitObjectContainer,
|
||||
approachCircles = new ApproachCircleProxyContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = -1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3,17 +3,23 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI
|
||||
{
|
||||
public class PlayfieldAdjustmentContainer : Container
|
||||
public class OsuPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer
|
||||
{
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container content;
|
||||
|
||||
public PlayfieldAdjustmentContainer()
|
||||
public OsuPlayfieldAdjustmentContainer()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Size = new Vector2(0.75f);
|
||||
|
||||
InternalChild = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
109
osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs
Normal file
109
osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI
|
||||
{
|
||||
public class OsuResumeOverlay : ResumeOverlay
|
||||
{
|
||||
private OsuClickToResumeCursor clickToResumeCursor;
|
||||
|
||||
private GameplayCursorContainer localCursorContainer;
|
||||
|
||||
public override CursorContainer LocalCursor => State == Visibility.Visible ? localCursorContainer : null;
|
||||
|
||||
protected override string Message => "Click the orange cursor to resume";
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(clickToResumeCursor = new OsuClickToResumeCursor { ResumeRequested = Resume });
|
||||
}
|
||||
|
||||
public override void Show()
|
||||
{
|
||||
base.Show();
|
||||
clickToResumeCursor.ShowAt(GameplayCursor.ActiveCursor.Position);
|
||||
|
||||
if (localCursorContainer == null)
|
||||
Add(localCursorContainer = new OsuCursorContainer());
|
||||
}
|
||||
|
||||
public override void Hide()
|
||||
{
|
||||
localCursorContainer?.Expire();
|
||||
localCursorContainer = null;
|
||||
|
||||
base.Hide();
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e) => true;
|
||||
|
||||
public class OsuClickToResumeCursor : OsuCursor, IKeyBindingHandler<OsuAction>
|
||||
{
|
||||
public override bool HandlePositionalInput => true;
|
||||
|
||||
public Action ResumeRequested;
|
||||
|
||||
public OsuClickToResumeCursor()
|
||||
{
|
||||
RelativePositionAxes = Axes.Both;
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
updateColour();
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateColour();
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
public bool OnPressed(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
if (!IsHovered) return false;
|
||||
|
||||
this.ScaleTo(new Vector2(2), TRANSITION_TIME, Easing.OutQuint);
|
||||
|
||||
ResumeRequested?.Invoke();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(OsuAction action) => false;
|
||||
|
||||
public void ShowAt(Vector2 activeCursorPosition) => Schedule(() =>
|
||||
{
|
||||
updateColour();
|
||||
this.MoveTo(activeCursorPosition);
|
||||
this.ScaleTo(new Vector2(4)).Then().ScaleTo(Vector2.One, 1000, Easing.OutQuint);
|
||||
});
|
||||
|
||||
private void updateColour()
|
||||
{
|
||||
this.FadeColour(IsHovered ? Color4.White : Color4.Orange, 400, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -34,6 +34,11 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
LabelText = "Snaking out sliders",
|
||||
Bindable = config.GetBindable<bool>(OsuRulesetSetting.SnakingOutSliders)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Cursor trail",
|
||||
Bindable = config.GetBindable<bool>(OsuRulesetSetting.ShowCursorTrail)
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user