Skip to content

Commit

Permalink
Merge pull request #23508 from peppy/editor-slider-placement-input
Browse files Browse the repository at this point in the history
Allow commiting / undoing placement of blueprints using back / select bindings
  • Loading branch information
bdach committed May 14, 2023
2 parents 325de2d + 9a327d9 commit 144eba9
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
83 changes: 83 additions & 0 deletions osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// 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.Linq;
using NUnit.Framework;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Input.Bindings;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit.Compose.Components;
using osu.Game.Tests.Beatmaps;
using osuTK.Input;

namespace osu.Game.Tests.Visual.Editing
{
public partial class TestScenePlacementBlueprint : EditorTestScene
{
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();

protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);

private GlobalActionContainer globalActionContainer => this.ChildrenOfType<GlobalActionContainer>().Single();

[Test]
public void TestCommitPlacementViaGlobalAction()
{
Playfield playfield = null!;

AddStep("select slider placement tool", () => InputManager.Key(Key.Number3));
AddStep("move mouse to top left of playfield", () =>
{
playfield = this.ChildrenOfType<Playfield>().Single();
var location = (3 * playfield.ScreenSpaceDrawQuad.TopLeft + playfield.ScreenSpaceDrawQuad.BottomRight) / 4;
InputManager.MoveMouseTo(location);
});
AddStep("begin placement", () => InputManager.Click(MouseButton.Left));
AddStep("move mouse to bottom right of playfield", () =>
{
var location = (playfield.ScreenSpaceDrawQuad.TopLeft + 3 * playfield.ScreenSpaceDrawQuad.BottomRight) / 4;
InputManager.MoveMouseTo(location);
});
AddStep("confirm via global action", () =>
{
globalActionContainer.TriggerPressed(GlobalAction.Select);
globalActionContainer.TriggerReleased(GlobalAction.Select);
});
AddAssert("slider placed", () => EditorBeatmap.HitObjects.Count, () => Is.EqualTo(1));
}

[Test]
public void TestAbortPlacementViaGlobalAction()
{
Playfield playfield = null!;

AddStep("select slider placement tool", () => InputManager.Key(Key.Number3));
AddStep("move mouse to top left of playfield", () =>
{
playfield = this.ChildrenOfType<Playfield>().Single();
var location = (3 * playfield.ScreenSpaceDrawQuad.TopLeft + playfield.ScreenSpaceDrawQuad.BottomRight) / 4;
InputManager.MoveMouseTo(location);
});
AddStep("begin placement", () => InputManager.Click(MouseButton.Left));
AddStep("move mouse to bottom right of playfield", () =>
{
var location = (playfield.ScreenSpaceDrawQuad.TopLeft + 3 * playfield.ScreenSpaceDrawQuad.BottomRight) / 4;
InputManager.MoveMouseTo(location);
});
AddStep("abort via global action", () =>
{
globalActionContainer.TriggerPressed(GlobalAction.Back);
globalActionContainer.TriggerReleased(GlobalAction.Back);
});
AddAssert("editor is still current", () => Editor.IsCurrentScreen());
AddAssert("slider not placed", () => EditorBeatmap.HitObjects.Count, () => Is.EqualTo(0));
AddAssert("no active placement", () => this.ChildrenOfType<ComposeBlueprintContainer>().Single().CurrentPlacement.PlacementActive,
() => Is.EqualTo(PlacementBlueprint.PlacementState.Waiting));
}
}
}
28 changes: 27 additions & 1 deletion osu.Game/Rulesets/Edit/PlacementBlueprint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose;
Expand All @@ -24,7 +26,7 @@ namespace osu.Game.Rulesets.Edit
/// <summary>
/// A blueprint which governs the creation of a new <see cref="HitObject"/> to actualisation.
/// </summary>
public abstract partial class PlacementBlueprint : CompositeDrawable
public abstract partial class PlacementBlueprint : CompositeDrawable, IKeyBindingHandler<GlobalAction>
{
/// <summary>
/// Whether the <see cref="HitObject"/> is currently mid-placement, but has not necessarily finished being placed.
Expand Down Expand Up @@ -115,6 +117,30 @@ public void EndPlacement(bool commit)
PlacementActive = PlacementState.Finished;
}

public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{
if (PlacementActive == PlacementState.Waiting)
return false;

switch (e.Action)
{
case GlobalAction.Select:
EndPlacement(true);
return true;

case GlobalAction.Back:
EndPlacement(false);
return true;

default:
return false;
}
}

public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
{
}

/// <summary>
/// Updates the time and position of this <see cref="PlacementBlueprint"/> based on the provided snap information.
/// </summary>
Expand Down

0 comments on commit 144eba9

Please sign in to comment.