1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 02:42:54 +08:00

Merge pull request #10277 from peppy/editor-implicit-autoplay

Add autoplay support to editor
This commit is contained in:
Dan Balasescu 2020-09-28 17:41:26 +09:00 committed by GitHub
commit 2f5a2d3bba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 13 deletions

View File

@ -8,6 +8,7 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI;
using osuTK;
@ -20,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Edit
/// Hit objects are intentionally made to fade out at a constant slower rate than in gameplay.
/// This allows a mapper to gain better historical context and use recent hitobjects as reference / snap points.
/// </summary>
private const double editor_hit_object_fade_out_extension = 500;
private const double editor_hit_object_fade_out_extension = 700;
public DrawableOsuEditRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods)
@ -32,20 +33,37 @@ namespace osu.Game.Rulesets.Osu.Edit
private void updateState(DrawableHitObject hitObject, ArmedState state)
{
switch (state)
if (state == ArmedState.Idle)
return;
// adjust the visuals of certain object types to make them stay on screen for longer than usual.
switch (hitObject)
{
case ArmedState.Miss:
// Get the existing fade out transform
var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));
if (existing == null)
return;
default:
// there are quite a few drawable hit types we don't want to extent (spinners, ticks etc.)
return;
hitObject.RemoveTransform(existing);
case DrawableSlider _:
// no specifics to sliders but let them fade slower below.
break;
using (hitObject.BeginAbsoluteSequence(existing.StartTime))
hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire();
case DrawableHitCircle circle: // also handles slider heads
circle.ApproachCircle
.FadeOutFromOne(editor_hit_object_fade_out_extension)
.Expire();
break;
}
// Get the existing fade out transform
var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));
if (existing == null)
return;
hitObject.RemoveTransform(existing);
using (hitObject.BeginAbsoluteSequence(existing.StartTime))
hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire();
}
protected override Playfield CreatePlayfield() => new OsuPlayfieldNoCursor();

View File

@ -45,15 +45,21 @@ namespace osu.Game.Rulesets.Edit
base.LoadComplete();
beatmap.HitObjectAdded += addHitObject;
beatmap.HitObjectUpdated += updateReplay;
beatmap.HitObjectRemoved += removeHitObject;
}
private void updateReplay(HitObject obj = null) =>
drawableRuleset.RegenerateAutoplay();
private void addHitObject(HitObject hitObject)
{
var drawableObject = drawableRuleset.CreateDrawableRepresentation((TObject)hitObject);
drawableRuleset.Playfield.Add(drawableObject);
drawableRuleset.Playfield.PostProcess();
updateReplay();
}
private void removeHitObject(HitObject hitObject)
@ -62,6 +68,8 @@ namespace osu.Game.Rulesets.Edit
drawableRuleset.Playfield.Remove(drawableObject);
drawableRuleset.Playfield.PostProcess();
drawableRuleset.RegenerateAutoplay();
}
public override bool PropagatePositionalInputSubTree => false;

View File

@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Edit
try
{
drawableRulesetWrapper = new DrawableEditRulesetWrapper<TObject>(CreateDrawableRuleset(Ruleset, EditorBeatmap.PlayableBeatmap))
drawableRulesetWrapper = new DrawableEditRulesetWrapper<TObject>(CreateDrawableRuleset(Ruleset, EditorBeatmap.PlayableBeatmap, new[] { Ruleset.GetAutoplayMod() }))
{
Clock = EditorClock,
ProcessCustomClock = false

View File

@ -151,8 +151,11 @@ namespace osu.Game.Rulesets.UI
public virtual PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new PlayfieldAdjustmentContainer();
[Resolved]
private OsuConfigManager config { get; set; }
[BackgroundDependencyLoader]
private void load(OsuConfigManager config, CancellationToken? cancellationToken)
private void load(CancellationToken? cancellationToken)
{
InternalChildren = new Drawable[]
{
@ -178,11 +181,18 @@ namespace osu.Game.Rulesets.UI
.WithChild(ResumeOverlay)));
}
applyRulesetMods(Mods, config);
RegenerateAutoplay();
loadObjects(cancellationToken);
}
public void RegenerateAutoplay()
{
// for now this is applying mods which aren't just autoplay.
// we'll need to reconsider this flow in the future.
applyRulesetMods(Mods, config);
}
/// <summary>
/// Creates and adds drawable representations of hit objects to the play field.
/// </summary>

View File

@ -212,6 +212,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
if (blueprint != null)
{
// doing this post-creations as adding the default hit sample should be the case regardless of the ruleset.
blueprint.HitObject.Samples.Add(new HitSampleInfo { Name = HitSampleInfo.HIT_NORMAL });
placementBlueprintContainer.Child = currentPlacement = blueprint;
// Fixes a 1-frame position discrepancy due to the first mouse move event happening in the next frame