diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 1b06aa4d17..6444127594 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -14,8 +14,8 @@ "jb" ] }, - "smoogipoo.nvika": { - "version": "1.0.3", + "nvika": { + "version": "2.2.0", "commands": [ "nvika" ] diff --git a/osu.Android.props b/osu.Android.props index 4887e3a95f..6d2e8428a7 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs b/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs index c8848ab7d8..656e333073 100644 --- a/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs +++ b/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using Newtonsoft.Json; using NUnit.Framework; @@ -67,9 +68,11 @@ namespace osu.Game.Tests.Online var deserialised = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(apiMod)); var converted = (TestModTimeRamp)deserialised?.ToMod(new TestRuleset()); - Assert.That(converted?.AdjustPitch.Value, Is.EqualTo(false)); - Assert.That(converted?.InitialRate.Value, Is.EqualTo(1.25)); - Assert.That(converted?.FinalRate.Value, Is.EqualTo(0.25)); + Assert.That(converted, Is.Not.Null); + + Assert.That(converted.AdjustPitch.Value, Is.EqualTo(false)); + Assert.That(converted.InitialRate.Value, Is.EqualTo(1.25)); + Assert.That(converted.FinalRate.Value, Is.EqualTo(0.25)); } [Test] @@ -121,11 +124,11 @@ namespace osu.Game.Tests.Online new TestModDifficultyAdjust() }; - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => throw new System.NotImplementedException(); + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => throw new NotImplementedException(); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new System.NotImplementedException(); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException(); - public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new System.NotImplementedException(); + public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException(); public override string Description { get; } = string.Empty; public override string ShortName { get; } = string.Empty; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs index a2a7b72283..dddd9f07ab 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs @@ -5,7 +5,10 @@ using System; using System.Linq; using NUnit.Framework; using osu.Framework.Testing; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; @@ -29,6 +32,9 @@ namespace osu.Game.Tests.Visual.Editing private ComposeBlueprintContainer blueprintContainer => Editor.ChildrenOfType().First(); + private ContextMenuContainer contextMenuContainer + => Editor.ChildrenOfType().First(); + private void moveMouseToObject(Func targetFunc) { AddStep("move mouse to object", () => @@ -42,6 +48,19 @@ namespace osu.Game.Tests.Visual.Editing }); } + [Test] + public void TestSelectAndShowContextMenu() + { + var addedObject = new HitCircle { StartTime = 100, Position = new Vector2(100, 100) }; + AddStep("add hitobject", () => EditorBeatmap.Add(addedObject)); + + moveMouseToObject(() => addedObject); + AddStep("right click", () => InputManager.Click(MouseButton.Right)); + + AddUntilStep("hitobject selected", () => EditorBeatmap.SelectedHitObjects.Single() == addedObject); + AddUntilStep("context menu is visible", () => contextMenuContainer.ChildrenOfType().Single().State == MenuState.Open); + } + [Test] public void TestNudgeSelection() { diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index d7d4642a39..29e3f12d03 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -108,11 +108,20 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseDown(MouseDownEvent e) { bool selectionPerformed = performMouseDownActions(e); - - // even if a selection didn't occur, a drag event may still move the selection. bool movementPossible = prepareSelectionMovement(); - return selectionPerformed || (e.Button == MouseButton.Left && movementPossible); + // check if selection has occurred + if (selectionPerformed) + { + // only unmodified right click should show context menu + bool shouldShowContextMenu = e.Button == MouseButton.Right && !e.ShiftPressed && !e.AltPressed && !e.SuperPressed; + + // stop propagation if not showing context menu + return !shouldShowContextMenu; + } + + // even if a selection didn't occur, a drag event may still move the selection. + return e.Button == MouseButton.Left && movementPossible; } protected SelectionBlueprint ClickedBlueprint { get; private set; } diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs index 5fb72e4151..307c2352e3 100644 --- a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Select new PopupDialogOkButton { Text = @"Yes. Totally. Delete it.", - Action = () => manager.Delete(beatmap), + Action = () => manager?.Delete(beatmap), }, new PopupDialogCancelButton { diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 99123627bd..9e3d3df915 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -77,10 +77,14 @@ namespace osu.Game.Storyboards { get { - string backgroundPath = BeatmapInfo.BeatmapSet?.Metadata?.BackgroundFile.ToLowerInvariant(); + string backgroundPath = BeatmapInfo.BeatmapSet?.Metadata?.BackgroundFile; + if (string.IsNullOrEmpty(backgroundPath)) return false; + // Importantly, do this after the NullOrEmpty because EF may have stored the non-nullable value as null to the database, bypassing compile-time constraints. + backgroundPath = backgroundPath.ToLowerInvariant(); + return GetLayer("Background").Elements.Any(e => e.Path.ToLowerInvariant() == backgroundPath); } } @@ -93,7 +97,7 @@ namespace osu.Game.Storyboards Drawable drawable = null; string storyboardPath = BeatmapInfo.BeatmapSet?.Files.Find(f => f.Filename.Equals(path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; - if (storyboardPath != null) + if (!string.IsNullOrEmpty(storyboardPath)) drawable = new Sprite { Texture = textureStore.Get(storyboardPath) }; // if the texture isn't available locally in the beatmap, some storyboards choose to source from the underlying skin lookup hierarchy. else if (UseSkinSprites) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 972d64a997..6dda1f77c6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index f6e4f61fde..df24a57e90 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - +