mirror of
https://github.com/ppy/osu.git
synced 2025-03-23 05:47:19 +08:00
Rework/rewrite beatmap parsing to parse to base hit objects, which mode-specific beatmap converters can then use.
This commit is contained in:
parent
c76a495d3d
commit
f50e0bbf3c
@ -75,7 +75,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
add(new DrawableSpinner(new Spinner
|
||||
{
|
||||
StartTime = framedClock.CurrentTime + 600,
|
||||
Length = 1000,
|
||||
EndTime = framedClock.CurrentTime + 1600,
|
||||
Position = new Vector2(0, 0),
|
||||
}));
|
||||
break;
|
||||
|
@ -10,7 +10,7 @@ namespace osu.Game.Modes.Catch.Beatmaps
|
||||
{
|
||||
internal class CatchBeatmapConverter : IBeatmapConverter<CatchBaseHit>
|
||||
{
|
||||
public Beatmap<CatchBaseHit> Convert(Beatmap original)
|
||||
public Beatmap<CatchBaseHit> ConvertBeatmap(Beatmap original)
|
||||
{
|
||||
return new Beatmap<CatchBaseHit>(original)
|
||||
{
|
||||
|
@ -5,7 +5,6 @@ using OpenTK.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Catch.UI;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
@ -88,8 +87,6 @@ namespace osu.Game.Modes.Catch
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount = 0) => null;
|
||||
|
||||
public override HitObjectParser CreateHitObjectParser() => new NullHitObjectParser();
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap);
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
using OpenTK;
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Catch.Objects
|
||||
{
|
||||
public abstract class CatchBaseHit : HitObject
|
||||
public abstract class CatchBaseHit : HitObject, IHasPosition
|
||||
{
|
||||
public float Position;
|
||||
public Vector2 Position { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Modes.Catch.Objects
|
||||
{
|
||||
internal class CatchConverter : HitObjectConverter<CatchBaseHit>
|
||||
{
|
||||
public override List<CatchBaseHit> Convert(Beatmap beatmap)
|
||||
{
|
||||
List<CatchBaseHit> output = new List<CatchBaseHit>();
|
||||
|
||||
foreach (HitObject i in beatmap.HitObjects)
|
||||
{
|
||||
CatchBaseHit h = i as CatchBaseHit;
|
||||
|
||||
if (h == null)
|
||||
{
|
||||
OsuHitObject o = i as OsuHitObject;
|
||||
|
||||
if (o == null) throw new HitObjectConvertException(@"Catch", i);
|
||||
|
||||
h = new Fruit
|
||||
{
|
||||
StartTime = o.StartTime,
|
||||
Position = o.Position.X,
|
||||
};
|
||||
}
|
||||
|
||||
output.Add(h);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using OpenTK;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Catch.Objects.Drawable
|
||||
{
|
||||
@ -21,7 +22,7 @@ namespace osu.Game.Modes.Catch.Objects.Drawable
|
||||
Origin = Anchor.Centre;
|
||||
Scale = new Vector2(0.1f);
|
||||
RelativePositionAxes = Axes.Y;
|
||||
Position = new Vector2(h.Position, -0.1f);
|
||||
Position = new Vector2(h.Position.X, -0.1f);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -29,8 +30,11 @@ namespace osu.Game.Modes.Catch.Objects.Drawable
|
||||
{
|
||||
Texture = textures.Get(@"Menu/logo");
|
||||
|
||||
Transforms.Add(new TransformPosition { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = new Vector2(h.Position, -0.1f), EndValue = new Vector2(h.Position, 0.9f) });
|
||||
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
|
||||
double endTime = (h as IHasEndTime)?.EndTime ?? h.StartTime;
|
||||
double duration = endTime - h.StartTime;
|
||||
|
||||
Transforms.Add(new TransformPosition { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = new Vector2(h.Position.X, -0.1f), EndValue = new Vector2(h.Position.X, 0.9f) });
|
||||
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 });
|
||||
Expire(true);
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,6 @@
|
||||
<Compile Include="Beatmaps\CatchBeatmapConverter.cs" />
|
||||
<Compile Include="CatchDifficultyCalculator.cs" />
|
||||
<Compile Include="Objects\CatchBaseHit.cs" />
|
||||
<Compile Include="Objects\CatchConverter.cs" />
|
||||
<Compile Include="Objects\Drawable\DrawableFruit.cs" />
|
||||
<Compile Include="Objects\Droplet.cs" />
|
||||
<Compile Include="Objects\Fruit.cs" />
|
||||
|
@ -10,7 +10,7 @@ namespace osu.Game.Modes.Mania.Beatmaps
|
||||
{
|
||||
internal class ManiaBeatmapConverter : IBeatmapConverter<ManiaBaseHit>
|
||||
{
|
||||
public Beatmap<ManiaBaseHit> Convert(Beatmap original)
|
||||
public Beatmap<ManiaBaseHit> ConvertBeatmap(Beatmap original)
|
||||
{
|
||||
return new Beatmap<ManiaBaseHit>(original)
|
||||
{
|
||||
|
@ -4,7 +4,6 @@
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Mania.UI;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
@ -103,8 +102,6 @@ namespace osu.Game.Modes.Mania
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount = 0) => null;
|
||||
|
||||
public override HitObjectParser CreateHitObjectParser() => new NullHitObjectParser();
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap);
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,16 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Mania.Objects
|
||||
{
|
||||
public abstract class ManiaBaseHit : HitObject
|
||||
public abstract class ManiaBaseHit : HitObject, IHasEndTime
|
||||
{
|
||||
public int Column;
|
||||
|
||||
public double EndTime { get; set; }
|
||||
|
||||
public double Duration { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Modes.Mania.Objects
|
||||
{
|
||||
internal class ManiaConverter : HitObjectConverter<ManiaBaseHit>
|
||||
{
|
||||
private readonly int columns;
|
||||
|
||||
public ManiaConverter(int columns)
|
||||
{
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
public override List<ManiaBaseHit> Convert(Beatmap beatmap)
|
||||
{
|
||||
List<ManiaBaseHit> output = new List<ManiaBaseHit>();
|
||||
|
||||
foreach (HitObject i in beatmap.HitObjects)
|
||||
{
|
||||
ManiaBaseHit h = i as ManiaBaseHit;
|
||||
|
||||
if (h == null)
|
||||
{
|
||||
OsuHitObject o = i as OsuHitObject;
|
||||
|
||||
if (o == null) throw new HitObjectConvertException(@"Mania", i);
|
||||
|
||||
h = new Note
|
||||
{
|
||||
StartTime = o.StartTime,
|
||||
Column = (int)Math.Round(o.Position.X / 512 * columns)
|
||||
};
|
||||
}
|
||||
|
||||
output.Add(h);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
@ -52,7 +52,6 @@
|
||||
<Compile Include="Objects\Drawable\DrawableNote.cs" />
|
||||
<Compile Include="Objects\HoldNote.cs" />
|
||||
<Compile Include="Objects\ManiaBaseHit.cs" />
|
||||
<Compile Include="Objects\ManiaConverter.cs" />
|
||||
<Compile Include="Objects\Note.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UI\ManiaHitRenderer.cs" />
|
||||
|
@ -8,29 +8,90 @@ using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Beatmaps
|
||||
{
|
||||
internal class OsuBeatmapConverter : IBeatmapConverter<OsuHitObject>
|
||||
{
|
||||
public Beatmap<OsuHitObject> Convert(Beatmap original)
|
||||
public Beatmap<OsuHitObject> ConvertBeatmap(Beatmap original)
|
||||
{
|
||||
return new Beatmap<OsuHitObject>(original)
|
||||
{
|
||||
HitObjects = convertHitObject(original.HitObjects, original.BeatmapInfo?.StackLeniency ?? 0.7f)
|
||||
HitObjects = convertHitObjects(original.HitObjects, original.BeatmapInfo?.StackLeniency ?? 0.7f)
|
||||
};
|
||||
}
|
||||
|
||||
private List<OsuHitObject> convertHitObject(List<HitObject> hitObjects, float stackLeniency)
|
||||
private OsuHitObject convertHitObject(HitObject original)
|
||||
{
|
||||
IHasCurve ihc = original as IHasCurve;
|
||||
IHasDistance ihd = original as IHasDistance;
|
||||
IHasEndTime ihet = original as IHasEndTime;
|
||||
IHasPosition ihp = original as IHasPosition;
|
||||
IHasRepeats ihr = original as IHasRepeats;
|
||||
IHasCombo ihco = original as IHasCombo;
|
||||
|
||||
if (ihc != null)
|
||||
{
|
||||
return new Slider
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Sample = original.Sample,
|
||||
|
||||
CurveType = ihc.CurveType,
|
||||
ControlPoints = ihc.ControlPoints,
|
||||
|
||||
Position = ihp?.Position ?? Vector2.Zero,
|
||||
ComboColour = ihco?.ComboColour ?? Color4.White,
|
||||
ComboIndex = ihco?.ComboIndex ?? 0,
|
||||
NewCombo = ihco?.NewCombo ?? false,
|
||||
Length = ihd?.Distance ?? 0,
|
||||
RepeatCount = ihr?.RepeatCount ?? 0
|
||||
};
|
||||
}
|
||||
|
||||
if (ihet != null)
|
||||
{
|
||||
return new Spinner
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Sample = original.Sample,
|
||||
Position = new Vector2(512, 384) / 2,
|
||||
|
||||
EndTime = ihet.EndTime,
|
||||
|
||||
ComboColour = ihco?.ComboColour ?? Color4.White,
|
||||
ComboIndex = ihco?.ComboIndex ?? 0,
|
||||
NewCombo = ihco?.NewCombo ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
return new HitCircle
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Sample = original.Sample,
|
||||
|
||||
Position = ihp?.Position ?? Vector2.Zero,
|
||||
ComboColour = ihco?.ComboColour ?? Color4.White,
|
||||
ComboIndex = ihco?.ComboIndex ?? 0,
|
||||
NewCombo = ihco?.NewCombo ?? false
|
||||
};
|
||||
}
|
||||
|
||||
private List<OsuHitObject> convertHitObjects(List<HitObject> hitObjects, float stackLeniency)
|
||||
{
|
||||
List<OsuHitObject> converted = new List<OsuHitObject>();
|
||||
|
||||
int combo = 0;
|
||||
foreach (HitObject h in hitObjects)
|
||||
{
|
||||
if (h.NewCombo) combo = 0;
|
||||
OsuHitObject c = convertHitObject(h);
|
||||
|
||||
h.ComboIndex = combo++;
|
||||
if (c.NewCombo)
|
||||
combo = 0;
|
||||
|
||||
c.ComboIndex = combo++;
|
||||
converted.Add(h as OsuHitObject);
|
||||
}
|
||||
|
||||
@ -62,9 +123,12 @@ namespace osu.Game.Modes.Osu.Beatmaps
|
||||
if (stackBaseObject is Spinner) break;
|
||||
|
||||
OsuHitObject objectN = hitObjects[n];
|
||||
if (objectN is Spinner) continue;
|
||||
if (objectN is Spinner)
|
||||
continue;
|
||||
|
||||
if (objectN.StartTime - stackBaseObject.EndTime > stackThreshold)
|
||||
double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime;
|
||||
|
||||
if (objectN.StartTime - endTime > stackThreshold)
|
||||
//We are no longer within stacking range of the next object.
|
||||
break;
|
||||
|
||||
@ -116,7 +180,9 @@ namespace osu.Game.Modes.Osu.Beatmaps
|
||||
OsuHitObject objectN = hitObjects[n];
|
||||
if (objectN is Spinner) continue;
|
||||
|
||||
if (objectI.StartTime - objectN.EndTime > stackThreshold)
|
||||
double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime;
|
||||
|
||||
if (objectI.StartTime - endTime > stackThreshold)
|
||||
//We are no longer within stacking range of the previous object.
|
||||
break;
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
|
||||
{
|
||||
@ -63,7 +64,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
|
||||
{
|
||||
Vector2 startPosition = prevHitObject.EndPosition;
|
||||
Vector2 endPosition = currHitObject.Position;
|
||||
double startTime = prevHitObject.EndTime;
|
||||
double startTime = (prevHitObject as IHasEndTime)?.EndTime ?? prevHitObject.StartTime;
|
||||
double endTime = currHitObject.StartTime;
|
||||
|
||||
Vector2 distanceVector = endPosition - startPosition;
|
||||
|
@ -7,6 +7,7 @@ using osu.Framework.Graphics.Transforms;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
{
|
||||
@ -35,11 +36,11 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
{
|
||||
glow = new GlowPiece
|
||||
{
|
||||
Colour = osuObject.Colour
|
||||
Colour = osuObject.ComboColour
|
||||
},
|
||||
circle = new CirclePiece
|
||||
{
|
||||
Colour = osuObject.Colour,
|
||||
Colour = osuObject.ComboColour,
|
||||
Hit = () =>
|
||||
{
|
||||
if (Judgement.Result.HasValue) return false;
|
||||
@ -57,11 +58,11 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
flash = new FlashPiece(),
|
||||
explode = new ExplodePiece
|
||||
{
|
||||
Colour = osuObject.Colour,
|
||||
Colour = osuObject.ComboColour,
|
||||
},
|
||||
ApproachCircle = new ApproachCircle
|
||||
{
|
||||
Colour = osuObject.Colour,
|
||||
Colour = osuObject.ComboColour,
|
||||
}
|
||||
};
|
||||
|
||||
@ -118,13 +119,16 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
|
||||
ApproachCircle.FadeOut();
|
||||
|
||||
glow.Delay(osuObject.Duration);
|
||||
double endTime = (osuObject as IHasEndTime)?.EndTime ?? osuObject.StartTime;
|
||||
double duration = endTime - osuObject.StartTime;
|
||||
|
||||
glow.Delay(duration);
|
||||
glow.FadeOut(400);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Idle:
|
||||
Delay(osuObject.Duration + TIME_PREEMPT);
|
||||
Delay(duration + TIME_PREEMPT);
|
||||
FadeOut(TIME_FADEOUT);
|
||||
break;
|
||||
case ArmedState.Miss:
|
||||
|
@ -60,7 +60,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
Position = s.StackedPosition,
|
||||
ComboIndex = s.ComboIndex,
|
||||
Scale = s.Scale,
|
||||
Colour = s.Colour,
|
||||
ComboColour = s.ComboColour,
|
||||
Sample = s.Sample,
|
||||
}),
|
||||
};
|
||||
@ -128,7 +128,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
var j = (OsuJudgementInfo)Judgement;
|
||||
var sc = (OsuJudgementInfo)initialCircle.Judgement;
|
||||
|
||||
if (!userTriggered && Time.Current >= HitObject.EndTime)
|
||||
if (!userTriggered && Time.Current >= slider.EndTime)
|
||||
{
|
||||
var ticksCount = ticks.Children.Count() + 1;
|
||||
var ticksHit = ticks.Children.Count(t => t.Judgement.Result == HitResult.Hit);
|
||||
@ -165,7 +165,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
|
||||
ball.FadeIn();
|
||||
|
||||
Delay(HitObject.Duration, true);
|
||||
Delay(slider.Duration, true);
|
||||
|
||||
body.FadeOut(160);
|
||||
ball.FadeOut(160);
|
||||
|
@ -47,7 +47,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = sliderTick.Colour,
|
||||
Colour = sliderTick.ComboColour,
|
||||
Alpha = 0.3f,
|
||||
}
|
||||
};
|
||||
|
@ -46,7 +46,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
Alpha = 0,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
DiscColour = s.Colour
|
||||
DiscColour = s.ComboColour
|
||||
},
|
||||
circleContainer = new Container
|
||||
{
|
||||
@ -82,7 +82,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
if (Progress >= 1)
|
||||
disc.Complete = true;
|
||||
|
||||
if (!userTriggered && Time.Current >= HitObject.EndTime)
|
||||
if (!userTriggered && Time.Current >= spinner.EndTime)
|
||||
{
|
||||
if (Progress >= 1)
|
||||
{
|
||||
@ -102,7 +102,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
else
|
||||
{
|
||||
j.Score = OsuScoreResult.Miss;
|
||||
if (Time.Current >= HitObject.EndTime)
|
||||
if (Time.Current >= spinner.EndTime)
|
||||
j.Result = HitResult.Miss;
|
||||
}
|
||||
}
|
||||
@ -140,7 +140,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
|
||||
base.UpdateState(state);
|
||||
|
||||
Delay(HitObject.Duration, true);
|
||||
Delay(spinner.Duration, true);
|
||||
|
||||
FadeOut(160);
|
||||
|
||||
|
@ -51,7 +51,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = slider.Colour,
|
||||
Colour = slider.ComboColour,
|
||||
Alpha = 0.4f,
|
||||
Width = width,
|
||||
Height = width,
|
||||
|
@ -110,10 +110,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
progress -= border_portion;
|
||||
|
||||
bytes[i * 4] = (byte)(slider.Colour.R * 255);
|
||||
bytes[i * 4 + 1] = (byte)(slider.Colour.G * 255);
|
||||
bytes[i * 4 + 2] = (byte)(slider.Colour.B * 255);
|
||||
bytes[i * 4 + 3] = (byte)((opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * (slider.Colour.A * 255));
|
||||
bytes[i * 4] = (byte)(slider.ComboColour.R * 255);
|
||||
bytes[i * 4 + 1] = (byte)(slider.ComboColour.G * 255);
|
||||
bytes[i * 4 + 2] = (byte)(slider.ComboColour.B * 255);
|
||||
bytes[i * 4 + 3] = (byte)((opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * (slider.ComboColour.A * 255));
|
||||
}
|
||||
}
|
||||
|
||||
|
10
osu.Game.Modes.Osu/Objects/HitObjectType.cs
Normal file
10
osu.Game.Modes.Osu/Objects/HitObjectType.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
public enum HitObjectType
|
||||
{
|
||||
Circle,
|
||||
Slider,
|
||||
Spinner,
|
||||
SliderTick
|
||||
}
|
||||
}
|
@ -1,15 +1,16 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Game.Modes.Objects;
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
public abstract class OsuHitObject : HitObject
|
||||
public abstract class OsuHitObject : HitObject, IHasCombo
|
||||
{
|
||||
public const double OBJECT_RADIUS = 64;
|
||||
|
||||
@ -36,6 +37,12 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
|
||||
public abstract HitObjectType Type { get; }
|
||||
|
||||
public virtual bool NewCombo { get; set; }
|
||||
|
||||
public Color4 ComboColour { get; set; }
|
||||
|
||||
public int ComboIndex { get; set; }
|
||||
|
||||
public double HitWindowFor(OsuScoreResult result)
|
||||
{
|
||||
switch (result)
|
||||
@ -69,16 +76,4 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
Scale = (1.0f - 0.7f * (beatmap.BeatmapInfo.BaseDifficulty.CircleSize - 5) / 5) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum HitObjectType
|
||||
{
|
||||
Circle = 1 << 0,
|
||||
Slider = 1 << 1,
|
||||
NewCombo = 1 << 2,
|
||||
Spinner = 1 << 3,
|
||||
ColourHax = 122,
|
||||
Hold = 1 << 7,
|
||||
SliderTick = 1 << 8,
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,16 @@ using OpenTK;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
public class Slider : OsuHitObject
|
||||
public class Slider : OsuHitObject, IHasEndTime
|
||||
{
|
||||
public override double EndTime => StartTime + RepeatCount * Curve.Length / Velocity;
|
||||
public double EndTime => StartTime + RepeatCount * Curve.Length / Velocity;
|
||||
public double Duration => EndTime - StartTime;
|
||||
|
||||
public override Vector2 EndPosition => PositionAt(1);
|
||||
|
||||
@ -64,7 +66,7 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
set { Curve.Length = value; }
|
||||
}
|
||||
|
||||
public CurveTypes CurveType
|
||||
public CurveType CurveType
|
||||
{
|
||||
get { return Curve.CurveType; }
|
||||
set { Curve.CurveType = value; }
|
||||
@ -124,7 +126,7 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
Position = Curve.PositionAt(distanceProgress),
|
||||
StackHeight = StackHeight,
|
||||
Scale = Scale,
|
||||
Colour = Colour,
|
||||
ComboColour = ComboColour,
|
||||
Sample = new HitSampleInfo
|
||||
{
|
||||
Type = SampleType.None,
|
||||
@ -138,12 +140,4 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
|
||||
public override HitObjectType Type => HitObjectType.Slider;
|
||||
}
|
||||
|
||||
public enum CurveTypes
|
||||
{
|
||||
Catmull,
|
||||
Bezier,
|
||||
Linear,
|
||||
PerfectCurve
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
using System.Linq;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
@ -14,7 +15,7 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
|
||||
public List<Vector2> ControlPoints;
|
||||
|
||||
public CurveTypes CurveType = CurveTypes.PerfectCurve;
|
||||
public CurveType CurveType = CurveType.PerfectCurve;
|
||||
|
||||
public Vector2 Offset;
|
||||
|
||||
@ -25,9 +26,9 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
switch (CurveType)
|
||||
{
|
||||
case CurveTypes.Linear:
|
||||
case CurveType.Linear:
|
||||
return subControlPoints;
|
||||
case CurveTypes.PerfectCurve:
|
||||
case CurveType.PerfectCurve:
|
||||
//we can only use CircularArc iff we have exactly three control points and no dissection.
|
||||
if (ControlPoints.Count != 3 || subControlPoints.Count != 3)
|
||||
break;
|
||||
|
@ -1,14 +1,18 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
public class Spinner : OsuHitObject
|
||||
public class Spinner : OsuHitObject, IHasEndTime
|
||||
{
|
||||
public double Length;
|
||||
|
||||
public override double EndTime => StartTime + Length;
|
||||
public double EndTime { get; set; }
|
||||
public double Duration => EndTime - StartTime;
|
||||
|
||||
public override HitObjectType Type => HitObjectType.Spinner;
|
||||
|
||||
public override bool NewCombo => true;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ using osu.Framework.Graphics.Transforms;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using osu.Framework.MathUtils;
|
||||
using System.Diagnostics;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
{
|
||||
@ -100,20 +101,22 @@ namespace osu.Game.Modes.Osu
|
||||
{
|
||||
OsuHitObject last = (OsuHitObject)beatmap.HitObjects[i - 1];
|
||||
|
||||
double endTime = (last as IHasEndTime)?.EndTime ?? last.StartTime;
|
||||
|
||||
//Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
|
||||
if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > last.EndTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
{
|
||||
if (!(last is Spinner) && h.StartTime - last.EndTime < 1000) addFrameToReplay(new LegacyReplayFrame(last.EndTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
||||
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.Position.X, h.Position.Y, LegacyButtonState.None));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > last.EndTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
{
|
||||
if (!(last is Spinner) && h.StartTime - last.EndTime < 1000) addFrameToReplay(new LegacyReplayFrame(last.EndTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
||||
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.Position.X, h.Position.Y, LegacyButtonState.None));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > last.EndTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50)
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > endTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50)
|
||||
{
|
||||
if (!(last is Spinner) && h.StartTime - last.EndTime < 1000) addFrameToReplay(new LegacyReplayFrame(last.EndTime + h.HitWindowFor(OsuScoreResult.Hit100), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
||||
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.Position.X, h.Position.Y, LegacyButtonState.None));
|
||||
}
|
||||
}
|
||||
@ -206,8 +209,10 @@ namespace osu.Game.Modes.Osu
|
||||
|
||||
LegacyButtonState button = buttonIndex % 2 == 0 ? LegacyButtonState.Left1 : LegacyButtonState.Right1;
|
||||
|
||||
double hEndTime = (h as IHasEndTime)?.EndTime ?? h.StartTime;
|
||||
|
||||
LegacyReplayFrame newFrame = new LegacyReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button);
|
||||
LegacyReplayFrame endFrame = new LegacyReplayFrame(h.EndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, LegacyButtonState.None);
|
||||
LegacyReplayFrame endFrame = new LegacyReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, LegacyButtonState.None);
|
||||
|
||||
// Decrement because we want the previous frame, not the next one
|
||||
int index = findInsertionIndex(newFrame) - 1;
|
||||
@ -251,6 +256,8 @@ namespace osu.Game.Modes.Osu
|
||||
// We add intermediate frames for spinning / following a slider here.
|
||||
if (h is Spinner)
|
||||
{
|
||||
Spinner s = h as Spinner;
|
||||
|
||||
Vector2 difference = targetPosition - spinner_centre;
|
||||
|
||||
float radius = difference.Length;
|
||||
@ -258,7 +265,7 @@ namespace osu.Game.Modes.Osu
|
||||
|
||||
double t;
|
||||
|
||||
for (double j = h.StartTime + frameDelay; j < h.EndTime; j += frameDelay)
|
||||
for (double j = h.StartTime + frameDelay; j < s.EndTime; j += frameDelay)
|
||||
{
|
||||
t = applyModsToTime(j - h.StartTime) * spinnerDirection;
|
||||
|
||||
@ -266,10 +273,10 @@ namespace osu.Game.Modes.Osu
|
||||
addFrameToReplay(new LegacyReplayFrame((int)j, pos.X, pos.Y, button));
|
||||
}
|
||||
|
||||
t = applyModsToTime(h.EndTime - h.StartTime) * spinnerDirection;
|
||||
t = applyModsToTime(s.EndTime - h.StartTime) * spinnerDirection;
|
||||
Vector2 endPosition = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
|
||||
|
||||
addFrameToReplay(new LegacyReplayFrame(h.EndTime, endPosition.X, endPosition.Y, button));
|
||||
addFrameToReplay(new LegacyReplayFrame(s.EndTime, endPosition.X, endPosition.Y, button));
|
||||
|
||||
endFrame.MouseX = endPosition.X;
|
||||
endFrame.MouseY = endPosition.Y;
|
||||
@ -284,7 +291,7 @@ namespace osu.Game.Modes.Osu
|
||||
addFrameToReplay(new LegacyReplayFrame(h.StartTime + j, pos.X, pos.Y, button));
|
||||
}
|
||||
|
||||
addFrameToReplay(new LegacyReplayFrame(h.EndTime, s.EndPosition.X, s.EndPosition.Y, button));
|
||||
addFrameToReplay(new LegacyReplayFrame(s.EndTime, s.EndPosition.X, s.EndPosition.Y, button));
|
||||
}
|
||||
|
||||
// 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!
|
||||
|
@ -4,7 +4,6 @@
|
||||
using OpenTK.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Modes.Osu.UI;
|
||||
using osu.Game.Modes.UI;
|
||||
@ -94,8 +93,6 @@ namespace osu.Game.Modes.Osu
|
||||
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_osu_o;
|
||||
|
||||
public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount = 0) => new OsuScoreProcessor(hitObjectCount);
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new OsuDifficultyCalculator(beatmap);
|
||||
|
@ -67,8 +67,8 @@
|
||||
<Compile Include="Objects\Drawables\Pieces\TrianglesPiece.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\SliderBall.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\SliderBody.cs" />
|
||||
<Compile Include="Objects\HitObjectType.cs" />
|
||||
<Compile Include="Objects\OsuHitObjectDifficulty.cs" />
|
||||
<Compile Include="Objects\OsuHitObjectParser.cs" />
|
||||
<Compile Include="Objects\SliderCurve.cs" />
|
||||
<Compile Include="Objects\SliderTick.cs" />
|
||||
<Compile Include="OsuAutoReplay.cs" />
|
||||
|
@ -9,7 +9,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps
|
||||
{
|
||||
internal class TaikoBeatmapConverter : IBeatmapConverter<TaikoBaseHit>
|
||||
{
|
||||
public Beatmap<TaikoBaseHit> Convert(Beatmap original)
|
||||
public Beatmap<TaikoBaseHit> ConvertBeatmap(Beatmap original)
|
||||
{
|
||||
return new Beatmap<TaikoBaseHit>(original)
|
||||
{
|
||||
|
@ -7,6 +7,7 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using OpenTK;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
||||
{
|
||||
@ -29,8 +30,11 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
||||
{
|
||||
Texture = textures.Get(@"Menu/logo");
|
||||
|
||||
double endTime = (h as IHasEndTime)?.EndTime ?? h.StartTime;
|
||||
double duration = endTime - h.StartTime;
|
||||
|
||||
Transforms.Add(new TransformPositionX { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = 1.1f, EndValue = 0.1f });
|
||||
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
|
||||
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 });
|
||||
Expire(true);
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects
|
||||
{
|
||||
internal class TaikoConverter : HitObjectConverter<TaikoBaseHit>
|
||||
{
|
||||
public override List<TaikoBaseHit> Convert(Beatmap beatmap)
|
||||
{
|
||||
List<TaikoBaseHit> output = new List<TaikoBaseHit>();
|
||||
|
||||
foreach (HitObject i in beatmap.HitObjects)
|
||||
{
|
||||
TaikoBaseHit h = i as TaikoBaseHit;
|
||||
|
||||
if (h == null)
|
||||
{
|
||||
OsuHitObject o = i as OsuHitObject;
|
||||
|
||||
if (o == null) throw new HitObjectConvertException(@"Taiko", i);
|
||||
|
||||
h = new TaikoBaseHit
|
||||
{
|
||||
StartTime = o.StartTime,
|
||||
};
|
||||
}
|
||||
|
||||
output.Add(h);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
using OpenTK.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Taiko.UI;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
@ -89,8 +88,6 @@ namespace osu.Game.Modes.Taiko
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount = 0) => null;
|
||||
|
||||
public override HitObjectParser CreateHitObjectParser() => new NullHitObjectParser();
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap);
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,6 @@
|
||||
<Compile Include="TaikoDifficultyCalculator.cs" />
|
||||
<Compile Include="Objects\Drawable\DrawableTaikoHit.cs" />
|
||||
<Compile Include="Objects\TaikoBaseHit.cs" />
|
||||
<Compile Include="Objects\TaikoConverter.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UI\TaikoHitRenderer.cs" />
|
||||
<Compile Include="UI\TaikoPlayfield.cs" />
|
||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
protected DifficultyCalculator(Beatmap beatmap)
|
||||
{
|
||||
Objects = CreateBeatmapConverter().Convert(beatmap).HitObjects;
|
||||
Objects = CreateBeatmapConverter().ConvertBeatmap(beatmap).HitObjects;
|
||||
PreprocessHitObjects();
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ using osu.Game.Modes.Objects;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
@ -81,8 +82,13 @@ namespace osu.Game.Beatmaps.Formats
|
||||
|
||||
foreach (HitObject h in b.HitObjects)
|
||||
{
|
||||
if (h.NewCombo || i == -1) i = (i + 1) % colours.Count;
|
||||
h.Colour = colours[i];
|
||||
IHasCombo ihc = h as IHasCombo;
|
||||
|
||||
if (ihc == null)
|
||||
continue;
|
||||
|
||||
if (ihc.NewCombo || i == -1) i = (i + 1) % colours.Count;
|
||||
ihc.ComboColour = colours[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
case Section.General:
|
||||
handleGeneral(beatmap, key, val);
|
||||
parser = Ruleset.GetRuleset(beatmap.BeatmapInfo.Mode).CreateHitObjectParser();
|
||||
parser = new LegacyHitObjectParser();
|
||||
break;
|
||||
case Section.Editor:
|
||||
handleEditor(beatmap, key, val);
|
||||
|
@ -5,8 +5,17 @@ using osu.Game.Modes.Objects;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Beatmap for another mode.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of HitObject stored in the Beatmap.</typeparam>
|
||||
public interface IBeatmapConverter<T> where T : HitObject
|
||||
{
|
||||
Beatmap<T> Convert(Beatmap original);
|
||||
/// <summary>
|
||||
/// Converts a Beatmap to another mode.
|
||||
/// </summary>
|
||||
/// <param name="original">The original Beatmap.</param>
|
||||
/// <returns>The converted Beatmap.</returns>
|
||||
Beatmap<T> ConvertBeatmap(Beatmap original);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ using osu.Framework.Audio.Sample;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using OpenTK;
|
||||
using Container = osu.Framework.Graphics.Containers.Container;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Drawables
|
||||
{
|
||||
@ -67,14 +68,14 @@ namespace osu.Game.Modes.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class DrawableHitObject<HitObjectType> : DrawableHitObject
|
||||
where HitObjectType : HitObject
|
||||
public abstract class DrawableHitObject<TObject> : DrawableHitObject
|
||||
where TObject : HitObject
|
||||
{
|
||||
public event Action<DrawableHitObject<HitObjectType>, JudgementInfo> OnJudgement;
|
||||
public event Action<DrawableHitObject<TObject>, JudgementInfo> OnJudgement;
|
||||
|
||||
public HitObjectType HitObject;
|
||||
public TObject HitObject;
|
||||
|
||||
protected DrawableHitObject(HitObjectType hitObject)
|
||||
protected DrawableHitObject(TObject hitObject)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
}
|
||||
@ -88,7 +89,9 @@ namespace osu.Game.Modes.Objects.Drawables
|
||||
if (Judgement.Result != null)
|
||||
return false;
|
||||
|
||||
Judgement.TimeOffset = Time.Current - HitObject.EndTime;
|
||||
double endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
|
||||
|
||||
Judgement.TimeOffset = Time.Current - endTime;
|
||||
|
||||
CheckJudgement(userTriggered);
|
||||
|
||||
@ -138,14 +141,14 @@ namespace osu.Game.Modes.Objects.Drawables
|
||||
Sample = audio.Sample.Get($@"Gameplay/{sampleSet.ToString().ToLower()}-hit{type.ToString().ToLower()}");
|
||||
}
|
||||
|
||||
private List<DrawableHitObject<HitObjectType>> nestedHitObjects;
|
||||
private List<DrawableHitObject<TObject>> nestedHitObjects;
|
||||
|
||||
protected IEnumerable<DrawableHitObject<HitObjectType>> NestedHitObjects => nestedHitObjects;
|
||||
protected IEnumerable<DrawableHitObject<TObject>> NestedHitObjects => nestedHitObjects;
|
||||
|
||||
protected void AddNested(DrawableHitObject<HitObjectType> h)
|
||||
protected void AddNested(DrawableHitObject<TObject> h)
|
||||
{
|
||||
if (nestedHitObjects == null)
|
||||
nestedHitObjects = new List<DrawableHitObject<HitObjectType>>();
|
||||
nestedHitObjects = new List<DrawableHitObject<TObject>>();
|
||||
|
||||
h.OnJudgement += (d, j) => { OnJudgement?.Invoke(d, j); } ;
|
||||
nestedHitObjects.Add(h);
|
||||
|
15
osu.Game/Modes/Objects/Hit.cs
Normal file
15
osu.Game/Modes/Objects/Hit.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
internal class Hit : HitObject, IHasPosition, IHasCombo
|
||||
{
|
||||
public Vector2 Position { get; set; }
|
||||
public Color4 ComboColour { get; set; }
|
||||
|
||||
public bool NewCombo { get; set; }
|
||||
public int ComboIndex { get; set; }
|
||||
}
|
||||
}
|
@ -3,28 +3,31 @@
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// A hitobject describes a point in a beatmap
|
||||
/// A HitObject describes an object in a Beatmap.
|
||||
/// <para>
|
||||
/// HitObjects may contain more properties for which you should be checking through the IHas* types.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public abstract class HitObject
|
||||
public class HitObject
|
||||
{
|
||||
public double StartTime;
|
||||
public virtual double EndTime => StartTime;
|
||||
/// <summary>
|
||||
/// The time at which the HitObject starts.
|
||||
/// </summary>
|
||||
public double StartTime { get; set; }
|
||||
|
||||
public bool NewCombo { get; set; }
|
||||
|
||||
public Color4 Colour = new Color4(17, 136, 170, 255);
|
||||
|
||||
public double Duration => EndTime - StartTime;
|
||||
|
||||
public HitSampleInfo Sample;
|
||||
|
||||
public int ComboIndex;
|
||||
/// <summary>
|
||||
/// The sample to be played when this HitObject is hit.
|
||||
/// </summary>
|
||||
public HitSampleInfo Sample { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets default parameters from a beatmap.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to set from.</param>
|
||||
public virtual void SetDefaultsFromBeatmap(Beatmap beatmap) { }
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
public abstract class HitObjectConverter<T>
|
||||
where T : HitObject
|
||||
{
|
||||
public abstract List<T> Convert(Beatmap beatmap);
|
||||
}
|
||||
|
||||
public class HitObjectConvertException : Exception
|
||||
{
|
||||
public HitObject Input { get; }
|
||||
public HitObjectConvertException(string modeName, HitObject input)
|
||||
: base($@"Can't convert from {input.GetType().Name} to {modeName} HitObject!")
|
||||
{
|
||||
Input = input;
|
||||
}
|
||||
}
|
||||
}
|
17
osu.Game/Modes/Objects/IHitObjectConverter.cs
Normal file
17
osu.Game/Modes/Objects/IHitObjectConverter.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts HitObjects to another mode.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of HitObject to be converted to.</typeparam>
|
||||
public interface IHitObjectConverter<T>
|
||||
where T : HitObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="HitObject"/> to another mode.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The base HitObject to convert.</param>
|
||||
/// <returns>The converted HitObject.</returns>
|
||||
T Convert(HitObject hitObject);
|
||||
}
|
||||
}
|
@ -1,16 +1,13 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using osu.Game.Modes.Objects;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
public class OsuHitObjectParser : HitObjectParser
|
||||
internal class LegacyHitObjectParser : HitObjectParser
|
||||
{
|
||||
public override HitObject Parse(string text)
|
||||
{
|
||||
@ -19,17 +16,19 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
bool combo = type.HasFlag(HitObjectType.NewCombo);
|
||||
type &= (HitObjectType)0xF;
|
||||
type &= ~HitObjectType.NewCombo;
|
||||
OsuHitObject result;
|
||||
|
||||
HitObject result;
|
||||
switch (type)
|
||||
{
|
||||
case HitObjectType.Circle:
|
||||
result = new HitCircle
|
||||
result = new Hit
|
||||
{
|
||||
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1]))
|
||||
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
|
||||
NewCombo = combo
|
||||
};
|
||||
break;
|
||||
case HitObjectType.Slider:
|
||||
CurveTypes curveType = CurveTypes.Catmull;
|
||||
CurveType curveType = CurveType.Catmull;
|
||||
double length = 0;
|
||||
List<Vector2> points = new List<Vector2> { new Vector2(int.Parse(split[0]), int.Parse(split[1])) };
|
||||
|
||||
@ -41,16 +40,16 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
switch (t)
|
||||
{
|
||||
case @"C":
|
||||
curveType = CurveTypes.Catmull;
|
||||
curveType = CurveType.Catmull;
|
||||
break;
|
||||
case @"B":
|
||||
curveType = CurveTypes.Bezier;
|
||||
curveType = CurveType.Bezier;
|
||||
break;
|
||||
case @"L":
|
||||
curveType = CurveTypes.Linear;
|
||||
curveType = CurveType.Linear;
|
||||
break;
|
||||
case @"P":
|
||||
curveType = CurveTypes.PerfectCurve;
|
||||
curveType = CurveType.PerfectCurve;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@ -75,17 +74,17 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
result = new Slider
|
||||
{
|
||||
ControlPoints = points,
|
||||
Length = length,
|
||||
Distance = length,
|
||||
CurveType = curveType,
|
||||
RepeatCount = repeatCount,
|
||||
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1]))
|
||||
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
|
||||
NewCombo = combo
|
||||
};
|
||||
break;
|
||||
case HitObjectType.Spinner:
|
||||
result = new Spinner
|
||||
{
|
||||
Length = Convert.ToDouble(split[5], CultureInfo.InvariantCulture) - Convert.ToDouble(split[2], CultureInfo.InvariantCulture),
|
||||
Position = new Vector2(512, 384) / 2,
|
||||
EndTime = Convert.ToDouble(split[5], CultureInfo.InvariantCulture)
|
||||
};
|
||||
break;
|
||||
default:
|
||||
@ -97,8 +96,9 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
Type = (SampleType)int.Parse(split[4]),
|
||||
Set = SampleSet.Soft,
|
||||
};
|
||||
result.NewCombo = combo;
|
||||
|
||||
// TODO: "addition" field
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns null HitObjects but at least allows us to run.
|
||||
/// </summary>
|
||||
public class NullHitObjectParser : HitObjectParser
|
||||
{
|
||||
public override HitObject Parse(string text) => null;
|
||||
}
|
||||
}
|
23
osu.Game/Modes/Objects/Slider.cs
Normal file
23
osu.Game/Modes/Objects/Slider.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
internal class Slider : HitObject, IHasCurve, IHasDistance, IHasPosition, IHasCombo, IHasRepeats
|
||||
{
|
||||
public List<Vector2> ControlPoints { get; set; }
|
||||
public CurveType CurveType { get; set; }
|
||||
|
||||
public double Distance { get; set; }
|
||||
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public Color4 ComboColour { get; set; }
|
||||
public bool NewCombo { get; set; }
|
||||
public int ComboIndex { get; set; }
|
||||
|
||||
public int RepeatCount { get; set; }
|
||||
}
|
||||
}
|
11
osu.Game/Modes/Objects/Spinner.cs
Normal file
11
osu.Game/Modes/Objects/Spinner.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
internal class Spinner : HitObject, IHasEndTime
|
||||
{
|
||||
public double EndTime { get; set; }
|
||||
|
||||
public double Duration => EndTime - StartTime;
|
||||
}
|
||||
}
|
10
osu.Game/Modes/Objects/Types/CurveType.cs
Normal file
10
osu.Game/Modes/Objects/Types/CurveType.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
public enum CurveType
|
||||
{
|
||||
Catmull,
|
||||
Bezier,
|
||||
Linear,
|
||||
PerfectCurve
|
||||
}
|
||||
}
|
25
osu.Game/Modes/Objects/Types/IHasCombo.cs
Normal file
25
osu.Game/Modes/Objects/Types/IHasCombo.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that is part of a combo.
|
||||
/// </summary>
|
||||
public interface IHasCombo
|
||||
{
|
||||
/// <summary>
|
||||
/// The colour of this HitObject in the combo.
|
||||
/// </summary>
|
||||
Color4 ComboColour { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the HitObject starts a new combo.
|
||||
/// </summary>
|
||||
bool NewCombo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The combo index.
|
||||
/// </summary>
|
||||
int ComboIndex { get; }
|
||||
}
|
||||
}
|
21
osu.Game/Modes/Objects/Types/IHasCurve.cs
Normal file
21
osu.Game/Modes/Objects/Types/IHasCurve.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that has a curve.
|
||||
/// </summary>
|
||||
public interface IHasCurve
|
||||
{
|
||||
/// <summary>
|
||||
/// The control points that shape the curve.
|
||||
/// </summary>
|
||||
List<Vector2> ControlPoints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of curve.
|
||||
/// </summary>
|
||||
CurveType CurveType { get; }
|
||||
}
|
||||
}
|
13
osu.Game/Modes/Objects/Types/IHasDistance.cs
Normal file
13
osu.Game/Modes/Objects/Types/IHasDistance.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that has a distance.
|
||||
/// </summary>
|
||||
public interface IHasDistance
|
||||
{
|
||||
/// <summary>
|
||||
/// The distance of the HitObject.
|
||||
/// </summary>
|
||||
double Distance { get; }
|
||||
}
|
||||
}
|
18
osu.Game/Modes/Objects/Types/IHasEndTime.cs
Normal file
18
osu.Game/Modes/Objects/Types/IHasEndTime.cs
Normal file
@ -0,0 +1,18 @@
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that ends at a different time than its start time.
|
||||
/// </summary>
|
||||
public interface IHasEndTime
|
||||
{
|
||||
/// <summary>
|
||||
/// The time at which the HitObject ends.
|
||||
/// </summary>
|
||||
double EndTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The duration of the HitObject.
|
||||
/// </summary>
|
||||
double Duration { get; }
|
||||
}
|
||||
}
|
15
osu.Game/Modes/Objects/Types/IHasPosition.cs
Normal file
15
osu.Game/Modes/Objects/Types/IHasPosition.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that has a starting position.
|
||||
/// </summary>
|
||||
public interface IHasPosition
|
||||
{
|
||||
/// <summary>
|
||||
/// The starting position of the HitObject.
|
||||
/// </summary>
|
||||
Vector2 Position { get; }
|
||||
}
|
||||
}
|
13
osu.Game/Modes/Objects/Types/IHasRepeats.cs
Normal file
13
osu.Game/Modes/Objects/Types/IHasRepeats.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that spans some length.
|
||||
/// </summary>
|
||||
public interface IHasRepeats
|
||||
{
|
||||
/// <summary>
|
||||
/// The amount of times the HitObject repeats.
|
||||
/// </summary>
|
||||
int RepeatCount { get; }
|
||||
}
|
||||
}
|
16
osu.Game/Modes/Objects/Types/LegacyHitObjectLive.cs
Normal file
16
osu.Game/Modes/Objects/Types/LegacyHitObjectLive.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
[Flags]
|
||||
public enum HitObjectType
|
||||
{
|
||||
Circle = 1 << 0,
|
||||
Slider = 1 << 1,
|
||||
NewCombo = 1 << 2,
|
||||
Spinner = 1 << 3,
|
||||
ColourHax = 122,
|
||||
Hold = 1 << 7,
|
||||
SliderTick = 1 << 8,
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using System;
|
||||
@ -33,8 +32,6 @@ namespace osu.Game.Modes
|
||||
|
||||
public abstract HitRenderer CreateHitRendererWith(Beatmap beatmap);
|
||||
|
||||
public abstract HitObjectParser CreateHitObjectParser();
|
||||
|
||||
public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap);
|
||||
|
||||
public static void Register(Ruleset ruleset) => availableRulesets.TryAdd(ruleset.PlayMode, ruleset.GetType());
|
||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Modes.UI
|
||||
|
||||
protected HitRenderer(Beatmap beatmap)
|
||||
{
|
||||
Beatmap = CreateBeatmapConverter().Convert(beatmap);
|
||||
Beatmap = CreateBeatmapConverter().ConvertBeatmap(beatmap);
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
|
@ -21,6 +21,8 @@ using osu.Framework.MathUtils;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Modes;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
@ -69,11 +71,14 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
if (beatmap.Beatmap != null)
|
||||
{
|
||||
HitObject lastObject = beatmap.Beatmap.HitObjects.Last();
|
||||
double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime;
|
||||
|
||||
labels.Add(new InfoLabel(new BeatmapStatistic
|
||||
{
|
||||
Name = "Length",
|
||||
Icon = FontAwesome.fa_clock_o,
|
||||
Content = beatmap.Beatmap.HitObjects.Count == 0 ? "-" : TimeSpan.FromMilliseconds(beatmap.Beatmap.HitObjects.Last().EndTime - beatmap.Beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"),
|
||||
Content = beatmap.Beatmap.HitObjects.Count == 0 ? "-" : TimeSpan.FromMilliseconds(endTime - beatmap.Beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"),
|
||||
}));
|
||||
|
||||
labels.Add(new InfoLabel(new BeatmapStatistic
|
||||
|
@ -91,9 +91,21 @@
|
||||
<Compile Include="IO\Legacy\SerializationWriter.cs" />
|
||||
<Compile Include="IPC\ScoreIPCChannel.cs" />
|
||||
<Compile Include="Modes\LegacyReplay.cs" />
|
||||
<Compile Include="Modes\Objects\Hit.cs" />
|
||||
<Compile Include="Modes\Objects\IHitObjectConverter.cs" />
|
||||
<Compile Include="Modes\Objects\LegacyHitObjectParser.cs" />
|
||||
<Compile Include="Modes\Objects\Slider.cs" />
|
||||
<Compile Include="Modes\Objects\Spinner.cs" />
|
||||
<Compile Include="Modes\Objects\Types\CurveType.cs" />
|
||||
<Compile Include="Modes\Objects\Drawables\IDrawableHitObjectWithProxiedApproach.cs" />
|
||||
<Compile Include="Modes\Objects\HitObjectParser.cs" />
|
||||
<Compile Include="Modes\Objects\NullHitObjectParser.cs" />
|
||||
<Compile Include="Modes\Objects\Types\IHasCombo.cs" />
|
||||
<Compile Include="Modes\Objects\Types\IHasEndTime.cs" />
|
||||
<Compile Include="Modes\Objects\Types\IHasDistance.cs" />
|
||||
<Compile Include="Modes\Objects\Types\IHasCurve.cs" />
|
||||
<Compile Include="Modes\Objects\Types\IHasRepeats.cs" />
|
||||
<Compile Include="Modes\Objects\Types\IHasPosition.cs" />
|
||||
<Compile Include="Modes\Objects\Types\LegacyHitObjectLive.cs" />
|
||||
<Compile Include="Modes\Replay.cs" />
|
||||
<Compile Include="Modes\Score.cs" />
|
||||
<Compile Include="Modes\ScoreProcesssor.cs" />
|
||||
@ -114,7 +126,6 @@
|
||||
<Compile Include="Beatmaps\Drawables\Panel.cs" />
|
||||
<Compile Include="Modes\Objects\Drawables\DrawableHitObject.cs" />
|
||||
<Compile Include="Modes\Objects\HitObject.cs" />
|
||||
<Compile Include="Modes\Objects\HitObjectConverter.cs" />
|
||||
<Compile Include="Beatmaps\Samples\HitSampleInfo.cs" />
|
||||
<Compile Include="Beatmaps\Samples\SampleBank.cs" />
|
||||
<Compile Include="Beatmaps\Samples\SampleInfo.cs" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user