1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-15 15:32:53 +08:00

Compare commits

...

105 Commits

126 changed files with 836 additions and 509 deletions
+4 -2
View File
@@ -1,5 +1,7 @@
<Project>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputPath>bin\$(Configuration)</OutputPath>
<WarningLevel>4</WarningLevel>
<SchemaVersion>2.0</SchemaVersion>
@@ -35,7 +37,7 @@
<DebugType>None</DebugType>
<Optimize>True</Optimize>
<ErrorReport>prompt</ErrorReport>
<EnableLLVM>true</EnableLLVM>
<EnableLLVM>true</EnableLLVM>
<AndroidManagedSymbols>false</AndroidManagedSymbols>
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
@@ -61,6 +63,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.904.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2019.905.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2019.909.0" />
</ItemGroup>
</Project>
@@ -6,6 +6,7 @@ using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Catch.Objects
{
@@ -1,10 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Catch.Objects
namespace osu.Game.Rulesets.Catch.Scoring
{
public class CatchHitWindows : HitWindows
{
@@ -4,7 +4,6 @@
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
@@ -3,6 +3,7 @@
using System.Linq;
using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Replays;
@@ -12,6 +13,7 @@ using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Mania.Tests
{
[TestFixture]
[HeadlessTest]
public class TestSceneAutoGeneration : OsuTestScene
{
[Test]
@@ -1,4 +1,4 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
@@ -11,6 +11,7 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics;
@@ -40,6 +41,7 @@ namespace osu.Game.Rulesets.Mania.Tests
{
Child = new FillFlowContainer
{
Clock = new FramedClock(new ManualClock()),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
@@ -62,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Tests
private Drawable createNoteDisplay(ScrollingDirection direction, int identifier, out DrawableNote hitObject)
{
var note = new Note { StartTime = 999999999 };
var note = new Note { StartTime = 0 };
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
return new ScrollingTestContainer(direction)
@@ -77,7 +79,7 @@ namespace osu.Game.Rulesets.Mania.Tests
private Drawable createHoldNoteDisplay(ScrollingDirection direction, int identifier, out DrawableHoldNote hitObject)
{
var note = new HoldNote { StartTime = 999999999, Duration = 5000 };
var note = new HoldNote { StartTime = 0, Duration = 5000 };
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
return new ScrollingTestContainer(direction)
@@ -133,7 +135,7 @@ namespace osu.Game.Rulesets.Mania.Tests
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.Both,
Width = 1.25f,
Colour = Color4.Black.Opacity(0.5f)
Colour = Color4.Green.Opacity(0.5f)
},
content = new Container { RelativeSizeAxes = Axes.Both }
}
@@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI.Scrolling;
using osu.Game.Tests.Visual;
using osuTK;
@@ -114,8 +115,7 @@ namespace osu.Game.Rulesets.Mania.Tests
var obj = new BarLine
{
StartTime = Time.Current + 2000,
ControlPoint = new TimingControlPoint(),
BeatIndex = major ? 0 : 1
Major = major,
};
obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
@@ -11,9 +11,9 @@ using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Difficulty.Preprocessing;
using osu.Game.Rulesets.Mania.Difficulty.Skills;
using osu.Game.Rulesets.Mania.Mods;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Difficulty
{
@@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
StarRating = difficultyValue(skills) * star_scaling_factor,
Mods = mods,
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
GreatHitWindow = (int)(hitWindows.Great / 2) / clockRate,
GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate,
Skills = skills
};
}
@@ -1,21 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Beatmaps.ControlPoints;
namespace osu.Game.Rulesets.Mania.Objects
{
public class BarLine : ManiaHitObject
{
/// <summary>
/// The control point which this bar line is part of.
/// </summary>
public TimingControlPoint ControlPoint;
/// <summary>
/// The index of the beat which this bar line represents within the control point.
/// This is a "major" bar line if <see cref="BeatIndex"/> % <see cref="TimingControlPoint.TimeSignature"/> == 0.
/// </summary>
public int BeatIndex;
}
}
@@ -4,6 +4,7 @@
using osuTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osuTK.Graphics;
@@ -13,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
/// Visualises a <see cref="BarLine"/>. Although this derives DrawableManiaHitObject,
/// this does not handle input/sound like a normal hit object.
/// </summary>
public class DrawableBarLine : DrawableManiaHitObject<BarLine>
public class DrawableBarLine : DrawableHitObject<BarLine>
{
/// <summary>
/// Height of major bar line triangles.
@@ -40,9 +41,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Colour = new Color4(255, 204, 33, 255),
});
bool isMajor = barLine.BeatIndex % (int)barLine.ControlPoint.TimeSignature == 0;
if (isMajor)
if (barLine.Major)
{
AddInternal(new EquilateralTriangle
{
@@ -65,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
});
}
if (!isMajor && barLine.BeatIndex % 2 == 1)
if (!barLine.Major)
Alpha = 0.2f;
}
+1 -1
View File
@@ -5,8 +5,8 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Objects
{
@@ -3,7 +3,7 @@
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Objects
{
@@ -3,7 +3,9 @@
using osu.Framework.Bindables;
using osu.Game.Rulesets.Mania.Objects.Types;
using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Objects
{
@@ -1,35 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Objects
{
public class ManiaHitWindows : HitWindows
{
private static readonly IReadOnlyDictionary<HitResult, (double od0, double od5, double od10)> base_ranges = new Dictionary<HitResult, (double, double, double)>
{
{ HitResult.Perfect, (44.8, 38.8, 27.8) },
{ HitResult.Great, (128, 98, 68) },
{ HitResult.Good, (194, 164, 134) },
{ HitResult.Ok, (254, 224, 194) },
{ HitResult.Meh, (302, 272, 242) },
{ HitResult.Miss, (376, 346, 316) },
};
public override bool IsHitResultAllowed(HitResult result) => true;
public override void SetDifficulty(double difficulty)
{
Perfect = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Perfect]);
Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]);
Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]);
Ok = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Ok]);
Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]);
Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]);
}
}
}
@@ -1,9 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Rulesets.Taiko.Objects
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Scoring
{
public class BarLine : TaikoHitObject
public class ManiaHitWindows : HitWindows
{
}
}
@@ -4,7 +4,6 @@
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
@@ -2,14 +2,11 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Input;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.Mania.Beatmaps;
@@ -19,8 +16,8 @@ using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling;
@@ -45,33 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI
public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods)
{
// Generate the bar lines
double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue;
var timingPoints = Beatmap.ControlPointInfo.TimingPoints;
var barLines = new List<BarLine>();
for (int i = 0; i < timingPoints.Count; i++)
{
TimingControlPoint point = timingPoints[i];
// Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object
double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - point.BeatLength : lastObjectTime + point.BeatLength * (int)point.TimeSignature;
int index = 0;
for (double t = timingPoints[i].Time; Precision.DefinitelyBigger(endTime, t); t += point.BeatLength, index++)
{
barLines.Add(new BarLine
{
StartTime = t,
ControlPoint = point,
BeatIndex = index
});
}
}
BarLines = barLines;
BarLines = new BarLineGenerator(Beatmap).BarLines;
}
[BackgroundDependencyLoader]
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI.Scrolling;
using osuTK;
+1
View File
@@ -12,6 +12,7 @@ using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

@@ -26,12 +26,12 @@ namespace osu.Game.Rulesets.Osu.Tests
}
[BackgroundDependencyLoader]
private void load(AudioManager audio)
private void load(AudioManager audio, SkinManager skinManager)
{
var dllStore = new DllResourceStore("osu.Game.Rulesets.Osu.Tests.dll");
metricsSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), audio, true);
defaultSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore<byte[]>(dllStore, "Resources/default_skin"), audio, false);
defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info);
specialSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore<byte[]>(dllStore, "Resources/special_skin"), audio, true);
}
@@ -6,23 +6,68 @@ using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Testing.Input;
using osu.Game.Rulesets.Osu.UI.Cursor;
using osuTK;
namespace osu.Game.Rulesets.Osu.Tests
{
[TestFixture]
public class TestSceneGameplayCursor : SkinnableTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(CursorTrail) };
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(OsuCursorContainer),
typeof(CursorTrail)
};
[BackgroundDependencyLoader]
private void load()
{
SetContents(() => new OsuCursorContainer
SetContents(() => new MovingCursorInputManager
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Child = new ClickingCursorContainer
{
RelativeSizeAxes = Axes.Both,
Masking = true,
}
});
}
private class ClickingCursorContainer : OsuCursorContainer
{
protected override void Update()
{
base.Update();
double currentTime = Time.Current;
if (((int)(currentTime / 1000)) % 2 == 0)
OnPressed(OsuAction.LeftButton);
else
OnReleased(OsuAction.LeftButton);
}
}
private class MovingCursorInputManager : ManualInputManager
{
public MovingCursorInputManager()
{
UseParentInput = false;
}
protected override void Update()
{
base.Update();
const double spin_duration = 5000;
double currentTime = Time.Current;
double angle = (currentTime % spin_duration) / spin_duration * 2 * Math.PI;
Vector2 rPos = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
MoveMouseTo(ToScreenSpace(DrawSize / 2 + DrawSize / 3 * rPos));
}
}
}
}
@@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Tests
Debug.Assert(drawableHitObject.HitObject.HitWindows != null);
double delay = drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.HalfWindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current;
double delay = drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.WindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current;
Scheduler.AddDelayed(() => drawableHitObject.TriggerJudgement(), delay);
return drawableHitObject;
@@ -9,11 +9,12 @@ using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
using osu.Game.Rulesets.Osu.Difficulty.Skills;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Difficulty
{
@@ -39,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
// Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future
double hitWindowGreat = (int)(hitWindows.Great / 2) / clockRate;
double hitWindowGreat = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate;
double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
int maxCombo = beatmap.HitObjects.Count;
@@ -10,8 +10,8 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
using osuTK;
using osu.Game.Rulesets.Scoring;
using osuTK;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
@@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (result == HitResult.None)
{
Shake(Math.Abs(timeOffset) - HitObject.HitWindows.HalfWindowFor(HitResult.Miss));
Shake(Math.Abs(timeOffset) - HitObject.HitWindows.WindowFor(HitResult.Miss));
return;
}
@@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
hitArea.HitAction = null;
// override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early.
LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss);
LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.WindowFor(HitResult.Miss);
break;
case ArmedState.Miss:
@@ -9,8 +9,8 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.MathUtils;
using osu.Game.Rulesets.Objects.Drawables;
using osuTK;
using osu.Game.Rulesets.Scoring;
using osuTK;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
@@ -8,9 +8,9 @@ using osu.Game.Rulesets.Objects.Drawables;
using osuTK;
using osuTK.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
@@ -13,8 +13,8 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites;
using osu.Game.Screens.Ranking;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Ranking;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
@@ -7,6 +7,8 @@ using osu.Game.Rulesets.Objects;
using osuTK;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects
{
@@ -1,29 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects
{
public class OsuHitWindows : HitWindows
{
private static readonly IReadOnlyDictionary<HitResult, (double od0, double od5, double od10)> base_ranges = new Dictionary<HitResult, (double, double, double)>
{
{ HitResult.Great, (160, 100, 40) },
{ HitResult.Good, (280, 200, 120) },
{ HitResult.Meh, (400, 300, 200) },
{ HitResult.Miss, (400, 400, 400) },
};
public override void SetDifficulty(double difficulty)
{
Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]);
Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]);
Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]);
Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]);
}
}
}
+1 -1
View File
@@ -5,8 +5,8 @@ using System;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects
{
+1
View File
@@ -13,6 +13,7 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects
{
@@ -5,6 +5,7 @@ using osu.Framework.Bindables;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects
{
+1 -1
View File
@@ -4,8 +4,8 @@
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects
{
+1 -1
View File
@@ -6,8 +6,8 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects
{
@@ -10,9 +10,9 @@ using System.Diagnostics;
using System.Linq;
using osu.Framework.Graphics;
using osu.Game.Replays;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Replays
@@ -118,29 +118,29 @@ namespace osu.Game.Rulesets.Osu.Replays
Debug.Assert(hitWindows != null);
// Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
if (h.StartTime - hitWindows.HalfWindowFor(HitResult.Miss) > endTime + hitWindows.HalfWindowFor(HitResult.Meh) + 50)
if (h.StartTime - hitWindows.WindowFor(HitResult.Miss) > endTime + hitWindows.WindowFor(HitResult.Meh) + 50)
{
if (!(prev is Spinner) && h.StartTime - endTime < 1000)
AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.WindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
if (!(h is Spinner))
AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.HalfWindowFor(HitResult.Miss), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.WindowFor(HitResult.Miss), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
}
else if (h.StartTime - hitWindows.HalfWindowFor(HitResult.Meh) > endTime + hitWindows.HalfWindowFor(HitResult.Meh) + 50)
else if (h.StartTime - hitWindows.WindowFor(HitResult.Meh) > endTime + hitWindows.WindowFor(HitResult.Meh) + 50)
{
if (!(prev is Spinner) && h.StartTime - endTime < 1000)
AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.WindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
if (!(h is Spinner))
AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.HalfWindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.WindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
}
else if (h.StartTime - hitWindows.HalfWindowFor(HitResult.Good) > endTime + hitWindows.HalfWindowFor(HitResult.Good) + 50)
else if (h.StartTime - hitWindows.WindowFor(HitResult.Good) > endTime + hitWindows.WindowFor(HitResult.Good) + 50)
{
if (!(prev is Spinner) && h.StartTime - endTime < 1000)
AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.HalfWindowFor(HitResult.Good), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.WindowFor(HitResult.Good), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
if (!(h is Spinner))
AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.HalfWindowFor(HitResult.Good), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.WindowFor(HitResult.Good), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
}
}
@@ -0,0 +1,34 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Scoring
{
public class OsuHitWindows : HitWindows
{
private static readonly DifficultyRange[] osu_ranges =
{
new DifficultyRange(HitResult.Great, 80, 50, 20),
new DifficultyRange(HitResult.Good, 140, 100, 60),
new DifficultyRange(HitResult.Meh, 200, 150, 100),
new DifficultyRange(HitResult.Miss, 200, 200, 200),
};
public override bool IsHitResultAllowed(HitResult result)
{
switch (result)
{
case HitResult.Great:
case HitResult.Good:
case HitResult.Meh:
case HitResult.Miss:
return true;
}
return false;
}
protected override DifficultyRange[] GetRanges() => osu_ranges;
}
}
@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Framework.Extensions;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
@@ -22,8 +20,6 @@ namespace osu.Game.Rulesets.Osu.Scoring
private float hpDrainRate;
private readonly Dictionary<ComboResult, int> comboResultCounts = new Dictionary<ComboResult, int>();
protected override void ApplyBeatmap(Beatmap<OsuHitObject> beatmap)
{
base.ApplyBeatmap(beatmap);
@@ -31,22 +27,6 @@ namespace osu.Game.Rulesets.Osu.Scoring
hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate;
}
protected override void Reset(bool storeResults)
{
base.Reset(storeResults);
comboResultCounts.Clear();
}
protected override void ApplyResult(JudgementResult result)
{
base.ApplyResult(result);
var osuResult = (OsuJudgementResult)result;
if (result.Type != HitResult.None)
comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1;
}
protected override double HealthAdjustmentFactorFor(JudgementResult result)
{
switch (result.Type)
@@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
return null;
case OsuSkinComponents.HitCircleText:
var font = GetConfig<OsuSkinConfiguration, string>(OsuSkinConfiguration.HitCircleFont)?.Value ?? "default";
var font = GetConfig<OsuSkinConfiguration, string>(OsuSkinConfiguration.HitCirclePrefix)?.Value ?? "default";
var overlap = GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? 0;
return !hasFont(font)
@@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
{
public enum OsuSkinConfiguration
{
HitCircleFont,
HitCirclePrefix,
HitCircleOverlap,
SliderBorderSize,
SliderPathRadius,
+21 -30
View File
@@ -22,28 +22,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
{
internal class CursorTrail : Drawable, IRequireHighFrequencyMousePosition
{
private int currentIndex;
private IShader shader;
private Texture texture;
private Vector2 size => texture.Size * Scale;
private double timeOffset;
private float time;
public override bool IsPresent => true;
private const int max_sprites = 2048;
private readonly TrailPart[] parts = new TrailPart[max_sprites];
private Vector2? lastPosition;
private readonly InputResampler resampler = new InputResampler();
protected override DrawNode CreateDrawNode() => new TrailDrawNode(this);
private int currentIndex;
private IShader shader;
private Texture texture;
private double timeOffset;
private float time;
public CursorTrail()
{
@@ -60,8 +46,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
}
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
[BackgroundDependencyLoader]
private void load(ShaderManager shaders, TextureStore textures)
{
@@ -76,6 +60,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
resetTime();
}
public override bool IsPresent => true;
protected override void Update()
{
base.Update();
@@ -101,6 +87,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
timeOffset = Time.Current;
}
private Vector2 size => texture.Size * Scale;
private Vector2? lastPosition;
private readonly InputResampler resampler = new InputResampler();
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
protected override bool OnMouseMove(MouseMoveEvent e)
{
Vector2 pos = e.ScreenSpaceMousePosition;
@@ -127,21 +120,19 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
for (float d = interval; d < distance; d += interval)
{
lastPosition = pos1 + direction * d;
addPosition(lastPosition.Value);
parts[currentIndex].Position = lastPosition.Value;
parts[currentIndex].Time = time;
++parts[currentIndex].InvalidationID;
currentIndex = (currentIndex + 1) % max_sprites;
}
}
return base.OnMouseMove(e);
}
private void addPosition(Vector2 pos)
{
parts[currentIndex].Position = pos;
parts[currentIndex].Time = time;
++parts[currentIndex].InvalidationID;
currentIndex = (currentIndex + 1) % max_sprites;
}
protected override DrawNode CreateDrawNode() => new TrailDrawNode(this);
private struct TrailPart
{
+4 -4
View File
@@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private bool cursorExpand;
private Bindable<double> cursorScale;
private Bindable<float> cursorScale;
private Bindable<bool> autoCursorScale;
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
@@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
this.beatmap.BindTo(beatmap);
this.beatmap.ValueChanged += _ => calculateScale();
cursorScale = config.GetBindable<double>(OsuSetting.GameplayCursorSize);
cursorScale = config.GetBindable<float>(OsuSetting.GameplayCursorSize);
cursorScale.ValueChanged += _ => calculateScale();
autoCursorScale = config.GetBindable<bool>(OsuSetting.AutoCursorSize);
@@ -71,12 +71,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private void calculateScale()
{
float scale = (float)cursorScale.Value;
float scale = cursorScale.Value;
if (autoCursorScale.Value && beatmap.Value != null)
{
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY);
scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY;
}
scaleTarget.Scale = new Vector2(scale);
@@ -14,13 +14,13 @@ using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Rulesets.Taiko.UI;
using osu.Game.Tests.Visual;
using osuTK;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.Tests
{
@@ -8,11 +8,12 @@ using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
using osu.Game.Rulesets.Taiko.Difficulty.Skills;
using osu.Game.Rulesets.Taiko.Mods;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Scoring;
namespace osu.Game.Rulesets.Taiko.Difficulty
{
@@ -38,7 +39,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
StarRating = skills.Single().DifficultyValue() * star_scaling_factor,
Mods = mods,
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
GreatHitWindow = (int)(hitWindows.Great / 2) / clockRate,
GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate,
MaxCombo = beatmap.HitObjects.Count(h => h is Hit),
Skills = skills
};
@@ -3,6 +3,7 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
using osuTK;
using osu.Game.Rulesets.Objects.Drawables;
@@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
/// <summary>
/// A line that scrolls alongside hit objects in the playfield and visualises control points.
/// </summary>
public class DrawableBarLine : DrawableHitObject<TaikoHitObject>
public class DrawableBarLine : DrawableHitObject<HitObject>
{
/// <summary>
/// The width of the line tracker.
@@ -5,6 +5,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osuTK;
using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{
@@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
validActionPressed = false;
UnproxyContent();
this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire();
this.Delay(HitObject.HitWindows.WindowFor(HitResult.Miss)).Expire();
break;
case ArmedState.Miss:
+1 -1
View File
@@ -6,7 +6,7 @@ using System;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements;
namespace osu.Game.Rulesets.Taiko.Objects
@@ -2,7 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements;
namespace osu.Game.Rulesets.Taiko.Objects
@@ -2,7 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements;
namespace osu.Game.Rulesets.Taiko.Objects
+1 -1
View File
@@ -4,7 +4,7 @@
using System;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements;
namespace osu.Game.Rulesets.Taiko.Objects
+1 -1
View File
@@ -2,7 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements;
namespace osu.Game.Rulesets.Taiko.Objects
@@ -4,7 +4,9 @@
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Scoring;
namespace osu.Game.Rulesets.Taiko.Objects
{
@@ -1,41 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.Objects
{
public class TaikoHitWindows : HitWindows
{
private static readonly IReadOnlyDictionary<HitResult, (double od0, double od5, double od10)> base_ranges = new Dictionary<HitResult, (double, double, double)>
{
{ HitResult.Great, (100, 70, 40) },
{ HitResult.Good, (240, 160, 100) },
{ HitResult.Miss, (270, 190, 140) },
};
public override bool IsHitResultAllowed(HitResult result)
{
switch (result)
{
case HitResult.Great:
case HitResult.Good:
case HitResult.Miss:
return true;
default:
return false;
}
}
public override void SetDifficulty(double difficulty)
{
Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]);
Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]);
Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]);
}
}
}
@@ -0,0 +1,32 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.Scoring
{
public class TaikoHitWindows : HitWindows
{
private static readonly DifficultyRange[] taiko_ranges =
{
new DifficultyRange(HitResult.Great, 50, 35, 20),
new DifficultyRange(HitResult.Good, 120, 80, 50),
new DifficultyRange(HitResult.Miss, 135, 95, 70),
};
public override bool IsHitResultAllowed(HitResult result)
{
switch (result)
{
case HitResult.Great:
case HitResult.Good:
case HitResult.Miss:
return true;
}
return false;
}
protected override DifficultyRange[] GetRanges() => taiko_ranges;
}
}
@@ -3,7 +3,6 @@
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.UI;
@@ -5,19 +5,18 @@ using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Taiko.Replays;
using System.Linq;
using osu.Framework.Input;
using osu.Game.Configuration;
using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI.Scrolling;
namespace osu.Game.Rulesets.Taiko.UI
@@ -38,49 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI
[BackgroundDependencyLoader]
private void load()
{
loadBarLines();
}
private void loadBarLines()
{
TaikoHitObject lastObject = Beatmap.HitObjects[Beatmap.HitObjects.Count - 1];
double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime);
var timingPoints = Beatmap.ControlPointInfo.TimingPoints.ToList();
if (timingPoints.Count == 0)
return;
int currentIndex = 0;
int currentBeat = 0;
double time = timingPoints[currentIndex].Time;
while (time <= lastHitTime)
{
int nextIndex = currentIndex + 1;
if (nextIndex < timingPoints.Count && time > timingPoints[nextIndex].Time)
{
currentIndex = nextIndex;
time = timingPoints[currentIndex].Time;
currentBeat = 0;
}
var currentPoint = timingPoints[currentIndex];
var barLine = new BarLine
{
StartTime = time,
};
barLine.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty);
bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0;
Playfield.Add(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine));
time += currentPoint.BeatLength * (int)currentPoint.TimeSignature;
currentBeat++;
}
new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar)));
}
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this);
@@ -9,8 +9,8 @@ using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using osu.Game.IO.Serialization;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osu.Game.Tests.Resources;
using osuTK;
@@ -3,18 +3,18 @@
using NUnit.Framework;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Catch.Objects;
using System;
using System.Collections.Generic;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Framework.MathUtils;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Catch.Scoring;
using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Scoring;
using osu.Game.Screens.Play.HUD.HitErrorMeters;
namespace osu.Game.Tests.Visual.Gameplay
@@ -36,8 +36,8 @@ namespace osu.Game.Tests.Visual.Gameplay
AddRepeatStep("New random judgement", () => newJudgement(), 40);
AddRepeatStep("New max negative", () => newJudgement(-hitWindows.HalfWindowFor(HitResult.Meh)), 20);
AddRepeatStep("New max positive", () => newJudgement(hitWindows.HalfWindowFor(HitResult.Meh)), 20);
AddRepeatStep("New max negative", () => newJudgement(-hitWindows.WindowFor(HitResult.Meh)), 20);
AddRepeatStep("New max positive", () => newJudgement(hitWindows.WindowFor(HitResult.Meh)), 20);
AddStep("New fixed judgement (50ms)", () => newJudgement(50));
}
@@ -85,9 +85,9 @@ namespace osu.Game.Tests.Visual.Gameplay
AutoSizeAxes = Axes.Both,
Children = new[]
{
new SpriteText { Text = $@"Great: {hitWindows?.Great}" },
new SpriteText { Text = $@"Good: {hitWindows?.Good}" },
new SpriteText { Text = $@"Meh: {hitWindows?.Meh}" },
new SpriteText { Text = $@"Great: {hitWindows?.WindowFor(HitResult.Great)}" },
new SpriteText { Text = $@"Good: {hitWindows?.WindowFor(HitResult.Good)}" },
new SpriteText { Text = $@"Meh: {hitWindows?.WindowFor(HitResult.Meh)}" },
}
});
@@ -0,0 +1,52 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Screens.Play;
namespace osu.Game.Tests.Visual.Gameplay
{
public class TestSceneFailJudgement : AllPlayersTestScene
{
protected override Player CreatePlayer(Ruleset ruleset)
{
Mods.Value = Array.Empty<Mod>();
var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Array.Empty<Mod>());
return new FailPlayer(ruleset.GetAutoplayMod().CreateReplayScore(beatmap));
}
protected override void AddCheckSteps()
{
AddUntilStep("wait for fail", () => Player.HasFailed);
AddUntilStep("wait for multiple judged objects", () => ((FailPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.Count(h => h.AllJudged) > 1);
AddAssert("total judgements == 1", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits == 1);
}
private class FailPlayer : ReplayPlayer
{
public new DrawableRuleset DrawableRuleset => base.DrawableRuleset;
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
protected override bool PauseOnFocusLost => false;
public FailPlayer(Score score)
: base(score, false, false)
{
}
protected override void LoadComplete()
{
base.LoadComplete();
ScoreProcessor.FailConditions += (_, __) => true;
}
}
}
}
@@ -0,0 +1,108 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.Containers;
using osu.Game.Online.Chat;
using osu.Game.Overlays.Chat;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Online
{
[TestFixture]
public class TestSceneChatLineTruncation : OsuTestScene
{
private readonly TestChatLineContainer textContainer;
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(ChatLine),
typeof(Message),
typeof(LinkFlowContainer),
typeof(MessageFormatter)
};
public TestSceneChatLineTruncation()
{
Add(textContainer = new TestChatLineContainer
{
Padding = new MarginPadding { Left = 20, Right = 20 },
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
});
}
[BackgroundDependencyLoader]
private void load()
{
testFormatting();
}
private void clear() => AddStep("clear messages", textContainer.Clear);
private void addMessageWithChecks(string text, bool isAction = false, bool isImportant = false, string username = null)
{
int index = textContainer.Count + 1;
var newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index, username));
textContainer.Add(newLine);
}
private void testFormatting()
{
for (int a = 0; a < 25; a++)
addMessageWithChecks($"Wide {a} character username.", username: new string('w', a));
addMessageWithChecks("Short name with spaces.", username: "sho rt name");
addMessageWithChecks("Long name with spaces.", username: "long name with s p a c e s");
}
private class DummyMessage : Message
{
private static long messageCounter;
internal static readonly User TEST_SENDER_BACKGROUND = new User
{
Username = @"i-am-important",
Id = 42,
Colour = "#250cc9",
};
internal static readonly User TEST_SENDER = new User
{
Username = @"Somebody",
Id = 1,
};
public new DateTimeOffset Timestamp = DateTimeOffset.Now;
public DummyMessage(string text, bool isAction = false, bool isImportant = false, int number = 0, string username = null)
: base(messageCounter++)
{
Content = text;
IsAction = isAction;
Sender = new User
{
Username = username ?? $"user {number}",
Id = number,
Colour = isImportant ? "#250cc9" : null,
};
}
}
private class TestChatLineContainer : FillFlowContainer<ChatLine>
{
protected override int Compare(Drawable x, Drawable y)
{
var xC = (ChatLine)x;
var yC = (ChatLine)y;
return xC.Message.CompareTo(yC.Message);
}
}
}
}
@@ -9,6 +9,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Screens.Select;
using osu.Game.Tests.Beatmaps;
using osuTK;
namespace osu.Game.Tests.Visual.SongSelect
@@ -30,45 +31,44 @@ namespace osu.Game.Tests.Visual.SongSelect
Size = new Vector2(550f, 450f),
});
AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
BeatmapSetInfo =
BeatmapSet = new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
BeatmapInfo =
Version = "All Metrics",
Metadata = new BeatmapMetadata
{
Version = "All Metrics",
Metadata = new BeatmapMetadata
{
Source = "osu!lazer",
Tags = "this beatmap has all the metrics",
},
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 7,
DrainRate = 1,
OverallDifficulty = 5.7f,
ApproachRate = 3.5f,
},
StarDifficulty = 5.3f,
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
Source = "osu!lazer",
Tags = "this beatmap has all the metrics",
},
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 7,
DrainRate = 1,
OverallDifficulty = 5.7f,
ApproachRate = 3.5f,
},
StarDifficulty = 5.3f,
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
);
}));
AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
AddStep("all except source", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapSetInfo =
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
BeatmapInfo =
{
BeatmapSet = new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
Version = "All Metrics",
Metadata = new BeatmapMetadata
{
@@ -88,16 +88,16 @@ namespace osu.Game.Tests.Visual.SongSelect
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
});
}));
AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
AddStep("ratings", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapSetInfo =
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
BeatmapInfo =
{
BeatmapSet = new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
Version = "Only Ratings",
Metadata = new BeatmapMetadata
{
@@ -113,9 +113,9 @@ namespace osu.Game.Tests.Visual.SongSelect
},
StarDifficulty = 4.8f
}
});
}));
AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
AddStep("fails+retries", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
@@ -139,9 +139,9 @@ namespace osu.Game.Tests.Visual.SongSelect
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
});
}));
AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
AddStep("null metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
@@ -160,7 +160,7 @@ namespace osu.Game.Tests.Visual.SongSelect
},
StarDifficulty = 1.97f,
}
});
}));
AddStep("null beatmap", () => detailsArea.Beatmap = null);
}
@@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter));
AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn));
AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable));
AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected));
foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus)))
AddStep($"{status} beatmap", () => showBeatmapWithStatus(status));
}
+3 -3
View File
@@ -31,7 +31,7 @@ namespace osu.Game.Configuration
Set(OsuSetting.RandomSelectAlgorithm, RandomSelectAlgorithm.RandomPermutation);
Set(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2, 1);
Set(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2f, 1f);
// Online settings
Set(OsuSetting.Username, string.Empty);
@@ -58,8 +58,8 @@ namespace osu.Game.Configuration
Set(OsuSetting.AudioOffset, 0, -500.0, 500.0, 1);
// Input
Set(OsuSetting.MenuCursorSize, 1.0, 0.5f, 2, 0.01);
Set(OsuSetting.GameplayCursorSize, 1.0, 0.1f, 2, 0.01);
Set(OsuSetting.MenuCursorSize, 1.0f, 0.5f, 2f, 0.01f);
Set(OsuSetting.GameplayCursorSize, 1.0f, 0.1f, 2f, 0.01f);
Set(OsuSetting.AutoCursorSize, false);
Set(OsuSetting.MouseDisableButtons, false);
@@ -62,21 +62,31 @@ namespace osu.Game.Graphics.Containers
protected override bool OnClick(ClickEvent e)
{
closeIfOutside(e);
if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition))
Hide();
return base.OnClick(e);
}
protected override bool OnDragEnd(DragEndEvent e)
{
closeIfOutside(e);
return base.OnDragEnd(e);
}
private bool closeOnDragEnd;
private void closeIfOutside(MouseEvent e)
protected override bool OnDragStart(DragStartEvent e)
{
if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition))
closeOnDragEnd = true;
return base.OnDragStart(e);
}
protected override bool OnDragEnd(DragEndEvent e)
{
if (closeOnDragEnd)
{
Hide();
closeOnDragEnd = false;
}
return base.OnDragEnd(e);
}
public virtual bool OnPressed(GlobalAction action)
+3 -4
View File
@@ -124,7 +124,7 @@ namespace osu.Game.Graphics.Cursor
public class Cursor : Container
{
private Container cursorContainer;
private Bindable<double> cursorScale;
private Bindable<float> cursorScale;
private const float base_scale = 0.15f;
public Sprite AdditiveLayer;
@@ -159,9 +159,8 @@ namespace osu.Game.Graphics.Cursor
}
};
cursorScale = config.GetBindable<double>(OsuSetting.MenuCursorSize);
cursorScale.ValueChanged += scale => cursorContainer.Scale = new Vector2((float)scale.NewValue * base_scale);
cursorScale.TriggerChange();
cursorScale = config.GetBindable<float>(OsuSetting.MenuCursorSize);
cursorScale.BindValueChanged(scale => cursorContainer.Scale = new Vector2(scale.NewValue * base_scale), true);
}
}
@@ -133,6 +133,10 @@ namespace osu.Game.Online.Leaderboards
});
break;
case PlaceholderState.NoneSelected:
replacePlaceholder(new MessagePlaceholder(@"Please select a beatmap!"));
break;
case PlaceholderState.Unavailable:
replacePlaceholder(new MessagePlaceholder(@"Leaderboards are not available for this beatmap!"));
break;
@@ -9,6 +9,7 @@ namespace osu.Game.Online.Leaderboards
Retrieving,
NetworkFailure,
Unavailable,
NoneSelected,
NoScores,
NotLoggedIn,
NotSupporter,
+1
View File
@@ -207,6 +207,7 @@ namespace osu.Game
FileStore.Cleanup();
AddInternal(API);
AddInternal(RulesetConfigCache);
GlobalActionContainer globalBinding;
+9 -1
View File
@@ -31,6 +31,8 @@ namespace osu.Game.Overlays.Chat
protected virtual float MessagePadding => default_message_padding;
private const float timestamp_padding = 65;
private const float default_horizontal_padding = 15;
protected virtual float HorizontalPadding => default_horizontal_padding;
@@ -87,7 +89,12 @@ namespace osu.Game.Overlays.Chat
{
Shadow = false,
Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length],
Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true)
Truncate = true,
EllipsisString = "… :",
Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true),
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
MaxWidth = default_message_padding - timestamp_padding
};
if (hasBackground)
@@ -142,6 +149,7 @@ namespace osu.Game.Overlays.Chat
new MessageSender(message.Sender)
{
AutoSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = timestamp_padding },
Origin = Anchor.TopRight,
Anchor = Anchor.TopRight,
Child = effectedUsername,
+9 -10
View File
@@ -54,7 +54,7 @@ namespace osu.Game.Overlays
private Box chatBackground;
private Box tabBackground;
public Bindable<double> ChatHeight { get; set; }
public Bindable<float> ChatHeight { get; set; }
private Container channelSelectionContainer;
protected ChannelSelectionOverlay ChannelSelectionOverlay;
@@ -190,14 +190,13 @@ namespace osu.Game.Overlays
ChannelSelectionOverlay.OnRequestJoin = channel => channelManager.JoinChannel(channel);
ChannelSelectionOverlay.OnRequestLeave = channelManager.LeaveChannel;
ChatHeight = config.GetBindable<double>(OsuSetting.ChatDisplayHeight);
ChatHeight.ValueChanged += height =>
ChatHeight = config.GetBindable<float>(OsuSetting.ChatDisplayHeight);
ChatHeight.BindValueChanged(height =>
{
chatContainer.Height = (float)height.NewValue;
channelSelectionContainer.Height = 1f - (float)height.NewValue;
tabBackground.FadeTo(height.NewValue == 1 ? 1 : 0.8f, 200);
};
ChatHeight.TriggerChange();
chatContainer.Height = height.NewValue;
channelSelectionContainer.Height = 1f - height.NewValue;
tabBackground.FadeTo(height.NewValue == 1f ? 1f : 0.8f, 200);
}, true);
chatBackground.Colour = colours.ChatBlue;
@@ -273,7 +272,7 @@ namespace osu.Game.Overlays
}
}
private double startDragChatHeight;
private float startDragChatHeight;
private bool isDragging;
protected override bool OnDragStart(DragStartEvent e)
@@ -291,7 +290,7 @@ namespace osu.Game.Overlays
{
if (isDragging)
{
double targetChatHeight = startDragChatHeight - (e.MousePosition.Y - e.MouseDownPosition.Y) / Parent.DrawSize.Y;
float targetChatHeight = startDragChatHeight - (e.MousePosition.Y - e.MouseDownPosition.Y) / Parent.DrawSize.Y;
// If the channel selection screen is shown, mind its minimum height
if (ChannelSelectionOverlay.State.Value == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height)
@@ -35,16 +35,16 @@ namespace osu.Game.Overlays.Settings.Sections
Children = new Drawable[]
{
skinDropdown = new SkinSettingsDropdown(),
new SettingsSlider<double, SizeSlider>
new SettingsSlider<float, SizeSlider>
{
LabelText = "Menu cursor size",
Bindable = config.GetBindable<double>(OsuSetting.MenuCursorSize),
Bindable = config.GetBindable<float>(OsuSetting.MenuCursorSize),
KeyboardStep = 0.01f
},
new SettingsSlider<double, SizeSlider>
new SettingsSlider<float, SizeSlider>
{
LabelText = "Gameplay cursor size",
Bindable = config.GetBindable<double>(OsuSetting.GameplayCursorSize),
Bindable = config.GetBindable<float>(OsuSetting.GameplayCursorSize),
KeyboardStep = 0.01f
},
new SettingsCheckbox
@@ -95,7 +95,7 @@ namespace osu.Game.Overlays.Settings.Sections
}
}
private class SizeSlider : OsuSliderBar<double>
private class SizeSlider : OsuSliderBar<float>
{
public override string TooltipText => Current.Value.ToString(@"0.##x");
}
@@ -51,6 +51,11 @@ namespace osu.Game.Rulesets.Judgements
/// </summary>
public double HealthAtJudgement { get; internal set; }
/// <summary>
/// Whether the user was in a failed state prior to this <see cref="JudgementResult"/> occurring.
/// </summary>
public bool FailedAtJudgement { get; internal set; }
/// <summary>
/// Whether a miss or hit occurred.
/// </summary>
+16
View File
@@ -0,0 +1,16 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Rulesets.Objects
{
/// <summary>
/// A hit object representing the end of a bar.
/// </summary>
public class BarLine : HitObject
{
/// <summary>
/// Whether this barline is a prominent beat (based on time signature of beatmap).
/// </summary>
public bool Major;
}
}
@@ -0,0 +1,58 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects
{
public class BarLineGenerator
{
/// <summary>
/// The generated bar lines.
/// </summary>
public readonly List<BarLine> BarLines = new List<BarLine>();
/// <summary>
/// Constructs and generates bar lines for provided beatmap.
/// </summary>
/// <param name="beatmap">The beatmap to generate bar lines for.</param>
public BarLineGenerator(IBeatmap beatmap)
{
if (beatmap.HitObjects.Count == 0)
return;
HitObject lastObject = beatmap.HitObjects.Last();
double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime);
var timingPoints = beatmap.ControlPointInfo.TimingPoints;
if (timingPoints.Count == 0)
return;
for (int i = 0; i < timingPoints.Count; i++)
{
TimingControlPoint currentTimingPoint = timingPoints[i];
int currentBeat = 0;
// Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object
double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - currentTimingPoint.BeatLength : lastHitTime + currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature;
double barLength = currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature;
for (double t = currentTimingPoint.Time; Precision.DefinitelyBigger(endTime, t); t += barLength, currentBeat++)
{
BarLines.Add(new BarLine
{
StartTime = t,
Major = currentBeat % (int)currentTimingPoint.TimeSignature == 0
});
}
}
}
}
}
@@ -76,8 +76,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
/// </summary>
public JudgementResult Result { get; private set; }
private bool judgementOccurred;
public override bool RemoveWhenNotAlive => false;
public override bool RemoveCompletedTransforms => false;
protected override bool RequiresChildrenUpdate => true;
@@ -164,7 +162,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
{
UpdateInitialTransforms();
var judgementOffset = Math.Min(HitObject.HitWindows?.HalfWindowFor(HitResult.Miss) ?? double.MaxValue, Result?.TimeOffset ?? 0);
var judgementOffset = Math.Min(HitObject.HitWindows?.WindowFor(HitResult.Miss) ?? double.MaxValue, Result?.TimeOffset ?? 0);
using (BeginDelayedSequence(InitialLifetimeOffset + judgementOffset, true))
{
@@ -346,8 +344,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
if (!Result.HasResult)
throw new InvalidOperationException($"{GetType().ReadableName()} applied a {nameof(JudgementResult)} but did not update {nameof(JudgementResult.Type)}.");
judgementOccurred = true;
// Ensure that the judgement is given a valid time offset, because this may not get set by the caller
var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
Result.TimeOffset = Time.Current - endTime;
@@ -380,21 +376,13 @@ namespace osu.Game.Rulesets.Objects.Drawables
if (Time.Elapsed < 0)
return false;
judgementOccurred = false;
if (AllJudged)
if (Judged)
return false;
foreach (var d in NestedHitObjects)
judgementOccurred |= d.UpdateResult(userTriggered);
if (judgementOccurred || Judged)
return judgementOccurred;
var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
CheckForResult(userTriggered, Time.Current - endTime);
return judgementOccurred;
return Judged;
}
/// <summary>
+1
View File
@@ -9,6 +9,7 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects
{

Some files were not shown because too many files have changed in this diff Show More