Allow hitobject placement while song is playing (live mapping)
In addition to the current beatmap editor, allow beatmap creators to play the song over a blank beatmap, and when they click it puts a circle there, and when they click and drag it puts a slider there.
I think this could be a much more fun and easy way to create beatmaps, definitely in the beginning.
Maybe once all the sliders and circles are put using this method, their positions can be fine-tuned (and combos can be chosen etc.) in the traditional editor.
Also, alternatively/additionally, combos etc. and other features could be handled via key binds in this "fast" editor.
Basic features I think would be useful:
- quantization (and you can choose the timings)
- setting for "smoothness" of sliders
- based on the setting, automatically place sharp bends and reverse arrows
- also provided key binds, for sharp bends in sliders, and reverse arrows
I support this.
This is called live mapping. I believe it is supported in stable and will also come to lazer eventually.
Will this be standard only?
Editor features will be present in all bundled rulesets.
Has this been added to Lazer yet? Was trying to map a song and wanted to see if it made it in before I opened a request for it.
Has this been added to Lazer yet? Was trying to map a song and wanted to see if it made it in before I opened a request for it.
Doesn't seem like it.
IMO this is more important than any other type of editor. If osu! only had one way to create maps, it should be live mapping.
You can basically do this now? Have you tried?
I think this should be closed, live mapping is possible.
https://github.com/ppy/osu/assets/104220939/b878b15e-2e9f-4f73-8905-f3e33bae68c4
The title is kind of misleading. "Live mapping" in stable uses keyboard bindings (instead of mouse) to place circles (ref: https://osu.ppy.sh/wiki/en/Client/Beatmap_editor/Menu#compose). Stable also doesn't support slider placement, which OP also wanted and can be exclusive to lazer.
TL;DR (or in a different way to say it):
- use keyboard bindings to place circles, and when holding key and dragging, place a slider instead (i.e. automatically switch to slider mode drawing)
- probably also add the hold and drag behavior to mouse
- decide whether this should be a toggle (to not conflict existing editor keybinds) or make it work and have it always default behavior
Tried to do a barebones implementation of this for taiko and hit a few walls.
diff --git a/osu.Game.Rulesets.Taiko/Edit/DrawableTaikoEditorRuleset.cs b/osu.Game.Rulesets.Taiko/Edit/DrawableTaikoEditorRuleset.cs
index 217bb8139c..f206130dd2 100644
--- a/osu.Game.Rulesets.Taiko/Edit/DrawableTaikoEditorRuleset.cs
+++ b/osu.Game.Rulesets.Taiko/Edit/DrawableTaikoEditorRuleset.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
+using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
@@ -20,6 +21,12 @@ public DrawableTaikoEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyLi
{
}
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ KeyBindingInputManager.Add(new TaikoLiveMapper());
+ }
+
protected override void LoadComplete()
{
base.LoadComplete();
diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoLiveMapper.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoLiveMapper.cs
new file mode 100644
index 0000000000..c3a0092695
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko/Edit/TaikoLiveMapper.cs
@@ -0,0 +1,68 @@
+// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Linq;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Input.Bindings;
+using osu.Framework.Input.Events;
+using osu.Game.Rulesets.Edit;
+using osu.Game.Rulesets.Taiko.Objects;
+using osu.Game.Screens.Edit;
+
+namespace osu.Game.Rulesets.Taiko.Edit
+{
+ public partial class TaikoLiveMapper : Component, IKeyBindingHandler<TaikoAction>
+ {
+ [Resolved]
+ private EditorBeatmap editorBeatmap { get; set; } = null!;
+
+ [Resolved]
+ private IBeatSnapProvider beatSnapProvider { get; set; } = null!;
+
+ [Resolved]
+ private EditorClock editorClock { get; set; } = null!;
+
+ public bool OnPressed(KeyBindingPressEvent<TaikoAction> e)
+ {
+ if (e.Repeat)
+ return false;
+
+ double quantisedTime = beatSnapProvider.SnapTime(editorClock.CurrentTime);
+
+ var existing = editorBeatmap.HitObjects.FirstOrDefault(h => h.StartTime == quantisedTime);
+
+ switch (existing)
+ {
+ case Hit hit:
+ {
+ if ((hit.Type == HitType.Centre && (e.Action == TaikoAction.LeftCentre || e.Action == TaikoAction.RightCentre)) ||
+ (hit.Type == HitType.Rim && (e.Action == TaikoAction.LeftRim || e.Action == TaikoAction.RightRim)))
+ {
+ hit.IsStrong = true;
+ }
+
+ return true;
+ }
+
+ case null:
+ {
+ editorBeatmap.Add(new Hit
+ {
+ Type = e.Action == TaikoAction.LeftCentre || e.Action == TaikoAction.RightCentre ? HitType.Centre : HitType.Rim,
+ StartTime = quantisedTime
+ });
+
+ return true;
+ }
+
+ default:
+ return false;
+ }
+ }
+
+ public void OnReleased(KeyBindingReleaseEvent<TaikoAction> e)
+ {
+ }
+ }
+}
diff --git a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs
index 174b278d89..04fcad4262 100644
--- a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs
+++ b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs
@@ -68,7 +68,7 @@ protected override void LoadComplete()
private void regenerateAutoplay()
{
var autoplayMod = drawableRuleset.Mods.OfType<ModAutoplay>().Single();
- drawableRuleset.SetReplayScore(autoplayMod.CreateScoreFromReplayData(drawableRuleset.Beatmap, drawableRuleset.Mods));
+ //drawableRuleset.SetReplayScore(autoplayMod.CreateScoreFromReplayData(drawableRuleset.Beatmap, drawableRuleset.Mods));
}
private void addHitObject(HitObject hitObject)
@@ -85,7 +85,7 @@ private void removeHitObject(HitObject hitObject)
public override bool PropagatePositionalInputSubTree => false;
- public override bool PropagateNonPositionalInputSubTree => false;
+ //public override bool PropagateNonPositionalInputSubTree => false;
public PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => drawableRuleset.CreatePlayfieldAdjustmentContainer();
- To listen to user bindings the
TaikoLiveMapperhas to be under aRulesetInputManager. Instantiating one is currently not obvious, and attempting to reuse existing... - requires both autoplay replays (which power simulation of gameplay during playback) to be disabled and for the
PropagateNonPositionalInputoverride to be gone. - Also there are keybinding priority conflicts; with this patch only the left default bindings work, the right ones are eaten by timeline.
The play here is probably to make instantiating the ruleset input manager easier. I can't imagine trying to jam the live mapper in the only current viable place is going to be nice or easy.