diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 58c24181d3..b51ecb4f7e 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -31,6 +31,12 @@
"commands": [
"CodeFileSanity"
]
+ },
+ "ppy.localisationanalyser.tools": {
+ "version": "2021.524.0",
+ "commands": [
+ "localisation"
+ ]
}
}
}
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/02-feature-request-issues.md b/.github/ISSUE_TEMPLATE/02-feature-request-issues.md
deleted file mode 100644
index c3357dd780..0000000000
--- a/.github/ISSUE_TEMPLATE/02-feature-request-issues.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: Feature Request
-about: Propose a feature you would like to see in the game!
----
-**Describe the new feature:**
-
-**Proposal designs of the feature:**
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 69baeee60c..c62231e8e0 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,5 +1,12 @@
blank_issues_enabled: false
contact_links:
+ - name: Suggestions or feature request
+ url: https://github.com/ppy/osu/discussions/categories/ideas
+ about: Got something you think should change or be added? Search for or start a new discussion!
+ - name: Help
+ url: https://github.com/ppy/osu/discussions/categories/q-a
+ about: osu! not working as you'd expect? Not sure it's a bug? Check the Q&A section!
- name: osu!stable issues
url: https://github.com/ppy/osu-stable-issues
- about: For issues regarding osu!stable (not osu!lazer), open them here.
+ about: For osu!stable bugs (not osu!lazer), check out the dedicated repository. Note that we only accept serious bug reports.
+
diff --git a/osu.Android.props b/osu.Android.props
index 90d131b117..bcd5f9bd9a 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,6 +52,6 @@
-
+
diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs
index e3c457693e..23ce444560 100644
--- a/osu.Game.Rulesets.Catch/CatchRuleset.cs
+++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs
@@ -161,13 +161,13 @@ namespace osu.Game.Rulesets.Catch
switch (result)
{
case HitResult.LargeTickHit:
- return "large droplet";
+ return "Large droplet";
case HitResult.SmallTickHit:
- return "small droplet";
+ return "Small droplet";
case HitResult.LargeBonus:
- return "banana";
+ return "Banana";
}
return base.GetDisplayNameForHitResult(result);
diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs
index 46a9cc6f70..05580f6d06 100644
--- a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs
+++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs
@@ -44,53 +44,51 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
break;
}
-
- return null;
}
- if (!(component is CatchSkinComponent catchSkinComponent))
- return null;
-
- switch (catchSkinComponent.Component)
+ if (component is CatchSkinComponent catchSkinComponent)
{
- case CatchSkinComponents.Fruit:
- if (GetTexture("fruit-pear") != null)
- return new LegacyFruitPiece();
+ switch (catchSkinComponent.Component)
+ {
+ case CatchSkinComponents.Fruit:
+ if (GetTexture("fruit-pear") != null)
+ return new LegacyFruitPiece();
- break;
+ return null;
- case CatchSkinComponents.Banana:
- if (GetTexture("fruit-bananas") != null)
- return new LegacyBananaPiece();
+ case CatchSkinComponents.Banana:
+ if (GetTexture("fruit-bananas") != null)
+ return new LegacyBananaPiece();
- break;
+ return null;
- case CatchSkinComponents.Droplet:
- if (GetTexture("fruit-drop") != null)
- return new LegacyDropletPiece();
+ case CatchSkinComponents.Droplet:
+ if (GetTexture("fruit-drop") != null)
+ return new LegacyDropletPiece();
- break;
+ return null;
- case CatchSkinComponents.CatcherIdle:
- return this.GetAnimation("fruit-catcher-idle", true, true, true) ??
- this.GetAnimation("fruit-ryuuta", true, true, true);
+ case CatchSkinComponents.CatcherIdle:
+ return this.GetAnimation("fruit-catcher-idle", true, true, true) ??
+ this.GetAnimation("fruit-ryuuta", true, true, true);
- case CatchSkinComponents.CatcherFail:
- return this.GetAnimation("fruit-catcher-fail", true, true, true) ??
- this.GetAnimation("fruit-ryuuta", true, true, true);
+ case CatchSkinComponents.CatcherFail:
+ return this.GetAnimation("fruit-catcher-fail", true, true, true) ??
+ this.GetAnimation("fruit-ryuuta", true, true, true);
- case CatchSkinComponents.CatcherKiai:
- return this.GetAnimation("fruit-catcher-kiai", true, true, true) ??
- this.GetAnimation("fruit-ryuuta", true, true, true);
+ case CatchSkinComponents.CatcherKiai:
+ return this.GetAnimation("fruit-catcher-kiai", true, true, true) ??
+ this.GetAnimation("fruit-ryuuta", true, true, true);
- case CatchSkinComponents.CatchComboCounter:
- if (providesComboCounter)
- return new LegacyCatchComboCounter(Source);
+ case CatchSkinComponents.CatchComboCounter:
+ if (providesComboCounter)
+ return new LegacyCatchComboCounter(Source);
- break;
+ return null;
+ }
}
- return null;
+ return Source.GetDrawableComponent(component);
}
public override IBindable GetConfig(TLookup lookup)
diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs
index 24ccae895d..261b8b1fad 100644
--- a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs
+++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs
@@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
break;
}
- return null;
+ return Source.GetDrawableComponent(component);
}
private Drawable getResult(HitResult result)
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs
index f697a77d94..0a7ef443b1 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs
@@ -5,12 +5,14 @@ using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
+using osu.Framework.Testing;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
+using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Rulesets.Osu.Tests
@@ -32,6 +34,16 @@ namespace osu.Game.Rulesets.Osu.Tests
AddStep($"{term} Small", () => SetContents(() => testSingle(7, autoplay)));
}
+ [Test]
+ public void TestSpinningSamplePitchShift()
+ {
+ AddStep("Add spinner", () => SetContents(() => testSingle(5, true, 4000)));
+ AddUntilStep("Pitch starts low", () => getSpinningSample().Frequency.Value < 0.8);
+ AddUntilStep("Pitch increases", () => getSpinningSample().Frequency.Value > 0.8);
+
+ PausableSkinnableSound getSpinningSample() => drawableSpinner.ChildrenOfType().FirstOrDefault(s => s.Samples.Any(i => i.LookupNames.Any(l => l.Contains("spinnerspin"))));
+ }
+
[TestCase(false)]
[TestCase(true)]
public void TestLongSpinner(bool autoplay)
@@ -93,7 +105,7 @@ namespace osu.Game.Rulesets.Osu.Tests
{
base.Update();
if (auto)
- RotationTracker.AddRotation((float)(Clock.ElapsedFrameTime * 3));
+ RotationTracker.AddRotation((float)(Clock.ElapsedFrameTime * 2));
}
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
index 44c3056910..c36768baba 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
@@ -243,7 +243,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
int totalCount = Pieces.Count(p => p.IsSelected.Value);
int countOfState = Pieces.Where(p => p.IsSelected.Value).Count(p => p.ControlPoint.Type.Value == type);
- var item = new PathTypeMenuItem(type, () =>
+ var item = new TernaryStateRadioMenuItem(type == null ? "Inherit" : type.ToString().Humanize(), MenuItemType.Standard, _ =>
{
foreach (var p in Pieces.Where(p => p.IsSelected.Value))
updatePathType(p, type);
@@ -258,15 +258,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
return item;
}
-
- private class PathTypeMenuItem : TernaryStateMenuItem
- {
- public PathTypeMenuItem(PathType? type, Action action)
- : base(type == null ? "Inherit" : type.ToString().Humanize(), changeState, MenuItemType.Standard, _ => action?.Invoke())
- {
- }
-
- private static TernaryState changeState(TernaryState state) => TernaryState.True;
- }
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs
index ec97f1fd78..e810d2fe0c 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs
@@ -16,6 +16,7 @@ using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
using osu.Game.Rulesets.Osu.Objects;
+using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose;
using osuTK;
@@ -25,6 +26,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
public class SliderSelectionBlueprint : OsuSelectionBlueprint
{
+ protected new DrawableSlider DrawableObject => (DrawableSlider)base.DrawableObject;
+
protected SliderBodyPiece BodyPiece { get; private set; }
protected SliderCircleOverlay HeadOverlay { get; private set; }
protected SliderCircleOverlay TailOverlay { get; private set; }
@@ -236,7 +239,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)),
};
- public override Vector2 ScreenSpaceSelectionPoint => BodyPiece.ToScreenSpace(BodyPiece.PathStartLocation);
+ // Always refer to the drawable object's slider body so subsequent movement deltas are calculated with updated positions.
+ public override Vector2 ScreenSpaceSelectionPoint => DrawableObject.SliderBody?.ToScreenSpace(DrawableObject.SliderBody.PathOffset)
+ ?? BodyPiece.ToScreenSpace(BodyPiece.PathStartLocation);
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
BodyPiece.ReceivePositionalInputAt(screenSpacePos) || ControlPointVisualiser?.Pieces.Any(p => p.ReceivePositionalInputAt(screenSpacePos)) == true;
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs
index aaf3517c9c..57d0cd859d 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs
@@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd . 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.Graphics;
@@ -12,7 +11,7 @@ using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit.Compose.Components;
-using Vector2 = osuTK.Vector2;
+using osuTK;
namespace osu.Game.Rulesets.Osu.Edit
{
@@ -173,12 +172,12 @@ namespace osu.Game.Rulesets.Osu.Edit
foreach (var h in hitObjects)
{
- h.Position = rotatePointAroundOrigin(h.Position, referenceOrigin.Value, delta);
+ h.Position = RotatePointAroundOrigin(h.Position, referenceOrigin.Value, delta);
if (h is IHasPath path)
{
foreach (var point in path.Path.ControlPoints)
- point.Position.Value = rotatePointAroundOrigin(point.Position.Value, Vector2.Zero, delta);
+ point.Position.Value = RotatePointAroundOrigin(point.Position.Value, Vector2.Zero, delta);
}
}
@@ -225,26 +224,10 @@ namespace osu.Game.Rulesets.Osu.Edit
private void scaleHitObjects(OsuHitObject[] hitObjects, Anchor reference, Vector2 scale)
{
scale = getClampedScale(hitObjects, reference, scale);
-
- // move the selection before scaling if dragging from top or left anchors.
- float xOffset = ((reference & Anchor.x0) > 0) ? -scale.X : 0;
- float yOffset = ((reference & Anchor.y0) > 0) ? -scale.Y : 0;
-
Quad selectionQuad = getSurroundingQuad(hitObjects);
foreach (var h in hitObjects)
- {
- var newPosition = h.Position;
-
- // guard against no-ops and NaN.
- if (scale.X != 0 && selectionQuad.Width > 0)
- newPosition.X = selectionQuad.TopLeft.X + xOffset + (h.X - selectionQuad.TopLeft.X) / selectionQuad.Width * (selectionQuad.Width + scale.X);
-
- if (scale.Y != 0 && selectionQuad.Height > 0)
- newPosition.Y = selectionQuad.TopLeft.Y + yOffset + (h.Y - selectionQuad.TopLeft.Y) / selectionQuad.Height * (selectionQuad.Height + scale.Y);
-
- h.Position = newPosition;
- }
+ h.Position = GetScaledPosition(reference, scale, selectionQuad, h.Position);
}
private (bool X, bool Y) isQuadInBounds(Quad quad)
@@ -340,28 +323,5 @@ namespace osu.Game.Rulesets.Osu.Edit
private OsuHitObject[] selectedMovableObjects => SelectedItems.OfType()
.Where(h => !(h is Spinner))
.ToArray();
-
- ///
- /// Rotate a point around an arbitrary origin.
- ///
- /// The point.
- /// The centre origin to rotate around.
- /// The angle to rotate (in degrees).
- private static Vector2 rotatePointAroundOrigin(Vector2 point, Vector2 origin, float angle)
- {
- angle = -angle;
-
- point.X -= origin.X;
- point.Y -= origin.Y;
-
- Vector2 ret;
- ret.X = point.X * MathF.Cos(MathUtils.DegreesToRadians(angle)) + point.Y * MathF.Sin(MathUtils.DegreesToRadians(angle));
- ret.Y = point.X * -MathF.Sin(MathUtils.DegreesToRadians(angle)) + point.Y * MathF.Cos(MathUtils.DegreesToRadians(angle));
-
- ret.X += origin.X;
- ret.Y += origin.Y;
-
- return ret;
- }
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index 82b5492de6..0bec33bf77 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -34,7 +34,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public override bool DisplayResult => !HitObject.OnlyJudgeNestedObjects;
- private PlaySliderBody sliderBody => Body.Drawable as PlaySliderBody;
+ [CanBeNull]
+ public PlaySliderBody SliderBody => Body.Drawable as PlaySliderBody;
public IBindable PathVersion => pathVersion;
private readonly Bindable pathVersion = new Bindable();
@@ -215,16 +216,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
double completionProgress = Math.Clamp((Time.Current - HitObject.StartTime) / HitObject.Duration, 0, 1);
Ball.UpdateProgress(completionProgress);
- sliderBody?.UpdateProgress(completionProgress);
+ SliderBody?.UpdateProgress(completionProgress);
foreach (DrawableHitObject hitObject in NestedHitObjects)
{
- if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(HitObject.Path.PositionAt(sliderBody?.SnakedStart ?? 0), HitObject.Path.PositionAt(sliderBody?.SnakedEnd ?? 0));
+ if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(HitObject.Path.PositionAt(SliderBody?.SnakedStart ?? 0), HitObject.Path.PositionAt(SliderBody?.SnakedEnd ?? 0));
if (hitObject is IRequireTracking t) t.Tracking = Ball.Tracking;
}
- Size = sliderBody?.Size ?? Vector2.Zero;
- OriginPosition = sliderBody?.PathOffset ?? Vector2.Zero;
+ Size = SliderBody?.Size ?? Vector2.Zero;
+ OriginPosition = SliderBody?.PathOffset ?? Vector2.Zero;
if (DrawSize != Vector2.Zero)
{
@@ -238,7 +239,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public override void OnKilled()
{
base.OnKilled();
- sliderBody?.RecyclePath();
+ SliderBody?.RecyclePath();
}
protected override void ApplySkin(ISkinSource skin, bool allowFallback)
@@ -324,7 +325,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
case ArmedState.Hit:
Ball.ScaleTo(HitObject.Scale * 1.4f, fade_out_time, Easing.Out);
- if (sliderBody?.SnakingOut.Value == true)
+ if (SliderBody?.SnakingOut.Value == true)
Body.FadeOut(40); // short fade to allow for any body colour to smoothly disappear.
break;
}
@@ -332,7 +333,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
this.FadeOut(fade_out_time, Easing.OutQuint).Expire();
}
- public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => sliderBody?.ReceivePositionalInputAt(screenSpacePos) ?? base.ReceivePositionalInputAt(screenSpacePos);
+ public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => SliderBody?.ReceivePositionalInputAt(screenSpacePos) ?? base.ReceivePositionalInputAt(screenSpacePos);
private class DefaultSliderBody : PlaySliderBody
{
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs
index d81af053d1..cd6bf1d8d2 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs
@@ -7,13 +7,14 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects.Drawables;
+using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Skinning.Default;
using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
- public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking, ITrackSnaking, IHasMainCirclePiece
+ public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking, IHasMainCirclePiece
{
public new SliderTailCircle HitObject => (SliderTailCircle)base.HitObject;
@@ -111,7 +112,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
ApplyResult(r => r.Type = Tracking ? r.Judgement.MaxResult : r.Judgement.MinResult);
}
- public void UpdateSnakingPosition(Vector2 start, Vector2 end) =>
- Position = HitObject.RepeatIndex % 2 == 0 ? end : start;
+ protected override void OnApply()
+ {
+ base.OnApply();
+
+ if (Slider != null)
+ Position = Slider.CurvePositionAt(HitObject.RepeatIndex % 2 == 0 ? 1 : 0);
+ }
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
index 3a4753761a..19cee61f26 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
@@ -39,6 +39,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private Bindable isSpinning;
private bool spinnerFrequencyModulate;
+ private const float spinning_sample_initial_frequency = 1.0f;
+ private const float spinning_sample_modulated_base_frequency = 0.5f;
+
///
/// The amount of bonus score gained from spinning after the required number of spins, for display purposes.
///
@@ -106,9 +109,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
isSpinning.BindValueChanged(updateSpinningSample);
}
- private const float spinning_sample_initial_frequency = 1.0f;
- private const float spinning_sample_modulated_base_frequency = 0.5f;
-
protected override void OnFree()
{
base.OnFree();
diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs
index 88302ebc57..ffd4f78400 100644
--- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs
+++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs
@@ -34,90 +34,90 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
public override Drawable GetDrawableComponent(ISkinComponent component)
{
- if (!(component is OsuSkinComponent osuComponent))
- return null;
-
- switch (osuComponent.Component)
+ if (component is OsuSkinComponent osuComponent)
{
- case OsuSkinComponents.FollowPoint:
- return this.GetAnimation(component.LookupName, true, false, true, startAtCurrentTime: false);
+ switch (osuComponent.Component)
+ {
+ case OsuSkinComponents.FollowPoint:
+ return this.GetAnimation(component.LookupName, true, false, true, startAtCurrentTime: false);
- case OsuSkinComponents.SliderFollowCircle:
- var followCircle = this.GetAnimation("sliderfollowcircle", true, true, true);
- if (followCircle != null)
- // follow circles are 2x the hitcircle resolution in legacy skins (since they are scaled down from >1x
- followCircle.Scale *= 0.5f;
- return followCircle;
+ case OsuSkinComponents.SliderFollowCircle:
+ var followCircle = this.GetAnimation("sliderfollowcircle", true, true, true);
+ if (followCircle != null)
+ // follow circles are 2x the hitcircle resolution in legacy skins (since they are scaled down from >1x
+ followCircle.Scale *= 0.5f;
+ return followCircle;
- case OsuSkinComponents.SliderBall:
- var sliderBallContent = this.GetAnimation("sliderb", true, true, animationSeparator: "");
+ case OsuSkinComponents.SliderBall:
+ var sliderBallContent = this.GetAnimation("sliderb", true, true, animationSeparator: "");
- // todo: slider ball has a custom frame delay based on velocity
- // Math.Max((150 / Velocity) * GameBase.SIXTY_FRAME_TIME, GameBase.SIXTY_FRAME_TIME);
+ // todo: slider ball has a custom frame delay based on velocity
+ // Math.Max((150 / Velocity) * GameBase.SIXTY_FRAME_TIME, GameBase.SIXTY_FRAME_TIME);
- if (sliderBallContent != null)
- return new LegacySliderBall(sliderBallContent);
+ if (sliderBallContent != null)
+ return new LegacySliderBall(sliderBallContent);
- return null;
-
- case OsuSkinComponents.SliderBody:
- if (hasHitCircle.Value)
- return new LegacySliderBody();
-
- return null;
-
- case OsuSkinComponents.SliderTailHitCircle:
- if (hasHitCircle.Value)
- return new LegacyMainCirclePiece("sliderendcircle", false);
-
- return null;
-
- case OsuSkinComponents.SliderHeadHitCircle:
- if (hasHitCircle.Value)
- return new LegacyMainCirclePiece("sliderstartcircle");
-
- return null;
-
- case OsuSkinComponents.HitCircle:
- if (hasHitCircle.Value)
- return new LegacyMainCirclePiece();
-
- return null;
-
- case OsuSkinComponents.Cursor:
- if (Source.GetTexture("cursor") != null)
- return new LegacyCursor();
-
- return null;
-
- case OsuSkinComponents.CursorTrail:
- if (Source.GetTexture("cursortrail") != null)
- return new LegacyCursorTrail();
-
- return null;
-
- case OsuSkinComponents.HitCircleText:
- if (!this.HasFont(LegacyFont.HitCircle))
return null;
- return new LegacySpriteText(LegacyFont.HitCircle)
- {
- // stable applies a blanket 0.8x scale to hitcircle fonts
- Scale = new Vector2(0.8f),
- };
+ case OsuSkinComponents.SliderBody:
+ if (hasHitCircle.Value)
+ return new LegacySliderBody();
- case OsuSkinComponents.SpinnerBody:
- bool hasBackground = Source.GetTexture("spinner-background") != null;
+ return null;
- if (Source.GetTexture("spinner-top") != null && !hasBackground)
- return new LegacyNewStyleSpinner();
- else if (hasBackground)
- return new LegacyOldStyleSpinner();
+ case OsuSkinComponents.SliderTailHitCircle:
+ if (hasHitCircle.Value)
+ return new LegacyMainCirclePiece("sliderendcircle", false);
- return null;
+ return null;
+
+ case OsuSkinComponents.SliderHeadHitCircle:
+ if (hasHitCircle.Value)
+ return new LegacyMainCirclePiece("sliderstartcircle");
+
+ return null;
+
+ case OsuSkinComponents.HitCircle:
+ if (hasHitCircle.Value)
+ return new LegacyMainCirclePiece();
+
+ return null;
+
+ case OsuSkinComponents.Cursor:
+ if (Source.GetTexture("cursor") != null)
+ return new LegacyCursor();
+
+ return null;
+
+ case OsuSkinComponents.CursorTrail:
+ if (Source.GetTexture("cursortrail") != null)
+ return new LegacyCursorTrail();
+
+ return null;
+
+ case OsuSkinComponents.HitCircleText:
+ if (!this.HasFont(LegacyFont.HitCircle))
+ return null;
+
+ return new LegacySpriteText(LegacyFont.HitCircle)
+ {
+ // stable applies a blanket 0.8x scale to hitcircle fonts
+ Scale = new Vector2(0.8f),
+ };
+
+ case OsuSkinComponents.SpinnerBody:
+ bool hasBackground = Source.GetTexture("spinner-background") != null;
+
+ if (Source.GetTexture("spinner-top") != null && !hasBackground)
+ return new LegacyNewStyleSpinner();
+ else if (hasBackground)
+ return new LegacyOldStyleSpinner();
+
+ return null;
+ }
}
- return null;
+ return Source.GetDrawableComponent(component);
}
public override IBindable GetConfig(TLookup lookup)
diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
index b51f096d7d..90c99316b1 100644
--- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
+++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
@@ -79,8 +79,6 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
// Old osu! used hit sounding to determine various hit type information
IList samples = obj.Samples;
- bool strong = samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH);
-
switch (obj)
{
case IHasDistance distanceData:
@@ -94,15 +92,11 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing)
{
IList currentSamples = allSamples[i];
- bool isRim = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE);
- strong = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_FINISH);
yield return new Hit
{
StartTime = j,
- Type = isRim ? HitType.Rim : HitType.Centre,
Samples = currentSamples,
- IsStrong = strong
};
i = (i + 1) % allSamples.Count;
@@ -117,7 +111,6 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
{
StartTime = obj.StartTime,
Samples = obj.Samples,
- IsStrong = strong,
Duration = taikoDuration,
TickRate = beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate == 3 ? 3 : 4
};
@@ -143,16 +136,10 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
default:
{
- bool isRimDefinition(HitSampleInfo s) => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE;
-
- bool isRim = samples.Any(isRimDefinition);
-
yield return new Hit
{
StartTime = obj.StartTime,
- Type = isRim ? HitType.Rim : HitType.Centre,
Samples = samples,
- IsStrong = strong
};
break;
diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs
index 17e7fb81f6..0d0fd136a7 100644
--- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs
@@ -14,10 +14,10 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
{
private readonly HitPiece piece;
- private static Hit hit;
+ public new Hit HitObject => (Hit)base.HitObject;
public HitPlacementBlueprint()
- : base(hit = new Hit())
+ : base(new Hit())
{
InternalChild = piece = new HitPiece
{
@@ -30,12 +30,12 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
switch (e.Button)
{
case MouseButton.Left:
- hit.Type = HitType.Centre;
+ HitObject.Type = HitType.Centre;
EndPlacement(true);
return true;
case MouseButton.Right:
- hit.Type = HitType.Rim;
+ HitObject.Type = HitType.Rim;
EndPlacement(true);
return true;
}
diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs
index 48ee0d4cf4..ab3b729307 100644
--- a/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs
+++ b/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs
@@ -69,17 +69,21 @@ namespace osu.Game.Rulesets.Taiko.Edit
{
EditorBeatmap.PerformOnSelection(h =>
{
- if (h is Hit taikoHit) taikoHit.Type = state ? HitType.Rim : HitType.Centre;
+ if (h is Hit taikoHit)
+ {
+ taikoHit.Type = state ? HitType.Rim : HitType.Centre;
+ EditorBeatmap.Update(h);
+ }
});
}
protected override IEnumerable