-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Add osu! mod "Centered Cursor" #37487
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Rudicito
wants to merge
3
commits into
ppy:master
Choose a base branch
from
Rudicito:centered-cursor
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+131
−6
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModCenteredCursor.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // 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.Rulesets.Osu.Mods; | ||
|
|
||
| namespace osu.Game.Rulesets.Osu.Tests.Mods | ||
| { | ||
| public partial class TestSceneOsuModCenteredCursor : OsuModTestScene | ||
| { | ||
| [Test] | ||
| public void TestOsuModCenteredCursor() => CreateModTest(new ModTestData | ||
| { | ||
| Mod = new OsuModCenteredCursor(), | ||
| Autoplay = true, | ||
| PassCondition = () => true | ||
| }); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| // 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.Linq; | ||
| using osu.Framework.Graphics; | ||
| using osu.Framework.Input; | ||
| using osu.Framework.Input.Events; | ||
| using osu.Framework.Input.StateChanges; | ||
| using osu.Framework.Localisation; | ||
| using osu.Game.Rulesets.Mods; | ||
| using osu.Game.Rulesets.Osu.Objects; | ||
| using osu.Game.Rulesets.Osu.UI; | ||
| using osu.Game.Rulesets.UI; | ||
| using osu.Game.Screens.Play; | ||
| using osuTK; | ||
|
|
||
| namespace osu.Game.Rulesets.Osu.Mods | ||
| { | ||
| public partial class OsuModCenteredCursor : Mod, IUpdatableByPlayfield, IApplicableToDrawableRuleset<OsuHitObject>, IApplicableToPlayer | ||
| { | ||
| public override string Name => "Centered Cursor"; | ||
| public override LocalisableString Description => "Cursor stays in the middle!"; | ||
| public override double ScoreMultiplier => 1; | ||
| public override string Acronym => "CC"; | ||
| public override ModType Type => ModType.Fun; | ||
| public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModFlashlight), typeof(OsuModAutopilot), typeof(OsuModRelax), typeof(OsuModBubbles), typeof(ModTouchDevice) }).ToArray(); | ||
|
|
||
| private OsuInputManager osuInputManager = null!; | ||
| private bool hasReplay; | ||
| private ExternalMousePosGetter externalMousePosGetter = null!; | ||
|
|
||
| public void Update(Playfield playfield) | ||
| { | ||
| externalMousePosGetter.Enable = !hasReplay; | ||
|
|
||
| // The coords of the cursor in playfield local space | ||
| Vector2 osuPos; | ||
|
|
||
| // If it's a replay we don't need to do mouse conversion | ||
| if (hasReplay) | ||
| { | ||
| osuPos = playfield.Cursor!.ActiveCursor.Position; | ||
| } | ||
| else | ||
| { | ||
| var mousePos = externalMousePosGetter.MousePos; | ||
|
|
||
| // We convert the coords using the playfield parent because the playfield is moving so the values would be wrong | ||
| osuPos = playfield.Parent!.ToLocalSpace(mousePos); | ||
|
|
||
| new ConvertedMousePositionAbsoluteInput { Position = playfield.ToScreenSpace(osuPos) }.Apply(osuInputManager.CurrentState, osuInputManager); | ||
| } | ||
|
|
||
| playfield.Position = playfield.LayoutSize / 2 - osuPos; | ||
| } | ||
|
|
||
| public void ApplyToDrawableRuleset(DrawableRuleset<OsuHitObject> drawableRuleset) | ||
| { | ||
| // Grab the input manager for future use | ||
| osuInputManager = ((DrawableOsuRuleset)drawableRuleset).KeyBindingInputManager; | ||
|
|
||
| // Added this way, ExternalMousePosGetter receives OnMouseMove before the playfield drawables, so it can block propagation to the playfield | ||
| drawableRuleset.PlayfieldAdjustmentContainer.Add(externalMousePosGetter = new ExternalMousePosGetter { RelativeSizeAxes = Axes.Both }); | ||
|
|
||
| // Reset playfield position while paused so the resume overlay reads the real cursor position correctly. | ||
| // This avoids the resume overlay forcing the user to move the mouse to the center, which would cause a cursor jump/teleportation when resuming. | ||
| drawableRuleset.IsPaused.BindValueChanged(p => | ||
| { | ||
| if (p.NewValue) drawableRuleset.Playfield.Position = Vector2.Zero; | ||
| }); | ||
| } | ||
|
|
||
| public void ApplyToPlayer(Player player) | ||
| { | ||
| if (osuInputManager.ReplayInputHandler != null) hasReplay = true; | ||
| } | ||
|
|
||
| private class ConvertedMousePositionAbsoluteInput : MousePositionAbsoluteInput; | ||
|
|
||
| private partial class ExternalMousePosGetter : Drawable, IRequireHighFrequencyMousePosition | ||
| { | ||
| public bool Enable = true; | ||
| public Vector2 MousePos { get; private set; } = Vector2.Zero; | ||
|
|
||
| public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; | ||
|
|
||
| protected override bool OnMouseMove(MouseMoveEvent e) | ||
| { | ||
| if (!Enable) | ||
| return base.OnMouseMove(e); | ||
|
|
||
| // We skip our own added mouse position | ||
| if (e.CurrentState.Mouse.LastSource is ConvertedMousePositionAbsoluteInput) | ||
| return base.OnMouseMove(e); | ||
|
|
||
| MousePos = e.ScreenSpaceMousePosition; | ||
|
|
||
| // We block real mouse position propagation to the playfield | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this could have been done in
ApplyToDrawableRuleset()but I just done the same thing thatOsuModRelax:https://github.com/ppy/osu/blob/master/osu.Game.Rulesets.Osu%2FMods%2FOsuModRelax.cs#L55-L71