1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 17:32:54 +08:00

Merge branch 'master' into editor-fix-beat-snapping-new-beatmap

This commit is contained in:
Dean Herbert 2020-12-02 14:37:00 +09:00
commit d6e0dc2216
40 changed files with 287 additions and 155 deletions

View File

@ -5,6 +5,6 @@
"version": "3.1.100"
},
"msbuild-sdks": {
"Microsoft.Build.Traversal": "2.2.3"
"Microsoft.Build.Traversal": "3.0.2"
}
}

View File

@ -52,6 +52,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.1030.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.1127.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.1201.0" />
</ItemGroup>
</Project>

View File

@ -59,7 +59,7 @@ namespace osu.Desktop
try
{
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString()?.Split('"')[1].Replace("osu!.exe", "");
stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
if (checkExists(stableInstallPath))
return stableInstallPath;
@ -138,7 +138,7 @@ namespace osu.Desktop
break;
// SDL2 DesktopWindow
case DesktopWindow desktopWindow:
case SDL2DesktopWindow desktopWindow:
desktopWindow.CursorState |= CursorState.Hidden;
desktopWindow.SetIconFromStream(iconStream);
desktopWindow.Title = Name;

View File

@ -22,9 +22,9 @@ namespace osu.Desktop
{
// Back up the cwd before DesktopGameHost changes it
var cwd = Environment.CurrentDirectory;
bool useSdl = args.Contains("--sdl");
bool useOsuTK = args.Contains("--tk");
using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true, useSdl: useSdl))
using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true, useOsuTK: useOsuTK))
{
host.ExceptionThrown += handleException;

View File

@ -24,12 +24,12 @@
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="System.IO.Packaging" Version="4.7.0" />
<PackageReference Include="System.IO.Packaging" Version="5.0.0" />
<PackageReference Include="ppy.squirrel.windows" Version="1.9.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6" />
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
<PackageReference Include="DiscordRichPresence" Version="1.0.150" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="DiscordRichPresence" Version="1.0.166" />
<!-- .NET 3.1 SDK seems to cause issues with a runtime specification. This will likely be resolved in .NET 5. -->
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
<PackageReference Include="System.Runtime.Handles" Version="4.3.0" />

View File

@ -0,0 +1,14 @@
// 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.Game.Tests.Visual;
namespace osu.Game.Rulesets.Catch.Tests
{
[TestFixture]
public class TestSceneCatchPlayerLegacySkin : LegacySkinPlayerTestScene
{
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
}
}

View File

@ -10,14 +10,12 @@ using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Configuration;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Judgements;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawables;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Catch.Tests
{
@ -103,7 +101,6 @@ namespace osu.Game.Rulesets.Catch.Tests
{
Anchor = Anchor.Centre,
Origin = Anchor.TopCentre,
CreateDrawableRepresentation = ((DrawableRuleset<CatchHitObject>)catchRuleset.CreateInstance().CreateDrawableRulesetWith(new CatchBeatmap())).CreateDrawableRepresentation
},
});
}

View File

@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Catch.Tests
if (juice.NestedHitObjects.Last() is CatchHitObject tail)
tail.LastInCombo = true; // usually the (Catch)BeatmapProcessor would do this for us when necessary
addToPlayfield(new DrawableJuiceStream(juice, drawableRuleset.CreateDrawableRepresentation));
addToPlayfield(new DrawableJuiceStream(juice));
}
private void spawnBananas(bool hit = false)

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />

View File

@ -1,6 +1,7 @@
// 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 JetBrains.Annotations;
using osu.Framework.Graphics;
using osu.Framework.Utils;
@ -10,7 +11,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
{
protected override FruitVisualRepresentation GetVisualRepresentation(int indexInBeatmap) => FruitVisualRepresentation.Banana;
public DrawableBanana(Banana h)
public DrawableBanana()
: this(null)
{
}
public DrawableBanana([CanBeNull] Banana h)
: base(h)
{
}

View File

@ -1,26 +1,27 @@
// 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 JetBrains.Annotations;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Catch.Objects.Drawables
{
public class DrawableBananaShower : DrawableCatchHitObject
{
private readonly Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation;
private readonly Container bananaContainer;
public DrawableBananaShower(BananaShower s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation = null)
public DrawableBananaShower()
: this(null)
{
}
public DrawableBananaShower([CanBeNull] BananaShower s)
: base(s)
{
this.createDrawableRepresentation = createDrawableRepresentation;
RelativeSizeAxes = Axes.X;
Origin = Anchor.BottomLeft;
X = 0;
AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both });
}
@ -34,18 +35,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
protected override void ClearNestedHitObjects()
{
base.ClearNestedHitObjects();
bananaContainer.Clear();
}
protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject)
{
switch (hitObject)
{
case Banana banana:
return createDrawableRepresentation?.Invoke(banana);
}
return base.CreateNestedHitObject(hitObject);
bananaContainer.Clear(false);
}
}
}

View File

@ -1,6 +1,7 @@
// 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 JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Utils;
@ -13,7 +14,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
{
public override bool StaysOnPlate => false;
public DrawableDroplet(CatchHitObject h)
public DrawableDroplet()
: this(null)
{
}
public DrawableDroplet([CanBeNull] CatchHitObject h)
: base(h)
{
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Utils;
@ -16,7 +17,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
protected virtual FruitVisualRepresentation GetVisualRepresentation(int indexInBeatmap) => (FruitVisualRepresentation)(indexInBeatmap % 4);
public DrawableFruit(CatchHitObject h)
public DrawableFruit()
: this(null)
{
}
public DrawableFruit([CanBeNull] Fruit h)
: base(h)
{
}

View File

@ -1,37 +1,33 @@
// 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 JetBrains.Annotations;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osuTK;
namespace osu.Game.Rulesets.Catch.Objects.Drawables
{
public class DrawableJuiceStream : DrawableCatchHitObject
{
private readonly Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation;
private readonly Container dropletContainer;
public override Vector2 OriginPosition => base.OriginPosition - new Vector2(0, CatchHitObject.OBJECT_RADIUS);
public DrawableJuiceStream()
: this(null)
{
}
public DrawableJuiceStream(JuiceStream s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation = null)
public DrawableJuiceStream([CanBeNull] JuiceStream s)
: base(s)
{
this.createDrawableRepresentation = createDrawableRepresentation;
RelativeSizeAxes = Axes.X;
Origin = Anchor.BottomLeft;
X = 0;
AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, });
}
protected override void AddNestedHitObject(DrawableHitObject hitObject)
{
hitObject.Origin = Anchor.BottomCentre;
base.AddNestedHitObject(hitObject);
dropletContainer.Add(hitObject);
}
@ -39,18 +35,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
protected override void ClearNestedHitObjects()
{
base.ClearNestedHitObjects();
dropletContainer.Clear();
}
protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject)
{
switch (hitObject)
{
case CatchHitObject catchObject:
return createDrawableRepresentation?.Invoke(catchObject);
}
throw new ArgumentException($"{nameof(hitObject)} must be of type {nameof(CatchHitObject)}.");
dropletContainer.Clear(false);
}
}
}

View File

@ -1,13 +1,20 @@
// 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 JetBrains.Annotations;
namespace osu.Game.Rulesets.Catch.Objects.Drawables
{
public class DrawableTinyDroplet : DrawableDroplet
{
protected override float ScaleFactor => base.ScaleFactor / 2;
public DrawableTinyDroplet(TinyDroplet h)
public DrawableTinyDroplet()
: this(null)
{
}
public DrawableTinyDroplet([CanBeNull] TinyDroplet h)
: base(h)
{
}

View File

@ -19,7 +19,8 @@ namespace osu.Game.Rulesets.Catch.Skinning
{
private readonly string lookupName;
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
private readonly Bindable<Color4> accentColour = new Bindable<Color4>();
private readonly Bindable<bool> hyperDash = new Bindable<bool>();
private Sprite colouredSprite;
public LegacyFruitPiece(string lookupName)
@ -34,6 +35,7 @@ namespace osu.Game.Rulesets.Catch.Skinning
var drawableCatchObject = (DrawablePalpableCatchHitObject)drawableObject;
accentColour.BindTo(drawableCatchObject.AccentColour);
hyperDash.BindTo(drawableCatchObject.HyperDash);
InternalChildren = new Drawable[]
{
@ -51,9 +53,9 @@ namespace osu.Game.Rulesets.Catch.Skinning
},
};
if (drawableCatchObject.HitObject.HyperDash)
if (hyperDash.Value)
{
var hyperDash = new Sprite
var hyperDashOverlay = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@ -67,7 +69,7 @@ namespace osu.Game.Rulesets.Catch.Skinning
Catcher.DEFAULT_HYPER_DASH_COLOUR,
};
AddInternal(hyperDash);
AddInternal(hyperDashOverlay);
}
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
@ -42,7 +43,6 @@ namespace osu.Game.Rulesets.Catch.UI
CatcherArea = new CatcherArea(difficulty)
{
CreateDrawableRepresentation = createDrawableRepresentation,
ExplodingFruitTarget = explodingFruitContainer,
Anchor = Anchor.BottomLeft,
Origin = Anchor.TopLeft,
@ -57,6 +57,17 @@ namespace osu.Game.Rulesets.Catch.UI
};
}
[BackgroundDependencyLoader]
private void load()
{
RegisterPool<Droplet, DrawableDroplet>(50);
RegisterPool<TinyDroplet, DrawableTinyDroplet>(50);
RegisterPool<Fruit, DrawableFruit>(100);
RegisterPool<Banana, DrawableBanana>(100);
RegisterPool<JuiceStream, DrawableJuiceStream>(10);
RegisterPool<BananaShower, DrawableBananaShower>(2);
}
protected override void LoadComplete()
{
base.LoadComplete();

View File

@ -10,7 +10,6 @@ using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawables;
using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osuTK;
@ -21,8 +20,6 @@ namespace osu.Game.Rulesets.Catch.UI
{
public const float CATCHER_SIZE = 106.75f;
public Func<CatchHitObject, DrawableHitObject<CatchHitObject>> CreateDrawableRepresentation;
public readonly Catcher MovableCatcher;
private readonly CatchComboDisplay comboDisplay;
@ -72,7 +69,7 @@ namespace osu.Game.Rulesets.Catch.UI
if (result.IsHit && hitObject is DrawablePalpableCatchHitObject fruit)
{
// create a new (cloned) fruit to stay on the plate. the original is faded out immediately.
var caughtFruit = (DrawableCatchHitObject)CreateDrawableRepresentation?.Invoke(fruit.HitObject);
var caughtFruit = createCaughtFruit(fruit);
if (caughtFruit == null) return;
@ -127,5 +124,26 @@ namespace osu.Game.Rulesets.Catch.UI
comboDisplay.X = MovableCatcher.X;
}
private DrawableCatchHitObject createCaughtFruit(DrawablePalpableCatchHitObject hitObject)
{
switch (hitObject.HitObject)
{
case Banana banana:
return new DrawableBanana(banana);
case Fruit fruit:
return new DrawableFruit(fruit);
case TinyDroplet tiny:
return new DrawableTinyDroplet(tiny);
case Droplet droplet:
return new DrawableDroplet(droplet);
default:
return null;
}
}
}
}

View File

@ -8,7 +8,6 @@ using osu.Game.Configuration;
using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawables;
using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects.Drawables;
@ -40,30 +39,6 @@ namespace osu.Game.Rulesets.Catch.UI
protected override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo);
public override DrawableHitObject<CatchHitObject> CreateDrawableRepresentation(CatchHitObject h)
{
switch (h)
{
case Banana banana:
return new DrawableBanana(banana);
case Fruit fruit:
return new DrawableFruit(fruit);
case JuiceStream stream:
return new DrawableJuiceStream(stream, CreateDrawableRepresentation);
case BananaShower shower:
return new DrawableBananaShower(shower, CreateDrawableRepresentation);
case TinyDroplet tiny:
return new DrawableTinyDroplet(tiny);
case Droplet droplet:
return new DrawableDroplet(droplet);
}
return null;
}
public override DrawableHitObject<CatchHitObject> CreateDrawableRepresentation(CatchHitObject h) => null;
}
}

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />

View File

@ -5,7 +5,7 @@ using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests.Mods
{
public class OsuModTestScene : ModTestScene
public abstract class OsuModTestScene : ModTestScene
{
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
}

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />

View File

@ -44,6 +44,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
private OsuColour colours { get; set; }
private IBindable<Vector2> sliderPosition;
private IBindable<float> sliderScale;
private IBindable<Vector2> controlPointPosition;
public PathControlPointPiece(Slider slider, PathControlPoint controlPoint)
@ -69,13 +70,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(10),
Size = new Vector2(20),
},
markerRing = new CircularContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(14),
Size = new Vector2(28),
Masking = true,
BorderThickness = 2,
BorderColour = Color4.White,
@ -102,6 +103,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
controlPointPosition = ControlPoint.Position.GetBoundCopy();
controlPointPosition.BindValueChanged(_ => updateMarkerDisplay());
sliderScale = slider.ScaleBindable.GetBoundCopy();
sliderScale.BindValueChanged(_ => updateMarkerDisplay());
IsSelected.BindValueChanged(_ => updateMarkerDisplay());
updateMarkerDisplay();
@ -143,6 +147,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
protected override bool OnClick(ClickEvent e) => RequestSelection != null;
private Vector2 dragStartPosition;
protected override bool OnDragStart(DragStartEvent e)
{
if (RequestSelection == null)
@ -150,6 +156,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
if (e.Button == MouseButton.Left)
{
dragStartPosition = ControlPoint.Position.Value;
changeHandler?.BeginChange();
return true;
}
@ -174,7 +181,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
slider.Path.ControlPoints[i].Position.Value -= movementDelta;
}
else
ControlPoint.Position.Value += e.Delta;
ControlPoint.Position.Value = dragStartPosition + (e.MousePosition - e.MouseDownPosition);
}
protected override void OnDragEnd(DragEndEvent e) => changeHandler?.EndChange();
@ -194,6 +201,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
colour = colour.Lighten(1);
marker.Colour = colour;
marker.Scale = new Vector2(slider.Scale);
}
}
}

View File

@ -255,7 +255,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (userTriggered || Time.Current < HitObject.EndTime)
return;
ApplyResult(r => r.Type = r.Judgement.MaxResult);
ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult);
}
public override void PlaySamples()
@ -294,14 +294,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
case ArmedState.Hit:
Ball.ScaleTo(HitObject.Scale * 1.4f, fade_out_time, Easing.Out);
if (sliderBody?.SnakingOut.Value == true)
Body.FadeOut(40); // short fade to allow for any body colour to smoothly disappear.
break;
}
this.FadeOut(fade_out_time, Easing.OutQuint).Expire();
}
public Drawable ProxiedLayer => HeadCircle.ProxiedLayer;
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => sliderBody?.ReceivePositionalInputAt(screenSpacePos) ?? base.ReceivePositionalInputAt(screenSpacePos);
private class DefaultSliderBody : PlaySliderBody

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />

View File

@ -643,6 +643,55 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("Selected beatmap correct", () => songSelect.Carousel.SelectedBeatmap == filteredBeatmap);
}
[Test]
public void TestChangingRulesetOnMultiRulesetBeatmap()
{
int changeCount = 0;
AddStep("change convert setting", () => config.Set(OsuSetting.ShowConvertedBeatmaps, false));
AddStep("bind beatmap changed", () =>
{
Beatmap.ValueChanged += onChange;
changeCount = 0;
});
changeRuleset(0);
createSongSelect();
AddStep("import multi-ruleset map", () =>
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
manager.Import(createTestBeatmapSet(usableRulesets)).Wait();
});
int previousSetID = 0;
AddUntilStep("wait for selection", () => !Beatmap.IsDefault);
AddStep("record set ID", () => previousSetID = Beatmap.Value.BeatmapSetInfo.ID);
AddAssert("selection changed once", () => changeCount == 1);
AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0);
changeRuleset(3);
AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
AddUntilStep("selection changed", () => changeCount > 1);
AddAssert("Selected beatmap still same set", () => Beatmap.Value.BeatmapSetInfo.ID == previousSetID);
AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.ID == 3);
AddAssert("selection changed only fired twice", () => changeCount == 2);
AddStep("unbind beatmap changed", () => Beatmap.ValueChanged -= onChange);
AddStep("change convert setting", () => config.Set(OsuSetting.ShowConvertedBeatmaps, true));
// ReSharper disable once AccessToModifiedClosure
void onChange(ValueChangedEvent<WorkingBeatmap> valueChangedEvent) => changeCount++;
}
[Test]
public void TestDifficultyIconSelectingForDifferentRuleset()
{

View File

@ -3,7 +3,7 @@
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="DeepEqual" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />

View File

@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
</ItemGroup>

View File

@ -243,7 +243,7 @@ namespace osu.Game.Tournament.IPC
string stableInstallPath;
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", "");
stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
if (ipcFileExistsInDirectory(stableInstallPath))
return stableInstallPath;

View File

@ -9,6 +9,6 @@
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
</ItemGroup>
</Project>

View File

@ -184,7 +184,7 @@ namespace osu.Game.Configuration
return new TrackedSettings
{
new TrackedSetting<bool>(OsuSetting.MouseDisableButtons, v => new SettingDescription(!v, "gameplay mouse buttons", v ? "disabled" : "enabled", LookupKeyBindings(GlobalAction.ToggleGameplayMouseButtons))),
new TrackedSetting<HUDVisibilityMode>(OsuSetting.HUDVisibilityMode, m => new SettingDescription(m, "HUD Visibility", m.GetDescription(), $"cycle: shift-tab quick view: {LookupKeyBindings(GlobalAction.HoldForHUD)}")),
new TrackedSetting<HUDVisibilityMode>(OsuSetting.HUDVisibilityMode, m => new SettingDescription(m, "HUD Visibility", m.GetDescription(), $"cycle: {LookupKeyBindings(GlobalAction.ToggleInGameInterface)} quick view: {LookupKeyBindings(GlobalAction.HoldForHUD)}")),
new TrackedSetting<ScalingMode>(OsuSetting.Scaling, m => new SettingDescription(m, "scaling", m.GetDescription())),
new TrackedSetting<int>(OsuSetting.Skin, m =>
{

View File

@ -68,6 +68,7 @@ namespace osu.Game.Input.Bindings
new KeyBinding(new[] { InputKey.Control, InputKey.Tilde }, GlobalAction.QuickExit),
new KeyBinding(new[] { InputKey.Control, InputKey.Plus }, GlobalAction.IncreaseScrollSpeed),
new KeyBinding(new[] { InputKey.Control, InputKey.Minus }, GlobalAction.DecreaseScrollSpeed),
new KeyBinding(new[] { InputKey.Shift, InputKey.Tab }, GlobalAction.ToggleInGameInterface),
new KeyBinding(InputKey.MouseMiddle, GlobalAction.PauseGameplay),
new KeyBinding(InputKey.Space, GlobalAction.TogglePauseReplay),
new KeyBinding(InputKey.Control, GlobalAction.HoldForHUD),
@ -200,5 +201,8 @@ namespace osu.Game.Input.Bindings
[Description("Pause / resume replay")]
TogglePauseReplay,
[Description("Toggle in-game interface")]
ToggleInGameInterface,
}
}

View File

@ -208,7 +208,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
private IReadOnlyList<Size> getResolutions()
{
var resolutions = new List<Size> { new Size(9999, 9999) };
var currentDisplay = game.Window?.CurrentDisplay.Value;
var currentDisplay = game.Window?.CurrentDisplayBindable.Value;
if (currentDisplay != null)
{

View File

@ -25,6 +25,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
[Resolved]
private BindableBeatDivisor beatDivisor { get; set; }
[Resolved(CanBeNull = true)]
private IEditorChangeHandler changeHandler { get; set; }
[Resolved]
private OsuColour colours { get; set; }
@ -38,7 +41,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
[BackgroundDependencyLoader]
private void load()
{
beatDivisor.BindValueChanged(_ => tickCache.Invalidate());
beatDivisor.BindValueChanged(_ => invalidateTicks());
if (changeHandler != null)
// currently this is the best way to handle any kind of timing changes.
changeHandler.OnStateChange += invalidateTicks;
}
private void invalidateTicks()
{
tickCache.Invalidate();
}
/// <summary>
@ -165,5 +177,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
return point;
}
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (changeHandler != null)
changeHandler.OnStateChange -= invalidateTicks;
}
}
}

View File

@ -37,8 +37,8 @@ namespace osu.Game.Screens.Edit.Setup
Current = new BindableFloat(Beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize)
{
Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
MinValue = 2,
MaxValue = 7,
MinValue = 0,
MaxValue = 10,
Precision = 0.1f,
}
},

View File

@ -9,7 +9,6 @@ using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Configuration;
using osu.Game.Input.Bindings;
using osu.Game.Overlays;
@ -19,7 +18,6 @@ using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play.HUD;
using osuTK;
using osuTK.Input;
namespace osu.Game.Screens.Play
{
@ -181,7 +179,7 @@ namespace osu.Game.Screens.Play
notificationOverlay?.Post(new SimpleNotification
{
Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab."
Text = $"The score overlay is currently disabled. You can toggle this by pressing {config.LookupKeyBindings(GlobalAction.ToggleInGameInterface)}."
});
}
@ -273,37 +271,6 @@ namespace osu.Game.Screens.Play
Progress.BindDrawableRuleset(drawableRuleset);
}
protected override bool OnKeyDown(KeyDownEvent e)
{
if (e.Repeat) return false;
if (e.ShiftPressed)
{
switch (e.Key)
{
case Key.Tab:
switch (configVisibilityMode.Value)
{
case HUDVisibilityMode.Never:
configVisibilityMode.Value = HUDVisibilityMode.HideDuringGameplay;
break;
case HUDVisibilityMode.HideDuringGameplay:
configVisibilityMode.Value = HUDVisibilityMode.Always;
break;
case HUDVisibilityMode.Always:
configVisibilityMode.Value = HUDVisibilityMode.Never;
break;
}
return true;
}
}
return base.OnKeyDown(e);
}
protected virtual SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter();
protected virtual SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter();
@ -377,6 +344,24 @@ namespace osu.Game.Screens.Play
holdingForHUD = true;
updateVisibility();
return true;
case GlobalAction.ToggleInGameInterface:
switch (configVisibilityMode.Value)
{
case HUDVisibilityMode.Never:
configVisibilityMode.Value = HUDVisibilityMode.HideDuringGameplay;
break;
case HUDVisibilityMode.HideDuringGameplay:
configVisibilityMode.Value = HUDVisibilityMode.Always;
break;
case HUDVisibilityMode.Always:
configVisibilityMode.Value = HUDVisibilityMode.Never;
break;
}
return true;
}
return false;

View File

@ -376,7 +376,7 @@ namespace osu.Game.Screens.Select
if (selectionChangedDebounce?.Completed == false)
{
selectionChangedDebounce.RunTask();
selectionChangedDebounce.Cancel(); // cancel the already scheduled task.
selectionChangedDebounce?.Cancel(); // cancel the already scheduled task.
selectionChangedDebounce = null;
}
@ -465,19 +465,30 @@ namespace osu.Game.Screens.Select
void run()
{
// clear pending task immediately to track any potential nested debounce operation.
selectionChangedDebounce = null;
Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ID.ToString() ?? "null"}");
if (transferRulesetValue())
{
Mods.Value = Array.Empty<Mod>();
// transferRulesetValue() may trigger a refilter. If the current selection does not match the new ruleset, we want to switch away from it.
// transferRulesetValue() may trigger a re-filter. If the current selection does not match the new ruleset, we want to switch away from it.
// The default logic on WorkingBeatmap change is to switch to a matching ruleset (see workingBeatmapChanged()), but we don't want that here.
// We perform an early selection attempt and clear out the beatmap selection to avoid a second ruleset change (revert).
if (beatmap != null && !Carousel.SelectBeatmap(beatmap, false))
beatmap = null;
}
if (selectionChangedDebounce != null)
{
// a new nested operation was started; switch to it for further selection.
// this avoids having two separate debounces trigger from the same source.
selectionChangedDebounce.RunTask();
return;
}
// We may be arriving here due to another component changing the bindable Beatmap.
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
if (!EqualityComparer<BeatmapInfo>.Default.Equals(beatmap, Beatmap.Value.BeatmapInfo))

View File

@ -0,0 +1,38 @@
// 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.Allocation;
using osu.Framework.Audio;
using osu.Framework.IO.Stores;
using osu.Game.Rulesets;
using osu.Game.Skinning;
namespace osu.Game.Tests.Visual
{
[TestFixture]
public abstract class LegacySkinPlayerTestScene : PlayerTestScene
{
private ISkinSource legacySkinSource;
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(legacySkinSource);
[BackgroundDependencyLoader]
private void load(AudioManager audio, OsuGameBase game)
{
var legacySkin = new DefaultLegacySkin(new NamespacedResourceStore<byte[]>(game.Resources, "Skins/Legacy"), audio);
legacySkinSource = new SkinProvidingContainer(legacySkin);
}
public class SkinProvidingPlayer : TestPlayer
{
[Cached(typeof(ISkinSource))]
private readonly ISkinSource skinSource;
public SkinProvidingPlayer(ISkinSource skinSource)
{
this.skinSource = skinSource;
}
}
}
}

View File

@ -18,7 +18,7 @@
</None>
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Dapper" Version="2.0.35" />
<PackageReference Include="Dapper" Version="2.0.78" />
<PackageReference Include="DiffPlex" Version="1.6.3" />
<PackageReference Include="Humanizer" Version="2.8.26" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.9" />
@ -26,11 +26,11 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2020.1127.0" />
<PackageReference Include="ppy.osu.Framework" Version="2020.1201.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.1030.0" />
<PackageReference Include="Sentry" Version="2.1.6" />
<PackageReference Include="Sentry" Version="2.1.8" />
<PackageReference Include="SharpCompress" Version="0.26.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
</ItemGroup>
</Project>

View File

@ -70,7 +70,7 @@
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.1127.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.1201.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.1030.0" />
</ItemGroup>
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
@ -88,11 +88,11 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2020.1127.0" />
<PackageReference Include="ppy.osu.Framework" Version="2020.1201.0" />
<PackageReference Include="SharpCompress" Version="0.26.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="ppy.osu.Framework.NativeLibs" Version="2020.923.0" ExcludeAssets="all" />
</ItemGroup>
</Project>