mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 15:12:57 +08:00
Merge branch 'master' into drawnode-composability
This commit is contained in:
commit
d40177f97c
@ -1,6 +1,6 @@
|
|||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
version: '{branch}-{build}'
|
version: '{branch}-{build}'
|
||||||
image: Visual Studio 2017
|
image: Previous Visual Studio 2017
|
||||||
test: off
|
test: off
|
||||||
install:
|
install:
|
||||||
- cmd: git submodule update --init --recursive --depth=5
|
- cmd: git submodule update --init --recursive --depth=5
|
||||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset)
|
protected override Player CreatePlayer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
|
Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||||
return base.CreatePlayer(ruleset);
|
return base.CreatePlayer(ruleset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
{
|
{
|
||||||
public class CatchRuleset : Ruleset
|
public class CatchRuleset : Ruleset
|
||||||
{
|
{
|
||||||
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableCatchRuleset(this, beatmap);
|
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableCatchRuleset(this, beatmap, mods);
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap);
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap);
|
||||||
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap);
|
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap);
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Judgements
|
|||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
case HitResult.Perfect:
|
case HitResult.Perfect:
|
||||||
return 8;
|
return 0.008;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ namespace osu.Game.Rulesets.Catch.Judgements
|
|||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
return 0;
|
return base.HealthIncreaseFor(result);
|
||||||
case HitResult.Perfect:
|
case HitResult.Perfect:
|
||||||
return 7;
|
return 0.007;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ namespace osu.Game.Rulesets.Catch.Judgements
|
|||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
return 0;
|
return -0.02;
|
||||||
case HitResult.Perfect:
|
case HitResult.Perfect:
|
||||||
return 10.2;
|
return 0.01;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Catch.Judgements
|
|||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
case HitResult.Perfect:
|
case HitResult.Perfect:
|
||||||
return 4;
|
return 0.004;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
@ -27,20 +26,15 @@ namespace osu.Game.Rulesets.Catch.Scoring
|
|||||||
hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate;
|
hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private const double harshness = 0.01;
|
protected override double HealthAdjustmentFactorFor(JudgementResult result)
|
||||||
|
|
||||||
protected override void ApplyResult(JudgementResult result)
|
|
||||||
{
|
{
|
||||||
base.ApplyResult(result);
|
switch (result.Type)
|
||||||
|
|
||||||
if (result.Type == HitResult.Miss)
|
|
||||||
{
|
{
|
||||||
if (!result.Judgement.IsBonus)
|
case HitResult.Miss:
|
||||||
Health.Value -= hpDrainRate * (harshness * 2);
|
return hpDrainRate;
|
||||||
return;
|
default:
|
||||||
|
return 10.2 - hpDrainRate; // Award less HP as drain rate is increased
|
||||||
}
|
}
|
||||||
|
|
||||||
Health.Value += Math.Max(result.Judgement.HealthIncreaseFor(result) - hpDrainRate, 0) * harshness;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override HitWindows CreateHitWindows() => new CatchHitWindows();
|
public override HitWindows CreateHitWindows() => new CatchHitWindows();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
@ -10,6 +11,7 @@ using osu.Game.Rulesets.Catch.Objects;
|
|||||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
||||||
using osu.Game.Rulesets.Catch.Replays;
|
using osu.Game.Rulesets.Catch.Replays;
|
||||||
using osu.Game.Rulesets.Catch.Scoring;
|
using osu.Game.Rulesets.Catch.Scoring;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
@ -23,8 +25,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
protected override bool UserScrollSpeedAdjustment => false;
|
protected override bool UserScrollSpeedAdjustment => false;
|
||||||
|
|
||||||
public DrawableCatchRuleset(Ruleset ruleset, WorkingBeatmap beatmap)
|
public DrawableCatchRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
Direction.Value = ScrollingDirection.Down;
|
Direction.Value = ScrollingDirection.Down;
|
||||||
TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
|
TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -8,6 +10,7 @@ using osu.Framework.Timing;
|
|||||||
using osu.Game.Rulesets.Mania.Edit;
|
using osu.Game.Rulesets.Mania.Edit;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
@ -21,6 +24,9 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
private readonly Column column;
|
private readonly Column column;
|
||||||
|
|
||||||
|
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||||
|
private IReadOnlyList<Mod> mods { get; set; } = Array.Empty<Mod>();
|
||||||
|
|
||||||
protected ManiaPlacementBlueprintTestCase()
|
protected ManiaPlacementBlueprintTestCase()
|
||||||
{
|
{
|
||||||
Add(column = new Column(0)
|
Add(column = new Column(0)
|
||||||
|
@ -13,6 +13,7 @@ using osu.Game.Rulesets.Mania.Objects;
|
|||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
using osu.Game.Rulesets.Mania.UI.Components;
|
using osu.Game.Rulesets.Mania.UI.Components;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -31,6 +32,9 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
typeof(ColumnHitObjectArea)
|
typeof(ColumnHitObjectArea)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||||
|
private IReadOnlyList<Mod> mods { get; set; } = Array.Empty<Mod>();
|
||||||
|
|
||||||
private readonly List<Column> columns = new List<Column>();
|
private readonly List<Column> columns = new List<Column>();
|
||||||
|
|
||||||
public TestCaseColumn()
|
public TestCaseColumn()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -13,6 +14,7 @@ using osu.Game.Rulesets.Mania.Beatmaps;
|
|||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -24,6 +26,9 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
private const int columns = 4;
|
private const int columns = 4;
|
||||||
|
|
||||||
|
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||||
|
private IReadOnlyList<Mod> mods { get; set; } = Array.Empty<Mod>();
|
||||||
|
|
||||||
private readonly List<ManiaStage> stages = new List<ManiaStage>();
|
private readonly List<ManiaStage> stages = new List<ManiaStage>();
|
||||||
|
|
||||||
private FillFlowContainer<ScrollingTestContainer> fill;
|
private FillFlowContainer<ScrollingTestContainer> fill;
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
|
||||||
@ -14,8 +16,8 @@ namespace osu.Game.Rulesets.Mania.Edit
|
|||||||
{
|
{
|
||||||
public new IScrollingInfo ScrollingInfo => base.ScrollingInfo;
|
public new IScrollingInfo ScrollingInfo => base.ScrollingInfo;
|
||||||
|
|
||||||
public DrawableManiaEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap)
|
public DrawableManiaEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ using System.Collections.Generic;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Screens.Edit.Compose.Components;
|
using osu.Game.Screens.Edit.Compose.Components;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -41,9 +42,9 @@ namespace osu.Game.Rulesets.Mania.Edit
|
|||||||
|
|
||||||
public int TotalColumns => ((ManiaPlayfield)DrawableRuleset.Playfield).TotalColumns;
|
public int TotalColumns => ((ManiaPlayfield)DrawableRuleset.Playfield).TotalColumns;
|
||||||
|
|
||||||
protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap)
|
protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
{
|
{
|
||||||
DrawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap);
|
DrawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods);
|
||||||
|
|
||||||
// This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it
|
// This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it
|
||||||
dependencies.CacheAs(DrawableRuleset.ScrollingInfo);
|
dependencies.CacheAs(DrawableRuleset.ScrollingInfo);
|
||||||
|
@ -10,5 +10,16 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
|||||||
public override bool AffectsCombo => false;
|
public override bool AffectsCombo => false;
|
||||||
|
|
||||||
protected override int NumericResultFor(HitResult result) => 20;
|
protected override int NumericResultFor(HitResult result) => 20;
|
||||||
|
|
||||||
|
protected override double HealthIncreaseFor(HitResult result)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case HitResult.Miss:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 0.040;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,5 +25,26 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
|||||||
return 300;
|
return 300;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override double HealthIncreaseFor(HitResult result)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case HitResult.Miss:
|
||||||
|
return -0.125;
|
||||||
|
case HitResult.Meh:
|
||||||
|
return 0.005;
|
||||||
|
case HitResult.Ok:
|
||||||
|
return 0.010;
|
||||||
|
case HitResult.Good:
|
||||||
|
return 0.035;
|
||||||
|
case HitResult.Great:
|
||||||
|
return 0.055;
|
||||||
|
case HitResult.Perfect:
|
||||||
|
return 0.065;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
{
|
{
|
||||||
public class ManiaRuleset : Ruleset
|
public class ManiaRuleset : Ruleset
|
||||||
{
|
{
|
||||||
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableManiaRuleset(this, beatmap);
|
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableManiaRuleset(this, beatmap, mods);
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
|
||||||
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score);
|
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score);
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mania.Judgements;
|
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -28,36 +27,6 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const double hp_multiplier_max = 1;
|
private const double hp_multiplier_max = 1;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The default BAD hit HP increase.
|
|
||||||
/// </summary>
|
|
||||||
private const double hp_increase_bad = 0.005;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The default OK hit HP increase.
|
|
||||||
/// </summary>
|
|
||||||
private const double hp_increase_ok = 0.010;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The default GOOD hit HP increase.
|
|
||||||
/// </summary>
|
|
||||||
private const double hp_increase_good = 0.035;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The default tick hit HP increase.
|
|
||||||
/// </summary>
|
|
||||||
private const double hp_increase_tick = 0.040;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The default GREAT hit HP increase.
|
|
||||||
/// </summary>
|
|
||||||
private const double hp_increase_great = 0.055;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The default PERFECT hit HP increase.
|
|
||||||
/// </summary>
|
|
||||||
private const double hp_increase_perfect = 0.065;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The MISS HP multiplier at OD = 0.
|
/// The MISS HP multiplier at OD = 0.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -73,11 +42,6 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const double hp_multiplier_miss_max = 1;
|
private const double hp_multiplier_miss_max = 1;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The default MISS HP increase.
|
|
||||||
/// </summary>
|
|
||||||
private const double hp_increase_miss = -0.125;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The MISS HP multiplier. This is multiplied to the miss hp increase.
|
/// The MISS HP multiplier. This is multiplied to the miss hp increase.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -88,10 +52,6 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private double hpMultiplier = 1;
|
private double hpMultiplier = 1;
|
||||||
|
|
||||||
public ManiaScoreProcessor()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public ManiaScoreProcessor(DrawableRuleset<ManiaHitObject> drawableRuleset)
|
public ManiaScoreProcessor(DrawableRuleset<ManiaHitObject> drawableRuleset)
|
||||||
: base(drawableRuleset)
|
: base(drawableRuleset)
|
||||||
{
|
{
|
||||||
@ -122,42 +82,8 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ApplyResult(JudgementResult result)
|
protected override double HealthAdjustmentFactorFor(JudgementResult result)
|
||||||
{
|
=> result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier;
|
||||||
base.ApplyResult(result);
|
|
||||||
|
|
||||||
bool isTick = result.Judgement is HoldNoteTickJudgement;
|
|
||||||
|
|
||||||
if (isTick)
|
|
||||||
{
|
|
||||||
if (result.IsHit)
|
|
||||||
Health.Value += hpMultiplier * hp_increase_tick;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (result.Type)
|
|
||||||
{
|
|
||||||
case HitResult.Miss:
|
|
||||||
Health.Value += hpMissMultiplier * hp_increase_miss;
|
|
||||||
break;
|
|
||||||
case HitResult.Meh:
|
|
||||||
Health.Value += hpMultiplier * hp_increase_bad;
|
|
||||||
break;
|
|
||||||
case HitResult.Ok:
|
|
||||||
Health.Value += hpMultiplier * hp_increase_ok;
|
|
||||||
break;
|
|
||||||
case HitResult.Good:
|
|
||||||
Health.Value += hpMultiplier * hp_increase_good;
|
|
||||||
break;
|
|
||||||
case HitResult.Great:
|
|
||||||
Health.Value += hpMultiplier * hp_increase_great;
|
|
||||||
break;
|
|
||||||
case HitResult.Perfect:
|
|
||||||
Health.Value += hpMultiplier * hp_increase_perfect;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override HitWindows CreateHitWindows() => new ManiaHitWindows();
|
public override HitWindows CreateHitWindows() => new ManiaHitWindows();
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ using osu.Game.Rulesets.Mania.Objects;
|
|||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mania.Replays;
|
using osu.Game.Rulesets.Mania.Replays;
|
||||||
using osu.Game.Rulesets.Mania.Scoring;
|
using osu.Game.Rulesets.Mania.Scoring;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -39,8 +40,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
private readonly Bindable<ManiaScrollingDirection> configDirection = new Bindable<ManiaScrollingDirection>();
|
private readonly Bindable<ManiaScrollingDirection> configDirection = new Bindable<ManiaScrollingDirection>();
|
||||||
|
|
||||||
public DrawableManiaRuleset(Ruleset ruleset, WorkingBeatmap beatmap)
|
public DrawableManiaRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
// Generate the bar lines
|
// Generate the bar lines
|
||||||
double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue;
|
double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue;
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
using Decoder = osu.Game.Beatmaps.Formats.Decoder;
|
using Decoder = osu.Game.Beatmaps.Formats.Decoder;
|
||||||
@ -22,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
using (var reader = new StreamReader(stream))
|
using (var reader = new StreamReader(stream))
|
||||||
{
|
{
|
||||||
var beatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
var beatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||||
var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo);
|
var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty<Mod>());
|
||||||
|
|
||||||
var objects = converted.HitObjects.ToList();
|
var objects = converted.HitObjects.ToList();
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
private int depthIndex;
|
private int depthIndex;
|
||||||
protected readonly List<Mod> Mods = new List<Mod>();
|
|
||||||
|
|
||||||
public TestCaseHitCircle()
|
public TestCaseHitCircle()
|
||||||
{
|
{
|
||||||
@ -68,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
Depth = depthIndex++
|
Depth = depthIndex++
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var mod in Mods.OfType<IApplicableToDrawableHitObjects>())
|
foreach (var mod in Mods.Value.OfType<IApplicableToDrawableHitObjects>())
|
||||||
mod.ApplyToDrawableHitObjects(new[] { drawable });
|
mod.ApplyToDrawableHitObjects(new[] { drawable });
|
||||||
|
|
||||||
Add(drawable);
|
Add(drawable);
|
||||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
public TestCaseHitCircleHidden()
|
public TestCaseHitCircleHidden()
|
||||||
{
|
{
|
||||||
Mods.Add(new OsuModHidden());
|
Mods.Value = new[] { new OsuModHidden() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
private int depthIndex;
|
private int depthIndex;
|
||||||
protected readonly List<Mod> Mods = new List<Mod>();
|
|
||||||
|
|
||||||
public TestCaseSlider()
|
public TestCaseSlider()
|
||||||
{
|
{
|
||||||
@ -292,7 +291,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
Depth = depthIndex++
|
Depth = depthIndex++
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var mod in Mods.OfType<IApplicableToDrawableHitObjects>())
|
foreach (var mod in Mods.Value.OfType<IApplicableToDrawableHitObjects>())
|
||||||
mod.ApplyToDrawableHitObjects(new[] { drawable });
|
mod.ApplyToDrawableHitObjects(new[] { drawable });
|
||||||
|
|
||||||
drawable.OnNewResult += onNewResult;
|
drawable.OnNewResult += onNewResult;
|
||||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
public TestCaseSliderHidden()
|
public TestCaseSliderHidden()
|
||||||
{
|
{
|
||||||
Mods.Add(new OsuModHidden());
|
Mods.Value = new[] { new OsuModHidden() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
private int depthIndex;
|
private int depthIndex;
|
||||||
protected readonly List<Mod> Mods = new List<Mod>();
|
|
||||||
|
|
||||||
public TestCaseSpinner()
|
public TestCaseSpinner()
|
||||||
{
|
{
|
||||||
@ -57,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
Depth = depthIndex++
|
Depth = depthIndex++
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var mod in Mods.OfType<IApplicableToDrawableHitObjects>())
|
foreach (var mod in Mods.Value.OfType<IApplicableToDrawableHitObjects>())
|
||||||
mod.ApplyToDrawableHitObjects(new[] { drawable });
|
mod.ApplyToDrawableHitObjects(new[] { drawable });
|
||||||
|
|
||||||
Add(drawable);
|
Add(drawable);
|
||||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
public TestCaseSpinnerHidden()
|
public TestCaseSpinnerHidden()
|
||||||
{
|
{
|
||||||
Mods.Add(new OsuModHidden());
|
Mods.Value = new[] { new OsuModHidden() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu.UI;
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -10,8 +12,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
public class DrawableOsuEditRuleset : DrawableOsuRuleset
|
public class DrawableOsuEditRuleset : DrawableOsuRuleset
|
||||||
{
|
{
|
||||||
public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap)
|
public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Edit.Tools;
|
using osu.Game.Rulesets.Edit.Tools;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
|
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
|
||||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||||
@ -23,8 +24,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DrawableRuleset<OsuHitObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap)
|
protected override DrawableRuleset<OsuHitObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
=> new DrawableOsuEditRuleset(ruleset, beatmap);
|
=> new DrawableOsuEditRuleset(ruleset, beatmap, mods);
|
||||||
|
|
||||||
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]
|
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]
|
||||||
{
|
{
|
||||||
|
@ -24,5 +24,20 @@ namespace osu.Game.Rulesets.Osu.Judgements
|
|||||||
return 300;
|
return 300;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override double HealthIncreaseFor(HitResult result)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case HitResult.Miss:
|
||||||
|
return -0.02;
|
||||||
|
case HitResult.Meh:
|
||||||
|
case HitResult.Good:
|
||||||
|
case HitResult.Great:
|
||||||
|
return 0.01;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
{
|
{
|
||||||
public class OsuRuleset : Ruleset
|
public class OsuRuleset : Ruleset
|
||||||
{
|
{
|
||||||
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableOsuRuleset(this, beatmap);
|
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableOsuRuleset(this, beatmap, mods);
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap);
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap);
|
||||||
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap);
|
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap);
|
||||||
|
|
||||||
|
@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
|||||||
comboResultCounts.Clear();
|
comboResultCounts.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private const double harshness = 0.01;
|
|
||||||
|
|
||||||
protected override void ApplyResult(JudgementResult result)
|
protected override void ApplyResult(JudgementResult result)
|
||||||
{
|
{
|
||||||
base.ApplyResult(result);
|
base.ApplyResult(result);
|
||||||
@ -47,28 +45,29 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
|||||||
|
|
||||||
if (result.Type != HitResult.None)
|
if (result.Type != HitResult.None)
|
||||||
comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1;
|
comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override double HealthAdjustmentFactorFor(JudgementResult result)
|
||||||
|
{
|
||||||
switch (result.Type)
|
switch (result.Type)
|
||||||
{
|
{
|
||||||
case HitResult.Great:
|
case HitResult.Great:
|
||||||
Health.Value += (10.2 - hpDrainRate) * harshness;
|
return 10.2 - hpDrainRate;
|
||||||
break;
|
|
||||||
|
|
||||||
case HitResult.Good:
|
case HitResult.Good:
|
||||||
Health.Value += (8 - hpDrainRate) * harshness;
|
return 8 - hpDrainRate;
|
||||||
break;
|
|
||||||
|
|
||||||
case HitResult.Meh:
|
case HitResult.Meh:
|
||||||
Health.Value += (4 - hpDrainRate) * harshness;
|
return 4 - hpDrainRate;
|
||||||
break;
|
|
||||||
|
|
||||||
/*case HitResult.SliderTick:
|
// case HitResult.SliderTick:
|
||||||
Health.Value += Math.Max(7 - hpDrainRate, 0) * 0.01;
|
// return Math.Max(7 - hpDrainRate, 0) * 0.01;
|
||||||
break;*/
|
|
||||||
|
|
||||||
case HitResult.Miss:
|
case HitResult.Miss:
|
||||||
Health.Value -= hpDrainRate * (harshness * 2);
|
return hpDrainRate;
|
||||||
break;
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Input.Handlers;
|
using osu.Game.Input.Handlers;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Osu.Configuration;
|
using osu.Game.Rulesets.Osu.Configuration;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
@ -22,8 +24,8 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
{
|
{
|
||||||
protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config;
|
protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config;
|
||||||
|
|
||||||
public DrawableOsuRuleset(Ruleset ruleset, WorkingBeatmap beatmap)
|
public DrawableOsuRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ using osu.Framework.MathUtils;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Taiko.Judgements;
|
using osu.Game.Rulesets.Taiko.Judgements;
|
||||||
@ -86,7 +87,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 768,
|
Height = 768,
|
||||||
Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap) }
|
Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap, Array.Empty<Mod>()) }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,19 +46,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
|
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ApplyResult(JudgementResult result)
|
protected override double HealthAdjustmentFactorFor(JudgementResult result)
|
||||||
{
|
=> result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier;
|
||||||
base.ApplyResult(result);
|
|
||||||
|
|
||||||
double hpIncrease = result.Judgement.HealthIncreaseFor(result);
|
|
||||||
|
|
||||||
if (result.Type == HitResult.Miss)
|
|
||||||
hpIncrease *= hpMissMultiplier;
|
|
||||||
else
|
|
||||||
hpIncrease *= hpMultiplier;
|
|
||||||
|
|
||||||
Health.Value += hpIncrease;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Reset(bool storeResults)
|
protected override void Reset(bool storeResults)
|
||||||
{
|
{
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko
|
|||||||
{
|
{
|
||||||
public class TaikoRuleset : Ruleset
|
public class TaikoRuleset : Ruleset
|
||||||
{
|
{
|
||||||
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableTaikoRuleset(this, beatmap);
|
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableTaikoRuleset(this, beatmap, mods);
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap);
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap);
|
||||||
|
|
||||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
|
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -16,6 +17,7 @@ using osu.Framework.Input;
|
|||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Input.Handlers;
|
using osu.Game.Input.Handlers;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.UI
|
namespace osu.Game.Rulesets.Taiko.UI
|
||||||
@ -26,8 +28,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
protected override bool UserScrollSpeedAdjustment => false;
|
protected override bool UserScrollSpeedAdjustment => false;
|
||||||
|
|
||||||
public DrawableTaikoRuleset(Ruleset ruleset, WorkingBeatmap beatmap)
|
public DrawableTaikoRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
Direction.Value = ScrollingDirection.Left;
|
Direction.Value = ScrollingDirection.Left;
|
||||||
TimeRange.Value = 7000;
|
TimeRange.Value = 7000;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -13,6 +14,7 @@ using osu.Game.Rulesets.Objects.Types;
|
|||||||
using osu.Game.Beatmaps.Formats;
|
using osu.Game.Beatmaps.Formats;
|
||||||
using osu.Game.Beatmaps.Timing;
|
using osu.Game.Beatmaps.Timing;
|
||||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Legacy;
|
using osu.Game.Rulesets.Objects.Legacy;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
@ -39,7 +41,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
|
|
||||||
Assert.AreEqual(6, working.BeatmapInfo.BeatmapVersion);
|
Assert.AreEqual(6, working.BeatmapInfo.BeatmapVersion);
|
||||||
Assert.AreEqual(6, working.Beatmap.BeatmapInfo.BeatmapVersion);
|
Assert.AreEqual(6, working.Beatmap.BeatmapInfo.BeatmapVersion);
|
||||||
Assert.AreEqual(6, working.GetPlayableBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapVersion);
|
Assert.AreEqual(6, working.GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty<Mod>()).BeatmapInfo.BeatmapVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
AddUntilStep("Song select has selection", () => songSelect.Carousel.SelectedBeatmap != null);
|
AddUntilStep("Song select has selection", () => songSelect.Carousel.SelectedBeatmap != null);
|
||||||
AddStep("Set default user settings", () =>
|
AddStep("Set default user settings", () =>
|
||||||
{
|
{
|
||||||
Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { new OsuModNoFail() });
|
Mods.Value = Mods.Value.Concat(new[] { new OsuModNoFail() }).ToArray();
|
||||||
songSelect.DimLevel.Value = 0.7f;
|
songSelect.DimLevel.Value = 0.7f;
|
||||||
songSelect.BlurLevel.Value = 0.4f;
|
songSelect.BlurLevel.Value = 0.4f;
|
||||||
});
|
});
|
||||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
protected override Player CreatePlayer(Ruleset ruleset)
|
protected override Player CreatePlayer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
|
Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||||
return new ScoreAccessiblePlayer();
|
return new ScoreAccessiblePlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,150 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Timing;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
|
{
|
||||||
|
public class TestCaseFrameStabilityContainer : OsuTestCase
|
||||||
|
{
|
||||||
|
private readonly ManualClock manualClock;
|
||||||
|
|
||||||
|
private readonly Container mainContainer;
|
||||||
|
|
||||||
|
private ClockConsumingChild consumer;
|
||||||
|
|
||||||
|
public TestCaseFrameStabilityContainer()
|
||||||
|
{
|
||||||
|
Child = mainContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Clock = new FramedClock(manualClock = new ManualClock()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestLargeJumps()
|
||||||
|
{
|
||||||
|
seekManualTo(0);
|
||||||
|
createStabilityContainer();
|
||||||
|
seekManualTo(100000);
|
||||||
|
|
||||||
|
confirmSeek(100000);
|
||||||
|
checkFrameCount(6000);
|
||||||
|
|
||||||
|
seekManualTo(0);
|
||||||
|
|
||||||
|
confirmSeek(0);
|
||||||
|
checkFrameCount(12000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSmallJumps()
|
||||||
|
{
|
||||||
|
seekManualTo(0);
|
||||||
|
createStabilityContainer();
|
||||||
|
seekManualTo(40);
|
||||||
|
|
||||||
|
confirmSeek(40);
|
||||||
|
checkFrameCount(3);
|
||||||
|
|
||||||
|
seekManualTo(0);
|
||||||
|
|
||||||
|
confirmSeek(0);
|
||||||
|
checkFrameCount(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSingleFrameJump()
|
||||||
|
{
|
||||||
|
seekManualTo(0);
|
||||||
|
createStabilityContainer();
|
||||||
|
seekManualTo(8);
|
||||||
|
confirmSeek(8);
|
||||||
|
checkFrameCount(1);
|
||||||
|
|
||||||
|
seekManualTo(16);
|
||||||
|
confirmSeek(16);
|
||||||
|
checkFrameCount(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestInitialSeek()
|
||||||
|
{
|
||||||
|
seekManualTo(100000);
|
||||||
|
createStabilityContainer();
|
||||||
|
|
||||||
|
confirmSeek(100000);
|
||||||
|
checkFrameCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createStabilityContainer() => AddStep("create container", () => mainContainer.Child = new FrameStabilityContainer().WithChild(consumer = new ClockConsumingChild()));
|
||||||
|
|
||||||
|
private void seekManualTo(double time) => AddStep($"seek manual clock to {time}", () => manualClock.CurrentTime = time);
|
||||||
|
|
||||||
|
private void confirmSeek(double time) => AddUntilStep($"wait for seek to {time}", () => consumer.Clock.CurrentTime == time);
|
||||||
|
|
||||||
|
private void checkFrameCount(int frames) =>
|
||||||
|
AddAssert($"elapsed frames is {frames}", () => consumer.ElapsedFrames == frames);
|
||||||
|
|
||||||
|
public class ClockConsumingChild : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly OsuSpriteText text;
|
||||||
|
private readonly OsuSpriteText text2;
|
||||||
|
private readonly OsuSpriteText text3;
|
||||||
|
|
||||||
|
public ClockConsumingChild()
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
text = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
text2 = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
text3 = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ElapsedFrames;
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (Clock.ElapsedFrameTime != 0)
|
||||||
|
ElapsedFrames++;
|
||||||
|
|
||||||
|
text.Text = $"current time: {Clock.CurrentTime:F0}";
|
||||||
|
if (Clock.ElapsedFrameTime != 0)
|
||||||
|
text2.Text = $"last elapsed frame time: {Clock.ElapsedFrameTime:F0}";
|
||||||
|
text3.Text = $"total frames: {ElapsedFrames:F0}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,43 +1,42 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Screens;
|
using osu.Game.Screens;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
{
|
{
|
||||||
public class TestCasePlayerLoader : ManualInputManagerTestCase
|
public class TestCasePlayerLoader : ManualInputManagerTestCase
|
||||||
{
|
{
|
||||||
private PlayerLoader loader;
|
private PlayerLoader loader;
|
||||||
private readonly OsuScreenStack stack;
|
private OsuScreenStack stack;
|
||||||
|
|
||||||
public TestCasePlayerLoader()
|
[SetUp]
|
||||||
|
public void Setup() => Schedule(() =>
|
||||||
{
|
{
|
||||||
InputManager.Add(stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both });
|
InputManager.Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both };
|
||||||
}
|
Beatmap.Value = new TestWorkingBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo), Clock);
|
||||||
|
});
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[Test]
|
||||||
private void load(OsuGameBase game)
|
public void TestLoadContinuation()
|
||||||
{
|
{
|
||||||
Beatmap.Value = new DummyWorkingBeatmap(game);
|
|
||||||
|
|
||||||
AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player(false, false))));
|
AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player(false, false))));
|
||||||
|
|
||||||
AddUntilStep("wait for current", () => loader.IsCurrentScreen());
|
AddUntilStep("wait for current", () => loader.IsCurrentScreen());
|
||||||
|
|
||||||
AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre));
|
AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre));
|
||||||
|
|
||||||
AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen());
|
AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen());
|
||||||
|
|
||||||
AddStep("exit loader", () => loader.Exit());
|
|
||||||
|
|
||||||
AddUntilStep("wait for no longer alive", () => !loader.IsAlive);
|
|
||||||
|
|
||||||
AddStep("load slow dummy beatmap", () =>
|
AddStep("load slow dummy beatmap", () =>
|
||||||
{
|
{
|
||||||
SlowLoadPlayer slow = null;
|
SlowLoadPlayer slow = null;
|
||||||
@ -50,6 +49,65 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen());
|
AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestModReinstantiation()
|
||||||
|
{
|
||||||
|
TestPlayer player = null;
|
||||||
|
TestMod gameMod = null;
|
||||||
|
TestMod playerMod1 = null;
|
||||||
|
TestMod playerMod2 = null;
|
||||||
|
|
||||||
|
AddStep("load player", () =>
|
||||||
|
{
|
||||||
|
Mods.Value = new[] { gameMod = new TestMod() };
|
||||||
|
stack.Push(loader = new PlayerLoader(() => player = new TestPlayer()));
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen());
|
||||||
|
AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre));
|
||||||
|
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen());
|
||||||
|
AddStep("retrieve mods", () => playerMod1 = (TestMod)player.Mods.Value.Single());
|
||||||
|
AddAssert("game mods not applied", () => gameMod.Applied == false);
|
||||||
|
AddAssert("player mods applied", () => playerMod1.Applied);
|
||||||
|
|
||||||
|
AddStep("restart player", () =>
|
||||||
|
{
|
||||||
|
var lastPlayer = player;
|
||||||
|
player = null;
|
||||||
|
lastPlayer.Restart();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen());
|
||||||
|
AddStep("retrieve mods", () => playerMod2 = (TestMod)player.Mods.Value.Single());
|
||||||
|
AddAssert("game mods not applied", () => gameMod.Applied == false);
|
||||||
|
AddAssert("player has different mods", () => playerMod1 != playerMod2);
|
||||||
|
AddAssert("player mods applied", () => playerMod2.Applied);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestMod : Mod, IApplicableToScoreProcessor
|
||||||
|
{
|
||||||
|
public override string Name => string.Empty;
|
||||||
|
public override string Acronym => string.Empty;
|
||||||
|
public override double ScoreMultiplier => 1;
|
||||||
|
|
||||||
|
public bool Applied { get; private set; }
|
||||||
|
|
||||||
|
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
|
||||||
|
{
|
||||||
|
Applied = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestPlayer : Player
|
||||||
|
{
|
||||||
|
public new Bindable<IReadOnlyList<Mod>> Mods => base.Mods;
|
||||||
|
|
||||||
|
public TestPlayer()
|
||||||
|
: base(false, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected class SlowLoadPlayer : Player
|
protected class SlowLoadPlayer : Player
|
||||||
{
|
{
|
||||||
public bool Ready;
|
public bool Ready;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
@ -15,7 +17,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
protected override Player CreatePlayer(Ruleset ruleset)
|
protected override Player CreatePlayer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo);
|
var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Array.Empty<Mod>());
|
||||||
|
|
||||||
return new ScoreAccessibleReplayPlayer(ruleset.GetAutoplayMod().CreateReplayScore(beatmap));
|
return new ScoreAccessibleReplayPlayer(ruleset.GetAutoplayMod().CreateReplayScore(beatmap));
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Timing;
|
using osu.Game.Rulesets.Timing;
|
||||||
@ -23,6 +25,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(Playfield) };
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(Playfield) };
|
||||||
|
|
||||||
|
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||||
|
private IReadOnlyList<Mod> mods { get; set; } = Array.Empty<Mod>();
|
||||||
|
|
||||||
private readonly ScrollingTestContainer[] scrollContainers = new ScrollingTestContainer[4];
|
private readonly ScrollingTestContainer[] scrollContainers = new ScrollingTestContainer[4];
|
||||||
private readonly TestPlayfield[] playfields = new TestPlayfield[4];
|
private readonly TestPlayfield[] playfields = new TestPlayfield[4];
|
||||||
|
|
||||||
|
@ -120,12 +120,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SecondarySource : ISkinSource
|
private class SecondarySource : ISkin
|
||||||
{
|
{
|
||||||
public event Action SourceChanged;
|
|
||||||
|
|
||||||
public void TriggerSourceChanged() => SourceChanged?.Invoke();
|
|
||||||
|
|
||||||
public Drawable GetDrawableComponent(string componentName) => new SecondarySourceBox();
|
public Drawable GetDrawableComponent(string componentName) => new SecondarySourceBox();
|
||||||
|
|
||||||
public Texture GetTexture(string componentName) => throw new NotImplementedException();
|
public Texture GetTexture(string componentName) => throw new NotImplementedException();
|
||||||
@ -135,12 +131,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration => throw new NotImplementedException();
|
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SkinSourceContainer : Container, ISkinSource
|
private class SkinSourceContainer : Container, ISkin
|
||||||
{
|
{
|
||||||
public event Action SourceChanged;
|
|
||||||
|
|
||||||
public void TriggerSourceChanged() => SourceChanged?.Invoke();
|
|
||||||
|
|
||||||
public Drawable GetDrawableComponent(string componentName) => new BaseSourceBox();
|
public Drawable GetDrawableComponent(string componentName) => new BaseSourceBox();
|
||||||
|
|
||||||
public Texture GetTexture(string componentName) => throw new NotImplementedException();
|
public Texture GetTexture(string componentName) => throw new NotImplementedException();
|
||||||
|
@ -23,7 +23,11 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
|
|
||||||
public TestCaseLoaderAnimation()
|
public TestCaseLoaderAnimation()
|
||||||
{
|
{
|
||||||
Child = logo = new OsuLogo { Depth = float.MinValue };
|
Child = logo = new OsuLogo
|
||||||
|
{
|
||||||
|
Alpha = 0,
|
||||||
|
Depth = float.MinValue
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -39,7 +43,7 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
LoadScreen(loader);
|
LoadScreen(loader);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAssert("loaded", () =>
|
AddUntilStep("loaded", () =>
|
||||||
{
|
{
|
||||||
logoVisible = loader.Logo?.Alpha > 0;
|
logoVisible = loader.Logo?.Alpha > 0;
|
||||||
return loader.Logo != null && loader.ScreenLoaded;
|
return loader.Logo != null && loader.ScreenLoaded;
|
||||||
|
@ -35,10 +35,6 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
private WorkingBeatmap defaultBeatmap;
|
private WorkingBeatmap defaultBeatmap;
|
||||||
private DatabaseContextFactory factory;
|
private DatabaseContextFactory factory;
|
||||||
|
|
||||||
[Cached]
|
|
||||||
[Cached(Type = typeof(IBindable<IEnumerable<Mod>>))]
|
|
||||||
private readonly Bindable<IEnumerable<Mod>> selectedMods = new Bindable<IEnumerable<Mod>>(new Mod[] { });
|
|
||||||
|
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(Screens.Select.SongSelect),
|
typeof(Screens.Select.SongSelect),
|
||||||
@ -175,19 +171,19 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
AddStep("change ruleset", () =>
|
AddStep("change ruleset", () =>
|
||||||
{
|
{
|
||||||
songSelect.CurrentBeatmap.Mods.ValueChanged += onModChange;
|
Mods.ValueChanged += onModChange;
|
||||||
songSelect.Ruleset.ValueChanged += onRulesetChange;
|
songSelect.Ruleset.ValueChanged += onRulesetChange;
|
||||||
|
|
||||||
Ruleset.Value = new TaikoRuleset().RulesetInfo;
|
Ruleset.Value = new TaikoRuleset().RulesetInfo;
|
||||||
|
|
||||||
songSelect.CurrentBeatmap.Mods.ValueChanged -= onModChange;
|
Mods.ValueChanged -= onModChange;
|
||||||
songSelect.Ruleset.ValueChanged -= onRulesetChange;
|
songSelect.Ruleset.ValueChanged -= onRulesetChange;
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAssert("mods changed before ruleset", () => modChangeIndex < rulesetChangeIndex);
|
AddAssert("mods changed before ruleset", () => modChangeIndex < rulesetChangeIndex);
|
||||||
AddAssert("empty mods", () => !selectedMods.Value.Any());
|
AddAssert("empty mods", () => !Mods.Value.Any());
|
||||||
|
|
||||||
void onModChange(ValueChangedEvent<IEnumerable<Mod>> e) => modChangeIndex = actionIndex++;
|
void onModChange(ValueChangedEvent<IReadOnlyList<Mod>> e) => modChangeIndex = actionIndex++;
|
||||||
void onRulesetChange(ValueChangedEvent<RulesetInfo> e) => rulesetChangeIndex = actionIndex--;
|
void onRulesetChange(ValueChangedEvent<RulesetInfo> e) => rulesetChangeIndex = actionIndex--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +214,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
private static int importId;
|
private static int importId;
|
||||||
private int getImportId() => ++importId;
|
private int getImportId() => ++importId;
|
||||||
|
|
||||||
private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => selectedMods.Value = mods);
|
private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => Mods.Value = mods);
|
||||||
|
|
||||||
private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id));
|
private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id));
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
buttons = new ButtonSystem(),
|
buttons = new ButtonSystem(),
|
||||||
logo = new OsuLogo()
|
logo = new OsuLogo { RelativePositionAxes = Axes.Both }
|
||||||
};
|
};
|
||||||
|
|
||||||
buttons.SetOsuLogo(logo);
|
buttons.SetOsuLogo(logo);
|
||||||
|
@ -0,0 +1,299 @@
|
|||||||
|
// 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.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Framework.MathUtils;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
|
{
|
||||||
|
public class TestCaseLogoTrackingContainer : OsuTestCase
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(PlayerLoader),
|
||||||
|
typeof(Player),
|
||||||
|
typeof(LogoTrackingContainer),
|
||||||
|
typeof(ButtonSystem),
|
||||||
|
typeof(ButtonSystemState),
|
||||||
|
typeof(Menu),
|
||||||
|
typeof(MainMenu)
|
||||||
|
};
|
||||||
|
|
||||||
|
private OsuLogo logo;
|
||||||
|
private TestLogoTrackingContainer trackingContainer;
|
||||||
|
private Container transferContainer;
|
||||||
|
private Box visualBox;
|
||||||
|
private Box transferContainerBox;
|
||||||
|
private Drawable logoFacade;
|
||||||
|
private bool randomPositions;
|
||||||
|
|
||||||
|
private const float visual_box_size = 72;
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public void SetUpSteps()
|
||||||
|
{
|
||||||
|
AddStep("Clear facades", () =>
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.Both });
|
||||||
|
trackingContainer = null;
|
||||||
|
transferContainer = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Move the facade to 0,0, then move it to a random new location while the logo is still transforming to it.
|
||||||
|
/// Check if the logo is still tracking the facade.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestMoveFacade()
|
||||||
|
{
|
||||||
|
AddToggleStep("Toggle move continuously", b => randomPositions = b);
|
||||||
|
AddStep("Add tracking containers", addFacadeContainers);
|
||||||
|
AddStep("Move facade to random position", moveLogoFacade);
|
||||||
|
waitForMove();
|
||||||
|
AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the facade is removed from the container, the logo stops tracking.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestRemoveFacade()
|
||||||
|
{
|
||||||
|
AddStep("Add tracking containers", addFacadeContainers);
|
||||||
|
AddStep("Move facade to random position", moveLogoFacade);
|
||||||
|
AddStep("Remove facade from FacadeContainer", removeFacade);
|
||||||
|
waitForMove();
|
||||||
|
AddAssert("Logo is not tracking", () => !trackingContainer.IsLogoTracking);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the facade gets added to a new container, tracking starts on the new facade.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestTransferFacade()
|
||||||
|
{
|
||||||
|
AddStep("Add tracking containers", addFacadeContainers);
|
||||||
|
AddStep("Move facade to random position", moveLogoFacade);
|
||||||
|
AddStep("Remove facade from FacadeContainer", removeFacade);
|
||||||
|
AddStep("Transfer facade to a new container", () =>
|
||||||
|
{
|
||||||
|
transferContainer.Add(logoFacade);
|
||||||
|
transferContainerBox.Colour = Color4.Tomato;
|
||||||
|
moveLogoFacade();
|
||||||
|
});
|
||||||
|
|
||||||
|
waitForMove();
|
||||||
|
AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a facade to a flow container, move the logo to the center of the screen, then start tracking on the facade.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestFlowContainer()
|
||||||
|
{
|
||||||
|
FillFlowContainer flowContainer;
|
||||||
|
|
||||||
|
AddStep("Create new flow container with facade", () =>
|
||||||
|
{
|
||||||
|
Add(trackingContainer = new TestLogoTrackingContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Child = flowContainer = new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
flowContainer.Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Colour = Color4.Azure,
|
||||||
|
Size = new Vector2(visual_box_size)
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Alpha = 0.35f,
|
||||||
|
RelativeSizeAxes = Axes.None,
|
||||||
|
Size = new Vector2(visual_box_size),
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
visualBox = new Box
|
||||||
|
{
|
||||||
|
Colour = Color4.White,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
trackingContainer.LogoFacade,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Colour = Color4.Azure,
|
||||||
|
Size = new Vector2(visual_box_size)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Perform logo movements", () =>
|
||||||
|
{
|
||||||
|
trackingContainer.StopTracking();
|
||||||
|
logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo);
|
||||||
|
|
||||||
|
visualBox.Colour = Color4.White;
|
||||||
|
|
||||||
|
Scheduler.AddDelayed(() =>
|
||||||
|
{
|
||||||
|
trackingContainer.StartTracking(logo, 1000, Easing.InOutExpo);
|
||||||
|
visualBox.Colour = Color4.Tomato;
|
||||||
|
}, 700);
|
||||||
|
});
|
||||||
|
|
||||||
|
waitForMove(8);
|
||||||
|
AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetFacadeSize()
|
||||||
|
{
|
||||||
|
bool failed = false;
|
||||||
|
|
||||||
|
AddStep("Set up scenario", () =>
|
||||||
|
{
|
||||||
|
failed = false;
|
||||||
|
addFacadeContainers();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Try setting facade size", () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logoFacade.Size = new Vector2(0, 0);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (e is InvalidOperationException)
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Exception thrown", () => failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetMultipleContainers()
|
||||||
|
{
|
||||||
|
bool failed = false;
|
||||||
|
LogoTrackingContainer newContainer = new LogoTrackingContainer();
|
||||||
|
|
||||||
|
AddStep("Set up scenario", () =>
|
||||||
|
{
|
||||||
|
failed = false;
|
||||||
|
newContainer = new LogoTrackingContainer();
|
||||||
|
addFacadeContainers();
|
||||||
|
moveLogoFacade();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Try tracking new container", () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
newContainer.StartTracking(logo);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (e is InvalidOperationException)
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Exception thrown", () => failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFacadeContainers()
|
||||||
|
{
|
||||||
|
AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
trackingContainer = new TestLogoTrackingContainer
|
||||||
|
{
|
||||||
|
Alpha = 0.35f,
|
||||||
|
RelativeSizeAxes = Axes.None,
|
||||||
|
Size = new Vector2(visual_box_size),
|
||||||
|
Child = visualBox = new Box
|
||||||
|
{
|
||||||
|
Colour = Color4.Tomato,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transferContainer = new Container
|
||||||
|
{
|
||||||
|
Alpha = 0.35f,
|
||||||
|
RelativeSizeAxes = Axes.None,
|
||||||
|
Size = new Vector2(visual_box_size),
|
||||||
|
Child = transferContainerBox = new Box
|
||||||
|
{
|
||||||
|
Colour = Color4.White,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
trackingContainer.Add(logoFacade = trackingContainer.LogoFacade);
|
||||||
|
trackingContainer.StartTracking(logo, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitForMove(int count = 5) => AddWaitStep("Wait for transforms to finish", count);
|
||||||
|
|
||||||
|
private void removeFacade()
|
||||||
|
{
|
||||||
|
trackingContainer.Remove(logoFacade);
|
||||||
|
visualBox.Colour = Color4.White;
|
||||||
|
moveLogoFacade();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveLogoFacade()
|
||||||
|
{
|
||||||
|
if (logoFacade?.Transforms.Count == 0 && transferContainer?.Transforms.Count == 0)
|
||||||
|
{
|
||||||
|
Random random = new Random();
|
||||||
|
trackingContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300);
|
||||||
|
transferContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (randomPositions)
|
||||||
|
Schedule(moveLogoFacade);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestLogoTrackingContainer : LogoTrackingContainer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Check that the logo is tracking the position of the facade, with an acceptable precision lenience.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLogoTracking => Precision.AlmostEquals(Logo.Position, ComputeLogoTrackingPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -253,7 +253,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
private class TestModSelectOverlay : ModSelectOverlay
|
private class TestModSelectOverlay : ModSelectOverlay
|
||||||
{
|
{
|
||||||
public new Bindable<IEnumerable<Mod>> SelectedMods => base.SelectedMods;
|
public new Bindable<IReadOnlyList<Mod>> SelectedMods => base.SelectedMods;
|
||||||
|
|
||||||
public ModButton GetModButton(Mod mod)
|
public ModButton GetModButton(Mod mod)
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
namespace osu.Game.Audio
|
namespace osu.Game.Audio
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface for objects that can own <see cref="IPreviewTrack"/>s.
|
/// Interface for objects that can own <see cref="PreviewTrack"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <see cref="IPreviewTrackOwner"/>s can cancel the currently playing <see cref="PreviewTrack"/> through the
|
/// <see cref="IPreviewTrackOwner"/>s can cancel the currently playing <see cref="PreviewTrack"/> through the
|
||||||
|
@ -98,7 +98,7 @@ namespace osu.Game.Beatmaps
|
|||||||
protected abstract IEnumerable<Type> ValidConversionTypes { get; }
|
protected abstract IEnumerable<Type> ValidConversionTypes { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the <see cref="Beatmap{T}"/> that will be returned by this <see cref="BeatmapProcessor{T}"/>.
|
/// Creates the <see cref="Beatmap{T}"/> that will be returned by this <see cref="BeatmapProcessor"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual Beatmap<T> CreateBeatmap() => new Beatmap<T>();
|
protected virtual Beatmap<T> CreateBeatmap() => new Beatmap<T>();
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
request.Perform(api);
|
request.Perform(api);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch
|
||||||
{
|
{
|
||||||
// no need to handle here as exceptions will filter down to request.Failure above.
|
// no need to handle here as exceptions will filter down to request.Failure above.
|
||||||
}
|
}
|
||||||
@ -382,7 +382,6 @@ namespace osu.Game.Beatmaps
|
|||||||
/// Query the API to populate missing values like OnlineBeatmapID / OnlineBeatmapSetID or (Rank-)Status.
|
/// Query the API to populate missing values like OnlineBeatmapID / OnlineBeatmapSetID or (Rank-)Status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="beatmap">The beatmap to populate.</param>
|
/// <param name="beatmap">The beatmap to populate.</param>
|
||||||
/// <param name="otherBeatmaps">The other beatmaps contained within this set.</param>
|
|
||||||
/// <param name="force">Whether to re-query if the provided beatmap already has populated values.</param>
|
/// <param name="force">Whether to re-query if the provided beatmap already has populated values.</param>
|
||||||
/// <returns>True if population was successful.</returns>
|
/// <returns>True if population was successful.</returns>
|
||||||
private bool fetchAndPopulateOnlineValues(BeatmapInfo beatmap, bool force = false)
|
private bool fetchAndPopulateOnlineValues(BeatmapInfo beatmap, bool force = false)
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="Bindable{T}"/> for the <see cref="OsuGame"/> beatmap.
|
/// A <see cref="Bindable{T}"/> for the <see cref="OsuGame"/> beatmap.
|
||||||
/// This should be used sparingly in-favour of <see cref="IBindable<WorkingBeatmap>"/>.
|
/// This should be used sparingly in-favour of <see cref="IBindable{WorkingBeatmap}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BindableBeatmap : NonNullableBindable<WorkingBeatmap>
|
public abstract class BindableBeatmap : NonNullableBindable<WorkingBeatmap>
|
||||||
{
|
{
|
||||||
@ -67,6 +67,6 @@ namespace osu.Game.Beatmaps
|
|||||||
/// If you are further binding to events of the retrieved <see cref="BindableBeatmap"/>, ensure a local reference is held.
|
/// If you are further binding to events of the retrieved <see cref="BindableBeatmap"/>, ensure a local reference is held.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NotNull]
|
[NotNull]
|
||||||
public abstract BindableBeatmap GetBoundCopy();
|
public new abstract BindableBeatmap GetBoundCopy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
@ -52,7 +53,7 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
public override IEnumerable<Mod> GetModsFor(ModType type) => new Mod[] { };
|
public override IEnumerable<Mod> GetModsFor(ModType type) => new Mod[] { };
|
||||||
|
|
||||||
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap)
|
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@ -73,9 +74,18 @@ namespace osu.Game.Beatmaps
|
|||||||
private class DummyBeatmapConverter : IBeatmapConverter
|
private class DummyBeatmapConverter : IBeatmapConverter
|
||||||
{
|
{
|
||||||
public event Action<HitObject, IEnumerable<HitObject>> ObjectConverted;
|
public event Action<HitObject, IEnumerable<HitObject>> ObjectConverted;
|
||||||
|
|
||||||
public IBeatmap Beatmap { get; set; }
|
public IBeatmap Beatmap { get; set; }
|
||||||
|
|
||||||
public bool CanConvert => true;
|
public bool CanConvert => true;
|
||||||
public IBeatmap Convert() => Beatmap;
|
|
||||||
|
public IBeatmap Convert()
|
||||||
|
{
|
||||||
|
foreach (var obj in Beatmap.HitObjects)
|
||||||
|
ObjectConverted?.Invoke(obj, obj.Yield());
|
||||||
|
|
||||||
|
return Beatmap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
{
|
{
|
||||||
colour = new Color4(byte.Parse(split[0]), byte.Parse(split[1]), byte.Parse(split[2]), split.Length == 4 ? byte.Parse(split[3]) : (byte)255);
|
colour = new Color4(byte.Parse(split[0]), byte.Parse(split[1]), byte.Parse(split[2]), split.Length == 4 ? byte.Parse(split[3]) : (byte)255);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(@"Color must be specified with 8-bit integer components");
|
throw new InvalidOperationException(@"Color must be specified with 8-bit integer components");
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ using osu.Framework.IO.File;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Game.IO.Serialization;
|
using osu.Game.IO.Serialization;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
@ -28,16 +27,12 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public readonly BeatmapMetadata Metadata;
|
public readonly BeatmapMetadata Metadata;
|
||||||
|
|
||||||
public readonly Bindable<IEnumerable<Mod>> Mods = new Bindable<IEnumerable<Mod>>(new Mod[] { });
|
|
||||||
|
|
||||||
protected WorkingBeatmap(BeatmapInfo beatmapInfo)
|
protected WorkingBeatmap(BeatmapInfo beatmapInfo)
|
||||||
{
|
{
|
||||||
BeatmapInfo = beatmapInfo;
|
BeatmapInfo = beatmapInfo;
|
||||||
BeatmapSetInfo = beatmapInfo.BeatmapSet;
|
BeatmapSetInfo = beatmapInfo.BeatmapSet;
|
||||||
Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata();
|
Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata();
|
||||||
|
|
||||||
Mods.ValueChanged += _ => applyRateAdjustments();
|
|
||||||
|
|
||||||
beatmap = new RecyclableLazy<IBeatmap>(() =>
|
beatmap = new RecyclableLazy<IBeatmap>(() =>
|
||||||
{
|
{
|
||||||
var b = GetBeatmap() ?? new Beatmap();
|
var b = GetBeatmap() ?? new Beatmap();
|
||||||
@ -51,14 +46,7 @@ namespace osu.Game.Beatmaps
|
|||||||
return b;
|
return b;
|
||||||
});
|
});
|
||||||
|
|
||||||
track = new RecyclableLazy<Track>(() =>
|
track = new RecyclableLazy<Track>(() => GetTrack() ?? new VirtualBeatmapTrack(Beatmap));
|
||||||
{
|
|
||||||
// we want to ensure that we always have a track, even if it's a fake one.
|
|
||||||
var t = GetTrack() ?? new VirtualBeatmapTrack(Beatmap);
|
|
||||||
applyRateAdjustments(t);
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
|
|
||||||
background = new RecyclableLazy<Texture>(GetBackground, BackgroundStillValid);
|
background = new RecyclableLazy<Texture>(GetBackground, BackgroundStillValid);
|
||||||
waveform = new RecyclableLazy<Waveform>(GetWaveform);
|
waveform = new RecyclableLazy<Waveform>(GetWaveform);
|
||||||
storyboard = new RecyclableLazy<Storyboard>(GetStoryboard);
|
storyboard = new RecyclableLazy<Storyboard>(GetStoryboard);
|
||||||
@ -85,9 +73,10 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ruleset">The <see cref="RulesetInfo"/> to create a playable <see cref="IBeatmap"/> for.</param>
|
/// <param name="ruleset">The <see cref="RulesetInfo"/> to create a playable <see cref="IBeatmap"/> for.</param>
|
||||||
|
/// <param name="mods">The <see cref="Mod"/>s to apply to the <see cref="IBeatmap"/>.</param>
|
||||||
/// <returns>The converted <see cref="IBeatmap"/>.</returns>
|
/// <returns>The converted <see cref="IBeatmap"/>.</returns>
|
||||||
/// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception>
|
/// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception>
|
||||||
public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset)
|
public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods)
|
||||||
{
|
{
|
||||||
var rulesetInstance = ruleset.CreateInstance();
|
var rulesetInstance = ruleset.CreateInstance();
|
||||||
|
|
||||||
@ -98,19 +87,19 @@ namespace osu.Game.Beatmaps
|
|||||||
throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter}).");
|
throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter}).");
|
||||||
|
|
||||||
// Apply conversion mods
|
// Apply conversion mods
|
||||||
foreach (var mod in Mods.Value.OfType<IApplicableToBeatmapConverter>())
|
foreach (var mod in mods.OfType<IApplicableToBeatmapConverter>())
|
||||||
mod.ApplyToBeatmapConverter(converter);
|
mod.ApplyToBeatmapConverter(converter);
|
||||||
|
|
||||||
// Convert
|
// Convert
|
||||||
IBeatmap converted = converter.Convert();
|
IBeatmap converted = converter.Convert();
|
||||||
|
|
||||||
// Apply difficulty mods
|
// Apply difficulty mods
|
||||||
if (Mods.Value.Any(m => m is IApplicableToDifficulty))
|
if (mods.Any(m => m is IApplicableToDifficulty))
|
||||||
{
|
{
|
||||||
converted.BeatmapInfo = converted.BeatmapInfo.Clone();
|
converted.BeatmapInfo = converted.BeatmapInfo.Clone();
|
||||||
converted.BeatmapInfo.BaseDifficulty = converted.BeatmapInfo.BaseDifficulty.Clone();
|
converted.BeatmapInfo.BaseDifficulty = converted.BeatmapInfo.BaseDifficulty.Clone();
|
||||||
|
|
||||||
foreach (var mod in Mods.Value.OfType<IApplicableToDifficulty>())
|
foreach (var mod in mods.OfType<IApplicableToDifficulty>())
|
||||||
mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty);
|
mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +111,7 @@ namespace osu.Game.Beatmaps
|
|||||||
foreach (var obj in converted.HitObjects)
|
foreach (var obj in converted.HitObjects)
|
||||||
obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty);
|
obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty);
|
||||||
|
|
||||||
foreach (var mod in Mods.Value.OfType<IApplicableToHitObject>())
|
foreach (var mod in mods.OfType<IApplicableToHitObject>())
|
||||||
foreach (var obj in converted.HitObjects)
|
foreach (var obj in converted.HitObjects)
|
||||||
mod.ApplyToHitObject(obj);
|
mod.ApplyToHitObject(obj);
|
||||||
|
|
||||||
@ -188,16 +177,6 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RecycleTrack() => track.Recycle();
|
public void RecycleTrack() => track.Recycle();
|
||||||
|
|
||||||
private void applyRateAdjustments(Track t = null)
|
|
||||||
{
|
|
||||||
if (t == null && track.IsResultAvailable) t = Track;
|
|
||||||
if (t == null) return;
|
|
||||||
|
|
||||||
t.ResetSpeedAdjustments();
|
|
||||||
foreach (var mod in Mods.Value.OfType<IApplicableToClock>())
|
|
||||||
mod.ApplyToClock(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RecyclableLazy<T>
|
public class RecyclableLazy<T>
|
||||||
{
|
{
|
||||||
private Lazy<T> lazy;
|
private Lazy<T> lazy;
|
||||||
|
@ -563,7 +563,7 @@ namespace osu.Game.Database
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether an existing model already exists for a new import item.
|
/// Check whether an existing model already exists for a new import item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The new model proposed for import.
|
/// <param name="model">The new model proposed for import.</param>
|
||||||
/// <returns>An existing model which matches the criteria to skip importing, else null.</returns>
|
/// <returns>An existing model which matches the criteria to skip importing, else null.</returns>
|
||||||
protected TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash);
|
protected TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash);
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.EntityFrameworkCore.Storage;
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
@ -67,7 +66,7 @@ namespace osu.Game.Database
|
|||||||
context = threadContexts.Value;
|
context = threadContexts.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch
|
||||||
{
|
{
|
||||||
// retrieval of a context could trigger a fatal error.
|
// retrieval of a context could trigger a fatal error.
|
||||||
Monitor.Exit(writeLock);
|
Monitor.Exit(writeLock);
|
||||||
|
@ -70,7 +70,7 @@ namespace osu.Game.Database
|
|||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch
|
||||||
{
|
{
|
||||||
connection.Close();
|
connection.Close();
|
||||||
throw;
|
throw;
|
||||||
|
@ -103,7 +103,7 @@ namespace osu.Game.Graphics.Containers
|
|||||||
{
|
{
|
||||||
channelManager?.OpenChannel(linkArgument);
|
channelManager?.OpenChannel(linkArgument);
|
||||||
}
|
}
|
||||||
catch (ChannelNotFoundException e)
|
catch (ChannelNotFoundException)
|
||||||
{
|
{
|
||||||
Logger.Log($"The requested channel \"{linkArgument}\" does not exist");
|
Logger.Log($"The requested channel \"{linkArgument}\" does not exist");
|
||||||
}
|
}
|
||||||
|
157
osu.Game/Graphics/Containers/LogoTrackingContainer.cs
Normal file
157
osu.Game/Graphics/Containers/LogoTrackingContainer.cs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// 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 osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.MathUtils;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A container that handles tracking of an <see cref="OsuLogo"/> through different layout scenarios.
|
||||||
|
/// </summary>
|
||||||
|
public class LogoTrackingContainer : Container
|
||||||
|
{
|
||||||
|
public Facade LogoFacade => facade;
|
||||||
|
|
||||||
|
protected OsuLogo Logo { get; private set; }
|
||||||
|
|
||||||
|
private readonly InternalFacade facade = new InternalFacade();
|
||||||
|
|
||||||
|
private Easing easing;
|
||||||
|
private Vector2? startPosition;
|
||||||
|
private double? startTime;
|
||||||
|
private double duration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assign the logo that should track the facade's position, as well as how it should transform to its initial position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logo">The instance of the logo to be used for tracking.</param>
|
||||||
|
/// <param name="duration">The duration of the initial transform. Default is instant.</param>
|
||||||
|
/// <param name="easing">The easing type of the initial transform.</param>
|
||||||
|
public void StartTracking(OsuLogo logo, double duration = 0, Easing easing = Easing.None)
|
||||||
|
{
|
||||||
|
if (logo == null)
|
||||||
|
throw new ArgumentNullException(nameof(logo));
|
||||||
|
|
||||||
|
if (logo.IsTracking && Logo == null)
|
||||||
|
throw new InvalidOperationException($"Cannot track an instance of {typeof(OsuLogo)} to multiple {typeof(LogoTrackingContainer)}s");
|
||||||
|
|
||||||
|
if (Logo != logo && Logo != null)
|
||||||
|
{
|
||||||
|
// If we're replacing the logo to be tracked, the old one no longer has a tracking container
|
||||||
|
Logo.IsTracking = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logo = logo;
|
||||||
|
Logo.IsTracking = true;
|
||||||
|
|
||||||
|
this.duration = duration;
|
||||||
|
this.easing = easing;
|
||||||
|
|
||||||
|
startTime = null;
|
||||||
|
startPosition = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stops the logo assigned in <see cref="StartTracking"/> from tracking the facade's position.
|
||||||
|
/// </summary>
|
||||||
|
public void StopTracking()
|
||||||
|
{
|
||||||
|
if (Logo != null)
|
||||||
|
{
|
||||||
|
Logo.IsTracking = false;
|
||||||
|
Logo = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the position that the logo should move to with respect to the <see cref="LogoFacade"/>.
|
||||||
|
/// Manually performs a conversion of the Facade's position to the Logo's parent's relative space.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Will only be correct if the logo's <see cref="Drawable.RelativePositionAxes"/> are set to Axes.Both</remarks>
|
||||||
|
protected Vector2 ComputeLogoTrackingPosition()
|
||||||
|
{
|
||||||
|
var absolutePos = Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre);
|
||||||
|
|
||||||
|
return new Vector2(absolutePos.X / Logo.Parent.RelativeToAbsoluteFactor.X,
|
||||||
|
absolutePos.Y / Logo.Parent.RelativeToAbsoluteFactor.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (Logo == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Logo.RelativePositionAxes != Axes.Both)
|
||||||
|
throw new InvalidOperationException($"Tracking logo must have {nameof(RelativePositionAxes)} = Axes.Both");
|
||||||
|
|
||||||
|
// Account for the scale of the actual OsuLogo, as SizeForFlow only accounts for the sprite scale.
|
||||||
|
facade.SetSize(new Vector2(Logo.SizeForFlow * Logo.Scale.X));
|
||||||
|
|
||||||
|
var localPos = ComputeLogoTrackingPosition();
|
||||||
|
|
||||||
|
if (LogoFacade.Parent != null && Logo.Position != localPos)
|
||||||
|
{
|
||||||
|
// If this is our first update since tracking has started, initialize our starting values for interpolation
|
||||||
|
if (startTime == null || startPosition == null)
|
||||||
|
{
|
||||||
|
startTime = Time.Current;
|
||||||
|
startPosition = Logo.Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (duration != 0)
|
||||||
|
{
|
||||||
|
double elapsedDuration = (double)(Time.Current - startTime);
|
||||||
|
|
||||||
|
var amount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1));
|
||||||
|
|
||||||
|
// Interpolate the position of the logo, where amount 0 is where the logo was when it first began interpolating, and amount 1 is the target location.
|
||||||
|
Logo.Position = Vector2.Lerp(startPosition.Value, localPos, amount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logo.Position = localPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
if (Logo != null)
|
||||||
|
Logo.IsTracking = false;
|
||||||
|
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InternalFacade : Facade
|
||||||
|
{
|
||||||
|
public new void SetSize(Vector2 size)
|
||||||
|
{
|
||||||
|
base.SetSize(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dummy object used to denote another object's location.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Facade : Drawable
|
||||||
|
{
|
||||||
|
public override Vector2 Size
|
||||||
|
{
|
||||||
|
get => base.Size;
|
||||||
|
set => throw new InvalidOperationException($"Cannot set the Size of a {typeof(Facade)} outside of a {typeof(LogoTrackingContainer)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetSize(Vector2 size)
|
||||||
|
{
|
||||||
|
base.Size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -61,9 +61,9 @@ namespace osu.Game.Graphics
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the string representation of a <see cref="FontWeight"/>.
|
/// Retrieves the string representation of a <see cref="FontWeight"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="typeface">The <see cref="Typeface"/>.</param>
|
/// <param name="family">The family string.</param>
|
||||||
/// <param name="weight">The <see cref="FontWeight"/>.</param>
|
/// <param name="weight">The <see cref="FontWeight"/>.</param>
|
||||||
/// <returns>The string representation of <paramref name="weight"/> in the specified <paramref name="typeface"/>.</returns>
|
/// <returns>The string representation of <paramref name="weight"/> in the specified <paramref name="family"/>.</returns>
|
||||||
public static string GetWeightString(string family, FontWeight weight)
|
public static string GetWeightString(string family, FontWeight weight)
|
||||||
{
|
{
|
||||||
string weightString = weight.ToString();
|
string weightString = weight.ToString();
|
||||||
@ -81,6 +81,7 @@ namespace osu.Game.Graphics
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="FontUsage"/> by applying adjustments to this <see cref="FontUsage"/>.
|
/// Creates a new <see cref="FontUsage"/> by applying adjustments to this <see cref="FontUsage"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="usage">The base <see cref="FontUsage"/>.</param>
|
||||||
/// <param name="typeface">The font typeface. If null, the value is copied from this <see cref="FontUsage"/>.</param>
|
/// <param name="typeface">The font typeface. If null, the value is copied from this <see cref="FontUsage"/>.</param>
|
||||||
/// <param name="size">The text size. If null, the value is copied from this <see cref="FontUsage"/>.</param>
|
/// <param name="size">The text size. If null, the value is copied from this <see cref="FontUsage"/>.</param>
|
||||||
/// <param name="weight">The font weight. If null, the value is copied from this <see cref="FontUsage"/>.</param>
|
/// <param name="weight">The font weight. If null, the value is copied from this <see cref="FontUsage"/>.</param>
|
||||||
|
@ -8,7 +8,7 @@ using osu.Framework.Screens;
|
|||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="BreadcrumbControl"/> which follows the active screen (and allows navigation) in a <see cref="Screen"/> stack.
|
/// A <see cref="BreadcrumbControl{IScreen}"/> which follows the active screen (and allows navigation) in a <see cref="Screen"/> stack.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ScreenBreadcrumbControl : BreadcrumbControl<IScreen>
|
public class ScreenBreadcrumbControl : BreadcrumbControl<IScreen>
|
||||||
{
|
{
|
||||||
|
@ -253,7 +253,7 @@ namespace osu.Game.Online.API
|
|||||||
handleWebException(we);
|
handleWebException(we);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ using System.Linq;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Scoring.Legacy;
|
using osu.Game.Scoring.Legacy;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
@ -71,7 +70,6 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
{
|
{
|
||||||
foreach (var kvp in value)
|
foreach (var kvp in value)
|
||||||
{
|
{
|
||||||
HitResult newKey;
|
|
||||||
switch (kvp.Key)
|
switch (kvp.Key)
|
||||||
{
|
{
|
||||||
case @"count_geki":
|
case @"count_geki":
|
||||||
|
@ -10,16 +10,16 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
public class APIUserMostPlayedBeatmap
|
public class APIUserMostPlayedBeatmap
|
||||||
{
|
{
|
||||||
[JsonProperty("beatmap_id")]
|
[JsonProperty("beatmap_id")]
|
||||||
public int BeatmapID;
|
public int BeatmapID { get; set; }
|
||||||
|
|
||||||
[JsonProperty("count")]
|
[JsonProperty("count")]
|
||||||
public int PlayCount;
|
public int PlayCount { get; set; }
|
||||||
|
|
||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
private BeatmapInfo beatmap;
|
private BeatmapInfo beatmap { get; set; }
|
||||||
|
|
||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
private APIBeatmapSet beatmapSet;
|
private APIBeatmapSet beatmapSet { get; set; }
|
||||||
|
|
||||||
public BeatmapInfo GetBeatmapInfo(RulesetStore rulesets)
|
public BeatmapInfo GetBeatmapInfo(RulesetStore rulesets)
|
||||||
{
|
{
|
||||||
|
@ -27,8 +27,6 @@ namespace osu.Game.Online.Chat
|
|||||||
|
|
||||||
protected ChannelManager ChannelManager;
|
protected ChannelManager ChannelManager;
|
||||||
|
|
||||||
private ScrollContainer scroll;
|
|
||||||
|
|
||||||
private DrawableChannel drawableChannel;
|
private DrawableChannel drawableChannel;
|
||||||
|
|
||||||
private readonly bool postingTextbox;
|
private readonly bool postingTextbox;
|
||||||
|
@ -112,8 +112,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
// todo: move this to SongSelect once Screen has the ability to unsuspend.
|
// todo: move this to SongSelect once Screen has the ability to unsuspend.
|
||||||
[Cached]
|
[Cached]
|
||||||
[Cached(Type = typeof(IBindable<IEnumerable<Mod>>))]
|
[Cached(typeof(IBindable<IReadOnlyList<Mod>>))]
|
||||||
private readonly Bindable<IEnumerable<Mod>> selectedMods = new Bindable<IEnumerable<Mod>>(new Mod[] { });
|
private readonly Bindable<IReadOnlyList<Mod>> mods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||||
|
|
||||||
public OsuGame(string[] args = null)
|
public OsuGame(string[] args = null)
|
||||||
{
|
{
|
||||||
@ -272,7 +272,6 @@ namespace osu.Game
|
|||||||
/// Present a score's replay immediately.
|
/// Present a score's replay immediately.
|
||||||
/// The user should have already requested this interactively.
|
/// The user should have already requested this interactively.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="beatmap">The beatmap to select.</param>
|
|
||||||
public void PresentScore(ScoreInfo score)
|
public void PresentScore(ScoreInfo score)
|
||||||
{
|
{
|
||||||
var databasedScore = ScoreManager.GetScore(score);
|
var databasedScore = ScoreManager.GetScore(score);
|
||||||
@ -293,9 +292,8 @@ namespace osu.Game
|
|||||||
performFromMainMenu(() =>
|
performFromMainMenu(() =>
|
||||||
{
|
{
|
||||||
ruleset.Value = databasedScoreInfo.Ruleset;
|
ruleset.Value = databasedScoreInfo.Ruleset;
|
||||||
|
|
||||||
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap);
|
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap);
|
||||||
Beatmap.Value.Mods.Value = databasedScoreInfo.Mods;
|
mods.Value = databasedScoreInfo.Mods;
|
||||||
|
|
||||||
menuScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore)));
|
menuScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore)));
|
||||||
}, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true);
|
}, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true);
|
||||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private new void load(OsuColour colour)
|
private void load(OsuColour colour)
|
||||||
{
|
{
|
||||||
BackgroundInactive = colour.Gray2;
|
BackgroundInactive = colour.Gray2;
|
||||||
BackgroundActive = colour.Gray3;
|
BackgroundActive = colour.Gray3;
|
||||||
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Game.Online.Chat;
|
using osu.Game.Online.Chat;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -18,9 +17,6 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
{
|
{
|
||||||
public class PrivateChannelTabItem : ChannelTabItem
|
public class PrivateChannelTabItem : ChannelTabItem
|
||||||
{
|
{
|
||||||
private readonly OsuSpriteText username;
|
|
||||||
private readonly Avatar avatarContainer;
|
|
||||||
|
|
||||||
protected override IconUsage DisplayIcon => FontAwesome.Solid.At;
|
protected override IconUsage DisplayIcon => FontAwesome.Solid.At;
|
||||||
|
|
||||||
public PrivateChannelTabItem(Channel value)
|
public PrivateChannelTabItem(Channel value)
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An overlay which will display a black screen that dims over a period before confirming an exit action.
|
/// An overlay which will display a black screen that dims over a period before confirming an exit action.
|
||||||
/// Action is BYO (derived class will need to call <see cref="BeginConfirm"/> and <see cref="AbortConfirm"/> from a user event).
|
/// Action is BYO (derived class will need to call <see cref="HoldToConfirmContainer.BeginConfirm"/> and <see cref="HoldToConfirmContainer.AbortConfirm"/> from a user event).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class HoldToConfirmOverlay : HoldToConfirmContainer
|
public abstract class HoldToConfirmOverlay : HoldToConfirmContainer
|
||||||
{
|
{
|
||||||
|
@ -42,19 +42,19 @@ namespace osu.Game.Overlays.Mods
|
|||||||
|
|
||||||
protected readonly FillFlowContainer<ModSection> ModSectionsContainer;
|
protected readonly FillFlowContainer<ModSection> ModSectionsContainer;
|
||||||
|
|
||||||
protected readonly Bindable<IEnumerable<Mod>> SelectedMods = new Bindable<IEnumerable<Mod>>(new Mod[] { });
|
protected readonly Bindable<IReadOnlyList<Mod>> SelectedMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||||
|
|
||||||
protected readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
protected readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio, Bindable<IEnumerable<Mod>> selectedMods)
|
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio, Bindable<IReadOnlyList<Mod>> mods)
|
||||||
{
|
{
|
||||||
LowMultiplierColour = colours.Red;
|
LowMultiplierColour = colours.Red;
|
||||||
HighMultiplierColour = colours.Green;
|
HighMultiplierColour = colours.Green;
|
||||||
UnrankedLabel.Colour = colours.Blue;
|
UnrankedLabel.Colour = colours.Blue;
|
||||||
|
|
||||||
Ruleset.BindTo(ruleset);
|
Ruleset.BindTo(ruleset);
|
||||||
if (selectedMods != null) SelectedMods.BindTo(selectedMods);
|
if (mods != null) SelectedMods.BindTo(mods);
|
||||||
|
|
||||||
sampleOn = audio.Sample.Get(@"UI/check-on");
|
sampleOn = audio.Sample.Get(@"UI/check-on");
|
||||||
sampleOff = audio.Sample.Get(@"UI/check-off");
|
sampleOff = audio.Sample.Get(@"UI/check-off");
|
||||||
@ -87,14 +87,14 @@ namespace osu.Game.Overlays.Mods
|
|||||||
|
|
||||||
// attempt to re-select any already selected mods.
|
// attempt to re-select any already selected mods.
|
||||||
// this may be the first time we are receiving the ruleset, in which case they will still match.
|
// this may be the first time we are receiving the ruleset, in which case they will still match.
|
||||||
selectedModsChanged(new ValueChangedEvent<IEnumerable<Mod>>(SelectedMods.Value, SelectedMods.Value));
|
selectedModsChanged(new ValueChangedEvent<IReadOnlyList<Mod>>(SelectedMods.Value, SelectedMods.Value));
|
||||||
|
|
||||||
// write the mods back to the SelectedMods bindable in the case a change was not applicable.
|
// write the mods back to the SelectedMods bindable in the case a change was not applicable.
|
||||||
// this generally isn't required as the previous line will perform deselection; just here for safety.
|
// this generally isn't required as the previous line will perform deselection; just here for safety.
|
||||||
refreshSelectedMods();
|
refreshSelectedMods();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectedModsChanged(ValueChangedEvent<IEnumerable<Mod>> e)
|
private void selectedModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> e)
|
||||||
{
|
{
|
||||||
foreach (ModSection section in ModSectionsContainer.Children)
|
foreach (ModSection section in ModSectionsContainer.Children)
|
||||||
section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList());
|
section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList());
|
||||||
|
@ -23,6 +23,7 @@ using osu.Game.Graphics.Containers;
|
|||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Overlays.Music;
|
using osu.Game.Overlays.Music;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -50,12 +51,15 @@ namespace osu.Game.Overlays
|
|||||||
private BeatmapManager beatmaps;
|
private BeatmapManager beatmaps;
|
||||||
|
|
||||||
private List<BeatmapSetInfo> beatmapSets;
|
private List<BeatmapSetInfo> beatmapSets;
|
||||||
private BeatmapSetInfo currentSet;
|
|
||||||
|
|
||||||
private Container dragContainer;
|
private Container dragContainer;
|
||||||
private Container playerContainer;
|
private Container playerContainer;
|
||||||
|
|
||||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
[Resolved]
|
||||||
|
private Bindable<WorkingBeatmap> beatmap { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IBindable<IReadOnlyList<Mod>> mods { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provide a source for the toolbar height.
|
/// Provide a source for the toolbar height.
|
||||||
@ -74,7 +78,6 @@ namespace osu.Game.Overlays
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(Bindable<WorkingBeatmap> beatmap, BeatmapManager beatmaps, OsuColour colours)
|
private void load(Bindable<WorkingBeatmap> beatmap, BeatmapManager beatmaps, OsuColour colours)
|
||||||
{
|
{
|
||||||
this.beatmap.BindTo(beatmap);
|
|
||||||
this.beatmaps = beatmaps;
|
this.beatmaps = beatmaps;
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -232,6 +235,7 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
beatmap.BindValueChanged(beatmapChanged, true);
|
beatmap.BindValueChanged(beatmapChanged, true);
|
||||||
beatmap.BindDisabledChanged(beatmapDisabledChanged, true);
|
beatmap.BindDisabledChanged(beatmapDisabledChanged, true);
|
||||||
|
mods.BindValueChanged(_ => updateAudioAdjustments(), true);
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,10 +359,23 @@ namespace osu.Game.Overlays
|
|||||||
progressBar.CurrentTime = 0;
|
progressBar.CurrentTime = 0;
|
||||||
|
|
||||||
updateDisplay(current, direction);
|
updateDisplay(current, direction);
|
||||||
|
updateAudioAdjustments();
|
||||||
|
|
||||||
queuedDirection = null;
|
queuedDirection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateAudioAdjustments()
|
||||||
|
{
|
||||||
|
var track = current?.Track;
|
||||||
|
if (track == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
track.ResetSpeedAdjustments();
|
||||||
|
|
||||||
|
foreach (var mod in mods.Value.OfType<IApplicableToClock>())
|
||||||
|
mod.ApplyToClock(track);
|
||||||
|
}
|
||||||
|
|
||||||
private void currentTrackCompleted() => Schedule(() =>
|
private void currentTrackCompleted() => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (!current.Track.Looping && !beatmap.Disabled && beatmapSets.Any())
|
if (!current.Track.Looping && !beatmap.Disabled && beatmapSets.Any())
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Configuration;
|
using osu.Game.Rulesets.Configuration;
|
||||||
|
|
||||||
@ -9,7 +10,7 @@ namespace osu.Game.Overlays.Settings
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="SettingsSubsection"/> which provides subclasses with the <see cref="IRulesetConfigManager"/>
|
/// A <see cref="SettingsSubsection"/> which provides subclasses with the <see cref="IRulesetConfigManager"/>
|
||||||
/// from the <see cref="Ruleset"/>'s <see cref="Ruleset.CreateConfig()"/>.
|
/// from the <see cref="Ruleset"/>'s <see cref="Ruleset.CreateConfig(SettingsStore)"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class RulesetSettingsSubsection : SettingsSubsection
|
public abstract class RulesetSettingsSubsection : SettingsSubsection
|
||||||
{
|
{
|
||||||
|
@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings
|
|||||||
{
|
{
|
||||||
protected override OsuDropdown<T> CreateDropdown() => new DropdownControl();
|
protected override OsuDropdown<T> CreateDropdown() => new DropdownControl();
|
||||||
|
|
||||||
protected class DropdownControl : OsuEnumDropdown<T>
|
protected new class DropdownControl : OsuEnumDropdown<T>
|
||||||
{
|
{
|
||||||
public DropdownControl()
|
public DropdownControl()
|
||||||
{
|
{
|
||||||
|
@ -39,8 +39,7 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
{
|
{
|
||||||
mods = mods.Select(m => m.CreateCopy()).ToArray();
|
mods = mods.Select(m => m.CreateCopy()).ToArray();
|
||||||
|
|
||||||
beatmap.Mods.Value = mods;
|
IBeatmap playableBeatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods);
|
||||||
IBeatmap playableBeatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo);
|
|
||||||
|
|
||||||
var clock = new StopwatchClock();
|
var clock = new StopwatchClock();
|
||||||
mods.OfType<IApplicableToClock>().ForEach(m => m.ApplyToClock(clock));
|
mods.OfType<IApplicableToClock>().ForEach(m => m.ApplyToClock(clock));
|
||||||
@ -106,7 +105,7 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Mod[] CreateDifficultyAdjustmentModCombinations()
|
public Mod[] CreateDifficultyAdjustmentModCombinations()
|
||||||
{
|
{
|
||||||
return createDifficultyAdjustmentModCombinations(Enumerable.Empty<Mod>(), DifficultyAdjustmentMods).ToArray();
|
return createDifficultyAdjustmentModCombinations(Array.Empty<Mod>(), DifficultyAdjustmentMods).ToArray();
|
||||||
|
|
||||||
IEnumerable<Mod> createDifficultyAdjustmentModCombinations(IEnumerable<Mod> currentSet, Mod[] adjustmentSet, int currentSetCount = 0, int adjustmentSetStart = 0)
|
IEnumerable<Mod> createDifficultyAdjustmentModCombinations(IEnumerable<Mod> currentSet, Mod[] adjustmentSet, int currentSetCount = 0, int adjustmentSetStart = 0)
|
||||||
{
|
{
|
||||||
@ -166,7 +165,7 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the <see cref="Skill"/>s to calculate the difficulty of an <see cref="IBeatmap"/>.
|
/// Creates the <see cref="Skill"/>s to calculate the difficulty of an <see cref="IBeatmap"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="beatmap">The <see cref="IBeatmap"/> whose difficulty will be calculated.</param
|
/// <param name="beatmap">The <see cref="IBeatmap"/> whose difficulty will be calculated.</param>
|
||||||
/// <returns>The <see cref="Skill"/>s.</returns>
|
/// <returns>The <see cref="Skill"/>s.</returns>
|
||||||
protected abstract Skill[] CreateSkills(IBeatmap beatmap);
|
protected abstract Skill[] CreateSkills(IBeatmap beatmap);
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,7 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
Ruleset = ruleset;
|
Ruleset = ruleset;
|
||||||
Score = score;
|
Score = score;
|
||||||
|
|
||||||
beatmap.Mods.Value = score.Mods;
|
Beatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo, score.Mods);
|
||||||
Beatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo);
|
|
||||||
|
|
||||||
Attributes = ruleset.CreateDifficultyCalculator(beatmap).Calculate(score.Mods);
|
Attributes = ruleset.CreateDifficultyCalculator(beatmap).Calculate(score.Mods);
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ using osu.Framework.Timing;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Configuration;
|
using osu.Game.Rulesets.Configuration;
|
||||||
using osu.Game.Rulesets.Edit.Tools;
|
using osu.Game.Rulesets.Edit.Tools;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
@ -185,8 +186,8 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal override DrawableEditRuleset CreateDrawableRuleset()
|
internal override DrawableEditRuleset CreateDrawableRuleset()
|
||||||
=> new DrawableEditRuleset<TObject>(CreateDrawableRuleset(Ruleset, Beatmap.Value));
|
=> new DrawableEditRuleset<TObject>(CreateDrawableRuleset(Ruleset, Beatmap.Value, Array.Empty<Mod>()));
|
||||||
|
|
||||||
protected abstract DrawableRuleset<TObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap);
|
protected abstract DrawableRuleset<TObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Screens.Edit.Compose;
|
using osu.Game.Screens.Edit.Compose;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -108,7 +109,8 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invokes <see cref="HitObject.ApplyDefaults"/>, refreshing <see cref="HitObject.NestedHitObjects"/> and parameters for the <see cref="HitObject"/>.
|
/// Invokes <see cref="Objects.HitObject.ApplyDefaults(ControlPointInfo,BeatmapDifficulty)"/>,
|
||||||
|
/// refreshing <see cref="Objects.HitObject.NestedHitObjects"/> and parameters for the <see cref="HitObject"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected void ApplyDefaultsToHitObject() => HitObject.ApplyDefaults(beatmap.Value.Beatmap.ControlPointInfo, beatmap.Value.Beatmap.BeatmapInfo.BaseDifficulty);
|
protected void ApplyDefaultsToHitObject() => HitObject.ApplyDefaults(beatmap.Value.Beatmap.ControlPointInfo, beatmap.Value.Beatmap.BeatmapInfo.BaseDifficulty);
|
||||||
|
|
||||||
|
@ -68,9 +68,11 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
get => state;
|
get => state;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (state == value) return;
|
if (state == value)
|
||||||
|
return;
|
||||||
|
|
||||||
state = value;
|
state = value;
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case SelectionState.Selected:
|
case SelectionState.Selected:
|
||||||
@ -82,6 +84,8 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
Deselected?.Invoke(this);
|
Deselected?.Invoke(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StateChanged?.Invoke(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,11 @@ namespace osu.Game.Rulesets.Judgements
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int MaxNumericResult => NumericResultFor(MaxResult);
|
public int MaxNumericResult => NumericResultFor(MaxResult);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The health increase for the maximum achievable result.
|
||||||
|
/// </summary>
|
||||||
|
public double MaxHealthIncrease => HealthIncreaseFor(MaxResult);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the numeric score representation of a <see cref="HitResult"/>.
|
/// Retrieves the numeric score representation of a <see cref="HitResult"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -37,6 +37,11 @@ namespace osu.Game.Rulesets.Judgements
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int HighestComboAtJudgement { get; internal set; }
|
public int HighestComboAtJudgement { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The health prior to this <see cref="JudgementResult"/> occurring.
|
||||||
|
/// </summary>
|
||||||
|
public double HealthAtJudgement { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether a miss or hit occurred.
|
/// Whether a miss or hit occurred.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -2,14 +2,12 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mods
|
namespace osu.Game.Rulesets.Mods
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface for a <see cref="Mod"/> that applies changes to a <see cref="BeatmapConverter{TObject}"/>.
|
/// Interface for a <see cref="Mod"/> that applies changes to a <see cref="BeatmapConverter{TObject}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TObject">The type of converted <see cref="HitObject"/>.</typeparam>
|
|
||||||
public interface IApplicableToBeatmapConverter : IApplicableMod
|
public interface IApplicableToBeatmapConverter : IApplicableMod
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
public interface IApplicableToHitObject : IApplicableMod
|
public interface IApplicableToHitObject : IApplicableMod
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies this <see cref="IApplicableToHitObject{TObject}"/> to a <see cref="HitObject"/>.
|
/// Applies this <see cref="IApplicableToHitObject"/> to a <see cref="HitObject"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hitObject">The <see cref="HitObject"/> to apply to.</param>
|
/// <param name="hitObject">The <see cref="HitObject"/> to apply to.</param>
|
||||||
void ApplyToHitObject(HitObject hitObject);
|
void ApplyToHitObject(HitObject hitObject);
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.TypeExtensions;
|
using osu.Framework.Extensions.TypeExtensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Primitives;
|
using osu.Framework.Graphics.Primitives;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
@ -58,7 +59,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
public bool AllJudged => Judged && NestedHitObjects.All(h => h.AllJudged);
|
public bool AllJudged => Judged && NestedHitObjects.All(h => h.AllJudged);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this <see cref="DrawableHitObject"/> has been hit. This occurs if <see cref="Result.IsHit"/> is <see cref="true"/>.
|
/// Whether this <see cref="DrawableHitObject"/> has been hit. This occurs if <see cref="Result"/> is hit.
|
||||||
/// Note: This does NOT include nested hitobjects.
|
/// Note: This does NOT include nested hitobjects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsHit => Result?.IsHit ?? false;
|
public bool IsHit => Result?.IsHit ?? false;
|
||||||
@ -223,7 +224,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will called at least once after the <see cref="LifetimeEnd"/> of this <see cref="DrawableHitObject"/> has been passed.
|
/// Will called at least once after the <see cref="Drawable.LifetimeEnd"/> of this <see cref="DrawableHitObject"/> has been passed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void OnLifetimeEnd()
|
internal void OnLifetimeEnd()
|
||||||
{
|
{
|
||||||
|
@ -53,8 +53,6 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public bool Kiai { get; private set; }
|
public bool Kiai { get; private set; }
|
||||||
|
|
||||||
private float overallDifficulty = BeatmapDifficulty.DEFAULT_DIFFICULTY;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The hit windows for this <see cref="HitObject"/>.
|
/// The hit windows for this <see cref="HitObject"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -115,7 +113,7 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
/// Creates the <see cref="HitWindows"/> for this <see cref="HitObject"/>.
|
/// Creates the <see cref="HitWindows"/> for this <see cref="HitObject"/>.
|
||||||
/// This can be null to indicate that the <see cref="HitObject"/> has no <see cref="HitWindows"/>.
|
/// This can be null to indicate that the <see cref="HitObject"/> has no <see cref="HitWindows"/>.
|
||||||
/// <para>
|
/// <para>
|
||||||
/// This will only be invoked if <see cref="HitWindows"/> hasn't been set externally (e.g. from a <see cref="BeatmapConverter"/>.
|
/// This will only be invoked if <see cref="HitWindows"/> hasn't been set externally (e.g. from a <see cref="BeatmapConverter{T}"/>.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual HitWindows CreateHitWindows() => new HitWindows();
|
protected virtual HitWindows CreateHitWindows() => new HitWindows();
|
||||||
|
@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Given a time offset, whether the <see cref="HitObject"/> can ever be hit in the future with a non-<see cref="HitResult.Miss"/> result.
|
/// Given a time offset, whether the <see cref="HitObject"/> can ever be hit in the future with a non-<see cref="HitResult.Miss"/> result.
|
||||||
/// This happens if <paramref name="timeOffset"/> is less than what is required for a <see cref="SuccessfulHitWindow"/> result.
|
/// This happens if <paramref name="timeOffset"/> is less than what is required for <see cref="LowestSuccessfulHitResult"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="timeOffset">The time offset.</param>
|
/// <param name="timeOffset">The time offset.</param>
|
||||||
/// <returns>Whether the <see cref="HitObject"/> can be hit at any point in the future from this time offset.</returns>
|
/// <returns>Whether the <see cref="HitObject"/> can be hit at any point in the future from this time offset.</returns>
|
||||||
|
@ -277,12 +277,5 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
|
|
||||||
return ControlPoints.SequenceEqual(other.ControlPoints) && ExpectedDistance.Equals(other.ExpectedDistance) && Type == other.Type;
|
return ControlPoints.SequenceEqual(other.ControlPoints) && ExpectedDistance.Equals(other.ExpectedDistance) && Type == other.Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(null, obj)) return false;
|
|
||||||
|
|
||||||
return obj is SliderPath other && Equals(other);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,9 +53,10 @@ namespace osu.Game.Rulesets
|
|||||||
/// Attempt to create a hit renderer for a beatmap
|
/// Attempt to create a hit renderer for a beatmap
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="beatmap">The beatmap to create the hit renderer for.</param>
|
/// <param name="beatmap">The beatmap to create the hit renderer for.</param>
|
||||||
|
/// <param name="mods">The <see cref="Mod"/>s to apply.</param>
|
||||||
/// <exception cref="BeatmapInvalidForRulesetException">Unable to successfully load the beatmap to be usable with this ruleset.</exception>
|
/// <exception cref="BeatmapInvalidForRulesetException">Unable to successfully load the beatmap to be usable with this ruleset.</exception>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public abstract DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap);
|
public abstract DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList<Mod> mods);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a <see cref="IBeatmapConverter"/> to convert a <see cref="IBeatmap"/> to one that is applicable for this <see cref="Ruleset"/>.
|
/// Creates a <see cref="IBeatmapConverter"/> to convert a <see cref="IBeatmap"/> to one that is applicable for this <see cref="Ruleset"/>.
|
||||||
|
@ -154,7 +154,6 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Notifies subscribers of <see cref="NewJudgement"/> that a new judgement has occurred.
|
/// Notifies subscribers of <see cref="NewJudgement"/> that a new judgement has occurred.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="judgement">The judgement to notify subscribers of.</param>
|
|
||||||
/// <param name="result">The judgement scoring result to notify subscribers of.</param>
|
/// <param name="result">The judgement scoring result to notify subscribers of.</param>
|
||||||
protected void NotifyNewJudgement(JudgementResult result)
|
protected void NotifyNewJudgement(JudgementResult result)
|
||||||
{
|
{
|
||||||
@ -283,7 +282,6 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reverts the score change of a <see cref="JudgementResult"/> that was applied to this <see cref="ScoreProcessor"/>.
|
/// Reverts the score change of a <see cref="JudgementResult"/> that was applied to this <see cref="ScoreProcessor"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="judgement">The judgement to remove.</param>
|
|
||||||
/// <param name="result">The judgement scoring result.</param>
|
/// <param name="result">The judgement scoring result.</param>
|
||||||
private void revertResult(JudgementResult result)
|
private void revertResult(JudgementResult result)
|
||||||
{
|
{
|
||||||
@ -301,6 +299,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
{
|
{
|
||||||
result.ComboAtJudgement = Combo.Value;
|
result.ComboAtJudgement = Combo.Value;
|
||||||
result.HighestComboAtJudgement = HighestCombo.Value;
|
result.HighestComboAtJudgement = HighestCombo.Value;
|
||||||
|
result.HealthAtJudgement = Health.Value;
|
||||||
|
|
||||||
JudgedHits++;
|
JudgedHits++;
|
||||||
|
|
||||||
@ -332,17 +331,19 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
baseScore += result.Judgement.NumericResultFor(result);
|
baseScore += result.Judgement.NumericResultFor(result);
|
||||||
rollingMaxBaseScore += result.Judgement.MaxNumericResult;
|
rollingMaxBaseScore += result.Judgement.MaxNumericResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Health.Value += HealthAdjustmentFactorFor(result) * result.Judgement.HealthIncreaseFor(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reverts the score change of a <see cref="JudgementResult"/> that was applied to this <see cref="ScoreProcessor"/>.
|
/// Reverts the score change of a <see cref="JudgementResult"/> that was applied to this <see cref="ScoreProcessor"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="judgement">The judgement to remove.</param>
|
|
||||||
/// <param name="result">The judgement scoring result.</param>
|
/// <param name="result">The judgement scoring result.</param>
|
||||||
protected virtual void RevertResult(JudgementResult result)
|
protected virtual void RevertResult(JudgementResult result)
|
||||||
{
|
{
|
||||||
Combo.Value = result.ComboAtJudgement;
|
Combo.Value = result.ComboAtJudgement;
|
||||||
HighestCombo.Value = result.HighestComboAtJudgement;
|
HighestCombo.Value = result.HighestComboAtJudgement;
|
||||||
|
Health.Value = result.HealthAtJudgement;
|
||||||
|
|
||||||
JudgedHits--;
|
JudgedHits--;
|
||||||
|
|
||||||
@ -358,6 +359,13 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An adjustment factor which is multiplied into the health increase provided by a <see cref="JudgementResult"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="result">The <see cref="JudgementResult"/> for which the adjustment should apply.</param>
|
||||||
|
/// <returns>The adjustment factor.</returns>
|
||||||
|
protected virtual double HealthAdjustmentFactorFor(JudgementResult result) => 1;
|
||||||
|
|
||||||
private void updateScore()
|
private void updateScore()
|
||||||
{
|
{
|
||||||
if (rollingMaxBaseScore != 0)
|
if (rollingMaxBaseScore != 0)
|
||||||
|
@ -11,7 +11,6 @@ using osu.Game.Rulesets.Objects;
|
|||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
@ -82,7 +81,8 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The mods which are to be applied.
|
/// The mods which are to be applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IEnumerable<Mod> mods;
|
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||||
|
private readonly IReadOnlyList<Mod> mods;
|
||||||
|
|
||||||
private FrameStabilityContainer frameStabilityContainer;
|
private FrameStabilityContainer frameStabilityContainer;
|
||||||
|
|
||||||
@ -93,16 +93,19 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ruleset">The ruleset being represented.</param>
|
/// <param name="ruleset">The ruleset being represented.</param>
|
||||||
/// <param name="workingBeatmap">The beatmap to create the hit renderer for.</param>
|
/// <param name="workingBeatmap">The beatmap to create the hit renderer for.</param>
|
||||||
protected DrawableRuleset(Ruleset ruleset, WorkingBeatmap workingBeatmap)
|
/// <param name="mods">The <see cref="Mod"/>s to apply.</param>
|
||||||
|
protected DrawableRuleset(Ruleset ruleset, WorkingBeatmap workingBeatmap, IReadOnlyList<Mod> mods)
|
||||||
: base(ruleset)
|
: base(ruleset)
|
||||||
{
|
{
|
||||||
Debug.Assert(workingBeatmap != null, "DrawableRuleset initialized with a null beatmap.");
|
if (workingBeatmap == null)
|
||||||
|
throw new ArgumentException("Beatmap cannot be null.", nameof(workingBeatmap));
|
||||||
|
|
||||||
|
this.mods = mods.ToArray();
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
Beatmap = (Beatmap<TObject>)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo);
|
Beatmap = (Beatmap<TObject>)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods);
|
||||||
|
|
||||||
mods = workingBeatmap.Mods.Value;
|
|
||||||
applyBeatmapMods(mods);
|
applyBeatmapMods(mods);
|
||||||
|
|
||||||
KeyBindingInputManager = CreateInputManager();
|
KeyBindingInputManager = CreateInputManager();
|
||||||
@ -223,6 +226,12 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
if (replayInputManager.ReplayInputHandler != null)
|
if (replayInputManager.ReplayInputHandler != null)
|
||||||
replayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace;
|
replayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace;
|
||||||
|
|
||||||
|
if (!ProvidingUserCursor)
|
||||||
|
{
|
||||||
|
// The cursor is hidden by default (see Playfield.load()), but should be shown when there's a replay
|
||||||
|
Playfield.Cursor?.Show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -255,7 +264,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// Applies the active mods to the Beatmap.
|
/// Applies the active mods to the Beatmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mods"></param>
|
/// <param name="mods"></param>
|
||||||
private void applyBeatmapMods(IEnumerable<Mod> mods)
|
private void applyBeatmapMods(IReadOnlyList<Mod> mods)
|
||||||
{
|
{
|
||||||
if (mods == null)
|
if (mods == null)
|
||||||
return;
|
return;
|
||||||
@ -267,8 +276,9 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies the active mods to this DrawableRuleset.
|
/// Applies the active mods to this DrawableRuleset.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mods"></param>
|
/// <param name="mods">The <see cref="Mod"/>s to apply.</param>
|
||||||
private void applyRulesetMods(IEnumerable<Mod> mods, OsuConfigManager config)
|
/// <param name="config">The <see cref="OsuConfigManager"/> to apply.</param>
|
||||||
|
private void applyRulesetMods(IReadOnlyList<Mod> mods, OsuConfigManager config)
|
||||||
{
|
{
|
||||||
if (mods == null)
|
if (mods == null)
|
||||||
return;
|
return;
|
||||||
|
@ -68,6 +68,8 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
private const double sixty_frame_time = 1000.0 / 60;
|
private const double sixty_frame_time = 1000.0 / 60;
|
||||||
|
|
||||||
|
private bool firstConsumption = true;
|
||||||
|
|
||||||
public override bool UpdateSubTree()
|
public override bool UpdateSubTree()
|
||||||
{
|
{
|
||||||
requireMoreUpdateLoops = true;
|
requireMoreUpdateLoops = true;
|
||||||
@ -103,9 +105,20 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f)
|
if (firstConsumption)
|
||||||
{
|
{
|
||||||
newProposedTime = manualClock.Rate > 0
|
// On the first update, frame-stability seeking would result in unexpected/unwanted behaviour.
|
||||||
|
// Instead we perform an initial seek to the proposed time.
|
||||||
|
manualClock.CurrentTime = newProposedTime;
|
||||||
|
|
||||||
|
// do a second process to clear out ElapsedTime
|
||||||
|
framedClock.ProcessFrame();
|
||||||
|
|
||||||
|
firstConsumption = false;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f)
|
||||||
|
{
|
||||||
|
newProposedTime = newProposedTime > manualClock.CurrentTime
|
||||||
? Math.Min(newProposedTime, manualClock.CurrentTime + sixty_frame_time)
|
? Math.Min(newProposedTime, manualClock.CurrentTime + sixty_frame_time)
|
||||||
: Math.Max(newProposedTime, manualClock.CurrentTime - sixty_frame_time);
|
: Math.Max(newProposedTime, manualClock.CurrentTime - sixty_frame_time);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
public class GameplayCursorContainer : CursorContainer
|
public class GameplayCursorContainer : CursorContainer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Because Show/Hide are executed by a parent, <see cref="State"/> is updated immediately even if the cursor
|
/// Because Show/Hide are executed by a parent, <see cref="VisibilityContainer.State"/> is updated immediately even if the cursor
|
||||||
/// is in a non-updating state (via <see cref="FrameStabilityContainer"/> limitations).
|
/// is in a non-updating state (via <see cref="FrameStabilityContainer"/> limitations).
|
||||||
///
|
///
|
||||||
/// This holds the true visibility value.
|
/// This holds the true visibility value.
|
||||||
|
@ -57,17 +57,24 @@ namespace osu.Game.Rulesets.UI
|
|||||||
hitObjectContainerLazy = new Lazy<HitObjectContainer>(CreateHitObjectContainer);
|
hitObjectContainerLazy = new Lazy<HitObjectContainer>(CreateHitObjectContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorkingBeatmap beatmap;
|
[Resolved]
|
||||||
|
private IBindable<WorkingBeatmap> beatmap { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IReadOnlyList<Mod> mods { get; set; }
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IBindable<WorkingBeatmap> beatmap)
|
private void load()
|
||||||
{
|
{
|
||||||
this.beatmap = beatmap.Value;
|
|
||||||
|
|
||||||
Cursor = CreateCursor();
|
Cursor = CreateCursor();
|
||||||
if (Cursor != null)
|
if (Cursor != null)
|
||||||
|
{
|
||||||
|
// initial showing of the cursor will be handed by MenuCursorContainer (via DrawableRuleset's IProvideCursor implementation).
|
||||||
|
Cursor.Hide();
|
||||||
|
|
||||||
AddInternal(Cursor);
|
AddInternal(Cursor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs post-processing tasks (if any) after all DrawableHitObjects are loaded into this Playfield.
|
/// Performs post-processing tasks (if any) after all DrawableHitObjects are loaded into this Playfield.
|
||||||
@ -93,7 +100,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provide an optional cursor which is to be used for gameplay.
|
/// Provide an optional cursor which is to be used for gameplay.
|
||||||
/// If providing a cursor, <see cref="CursorTargetContainer"/> must also point to a valid target container.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The cursor, or null if a cursor is not rqeuired.</returns>
|
/// <returns>The cursor, or null if a cursor is not rqeuired.</returns>
|
||||||
protected virtual GameplayCursorContainer CreateCursor() => null;
|
protected virtual GameplayCursorContainer CreateCursor() => null;
|
||||||
@ -123,7 +129,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
if (beatmap != null)
|
if (beatmap != null)
|
||||||
foreach (var mod in beatmap.Mods.Value)
|
foreach (var mod in mods)
|
||||||
if (mod is IUpdatableByPlayfield updatable)
|
if (mod is IUpdatableByPlayfield updatable)
|
||||||
updatable.Update(this);
|
updatable.Update(this);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
|
|||||||
/// <param name="currentTime">The current time.</param>
|
/// <param name="currentTime">The current time.</param>
|
||||||
/// <param name="timeRange">The amount of visible time.</param>
|
/// <param name="timeRange">The amount of visible time.</param>
|
||||||
/// <param name="scrollLength">The absolute spatial length through <see cref="timeRange"/>.</param>
|
/// <param name="scrollLength">The absolute spatial length through <see cref="timeRange"/>.</param>
|
||||||
/// <returns>The time at which <see cref="PositionAt(t)"/> == <paramref name="position"/>.</returns>
|
/// <returns>The time at which <see cref="PositionAt(double,double,double,float)"/> == <paramref name="position"/>.</returns>
|
||||||
double TimeAt(float position, double currentTime, double timeRange, float scrollLength);
|
double TimeAt(float position, double currentTime, double timeRange, float scrollLength);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -13,6 +13,7 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Timing;
|
using osu.Game.Rulesets.Timing;
|
||||||
@ -64,7 +65,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
protected virtual ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Sequential;
|
protected virtual ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Sequential;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the player can change <see cref="VisibleTimeRange"/>.
|
/// Whether the player can change <see cref="TimeRange"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual bool UserScrollSpeedAdjustment => true;
|
protected virtual bool UserScrollSpeedAdjustment => true;
|
||||||
|
|
||||||
@ -80,8 +81,8 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
[Cached(Type = typeof(IScrollingInfo))]
|
[Cached(Type = typeof(IScrollingInfo))]
|
||||||
private readonly LocalScrollingInfo scrollingInfo;
|
private readonly LocalScrollingInfo scrollingInfo;
|
||||||
|
|
||||||
protected DrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap)
|
protected DrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
scrollingInfo = new LocalScrollingInfo();
|
scrollingInfo = new LocalScrollingInfo();
|
||||||
scrollingInfo.Direction.BindTo(Direction);
|
scrollingInfo.Direction.BindTo(Direction);
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Screens
|
|||||||
|
|
||||||
//public float ParallaxAmount { set => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * value; }
|
//public float ParallaxAmount { set => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * value; }
|
||||||
|
|
||||||
public new void Push(BackgroundScreen screen)
|
public void Push(BackgroundScreen screen)
|
||||||
{
|
{
|
||||||
if (screen == null)
|
if (screen == null)
|
||||||
return;
|
return;
|
||||||
|
@ -121,6 +121,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
/// Handle a blueprint requesting selection.
|
/// Handle a blueprint requesting selection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="blueprint">The blueprint.</param>
|
/// <param name="blueprint">The blueprint.</param>
|
||||||
|
/// <param name="state">The input state at the point of selection.</param>
|
||||||
internal void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state)
|
internal void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state)
|
||||||
{
|
{
|
||||||
if (state.Keyboard.ControlPressed)
|
if (state.Keyboard.ControlPressed)
|
||||||
@ -166,8 +167,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
|
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
|
||||||
var bottomRight = new Vector2(float.MinValue, float.MinValue);
|
var bottomRight = new Vector2(float.MinValue, float.MinValue);
|
||||||
|
|
||||||
bool hasSelection = false;
|
|
||||||
|
|
||||||
foreach (var blueprint in selectedBlueprints)
|
foreach (var blueprint in selectedBlueprints)
|
||||||
{
|
{
|
||||||
topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(blueprint.SelectionQuad.TopLeft));
|
topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(blueprint.SelectionQuad.TopLeft));
|
||||||
|
@ -92,13 +92,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
zoomedContent.Width = DrawWidth * currentZoom;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnScroll(ScrollEvent e)
|
protected override bool OnScroll(ScrollEvent e)
|
||||||
{
|
{
|
||||||
if (e.IsPrecise)
|
if (e.IsPrecise)
|
||||||
@ -138,7 +131,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
private readonly float scrollOffset;
|
private readonly float scrollOffset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transforms <see cref="TimeTimelinem"/> to a new value.
|
/// Transforms <see cref="ZoomableScrollContainer.currentZoom"/> to a new value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="focusPoint">The focus point in absolute coordinates local to the content.</param>
|
/// <param name="focusPoint">The focus point in absolute coordinates local to the content.</param>
|
||||||
/// <param name="contentSize">The size of the content.</param>
|
/// <param name="contentSize">The size of the content.</param>
|
||||||
@ -169,6 +162,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
float targetOffset = expectedWidth * (focusPoint / contentSize) - focusOffset;
|
float targetOffset = expectedWidth * (focusPoint / contentSize) - focusOffset;
|
||||||
|
|
||||||
d.currentZoom = newZoom;
|
d.currentZoom = newZoom;
|
||||||
|
|
||||||
|
d.zoomedContent.Width = d.DrawWidth * d.currentZoom;
|
||||||
|
// Temporarily here to make sure ScrollTo gets the correct DrawSize for scrollable area.
|
||||||
|
// TODO: Make sure draw size gets invalidated properly on the framework side, and remove this once it is.
|
||||||
|
d.Invalidate(Invalidation.DrawSize);
|
||||||
d.ScrollTo(targetOffset, false);
|
d.ScrollTo(targetOffset, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,9 +65,6 @@ namespace osu.Game.Screens.Edit
|
|||||||
dependencies.Cache(beatDivisor);
|
dependencies.Cache(beatDivisor);
|
||||||
|
|
||||||
EditorMenuBar menuBar;
|
EditorMenuBar menuBar;
|
||||||
TimeInfoContainer timeInfo;
|
|
||||||
SummaryTimeline timeline;
|
|
||||||
PlaybackControl playback;
|
|
||||||
|
|
||||||
var fileMenuItems = new List<MenuItem>();
|
var fileMenuItems = new List<MenuItem>();
|
||||||
if (RuntimeInfo.IsDesktop)
|
if (RuntimeInfo.IsDesktop)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user