diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 1132396608..65ac05261a 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2022.1.0-eap10", + "version": "2022.1.1", "commands": [ "jb" ] @@ -27,4 +27,4 @@ ] } } -} +} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 514acef525..729f2f266d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: uses: actions/cache@v3 with: path: ${{ github.workspace }}/inspectcode - key: inspectcode-${{ hashFiles('.config/dotnet-tools.json') }}-${{ hashFiles('.github/workflows/ci.yml' ) }} + key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', '.editorconfig', '.globalconfig') }} - name: Dotnet code style run: dotnet build -c Debug -warnaserror osu.Desktop.slnf -p:EnforceCodeStyleInBuild=true diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs index 4012a672ed..7c05abc2cd 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; @@ -66,6 +67,13 @@ namespace osu.Game.Tests.Visual.Editing }); } + [Test] + public void TestPopoverHasFocus() + { + clickDifficultyPiece(0); + velocityPopoverHasFocus(); + } + [Test] public void TestSingleSelection() { @@ -133,6 +141,15 @@ namespace osu.Game.Tests.Visual.Editing InputManager.Click(MouseButton.Left); }); + private void velocityPopoverHasFocus() => AddUntilStep("velocity popover textbox focused", () => + { + var popover = this.ChildrenOfType().SingleOrDefault(); + var slider = popover?.ChildrenOfType>().Single(); + var textbox = slider?.ChildrenOfType().Single(); + + return textbox?.HasFocus == true; + }); + private void velocityPopoverHasSingleValue(double velocity) => AddUntilStep($"velocity popover has {velocity}", () => { var popover = this.ChildrenOfType().SingleOrDefault(); @@ -151,6 +168,7 @@ namespace osu.Game.Tests.Visual.Editing private void dismissPopover() { + AddStep("unfocus textbox", () => InputManager.Key(Key.Escape)); AddStep("dismiss popover", () => InputManager.Key(Key.Escape)); AddUntilStep("wait for dismiss", () => !this.ChildrenOfType().Any(popover => popover.IsPresent)); } diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs index dca30a6fc0..4501eea88e 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs @@ -57,6 +57,13 @@ namespace osu.Game.Tests.Visual.Editing }); } + [Test] + public void TestPopoverHasFocus() + { + clickSamplePiece(0); + samplePopoverHasFocus(); + } + [Test] public void TestSingleSelection() { @@ -173,14 +180,23 @@ namespace osu.Game.Tests.Visual.Editing samplePopoverHasSingleBank("normal"); } - private void clickSamplePiece(int objectIndex) => AddStep($"click {objectIndex.ToOrdinalWords()} difficulty piece", () => + private void clickSamplePiece(int objectIndex) => AddStep($"click {objectIndex.ToOrdinalWords()} sample piece", () => { - var difficultyPiece = this.ChildrenOfType().Single(piece => piece.HitObject == EditorBeatmap.HitObjects.ElementAt(objectIndex)); + var samplePiece = this.ChildrenOfType().Single(piece => piece.HitObject == EditorBeatmap.HitObjects.ElementAt(objectIndex)); - InputManager.MoveMouseTo(difficultyPiece); + InputManager.MoveMouseTo(samplePiece); InputManager.Click(MouseButton.Left); }); + private void samplePopoverHasFocus() => AddUntilStep("sample popover textbox focused", () => + { + var popover = this.ChildrenOfType().SingleOrDefault(); + var slider = popover?.ChildrenOfType>().Single(); + var textbox = slider?.ChildrenOfType().Single(); + + return textbox?.HasFocus == true; + }); + private void samplePopoverHasSingleVolume(int volume) => AddUntilStep($"sample popover has volume {volume}", () => { var popover = this.ChildrenOfType().SingleOrDefault(); @@ -215,8 +231,9 @@ namespace osu.Game.Tests.Visual.Editing private void dismissPopover() { + AddStep("unfocus textbox", () => InputManager.Key(Key.Escape)); AddStep("dismiss popover", () => InputManager.Key(Key.Escape)); - AddUntilStep("wait for dismiss", () => !this.ChildrenOfType().Any(popover => popover.IsPresent)); + AddUntilStep("wait for dismiss", () => !this.ChildrenOfType().Any(popover => popover.IsPresent)); } private void setVolumeViaPopover(int volume) => AddStep($"set volume {volume} via popover", () => diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index b230bab0c2..eaaa663fe7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -122,6 +122,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline beatmap.EndChange(); }); } + + protected override void LoadComplete() + { + base.LoadComplete(); + ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(sliderVelocitySlider)); + } } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs index fc0952d4f0..ab21a83c43 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs @@ -126,6 +126,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline volume.Current.BindValueChanged(val => updateVolumeFor(relevantObjects, val.NewValue)); } + protected override void LoadComplete() + { + base.LoadComplete(); + ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(volume)); + } + private static string? getCommonBank(SampleControlPoint[] relevantControlPoints) => relevantControlPoints.Select(point => point.SampleBank).Distinct().Count() == 1 ? relevantControlPoints.First().SampleBank : null; private static int? getCommonVolume(SampleControlPoint[] relevantControlPoints) => relevantControlPoints.Select(point => point.SampleVolume).Distinct().Count() == 1 ? (int?)relevantControlPoints.First().SampleVolume : null; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 51b8792d87..7e66c57917 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -270,12 +270,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline protected override bool OnMouseDown(MouseDownEvent e) { if (base.OnMouseDown(e)) - { beginUserDrag(); - return true; - } - return false; + return true; } protected override void OnMouseUp(MouseUpEvent e) diff --git a/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs b/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs index 0cf2cf6c54..16a04982f5 100644 --- a/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs +++ b/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays.Settings; @@ -107,6 +108,14 @@ namespace osu.Game.Screens.Edit.Timing Current.BindValueChanged(_ => updateState(), true); } + public override bool AcceptsFocus => true; + + protected override void OnFocus(FocusEvent e) + { + base.OnFocus(e); + GetContainingInputManager().ChangeFocus(textBox); + } + private void updateState() { if (Current.Value is T nonNullValue) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index 02ff040a94..5dab845999 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -43,6 +43,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private readonly MultiplayerRoomUser[] users; + private readonly Bindable leaderboardExpanded = new BindableBool(); + private LoadingLayer loadingDisplay; private FillFlowContainer leaderboardFlow; @@ -76,13 +78,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Spacing = new Vector2(5) }); + HUDOverlay.HoldingForHUD.BindValueChanged(_ => updateLeaderboardExpandedState()); + LocalUserPlaying.BindValueChanged(_ => updateLeaderboardExpandedState(), true); + // todo: this should be implemented via a custom HUD implementation, and correctly masked to the main content area. LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(GameplayState.Ruleset.RulesetInfo, ScoreProcessor, users), l => { if (!LoadedBeatmapSuccessfully) return; - ((IBindable)leaderboard.Expanded).BindTo(HUDOverlay.ShowHud); + leaderboard.Expanded.BindTo(leaderboardExpanded); leaderboardFlow.Insert(0, l); @@ -99,7 +104,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer LoadComponentAsync(new GameplayChatDisplay(Room) { - Expanded = { BindTarget = HUDOverlay.ShowHud }, + Expanded = { BindTarget = leaderboardExpanded }, }, chat => leaderboardFlow.Insert(2, chat)); HUDOverlay.Add(loadingDisplay = new LoadingLayer(true) { Depth = float.MaxValue }); @@ -152,6 +157,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } } + private void updateLeaderboardExpandedState() => + leaderboardExpanded.Value = !LocalUserPlaying.Value || HUDOverlay.HoldingForHUD.Value; + private void failAndBail(string message = null) { if (!string.IsNullOrEmpty(message)) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index abfed1acd0..f6087e0958 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -68,7 +68,9 @@ namespace osu.Game.Screens.Play internal readonly IBindable IsPlaying = new Bindable(); - private bool holdingForHUD; + public IBindable HoldingForHUD => holdingForHUD; + + private readonly BindableBool holdingForHUD = new BindableBool(); private readonly SkinnableTargetContainer mainComponents; @@ -144,7 +146,8 @@ namespace osu.Game.Screens.Play hideTargets.ForEach(d => d.Hide()); } - public override void Hide() => throw new InvalidOperationException($"{nameof(HUDOverlay)} should not be hidden as it will remove the ability of a user to quit. Use {nameof(ShowHud)} instead."); + public override void Hide() => + throw new InvalidOperationException($"{nameof(HUDOverlay)} should not be hidden as it will remove the ability of a user to quit. Use {nameof(ShowHud)} instead."); protected override void LoadComplete() { @@ -152,6 +155,7 @@ namespace osu.Game.Screens.Play ShowHud.BindValueChanged(visible => hideTargets.ForEach(d => d.FadeTo(visible.NewValue ? 1 : 0, FADE_DURATION, FADE_EASING))); + holdingForHUD.BindValueChanged(_ => updateVisibility()); IsPlaying.BindValueChanged(_ => updateVisibility()); configVisibilityMode.BindValueChanged(_ => updateVisibility(), true); @@ -204,7 +208,7 @@ namespace osu.Game.Screens.Play if (ShowHud.Disabled) return; - if (holdingForHUD) + if (holdingForHUD.Value) { ShowHud.Value = true; return; @@ -287,8 +291,7 @@ namespace osu.Game.Screens.Play switch (e.Action) { case GlobalAction.HoldForHUD: - holdingForHUD = true; - updateVisibility(); + holdingForHUD.Value = true; return true; case GlobalAction.ToggleInGameInterface: @@ -318,8 +321,7 @@ namespace osu.Game.Screens.Play switch (e.Action) { case GlobalAction.HoldForHUD: - holdingForHUD = false; - updateVisibility(); + holdingForHUD.Value = false; break; } }