diff --git a/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneAllSlides.cs b/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneAllSlides.cs index 0f518cf99..f485bc8b6 100644 --- a/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneAllSlides.cs +++ b/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneAllSlides.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Sentakki.Objects; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Slides; using osu.Game.Rulesets.Sentakki.UI; using osu.Game.Rulesets.Sentakki.UI.Components; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneFanSlide.cs b/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneFanSlide.cs index e03ace635..d858603bc 100644 --- a/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneFanSlide.cs +++ b/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneFanSlide.cs @@ -2,7 +2,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Sentakki.Objects; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Slides; using osu.Game.Rulesets.Sentakki.UI; using osu.Game.Rulesets.Sentakki.UI.Components; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneSlide.cs b/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneSlide.cs index 114e2c225..58d6f3d00 100644 --- a/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneSlide.cs +++ b/osu.Game.Rulesets.Sentakki.Tests/Objects/Slides/TestSceneSlide.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Sentakki.Objects; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Slides; using osu.Game.Rulesets.Sentakki.UI; using osu.Game.Rulesets.Sentakki.UI.Components; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneSlideFan.cs b/osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneSlideFan.cs index 89eec7906..f70987325 100644 --- a/osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneSlideFan.cs +++ b/osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneSlideFan.cs @@ -8,7 +8,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Sentakki.Objects; using osu.Game.Rulesets.Sentakki.Objects.Drawables; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Slides; using osu.Game.Rulesets.Sentakki.UI; using osu.Game.Rulesets.Sentakki.UI.Components; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneSlideNote.cs b/osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneSlideNote.cs index 7bbb5c5e8..8210a8612 100644 --- a/osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneSlideNote.cs +++ b/osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneSlideNote.cs @@ -9,7 +9,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Sentakki.Objects; using osu.Game.Rulesets.Sentakki.Objects.Drawables; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Slides; using osu.Game.Rulesets.Sentakki.UI; using osu.Game.Rulesets.Sentakki.UI.Components; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Sentakki/Mods/SentakkiModHidden.cs b/osu.Game.Rulesets.Sentakki/Mods/SentakkiModHidden.cs index 213063e17..37a73ae55 100644 --- a/osu.Game.Rulesets.Sentakki/Mods/SentakkiModHidden.cs +++ b/osu.Game.Rulesets.Sentakki/Mods/SentakkiModHidden.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Sentakki.Localisation.Mods; using osu.Game.Rulesets.Sentakki.Objects; using osu.Game.Rulesets.Sentakki.Objects.Drawables; +using osu.Game.Rulesets.Sentakki.Skinning.Default.TouchHolds; using osu.Game.Rulesets.Sentakki.UI; using osu.Game.Rulesets.UI; using osuTK; @@ -59,7 +60,7 @@ protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, break; case DrawableTouchHold th: - th.TouchHoldBody.ProgressPiece.Hide(); + ((TouchHoldBody)th.TouchHoldBody.Drawable).ProgressPiece.Hide(); break; case DrawableSlideBody sb: diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableHold.cs b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableHold.cs index ba0b547e2..9b08fe799 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableHold.cs +++ b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableHold.cs @@ -8,8 +8,10 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Sentakki.Skinning; +using osu.Game.Rulesets.Sentakki.Skinning.Default; using osu.Game.Rulesets.Sentakki.UI; +using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -22,7 +24,7 @@ public class DrawableHold : DrawableSentakkiLanedHitObject, IKeyBindingHandler headContainer = null!; - public HoldBody NoteBody = null!; + public SkinnableDrawable NoteBody = null!; public override double LifetimeStart { @@ -54,7 +56,14 @@ private void load() Anchor = Anchor.Centre; Origin = Anchor.Centre; AddRangeInternal(new Drawable[]{ - NoteBody = new HoldBody(), + NoteBody = new ProxyableSkinnableDrawable(new SentakkiSkinComponent(SentakkiSkinComponents.Hold), _=> new HoldBody()) + { + Scale = Vector2.Zero, + Position = new Vector2(0, -SentakkiPlayfield.NOTESTARTDISTANCE), + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.None, + }, headContainer = new Container { RelativeSizeAxes = Axes.Both }, }); } @@ -72,7 +81,7 @@ protected override void UpdateInitialTransforms() double animTime = AdjustedAnimationDuration / 2; NoteBody.FadeInFromZero(animTime).ScaleTo(1, animTime); - NoteBody.FadeColour(AccentColour.Value); + NoteBody.Drawable.FadeColour(AccentColour.Value); using (BeginDelayedSequence(animTime, true)) { @@ -90,7 +99,7 @@ protected override void UpdateInitialTransforms() .ResizeHeightTo(0, stretchTime); if (HoldStartTime == null && !Auto) - NoteBody.Delay(animTime).FadeColour(Color4.Gray, 100); + NoteBody.Drawable.Delay(animTime).FadeColour(Color4.Gray, 100); } } @@ -133,7 +142,7 @@ protected override void UpdateHitStateTransforms(ArmedState state) break; case ArmedState.Miss: - NoteBody.ScaleTo(0.5f, time_fade_miss, Easing.InCubic) + NoteBody.Drawable.ScaleTo(0.5f, time_fade_miss, Easing.InCubic) .FadeColour(Color4.Red, time_fade_miss, Easing.OutQuint) .MoveToOffset(new Vector2(0, -100), time_fade_miss, Easing.OutCubic) .FadeOut(time_fade_miss); diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideBody.cs b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideBody.cs index 94c374898..0ad5b1e3d 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideBody.cs +++ b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideBody.cs @@ -9,7 +9,9 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides; +using osu.Game.Rulesets.Sentakki.Skinning; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Slides; +using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -27,7 +29,7 @@ public class DrawableSlideBody : DrawableSentakkiLanedHitObject public SlideVisual Slidepath { get; private set; } = null!; - public Container SlideStars { get; private set; } = null!; + public Container SlideStars { get; private set; } = null!; private float starProgress; public virtual float StarProgress @@ -65,7 +67,7 @@ private void load() AddRangeInternal(new Drawable[] { Slidepath = new SlideVisual(), - SlideStars = new Container{ + SlideStars = new Container{ Anchor = Anchor.Centre, Origin = Anchor.Centre, }, @@ -77,7 +79,7 @@ private void load() }); for (int i = 0; i < 3; ++i) - SlideStars.Add(new StarPiece + SlideStars.Add(new ProxyableSkinnableDrawable(new SentakkiSkinComponent(SentakkiSkinComponents.SlideStar), _ => new StarPiece()) { Alpha = 0, Scale = Vector2.Zero, @@ -220,7 +222,7 @@ protected override void UpdateHitStateTransforms(ArmedState state) foreach (var star in SlideStars) star.FadeOut(200); - this.FadeOut(200).Expire(); + this.Delay(200).Expire(); } break; diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideTap.cs b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideTap.cs index 3f41c057a..f46b41843 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideTap.cs +++ b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideTap.cs @@ -1,12 +1,21 @@ using System.Linq; using osu.Framework.Graphics; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides; +using osu.Game.Rulesets.Sentakki.Skinning; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Slides; +using osu.Game.Rulesets.Sentakki.UI; +using osuTK; namespace osu.Game.Rulesets.Sentakki.Objects.Drawables { public class DrawableSlideTap : DrawableTap { - protected override Drawable CreateTapRepresentation() => new SlideTapPiece(); + protected override Drawable CreateTapVisual() => new SlideTapPiece() + { + Scale = new Vector2(0f), + Position = new Vector2(0, -SentakkiPlayfield.NOTESTARTDISTANCE), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; public DrawableSlideTap() : this(null) { } public DrawableSlideTap(SlideTap? hitObject) @@ -16,7 +25,7 @@ protected override void UpdateInitialTransforms() { base.UpdateInitialTransforms(); - var note = (SlideTapPiece)TapVisual; + var note = (ISlideTapPiece)TapVisual; double spinDuration = 0; @@ -24,9 +33,9 @@ protected override void UpdateInitialTransforms() { spinDuration = ((Slide)slide.HitObject).SlideInfoList.FirstOrDefault().Duration; if (slide.SlideBodies.Count > 1) - note.SecondStar.Alpha = 1; + note.Stars[1].Alpha = 1; else - note.SecondStar.Alpha = 0; + note.Stars[1].Alpha = 0; } note.Stars.Spin(spinDuration, RotationDirection.Counterclockwise, 0).Loop(); diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTap.cs b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTap.cs index 47964e81a..84ac13fcd 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTap.cs +++ b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTap.cs @@ -1,3 +1,4 @@ + using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -5,7 +6,8 @@ using osu.Framework.Input.Events; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Sentakki.Skinning; +using osu.Game.Rulesets.Sentakki.Skinning.Default; using osu.Game.Rulesets.Sentakki.UI; using osuTK; using osuTK.Graphics; @@ -14,7 +16,13 @@ namespace osu.Game.Rulesets.Sentakki.Objects.Drawables { public class DrawableTap : DrawableSentakkiLanedHitObject, IKeyBindingHandler { - protected virtual Drawable CreateTapRepresentation() => new TapPiece(); + protected virtual Drawable CreateTapVisual() => new ProxyableSkinnableDrawable(new SentakkiSkinComponent(SentakkiSkinComponents.Tap), _ => new TapPiece()) + { + Scale = new Vector2(0f), + Position = new Vector2(0, -SentakkiPlayfield.NOTESTARTDISTANCE), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; public override double LifetimeStart { @@ -48,7 +56,7 @@ private void load() Origin = Anchor.Centre; Anchor = Anchor.Centre; AddRangeInternal(new Drawable[] { - TapVisual = CreateTapRepresentation(), + TapVisual = CreateTapVisual() }); } diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTouch.cs b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTouch.cs index 8e5dccf34..857b32d8e 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTouch.cs +++ b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTouch.cs @@ -5,7 +5,9 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Sentakki.Configuration; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Touches; +using osu.Game.Rulesets.Sentakki.Skinning; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Touches; +using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -24,7 +26,7 @@ public class DrawableTouch : DrawableSentakkiHitObject // Similar to IsHovered for mouse, this tracks whether a pointer (touch or mouse) is interacting with this drawable // Interaction == (IsHovered && ActionPressed) || (OnTouch && TouchPointerInBounds) public bool[] PointInteractionState = new bool[11]; - public TouchBody TouchBody = null!; + public SkinnableDrawable TouchBody = null!; private SentakkiInputManager sentakkiActionInputManager = null!; internal SentakkiInputManager SentakkiActionInputManager => sentakkiActionInputManager ??= (SentakkiInputManager)GetContainingInputManager(); @@ -42,7 +44,14 @@ private void load(SentakkiRulesetConfigManager? sentakkiConfigs) Origin = Anchor.Centre; Anchor = Anchor.Centre; AddRangeInternal(new Drawable[]{ - TouchBody = new TouchBody(), + TouchBody = new SkinnableDrawable(new SentakkiSkinComponent(SentakkiSkinComponents.Touch), _ => new TouchBody()) + { + Size = new Vector2(130), + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.None, + }, }); trackedKeys.BindValueChanged(x => @@ -80,7 +89,7 @@ protected override void UpdateInitialTransforms() using (BeginDelayedSequence(AdjustedAnimationDuration, true)) { TouchBody.ResizeTo(90, moveTo, Easing.InCirc); - TouchBody.BorderContainer.Delay(moveTo).FadeIn(); + ((ITouchPiece)TouchBody.Drawable).TouchBorder.Delay(moveTo).FadeIn(); } } @@ -124,9 +133,11 @@ protected override void UpdateHitStateTransforms(ArmedState state) break; case ArmedState.Miss: - this.ScaleTo(0.5f, time_fade_miss, Easing.InCubic) + TouchBody.ScaleTo(0.5f, time_fade_miss, Easing.InCubic) .FadeColour(Color4.Red, time_fade_miss, Easing.OutQuint) .FadeOut(time_fade_miss); + + this.Delay(time_fade_miss).Expire(); break; } } diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTouchHold.cs b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTouchHold.cs index 1b616e1e7..d8306cbd8 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTouchHold.cs +++ b/osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableTouchHold.cs @@ -12,7 +12,8 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Sentakki.Configuration; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.TouchHolds; +using osu.Game.Rulesets.Sentakki.Skinning; +using osu.Game.Rulesets.Sentakki.Skinning.Default.TouchHolds; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -30,7 +31,7 @@ public class DrawableTouchHold : DrawableSentakkiHitObject public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => TouchHoldBody.ReceivePositionalInputAt(screenSpacePos); - public TouchHoldBody TouchHoldBody = null!; + public SkinnableDrawable TouchHoldBody = null!; private PausableSkinnableSound holdSample = null!; @@ -46,10 +47,14 @@ private void load(SentakkiRulesetConfigManager? sentakkiConfigs) Colour = Color4.SlateGray; Anchor = Anchor.Centre; Origin = Anchor.Centre; - Scale = new Vector2(0f); - Alpha = 0; + AddRangeInternal(new Drawable[] { - TouchHoldBody = new TouchHoldBody(), + TouchHoldBody = new SkinnableDrawable(new SentakkiSkinComponent(SentakkiSkinComponents.TouchHold), _=> new TouchHoldBody()) + { + Size = new Vector2(110), + Scale = new Vector2(0f), + Alpha = 0, + }, holdSample = new PausableSkinnableSound { Volume = { Value = 0 }, @@ -102,10 +107,10 @@ protected override void UpdateInitialTransforms() { base.UpdateInitialTransforms(); double fadeIn = AdjustedAnimationDuration; - this.FadeInFromZero(fadeIn).ScaleTo(1, fadeIn); + TouchHoldBody.FadeInFromZero(fadeIn).ScaleTo(1, fadeIn); using (BeginDelayedSequence(fadeIn, true)) { - TouchHoldBody.ProgressPiece.TransformBindableTo(TouchHoldBody.ProgressPiece.ProgressBindable, 1, ((IHasDuration)HitObject).Duration); + ((ITouchHoldPiece)TouchHoldBody.Drawable).TransformTo(nameof(ITouchHoldPiece.Progress), 1.0, ((IHasDuration)HitObject).Duration); } } @@ -172,16 +177,17 @@ protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void UpdateHitStateTransforms(ArmedState state) { base.UpdateHitStateTransforms(state); - const double time_fade_hit = 100, time_fade_miss = 400; + const double time_fade_miss = 400; switch (state) { case ArmedState.Hit: - this.Delay(time_fade_hit).Expire(); + Expire(); break; case ArmedState.Miss: - this.ScaleTo(.0f, time_fade_miss).FadeOut(time_fade_miss).Expire(); + TouchHoldBody.ScaleTo(.0f, time_fade_miss).FadeOut(time_fade_miss).Expire(); + this.Delay(time_fade_miss).Expire(); break; } } diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideFanChevrons.cs b/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideFanChevrons.cs deleted file mode 100644 index 489e0243d..000000000 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideFanChevrons.cs +++ /dev/null @@ -1,161 +0,0 @@ -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Layout; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides -{ - /// - /// This drawable holds a set of all chevron buffered drawables, and is used to preload all/draw of them outside of playfield. (To avoid Playfield transforms re-rendering the chevrons) - ///
- /// A view of each chevron, along with their size, would be used by SlideFanVisual. - ///
- public class SlideFanChevrons : CompositeDrawable - { - private Container chevrons = null!; - - public SlideFanChevrons() - { - Alpha = 0; - AlwaysPresent = true; - - // we are doing this in ctor to guarantee that this object is properly initialized before BDL - loadChevronsTextures(); - } - - public (BufferedContainerView, IBindable) Get(int index) - { - var chevron = chevrons[index]; - - var view = chevron.CreateView(); - view.RelativeSizeAxes = Axes.Both; - - return (view, chevron.SizeBindable); - } - - private void loadChevronsTextures() - { - AddInternal(chevrons = new Container()); - - for (int i = 0; i < 11; ++i) - { - float progress = (i + 2) / (float)12; - float scale = progress; - - chevrons.Add(new ChevronBackingTexture(scale, scale)); - } - } - - private class ChevronBackingTexture : BufferedContainer - { - public Bindable SizeBindable { get; } = new Bindable(); - - // This is to ensure that drawables using this texture is sized correctly (since autosize only happens during the first update) - protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) - { - if (invalidation == Invalidation.DrawSize) - SizeBindable.Value = DrawSize; - - return base.OnInvalidate(invalidation, source); - } - - public ChevronBackingTexture(float lengthScale, float HeightScale) : base(cachedFrameBuffer: true) - { - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - AutoSizeAxes = Axes.Both; - - float chevHeight = 16 + (10 * HeightScale); - float chevWidth = 6 + (210 * lengthScale); - - AddInternal(new Container - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - AutoSizeAxes = Axes.Both, - Children = new Drawable[]{ - // Outlines - new Container - { - X = 2.5f, - Masking = true, - CornerRadius = chevHeight/4, - CornerExponent = 2.5f, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomRight, - Rotation = 22.5f, - Width = chevWidth, - Height = chevHeight, - Child = new Box{ - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray - }, - }, - new Container - { - X = -2.5f, - Masking = true, - CornerRadius = chevHeight/4, - CornerExponent = 2.5f, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomLeft, - Rotation = -22.5f, - Width = chevWidth, - Height = chevHeight, - Child = new Box{ - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray - }, - }, - // Inners - new Container - { - X = 2.5f, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomRight, - Size = new Vector2(chevWidth, chevHeight), - Rotation = 22.5f, - Padding = new MarginPadding(2), - Child = new Container{ - RelativeSizeAxes = Axes.Both, - Masking = true, - - CornerRadius = (chevHeight-4)/4, - CornerExponent = 2.5f, - Colour = Color4.White, - Child = new Box{ - RelativeSizeAxes = Axes.Both, - Colour = Color4.White - } - }, - }, - new Container - { - X = -2.5f, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomLeft, - Size = new Vector2(chevWidth, chevHeight), - Rotation = -22.5f, - Padding = new MarginPadding(2), - Child = new Container - { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = (chevHeight-4)/4, - CornerExponent = 2.5f, - Child = new Box{ - RelativeSizeAxes = Axes.Both, - Colour = Color4.White - } - }, - }, - } - }); - } - } - } -} diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Touches/TouchBlobs.cs b/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Touches/TouchBlobs.cs deleted file mode 100644 index 2c7784153..000000000 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Touches/TouchBlobs.cs +++ /dev/null @@ -1,122 +0,0 @@ -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Objects.Drawables; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Touches -{ - public class TouchBlob : CircularContainer - { - public TouchBlob() - { - Size = new Vector2(80); - Scale = new Vector2(.5f); - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Padding = new MarginPadding(1), - Child = new Container - { - Alpha = .5f, - Masking = true, - RelativeSizeAxes = Axes.Both, - CornerRadius = 20, - CornerExponent = 2.5f, - EdgeEffect = new EdgeEffectParameters - { - Hollow = true, - Type = EdgeEffectType.Shadow, - Radius = 15, - Colour = Color4.Black, - } - } - }, - new Container - { - CornerRadius = 20, - CornerExponent = 2.5f, - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = 16.35f, - BorderColour = Color4.Gray, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha= 0, - AlwaysPresent = true - } - }, - new Container - { - Masking = true, - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(1), - Child = new Container - { - CornerRadius = 20, - CornerExponent = 2.5f, - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = 15, - BorderColour = Color4.White, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, - } - } - }, - new Container - { - CornerRadius = 20, - CornerExponent = 2.5f, - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = 2, - BorderColour = Color4.Gray, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - } - }, - }; - } - - [BackgroundDependencyLoader] - private void load(DrawableHitObject drawableObject) - { - drawableObject.ApplyCustomUpdateState += updateState; - } - - private void updateState(DrawableHitObject drawableObject, ArmedState state) - { - using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime, true)) - { - switch (state) - { - case ArmedState.Hit: - const double flash_in = 40; - - this.Delay(flash_in).FadeOut(); - - break; - } - } - } - } -} diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TrianglesPiece.cs b/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TrianglesPiece.cs deleted file mode 100644 index 81f73b8f4..000000000 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TrianglesPiece.cs +++ /dev/null @@ -1,21 +0,0 @@ -using osu.Game.Graphics.Backgrounds; - -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces -{ - public class TrianglesPiece : Triangles - { - protected override float SpawnRatio => 1f; - - public TrianglesPiece() - { - TriangleScale = 1.2f; - HideAlphaDiscrepancies = false; - } - - protected override void Update() - { - if (IsPresent) - base.Update(); - } - } -} diff --git a/osu.Game.Rulesets.Sentakki/SentakkiRuleset.cs b/osu.Game.Rulesets.Sentakki/SentakkiRuleset.cs index 81bd00e8d..63061cbfe 100644 --- a/osu.Game.Rulesets.Sentakki/SentakkiRuleset.cs +++ b/osu.Game.Rulesets.Sentakki/SentakkiRuleset.cs @@ -28,11 +28,13 @@ using osu.Game.Rulesets.Sentakki.Objects; using osu.Game.Rulesets.Sentakki.Replays; using osu.Game.Rulesets.Sentakki.Scoring; +using osu.Game.Rulesets.Sentakki.Skinning.Legacy; using osu.Game.Rulesets.Sentakki.Statistics; using osu.Game.Rulesets.Sentakki.UI; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics; +using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -48,7 +50,10 @@ private static readonly Lazy is_development_build public override string Description => IsDevelopmentBuild ? "sentakki (Dev build)" : "sentakki"; public override string PlayingVerb => "Washing laundry"; - public override string ShortName => "Sentakki"; + + public const string SHORT_NAME = "Sentakki"; + + public override string ShortName => SHORT_NAME; public override ScoreProcessor CreateScoreProcessor() => new SentakkiScoreProcessor(this); @@ -68,6 +73,17 @@ public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap public override PerformanceCalculator CreatePerformanceCalculator() => new SentakkiPerformanceCalculator(this); + public override ISkin? CreateSkinTransformer(ISkin skin, IBeatmap beatmap) + { + switch (skin) + { + case LegacySkin: + return new SentakkiLegacySkinTransformer(skin); + } + + return base.CreateSkinTransformer(skin, beatmap); + } + public override IEnumerable GetModsFor(ModType type) { switch (type) @@ -206,8 +222,7 @@ public SentakkiIcon(Ruleset ruleset) [BackgroundDependencyLoader] private void load(GameHost host) { - if (textureStore is null) - textureStore = new LargeTextureStore(host.Renderer, host.CreateTextureLoaderStore(ruleset.CreateResourceStore())); + textureStore ??= new LargeTextureStore(host.Renderer, host.CreateTextureLoaderStore(ruleset.CreateResourceStore())); AddInternal(new Sprite { diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/DotPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/DotPiece.cs similarity index 96% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/DotPiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/DotPiece.cs index 6f4e8996c..6fe6a030e 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/DotPiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/DotPiece.cs @@ -6,7 +6,7 @@ using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Sentakki.Skinning.Default { public class DotPiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/HoldBody.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/HoldBody.cs similarity index 78% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/HoldBody.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/HoldBody.cs index 1bfe7b6fc..fa7812028 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/HoldBody.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/HoldBody.cs @@ -3,23 +3,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Sentakki.UI; -using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Sentakki.Skinning.Default { public class HoldBody : CompositeDrawable { - // This will be proxied, so a must. - public override bool RemoveWhenNotAlive => false; - public HoldBody() { - Scale = Vector2.Zero; - Position = new Vector2(0, -SentakkiPlayfield.NOTESTARTDISTANCE); Anchor = Anchor.Centre; Origin = Anchor.BottomCentre; + RelativeSizeAxes = Axes.Both; InternalChildren = new Drawable[] { new NoteRingPiece(), diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/NoteRingPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/NoteRingPiece.cs similarity index 92% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/NoteRingPiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/NoteRingPiece.cs index 8e20b6c0e..ce257f6a3 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/NoteRingPiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/NoteRingPiece.cs @@ -1,7 +1,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Sentakki.Skinning.Default { // This piece is used for laned notes, which share consistent elements // Each half is extends beyond the area of this drawable diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/RingPiece.cs similarity index 96% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/RingPiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/RingPiece.cs index 15b54190f..9e93bfaa3 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/RingPiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/RingPiece.cs @@ -3,7 +3,7 @@ using osu.Framework.Graphics.Shapes; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Sentakki.Skinning.Default { public class RingPiece : CircularContainer { diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/ShadowPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/ShadowPiece.cs similarity index 93% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/ShadowPiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/ShadowPiece.cs index 9098948e6..56d871db2 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/ShadowPiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/ShadowPiece.cs @@ -3,7 +3,7 @@ using osu.Framework.Graphics.Effects; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Sentakki.Skinning.Default { public class ShadowPiece : Container { diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/ISlideChevron.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/ISlideChevron.cs similarity index 81% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/ISlideChevron.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/ISlideChevron.cs index e9d409843..9b8dfb082 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/ISlideChevron.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/ISlideChevron.cs @@ -1,4 +1,4 @@ -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Slides { public interface ISlideChevron { diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideChevron.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideChevron.cs similarity index 77% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideChevron.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideChevron.cs index 4f3b96c97..819497190 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideChevron.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideChevron.cs @@ -3,8 +3,9 @@ using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Skinning; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Slides { public class SlideChevron : PoolableDrawable, ISlideChevron { @@ -19,12 +20,12 @@ public SlideChevron() [BackgroundDependencyLoader] private void load(TextureStore textures) { - AddInternal(new Sprite + AddInternal(new SkinnableDrawable(new SentakkiSkinComponent(SentakkiSkinComponents.SlideChevron), _ => new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Texture = textures.Get("slide"), - }); + })); } protected override void FreeAfterUse() diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideFanChevron.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideFanChevron.cs similarity index 91% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideFanChevron.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideFanChevron.cs index 194762aa1..407ab107e 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideFanChevron.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideFanChevron.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics.Sprites; using osuTK; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Slides { public class SlideFanChevron : CompositeDrawable, ISlideChevron { diff --git a/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideFanChevronPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideFanChevronPiece.cs new file mode 100644 index 000000000..646bb1277 --- /dev/null +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideFanChevronPiece.cs @@ -0,0 +1,100 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Slides +{ + public class SlideFanChevronPiece : CompositeDrawable + { + public SlideFanChevronPiece(float progress) + { + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; + AutoSizeAxes = Axes.Both; + + float chevHeight = 16 + (10 * progress); + float chevWidth = 6 + (210 * progress); + + InternalChildren = new Drawable[] + { + // Outlines + new Container + { + X = 2.5f, + Masking = true, + CornerRadius = chevHeight/4, + CornerExponent = 2.5f, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomRight, + Rotation = 22.5f, + Width = chevWidth, + Height = chevHeight, + Child = new Box{ + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray + }, + }, + new Container + { + X = -2.5f, + Masking = true, + CornerRadius = chevHeight/4, + CornerExponent = 2.5f, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomLeft, + Rotation = -22.5f, + Width = chevWidth, + Height = chevHeight, + Child = new Box{ + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray + }, + }, + // Inners + new Container + { + X = 2.5f, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomRight, + Size = new Vector2(chevWidth, chevHeight), + Rotation = 22.5f, + Padding = new MarginPadding(2), + Child = new Container{ + RelativeSizeAxes = Axes.Both, + Masking = true, + + CornerRadius = (chevHeight-4)/4, + CornerExponent = 2.5f, + Colour = Color4.White, + Child = new Box{ + RelativeSizeAxes = Axes.Both, + Colour = Color4.White + } + }, + }, + new Container + { + X = -2.5f, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomLeft, + Size = new Vector2(chevWidth, chevHeight), + Rotation = -22.5f, + Padding = new MarginPadding(2), + Child = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = (chevHeight-4)/4, + CornerExponent = 2.5f, + Child = new Box{ + RelativeSizeAxes = Axes.Both, + Colour = Color4.White + } + }, + }, + }; + } + } +} diff --git a/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideFanChevrons.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideFanChevrons.cs new file mode 100644 index 000000000..77847ae09 --- /dev/null +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideFanChevrons.cs @@ -0,0 +1,81 @@ +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Layout; +using osu.Game.Skinning; +using osuTK; + +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Slides +{ + /// + /// This drawable holds a set of all chevron buffered drawables, and is used to preload all/draw of them outside of playfield. (To avoid Playfield transforms re-rendering the chevrons) + ///
+ /// A view of each chevron, along with their size, would be used by SlideFanVisual. + ///
+ public class SlideFanChevrons : CompositeDrawable + { + private Container chevrons = null!; + + public SlideFanChevrons() + { + Alpha = 0; + AlwaysPresent = true; + + // we are doing this in ctor to guarantee that this object is properly initialized before BDL + loadChevronsTextures(); + } + + public (BufferedContainerView, IBindable) Get(int index) + { + var chevron = chevrons[index]; + + var view = chevron.CreateView(); + view.RelativeSizeAxes = Axes.Both; + + return (view, chevron.SizeBindable); + } + + private void loadChevronsTextures() + { + AddInternal(chevrons = new Container()); + + for (int i = 0; i < 11; ++i) + { + float progress = (i + 2) / (float)12; + float scale = progress; + + chevrons.Add(new ChevronBackingTexture(scale)); + } + } + + private class ChevronBackingTexture : BufferedContainer + { + public Bindable SizeBindable { get; } = new Bindable(); + + // This is to ensure that drawables using this texture is sized correctly (since autosize only happens during the first update) + protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) + { + if (invalidation == Invalidation.DrawSize) + SizeBindable.Value = DrawSize; + + return base.OnInvalidate(invalidation, source); + } + + public ChevronBackingTexture(float progress) : base(cachedFrameBuffer: true) + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + AutoSizeAxes = Axes.Both; + + AddInternal(new SkinnableDrawable(new SentakkiSkinComponent(SentakkiSkinComponents.SlideFanChevron), _ => new SlideFanChevronPiece(progress)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.None, + AutoSizeAxes = Axes.Both, + }); + } + } + } +} diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideTapPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideTapPiece.cs similarity index 53% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideTapPiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideTapPiece.cs index 92717bcb4..2f9c26c13 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideTapPiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideTapPiece.cs @@ -3,19 +3,20 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Sentakki.UI; +using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Slides { - public class SlideTapPiece : CompositeDrawable + public class SlideTapPiece : CompositeDrawable, ISlideTapPiece { - // This will be proxied, so a must. public override bool RemoveWhenNotAlive => false; + private readonly SkinnableDrawable secondStar; - public readonly Container Stars; - public readonly StarPiece SecondStar; + public Container Stars { get; private set; } + + public Drawable SecondStar => secondStar; public SlideTapPiece() { @@ -23,8 +24,6 @@ public SlideTapPiece() Anchor = Anchor.Centre; Origin = Anchor.Centre; - Scale = new Vector2(0f); - Position = new Vector2(0, -SentakkiPlayfield.NOTESTARTDISTANCE); InternalChildren = new Drawable[] { @@ -33,8 +32,19 @@ public SlideTapPiece() Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[]{ - new StarPiece(), - SecondStar = new StarPiece { Rotation = 36 } + new SkinnableDrawable(new SentakkiSkinComponent(SentakkiSkinComponents.SlideStar), _ => new StarPiece()) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.None, + }, + secondStar = new SkinnableDrawable(new SentakkiSkinComponent(SentakkiSkinComponents.SlideStar), _ => new StarPiece()) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.None, + Rotation = 36 + } } }, }; diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideVisual.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideVisual.cs similarity index 98% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideVisual.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideVisual.cs index 08c6d2603..82c79bdc8 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/SlideVisual.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/SlideVisual.cs @@ -7,8 +7,9 @@ using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Sentakki.Configuration; +using osu.Game.Rulesets.Sentakki.Objects; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Slides { public class SlideVisual : CompositeDrawable { diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/StarPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/StarPiece.cs similarity index 90% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/StarPiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/StarPiece.cs index 2a979089d..749e87b21 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Slides/StarPiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Slides/StarPiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Slides { public class StarPiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TapPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/TapPiece.cs similarity index 72% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TapPiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/TapPiece.cs index 6783d8a27..b7de9bbf6 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TapPiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/TapPiece.cs @@ -3,23 +3,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Sentakki.UI; -using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Sentakki.Skinning.Default { public class TapPiece : CompositeDrawable { - // This will be proxied, so a must. - public override bool RemoveWhenNotAlive => false; - public TapPiece() { Anchor = Anchor.Centre; Origin = Anchor.Centre; - Scale = new Vector2(0f); - Position = new Vector2(0, -SentakkiPlayfield.NOTESTARTDISTANCE); + RelativeSizeAxes = Axes.Both; InternalChildren = new Drawable[] { new NoteRingPiece(), diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TouchHolds/TouchHoldBody.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/TouchHolds/TouchHoldBody.cs similarity index 83% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TouchHolds/TouchHoldBody.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/TouchHolds/TouchHoldBody.cs index 54a8824e0..17badc052 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TouchHolds/TouchHoldBody.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/TouchHolds/TouchHoldBody.cs @@ -6,10 +6,16 @@ using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.TouchHolds +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.TouchHolds { - public class TouchHoldBody : CircularContainer + public class TouchHoldBody : CircularContainer, ITouchHoldPiece { + public double Progress + { + get => ProgressPiece.ProgressBindable.Value; + set => ProgressPiece.ProgressBindable.Value = value; + } + public readonly TouchHoldProgressPiece ProgressPiece; private readonly TouchHoldCentrePiece centrePiece; @@ -17,7 +23,6 @@ public class TouchHoldBody : CircularContainer public TouchHoldBody() { - Size = new Vector2(110); Anchor = Anchor.Centre; Origin = Anchor.Centre; InternalChildren = new Drawable[]{ diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TouchHolds/TouchHoldCentrePiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/TouchHolds/TouchHoldCentrePiece.cs similarity index 97% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TouchHolds/TouchHoldCentrePiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/TouchHolds/TouchHoldCentrePiece.cs index 1de9d0c80..dc54d3158 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TouchHolds/TouchHoldCentrePiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/TouchHolds/TouchHoldCentrePiece.cs @@ -6,7 +6,7 @@ using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.TouchHolds +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.TouchHolds { public class TouchHoldCentrePiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TouchHolds/TouchHoldProgressPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/TouchHolds/TouchHoldProgressPiece.cs similarity index 97% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TouchHolds/TouchHoldProgressPiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/TouchHolds/TouchHoldProgressPiece.cs index 883192977..8317a1e6e 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/TouchHolds/TouchHoldProgressPiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/TouchHolds/TouchHoldProgressPiece.cs @@ -7,7 +7,7 @@ using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.TouchHolds +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.TouchHolds { public class TouchHoldProgressPiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Touches/TouchBody.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Touches/TouchBody.cs similarity index 92% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Touches/TouchBody.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/Touches/TouchBody.cs index a1b4704da..3e0e05762 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Touches/TouchBody.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Touches/TouchBody.cs @@ -7,18 +7,19 @@ using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Touches +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Touches { - public class TouchBody : Container + public class TouchBody : Container, ITouchPiece { + public Drawable TouchBorder => BorderContainer; + public Container BorderContainer; public Container PieceContainer; public TouchBody() { - Size = new Vector2(130); Anchor = Anchor.Centre; Origin = Anchor.Centre; - Alpha = 0; + RelativeSizeAxes = Axes.Both; InternalChildren = new Drawable[]{ BorderContainer = new Container{ diff --git a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Touches/TouchPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/Default/Touches/TouchPiece.cs similarity index 93% rename from osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Touches/TouchPiece.cs rename to osu.Game.Rulesets.Sentakki/Skinning/Default/Touches/TouchPiece.cs index 6ee6b1a6d..c68c2553b 100644 --- a/osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/Touches/TouchPiece.cs +++ b/osu.Game.Rulesets.Sentakki/Skinning/Default/Touches/TouchPiece.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics.Textures; using osuTK; -namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Touches +namespace osu.Game.Rulesets.Sentakki.Skinning.Default.Touches { public class TouchPiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Sentakki/Skinning/ISlideTapPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/ISlideTapPiece.cs new file mode 100644 index 000000000..101748283 --- /dev/null +++ b/osu.Game.Rulesets.Sentakki/Skinning/ISlideTapPiece.cs @@ -0,0 +1,11 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Rulesets.Sentakki.Skinning +{ + public interface ISlideTapPiece : IDrawable + { + public Container Stars { get; } + public Drawable SecondStar { get; } + } +} diff --git a/osu.Game.Rulesets.Sentakki/Skinning/ITouchHoldPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/ITouchHoldPiece.cs new file mode 100644 index 000000000..9e8e482b1 --- /dev/null +++ b/osu.Game.Rulesets.Sentakki/Skinning/ITouchHoldPiece.cs @@ -0,0 +1,10 @@ +using osu.Framework.Graphics; + +namespace osu.Game.Rulesets.Sentakki.Skinning +{ + public interface ITouchHoldPiece : IDrawable + { + // Used to fill the progress bar after HitObject start time + double Progress { get; set; } + } +} diff --git a/osu.Game.Rulesets.Sentakki/Skinning/ITouchPiece.cs b/osu.Game.Rulesets.Sentakki/Skinning/ITouchPiece.cs new file mode 100644 index 000000000..3f9541b9a --- /dev/null +++ b/osu.Game.Rulesets.Sentakki/Skinning/ITouchPiece.cs @@ -0,0 +1,10 @@ +using osu.Framework.Graphics; + +namespace osu.Game.Rulesets.Sentakki.Skinning +{ + public interface ITouchPiece : IDrawable + { + // Shows as soon as Time >= StartTime + Drawable TouchBorder { get; } + } +} diff --git a/osu.Game.Rulesets.Sentakki/Skinning/Legacy/SentakkLegacySkinTransformer.cs b/osu.Game.Rulesets.Sentakki/Skinning/Legacy/SentakkLegacySkinTransformer.cs new file mode 100644 index 000000000..5a1a478a1 --- /dev/null +++ b/osu.Game.Rulesets.Sentakki/Skinning/Legacy/SentakkLegacySkinTransformer.cs @@ -0,0 +1,15 @@ +using osu.Framework.Graphics; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Sentakki.Skinning.Legacy +{ + public class SentakkiLegacySkinTransformer : LegacySkinTransformer + { + public SentakkiLegacySkinTransformer(ISkin skin) + : base(skin) + { + } + + public override Drawable? GetDrawableComponent(ISkinComponent component) => null; + } +} diff --git a/osu.Game.Rulesets.Sentakki/Skinning/ProxyableSkinnableDrawable.cs b/osu.Game.Rulesets.Sentakki/Skinning/ProxyableSkinnableDrawable.cs new file mode 100644 index 000000000..1d6287f7b --- /dev/null +++ b/osu.Game.Rulesets.Sentakki/Skinning/ProxyableSkinnableDrawable.cs @@ -0,0 +1,16 @@ +using System; +using osu.Framework.Graphics; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Sentakki.Skinning +{ + public class ProxyableSkinnableDrawable : SkinnableDrawable + { + public override bool RemoveWhenNotAlive => false; + + public ProxyableSkinnableDrawable(ISkinComponent component, Func defaultImplementation = null!, ConfineMode confineMode = ConfineMode.NoScaling) + : base(component, defaultImplementation, confineMode) + { + } + } +} diff --git a/osu.Game.Rulesets.Sentakki/Skinning/SentakkiSkinComponent.cs b/osu.Game.Rulesets.Sentakki/Skinning/SentakkiSkinComponent.cs new file mode 100644 index 000000000..6257869f7 --- /dev/null +++ b/osu.Game.Rulesets.Sentakki/Skinning/SentakkiSkinComponent.cs @@ -0,0 +1,16 @@ +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Sentakki.Skinning +{ + public class SentakkiSkinComponent : GameplaySkinComponent + { + public SentakkiSkinComponent(SentakkiSkinComponents component) + : base(component) + { + } + + protected override string RulesetPrefix => SentakkiRuleset.SHORT_NAME; + + protected override string ComponentName => Component.ToString().ToLowerInvariant(); + } +} diff --git a/osu.Game.Rulesets.Sentakki/Skinning/SentakkiSkinComponents.cs b/osu.Game.Rulesets.Sentakki/Skinning/SentakkiSkinComponents.cs new file mode 100644 index 000000000..8f3d16f49 --- /dev/null +++ b/osu.Game.Rulesets.Sentakki/Skinning/SentakkiSkinComponents.cs @@ -0,0 +1,13 @@ +namespace osu.Game.Rulesets.Sentakki.Skinning +{ + public enum SentakkiSkinComponents + { + Tap, + Hold, + Touch, + TouchHold, + SlideChevron, + SlideFanChevron, + SlideStar, + } +} diff --git a/osu.Game.Rulesets.Sentakki/UI/Components/SentakkiRing.cs b/osu.Game.Rulesets.Sentakki/UI/Components/SentakkiRing.cs index cb4628aca..4a57d9f84 100644 --- a/osu.Game.Rulesets.Sentakki/UI/Components/SentakkiRing.cs +++ b/osu.Game.Rulesets.Sentakki/UI/Components/SentakkiRing.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Sentakki.Configuration; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Sentakki.Skinning.Default; using osuTK; namespace osu.Game.Rulesets.Sentakki.UI.Components diff --git a/osu.Game.Rulesets.Sentakki/UI/DrawableSentakkiRuleset.cs b/osu.Game.Rulesets.Sentakki/UI/DrawableSentakkiRuleset.cs index 9b5764224..2aec2e8e7 100644 --- a/osu.Game.Rulesets.Sentakki/UI/DrawableSentakkiRuleset.cs +++ b/osu.Game.Rulesets.Sentakki/UI/DrawableSentakkiRuleset.cs @@ -10,8 +10,8 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Sentakki.Configuration; using osu.Game.Rulesets.Sentakki.Objects; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides; using osu.Game.Rulesets.Sentakki.Replays; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Slides; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Play; diff --git a/osu.Game.Rulesets.Sentakki/UI/LanedPlayfield.cs b/osu.Game.Rulesets.Sentakki/UI/LanedPlayfield.cs index 273735b42..0c42f0bc6 100644 --- a/osu.Game.Rulesets.Sentakki/UI/LanedPlayfield.cs +++ b/osu.Game.Rulesets.Sentakki/UI/LanedPlayfield.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Sentakki.Objects; using osu.Game.Rulesets.Sentakki.Objects.Drawables; -using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides; +using osu.Game.Rulesets.Sentakki.Skinning.Default.Slides; using osu.Game.Rulesets.Sentakki.UI.Components.HitObjectLine; using osu.Game.Rulesets.UI;