Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SlideTap removal / masquerade #552

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 27 additions & 21 deletions osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Sentakki.Objects;
using osuTK.Graphics;

Expand All @@ -20,14 +21,12 @@ public override void PostProcess()
Color4 twinColor = Color4.Gold;
Color4 breakColor = Color4.OrangeRed;

var hitObjectGroups = Beatmap.HitObjects.GroupBy(h => h.StartTime).ToList();
var hitObjectGroups = getColorableHitObject(Beatmap.HitObjects).GroupBy(h => new { isSlide = h is SlideBody, time = h.StartTime + (h is SlideBody s ? s.ShootDelay : 0) });

foreach (var group in hitObjectGroups)
{
bool isTwin = group.Count() > 1; // This determines whether the twin colour should be used

List<SlideBody> slideBodiesInGroup = new List<SlideBody>();

foreach (SentakkiHitObject hitObject in group)
{
Color4 noteColor = hitObject.DefaultNoteColour;
Expand All @@ -37,27 +36,34 @@ public override void PostProcess()
else if (isTwin)
noteColor = twinColor;

// SlideTaps follow the typical coloring rules, while SlideBodies follow a different set of rules
if (hitObject is Slide slide)
{
slide.SlideTap.NoteColour = noteColor;
slideBodiesInGroup.AddRange(slide.SlideBodies);
}
else
hitObject.NoteColour = noteColor;
hitObject.NoteColour = noteColor;
}
}
}

// Colour Slide bodies separately
foreach (var slideBody in slideBodiesInGroup)
{
if (slideBody.Break)
slideBody.NoteColour = breakColor;
else if (slideBodiesInGroup.Count > 1)
slideBody.NoteColour = twinColor;
else
slideBody.NoteColour = slideBody.DefaultNoteColour;
}
private IEnumerable<HitObject> getColorableHitObject(IReadOnlyList<HitObject> hitObjects)
{
for (int i = 0; i < hitObjects.Count; ++i)
{
var hitObject = hitObjects[i];
if (canBeColored(hitObject)) yield return hitObject;

foreach (var nested in getColorableHitObject(hitObject.NestedHitObjects).AsEnumerable())
yield return nested;
}
}

private bool canBeColored(HitObject hitObject)
{
switch (hitObject)
{
case Tap:
case SlideBody:
case Hold:
case Touch:
return true;
}
return false;
}
}
}
16 changes: 13 additions & 3 deletions osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlide.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public partial class DrawableSlide : DrawableSentakkiHitObject
public override bool DisplayResult => false;

public Container<DrawableSlideBody> SlideBodies = null!;
public Container<DrawableSlideTap> SlideTaps = null!;
public Container<DrawableTap> SlideTaps = null!;

public new Slide HitObject => (Slide)base.HitObject;

Expand All @@ -39,7 +39,7 @@ private void load()
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
SlideTaps = new Container<DrawableSlideTap>
SlideTaps = new Container<DrawableTap>
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Expand Down Expand Up @@ -75,6 +75,12 @@ protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject)
AutoBindable = { BindTarget = AutoBindable },
};

case Tap y:
return new DrawableTap(y)
{
AutoBindable = { BindTarget = AutoBindable },
};

case SlideBody slideBody:
return new DrawableSlideBody(slideBody)
{
Expand All @@ -95,7 +101,11 @@ protected override void AddNestedHitObject(DrawableHitObject hitObject)
SlideBodies.Add(body);
break;

case DrawableSlideTap tap:
case DrawableSlideTap slideTap:
SlideTaps.Child = slideTap;
break;

case DrawableTap tap:
SlideTaps.Child = tap;
break;
}
Expand Down
15 changes: 13 additions & 2 deletions osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideBody.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
Expand All @@ -23,7 +22,19 @@ public partial class DrawableSlideBody : DrawableSentakkiLanedHitObject
public new SlideBody HitObject => (SlideBody)base.HitObject;

// This slide body can only be interacted with iff the slidetap associated with this slide is judged
public bool IsHittable => ParentHitObject is not null && ParentHitObject.SlideTaps.Child.Judged;
public bool IsHittable
{
get
{
if (ParentHitObject is null)
return false;

if (ParentHitObject.HitObject.TapType is Slide.TapTypeEnum.None)
return Time.Current >= HitObject.StartTime;

return ParentHitObject.SlideTaps.Child.Judged;
}
}

public Container<DrawableSlideCheckpoint> SlideCheckpoints { get; private set; } = null!;

Expand Down
31 changes: 22 additions & 9 deletions osu.Game.Rulesets.Sentakki/Objects/Slide.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using osu.Framework.Bindables;
using osu.Game.Audio;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Types;
Expand All @@ -12,6 +13,13 @@ namespace osu.Game.Rulesets.Sentakki.Objects
{
public class Slide : SentakkiLanedHitObject, IHasDuration
{
public enum TapTypeEnum
{
Star,
Tap,
None,
}

protected override bool NeedBreakSample => false;

public double Duration
Expand All @@ -27,26 +35,31 @@ public double Duration
set => throw new NotSupportedException();
}

public TapTypeEnum TapType = TapTypeEnum.Star;

public double EndTime => StartTime + Duration;

public override Color4 DefaultNoteColour => Color4.Aqua;

public List<SlideBodyInfo> SlideInfoList = new List<SlideBodyInfo>();

public SlideTap SlideTap { get; private set; } = null!;
public Tap SlideTap { get; private set; } = null!;

public IList<SlideBody> SlideBodies { get; private set; } = null!;

protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
{
AddNested(SlideTap = new SlideTap
if (TapType is not TapTypeEnum.None)
{
LaneBindable = { BindTarget = LaneBindable },
StartTime = StartTime,
Samples = Samples,
Break = Break,
Ex = Ex
});
Tap tap = SlideTap = TapType is TapTypeEnum.Tap ? new Tap() : new SlideTap();
tap.LaneBindable.BindTarget = LaneBindable;
tap.StartTime = StartTime;
tap.Samples = Samples;
tap.Break = Break;
tap.Ex = Ex;

AddNested(tap);
}

createSlideBodies();
}

Expand Down
4 changes: 3 additions & 1 deletion osu.Game.Rulesets.Sentakki/UI/LanedPlayfield.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ public override void Add(HitObject hitObject)
if (hitObject is not SentakkiLanedHitObject lanedHitObject)
return;

HitObjectLineRenderer.AddHitObject(lanedHitObject);
if (hitObject is not Slide slide || slide.TapType is not Slide.TapTypeEnum.None)
HitObjectLineRenderer.AddHitObject(lanedHitObject);

Lanes[lanedHitObject.Lane].Add(lanedHitObject);
}

Expand Down
Loading