From 8a47e2431bbe7c3207e75004d61fd5fcbce103f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 May 2020 17:13:22 +0900 Subject: [PATCH 01/20] Move distance snap grid implementation to OsuHitObjectComposer --- .../Edit/OsuHitObjectComposer.cs | 64 +++++++++++++++- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 73 +++---------------- .../Compose/Components/BlueprintContainer.cs | 5 -- 3 files changed, 74 insertions(+), 68 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index cdf78a5902..9ba3e30445 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -4,6 +4,10 @@ using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Caching; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; @@ -12,6 +16,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit.Compose.Components; +using osuTK; namespace osu.Game.Rulesets.Osu.Edit { @@ -32,9 +37,66 @@ namespace osu.Game.Rulesets.Osu.Edit new SpinnerCompositionTool() }; + [BackgroundDependencyLoader] + private void load() + { + EditorBeatmap.SelectedHitObjects.CollectionChanged += (_, __) => updateDistanceSnapGrid(); + EditorBeatmap.PlacementObject.ValueChanged += _ => updateDistanceSnapGrid(); + + LayerBelowRuleset.Add(distanceSnapGridContainer = new Container { RelativeSizeAxes = Axes.Both }); + } + protected override ComposeBlueprintContainer CreateBlueprintContainer() => new OsuBlueprintContainer(HitObjects); - protected override DistanceSnapGrid CreateDistanceSnapGrid(IEnumerable selectedHitObjects) + private DistanceSnapGrid distanceSnapGrid; + private Container distanceSnapGridContainer; + + private readonly Cached distanceSnapGridCache = new Cached(); + private double? lastDistanceSnapGridTime; + + protected override void Update() + { + base.Update(); + + if (!(BlueprintContainer.CurrentTool is SelectTool)) + { + if (EditorClock.CurrentTime != lastDistanceSnapGridTime) + { + distanceSnapGridCache.Invalidate(); + lastDistanceSnapGridTime = EditorClock.CurrentTime; + } + + if (!distanceSnapGridCache.IsValid) + updateDistanceSnapGrid(); + } + } + + public override SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) + { + if (distanceSnapGrid == null) + return base.SnapScreenSpacePositionToValidTime(screenSpacePosition); + + (Vector2 pos, double time) = distanceSnapGrid.GetSnappedPosition(distanceSnapGrid.ToLocalSpace(screenSpacePosition)); + + return new SnapResult(distanceSnapGrid.ToScreenSpace(pos), time); + } + + private void updateDistanceSnapGrid() + { + distanceSnapGridContainer.Clear(); + distanceSnapGridCache.Invalidate(); + + if (BlueprintContainer.CurrentTool is SelectTool && !EditorBeatmap.SelectedHitObjects.Any()) + return; + + if ((distanceSnapGrid = createDistanceSnapGrid(EditorBeatmap.SelectedHitObjects)) != null) + { + distanceSnapGridContainer.Add(distanceSnapGrid); + distanceSnapGridCache.Validate(); + } + } + + private DistanceSnapGrid createDistanceSnapGrid(IEnumerable selectedHitObjects) { if (BlueprintContainer.CurrentTool is SpinnerCompositionTool) return null; diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index b437d81054..fd8af0afd5 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -3,8 +3,8 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -52,8 +52,9 @@ namespace osu.Game.Rulesets.Edit protected ComposeBlueprintContainer BlueprintContainer { get; private set; } private DrawableEditRulesetWrapper drawableRulesetWrapper; - private Container distanceSnapGridContainer; - private DistanceSnapGrid distanceSnapGrid; + + protected readonly Container LayerBelowRuleset = new Container { RelativeSizeAxes = Axes.Both }; + private readonly List layerContainers = new List(); private InputManager inputManager; @@ -87,7 +88,7 @@ namespace osu.Game.Rulesets.Edit var layerBelowRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChildren(new Drawable[] { - distanceSnapGridContainer = new Container { RelativeSizeAxes = Axes.Both }, + LayerBelowRuleset, new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both } }); @@ -139,7 +140,7 @@ namespace osu.Game.Rulesets.Edit setSelectTool(); - BlueprintContainer.SelectionChanged += selectionChanged; + EditorBeatmap.SelectedHitObjects.CollectionChanged += selectionChanged; } protected override bool OnKeyDown(KeyDownEvent e) @@ -165,16 +166,6 @@ namespace osu.Game.Rulesets.Edit inputManager = GetContainingInputManager(); } - private double lastGridUpdateTime; - - protected override void Update() - { - base.Update(); - - if (EditorClock.CurrentTime != lastGridUpdateTime && !(BlueprintContainer.CurrentTool is SelectTool)) - showGridFor(Enumerable.Empty()); - } - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -188,19 +179,13 @@ namespace osu.Game.Rulesets.Edit }); } - private void selectionChanged(IEnumerable selectedHitObjects) + private void selectionChanged(object sender, NotifyCollectionChangedEventArgs changedArgs) { - var hitObjects = selectedHitObjects.ToArray(); - - if (hitObjects.Any()) + if (EditorBeatmap.SelectedHitObjects.Any()) { // ensure in selection mode if a selection is made. setSelectTool(); - - showGridFor(hitObjects); } - else - distanceSnapGridContainer.Hide(); } private void setSelectTool() => toolboxCollection.Items.First().Select(); @@ -209,30 +194,12 @@ namespace osu.Game.Rulesets.Edit { BlueprintContainer.CurrentTool = tool; - if (tool is SelectTool) - distanceSnapGridContainer.Hide(); - else - { + if (!(tool is SelectTool)) EditorBeatmap.SelectedHitObjects.Clear(); - showGridFor(Enumerable.Empty()); - } - } - - private void showGridFor(IEnumerable selectedHitObjects) - { - distanceSnapGridContainer.Clear(); - distanceSnapGrid = CreateDistanceSnapGrid(selectedHitObjects); - - if (distanceSnapGrid != null) - { - distanceSnapGridContainer.Child = distanceSnapGrid; - distanceSnapGridContainer.Show(); - } - - lastGridUpdateTime = EditorClock.CurrentTime; } public override IEnumerable HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects; + public override bool CursorInPlacementArea => drawableRulesetWrapper.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); protected abstract IReadOnlyList CompositionTools { get; } @@ -257,21 +224,11 @@ namespace osu.Game.Rulesets.Edit if (adjustableClock.CurrentTime < hitObject.StartTime) adjustableClock.Seek(hitObject.StartTime); } - - showGridFor(Enumerable.Empty()); } public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject); - public override SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) - { - if (distanceSnapGrid == null) return new SnapResult(screenSpacePosition, null); - - // TODO: move distance snap grid to OsuHitObjectComposer. - (Vector2 pos, double time) = distanceSnapGrid.GetSnappedPosition(distanceSnapGrid.ToLocalSpace(screenSpacePosition)); - - return new SnapResult(distanceSnapGrid.ToScreenSpace(pos), time); - } + public override SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) => new SnapResult(screenSpacePosition, null); public override float GetBeatSnapDistanceAt(double referenceTime) { @@ -321,14 +278,6 @@ namespace osu.Game.Rulesets.Edit /// public abstract bool CursorInPlacementArea { get; } - /// - /// Creates the applicable for a selection. - /// - /// The selection. - /// The for . If empty, a grid is returned for the current point in time. - [CanBeNull] - protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable selectedHitObjects) => null; - public abstract SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition); public abstract float GetBeatSnapDistanceAt(double referenceTime); diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index e38df3d812..1e8a35c047 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Linq; @@ -29,8 +28,6 @@ namespace osu.Game.Screens.Edit.Compose.Components /// public abstract class BlueprintContainer : CompositeDrawable, IKeyBindingHandler { - public event Action> SelectionChanged; - protected DragBox DragBox { get; private set; } protected Container SelectionBlueprints { get; private set; } @@ -88,8 +85,6 @@ namespace osu.Game.Screens.Edit.Compose.Components SelectionBlueprints.FirstOrDefault(b => b.HitObject == o)?.Deselect(); break; } - - SelectionChanged?.Invoke(selectedHitObjects); }; } From dd09d7830d108ff1de968035507f66199fc2ab57 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 16:37:28 +0900 Subject: [PATCH 02/20] Cache and resolve editor clock as EditorClock in all cases --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 14 +++++-------- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 11 +++++----- .../Edit/Components/PlaybackControl.cs | 11 +++++----- .../Edit/Components/TimeInfoContainer.cs | 5 ++--- .../Timelines/Summary/Parts/MarkerPart.cs | 15 +++++++------ .../Timelines/Summary/SummaryTimeline.cs | 5 ++--- .../Compose/Components/BlueprintContainer.cs | 5 ++--- .../Compose/Components/Timeline/Timeline.cs | 21 +++++++++---------- osu.Game/Screens/Edit/Editor.cs | 3 +-- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 2 +- osu.Game/Tests/Visual/EditorClockTestScene.cs | 3 +-- 11 files changed, 41 insertions(+), 54 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index fd8af0afd5..1987148aed 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Framework.Logging; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Configuration; @@ -38,14 +37,11 @@ namespace osu.Game.Rulesets.Edit protected readonly Ruleset Ruleset; [Resolved] - protected IFrameBasedClock EditorClock { get; private set; } + protected EditorClock EditorClock { get; private set; } [Resolved] protected EditorBeatmap EditorBeatmap { get; private set; } - [Resolved] - private IAdjustableClock adjustableClock { get; set; } - [Resolved] protected IBeatSnapProvider BeatSnapProvider { get; private set; } @@ -68,7 +64,7 @@ namespace osu.Game.Rulesets.Edit } [BackgroundDependencyLoader] - private void load(IFrameBasedClock framedClock) + private void load() { Config = Dependencies.Get().GetConfigFor(Ruleset); @@ -76,7 +72,7 @@ namespace osu.Game.Rulesets.Edit { drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, EditorBeatmap.PlayableBeatmap)) { - Clock = framedClock, + Clock = EditorClock, ProcessCustomClock = false }; } @@ -221,8 +217,8 @@ namespace osu.Game.Rulesets.Edit { EditorBeatmap.Add(hitObject); - if (adjustableClock.CurrentTime < hitObject.StartTime) - adjustableClock.Seek(hitObject.StartTime); + if (EditorClock.CurrentTime < hitObject.StartTime) + EditorClock.Seek(hitObject.StartTime); } } diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index f0b63f8ea5..20584c66e5 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -6,10 +6,10 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose; using osuTK; @@ -30,7 +30,8 @@ namespace osu.Game.Rulesets.Edit /// protected readonly HitObject HitObject; - protected IClock EditorClock { get; private set; } + [Resolved] + protected EditorClock EditorClock { get; private set; } private readonly IBindable beatmap = new Bindable(); @@ -49,12 +50,10 @@ namespace osu.Game.Rulesets.Edit } [BackgroundDependencyLoader] - private void load(IBindable beatmap, IAdjustableClock clock) + private void load(IBindable beatmap) { this.beatmap.BindTo(beatmap); - EditorClock = clock; - ApplyDefaultsToHitObject(); } @@ -84,7 +83,7 @@ namespace osu.Game.Rulesets.Edit } [Resolved(canBeNull: true)] - private IFrameBasedClock editorClock { get; set; } + private EditorClock editorClock { get; set; } /// /// Updates the position of this to a new screen-space position. diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 897c6ec531..59b3d1c565 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; -using osu.Framework.Timing; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -26,7 +25,7 @@ namespace osu.Game.Screens.Edit.Components private IconButton playButton; [Resolved] - private IAdjustableClock adjustableClock { get; set; } + private EditorClock editorClock { get; set; } private readonly BindableNumber tempo = new BindableDouble(1); @@ -87,17 +86,17 @@ namespace osu.Game.Screens.Edit.Components private void togglePause() { - if (adjustableClock.IsRunning) - adjustableClock.Stop(); + if (editorClock.IsRunning) + editorClock.Stop(); else - adjustableClock.Start(); + editorClock.Start(); } protected override void Update() { base.Update(); - playButton.Icon = adjustableClock.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; + playButton.Icon = editorClock.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; } private class PlaybackTabControl : OsuTabControl diff --git a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs index 4bf21d240a..c1f54d7938 100644 --- a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs +++ b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using System; using osu.Framework.Allocation; -using osu.Framework.Timing; using osu.Game.Graphics; namespace osu.Game.Screens.Edit.Components @@ -15,7 +14,7 @@ namespace osu.Game.Screens.Edit.Components private readonly OsuSpriteText trackTimer; [Resolved] - private IAdjustableClock adjustableClock { get; set; } + private EditorClock editorClock { get; set; } public TimeInfoContainer() { @@ -35,7 +34,7 @@ namespace osu.Game.Screens.Edit.Components { base.Update(); - trackTimer.Text = TimeSpan.FromMilliseconds(adjustableClock.CurrentTime).ToString(@"mm\:ss\:fff"); + trackTimer.Text = TimeSpan.FromMilliseconds(editorClock.CurrentTime).ToString(@"mm\:ss\:fff"); } } } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 5d638d7919..82581dfc56 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Threading; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -20,14 +19,14 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// public class MarkerPart : TimelinePart { - private readonly Drawable marker; + private Drawable marker; - private readonly IAdjustableClock adjustableClock; + [Resolved] + private EditorClock editorClock { get; set; } - public MarkerPart(IAdjustableClock adjustableClock) + [BackgroundDependencyLoader] + private void load() { - this.adjustableClock = adjustableClock; - Add(marker = new MarkerVisualisation()); } @@ -59,14 +58,14 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts return; float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); - adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length); + editorClock.Seek(markerPos / DrawWidth * editorClock.TrackLength); }); } protected override void Update() { base.Update(); - marker.X = (float)adjustableClock.CurrentTime; + marker.X = (float)editorClock.CurrentTime; } protected override void LoadBeatmap(WorkingBeatmap beatmap) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs index 20db2cac21..02cd4bccb4 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Timing; using osu.Game.Graphics; using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; @@ -18,11 +17,11 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary public class SummaryTimeline : BottomBarContainer { [BackgroundDependencyLoader] - private void load(OsuColour colours, IAdjustableClock adjustableClock) + private void load(OsuColour colours) { Children = new Drawable[] { - new MarkerPart(adjustableClock) { RelativeSizeAxes = Axes.Both }, + new MarkerPart { RelativeSizeAxes = Axes.Both }, new ControlPointPart { Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 1e8a35c047..fba7671fca 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Primitives; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; -using osu.Framework.Timing; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -38,7 +37,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private IEditorChangeHandler changeHandler { get; set; } [Resolved] - private IAdjustableClock adjustableClock { get; set; } + private EditorClock editorClock { get; set; } [Resolved] private EditorBeatmap beatmap { get; set; } @@ -144,7 +143,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (clickedBlueprint == null) return false; - adjustableClock?.Seek(clickedBlueprint.HitObject.StartTime); + editorClock?.Seek(clickedBlueprint.HitObject.StartTime); return true; } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index ec2b11c0cf..121f3dc213 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -9,7 +9,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; using osu.Framework.Input.Events; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; @@ -25,7 +24,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public readonly IBindable Beatmap = new Bindable(); [Resolved] - private IAdjustableClock adjustableClock { get; set; } + private EditorClock editorClock { get; set; } public Timeline() { @@ -101,7 +100,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Content.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; // This needs to happen after transforms are updated, but before the scroll position is updated in base.UpdateAfterChildren - if (adjustableClock.IsRunning) + if (editorClock.IsRunning) scrollToTrackTime(); } @@ -111,21 +110,21 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (handlingDragInput) seekTrackToCurrent(); - else if (!adjustableClock.IsRunning) + else if (!editorClock.IsRunning) { // The track isn't running. There are two cases we have to be wary of: // 1) The user flick-drags on this timeline: We want the track to follow us // 2) The user changes the track time through some other means (scrolling in the editor or overview timeline): We want to follow the track time // The simplest way to cover both cases is by checking whether the scroll position has changed and the audio hasn't been changed externally - if (Current != lastScrollPosition && adjustableClock.CurrentTime == lastTrackTime) + if (Current != lastScrollPosition && editorClock.CurrentTime == lastTrackTime) seekTrackToCurrent(); else scrollToTrackTime(); } lastScrollPosition = Current; - lastTrackTime = adjustableClock.CurrentTime; + lastTrackTime = editorClock.CurrentTime; } private void seekTrackToCurrent() @@ -133,7 +132,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (!track.IsLoaded) return; - adjustableClock.Seek(Current / Content.DrawWidth * track.Length); + editorClock.Seek(Current / Content.DrawWidth * track.Length); } private void scrollToTrackTime() @@ -141,7 +140,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (!track.IsLoaded || track.Length == 0) return; - ScrollTo((float)(adjustableClock.CurrentTime / track.Length) * Content.DrawWidth, false); + ScrollTo((float)(editorClock.CurrentTime / track.Length) * Content.DrawWidth, false); } protected override bool OnMouseDown(MouseDownEvent e) @@ -164,15 +163,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void beginUserDrag() { handlingDragInput = true; - trackWasPlaying = adjustableClock.IsRunning; - adjustableClock.Stop(); + trackWasPlaying = editorClock.IsRunning; + editorClock.Stop(); } private void endUserDrag() { handlingDragInput = false; if (trackWasPlaying) - adjustableClock.Start(); + editorClock.Start(); } [Resolved] diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 54e4af94a4..54c5a23c3e 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -83,8 +83,7 @@ namespace osu.Game.Screens.Edit clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); - dependencies.CacheAs(clock); - dependencies.CacheAs(clock); + dependencies.CacheAs(clock); // todo: remove caching of this and consume via editorBeatmap? dependencies.Cache(beatDivisor); diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index d9da3ff92d..f3d1ec2cbb 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Edit.Timing private Bindable selectedGroup = new Bindable(); [Resolved] - private IAdjustableClock clock { get; set; } + private EditorClock clock { get; set; } protected override Drawable CreateMainContent() => new GridContainer { diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 830e6ed363..f0ec638fc9 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -30,8 +30,7 @@ namespace osu.Game.Tests.Visual var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); dependencies.Cache(BeatDivisor); - dependencies.CacheAs(Clock); - dependencies.CacheAs(Clock); + dependencies.CacheAs(Clock); return dependencies; } From d18eb663b157d63a2c46816d86f5c3194604bc40 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 16:40:52 +0900 Subject: [PATCH 03/20] Add tweening seek support to EditorClock --- .../Edit/OsuHitObjectComposer.cs | 3 +- .../Visual/Editing/TimelineTestScene.cs | 13 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- .../Timelines/Summary/Parts/MarkerPart.cs | 2 +- .../Compose/Components/BlueprintContainer.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 1 + osu.Game/Screens/Edit/EditorClock.cs | 129 ++++++++++++++++-- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 2 +- 8 files changed, 129 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 9ba3e30445..df14b11e8a 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -104,7 +104,8 @@ namespace osu.Game.Rulesets.Osu.Edit var objects = selectedHitObjects.ToList(); if (objects.Count == 0) - return createGrid(h => h.StartTime <= EditorClock.CurrentTime); + // use accurate time value to give more instantaneous feedback to the user. + return createGrid(h => h.StartTime <= EditorClock.CurrentTimeAccurate); double minTime = objects.Min(h => h.StartTime); return createGrid(h => h.StartTime < minTime, objects.Count + 1); diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index 01ef7e6170..3652d41e67 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -7,7 +7,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; @@ -69,7 +68,7 @@ namespace osu.Game.Tests.Visual.Editing private IBindable beatmap { get; set; } [Resolved] - private IAdjustableClock adjustableClock { get; set; } + private EditorClock adjustableClock { get; set; } public AudioVisualiser() { @@ -102,7 +101,7 @@ namespace osu.Game.Tests.Visual.Editing private class StartStopButton : OsuButton { - private IAdjustableClock adjustableClock; + private EditorClock editorClock; private bool started; public StartStopButton() @@ -115,21 +114,21 @@ namespace osu.Game.Tests.Visual.Editing } [BackgroundDependencyLoader] - private void load(IAdjustableClock adjustableClock) + private void load(EditorClock editorClock) { - this.adjustableClock = adjustableClock; + this.editorClock = editorClock; } private void onClick() { if (started) { - adjustableClock.Stop(); + editorClock.Stop(); Text = "Start"; } else { - adjustableClock.Start(); + editorClock.Start(); Text = "Stop"; } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 1987148aed..edbdd41d81 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -218,7 +218,7 @@ namespace osu.Game.Rulesets.Edit EditorBeatmap.Add(hitObject); if (EditorClock.CurrentTime < hitObject.StartTime) - EditorClock.Seek(hitObject.StartTime); + EditorClock.SeekTo(hitObject.StartTime); } } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 82581dfc56..9e9ac93d23 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts return; float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); - editorClock.Seek(markerPos / DrawWidth * editorClock.TrackLength); + editorClock.SeekTo(markerPos / DrawWidth * editorClock.TrackLength); }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index fba7671fca..cc417bbb10 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -143,7 +143,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (clickedBlueprint == null) return false; - editorClock?.Seek(clickedBlueprint.HitObject.StartTime); + editorClock?.SeekTo(clickedBlueprint.HitObject.StartTime); return true; } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 54c5a23c3e..9f61589c36 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -84,6 +84,7 @@ namespace osu.Game.Screens.Edit clock.ChangeSource(sourceClock); dependencies.CacheAs(clock); + AddInternal(clock); // todo: remove caching of this and consume via editorBeatmap? dependencies.Cache(beatDivisor); diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index e5e47507f3..321a25170a 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -3,6 +3,8 @@ using System; using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -13,7 +15,7 @@ namespace osu.Game.Screens.Edit /// /// A decoupled clock which adds editor-specific functionality, such as snapping to a user-defined beat divisor. /// - public class EditorClock : DecoupleableInterpolatingFramedClock + public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock { public readonly double TrackLength; @@ -21,12 +23,11 @@ namespace osu.Game.Screens.Edit private readonly BindableBeatDivisor beatDivisor; - public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) - { - this.beatDivisor = beatDivisor; + private readonly DecoupleableInterpolatingFramedClock underlyingClock; - ControlPointInfo = beatmap.Beatmap.ControlPointInfo; - TrackLength = beatmap.Track.Length; + public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) + : this(beatmap.Beatmap.ControlPointInfo, beatmap.Track.Length, beatDivisor) + { } public EditorClock(ControlPointInfo controlPointInfo, double trackLength, BindableBeatDivisor beatDivisor) @@ -35,6 +36,8 @@ namespace osu.Game.Screens.Edit ControlPointInfo = controlPointInfo; TrackLength = trackLength; + + underlyingClock = new DecoupleableInterpolatingFramedClock(); } /// @@ -79,20 +82,30 @@ namespace osu.Game.Screens.Edit private void seek(int direction, bool snapped, double amount = 1) { + double current = CurrentTime; + + // if a seek transform is active, use its end time instead of the reported current time. + var existingTransform = Transforms.OfType().FirstOrDefault(); + + // but only if the requested direction is in the same direction as the transform. + // this allows quick pivoting rather than resetting the transform for the first opposite direction movement. + if (existingTransform != null && Math.Sign(existingTransform.EndValue - current) == Math.Sign(direction)) + current = existingTransform.EndValue; + if (amount <= 0) throw new ArgumentException("Value should be greater than zero", nameof(amount)); - var timingPoint = ControlPointInfo.TimingPointAt(CurrentTime); + var timingPoint = ControlPointInfo.TimingPointAt(current); - if (direction < 0 && timingPoint.Time == CurrentTime) + if (direction < 0 && timingPoint.Time == current) // When going backwards and we're at the boundary of two timing points, we compute the seek distance with the timing point which we are seeking into - timingPoint = ControlPointInfo.TimingPointAt(CurrentTime - 1); + timingPoint = ControlPointInfo.TimingPointAt(current - 1); double seekAmount = timingPoint.BeatLength / beatDivisor.Value * amount; - double seekTime = CurrentTime + seekAmount * direction; + double seekTime = current + seekAmount * direction; if (!snapped || ControlPointInfo.TimingPoints.Count == 0) { - Seek(seekTime); + SeekTo(seekTime); return; } @@ -110,7 +123,7 @@ namespace osu.Game.Screens.Edit // Due to the rounding above, we may end up on the current beat. This will effectively cause 0 seeking to happen, but we don't want this. // Instead, we'll go to the next beat in the direction when this is the case - if (Precision.AlmostEquals(CurrentTime, seekTime)) + if (Precision.AlmostEquals(current, seekTime)) { closestBeat += direction > 0 ? 1 : -1; seekTime = timingPoint.Time + closestBeat * seekAmount; @@ -125,7 +138,97 @@ namespace osu.Game.Screens.Edit // Ensure the sought point is within the boundaries seekTime = Math.Clamp(seekTime, 0, TrackLength); - Seek(seekTime); + SeekTo(seekTime); + } + + /// + /// The current time of this clock, include any active transform seeks performed via . + /// + public double CurrentTimeAccurate => + Transforms.OfType().FirstOrDefault()?.EndValue ?? CurrentTime; + + public double CurrentTime => underlyingClock.CurrentTime; + + public void Reset() + { + ClearTransforms(); + underlyingClock.Reset(); + } + + public void Start() + { + ClearTransforms(); + underlyingClock.Start(); + } + + public void Stop() + { + underlyingClock.Stop(); + } + + public bool Seek(double position) + { + ClearTransforms(); + return underlyingClock.Seek(position); + } + + public void ResetSpeedAdjustments() => underlyingClock.ResetSpeedAdjustments(); + + double IAdjustableClock.Rate + { + get => underlyingClock.Rate; + set => underlyingClock.Rate = value; + } + + double IClock.Rate => underlyingClock.Rate; + + public bool IsRunning => underlyingClock.IsRunning; + + public void ProcessFrame() => underlyingClock.ProcessFrame(); + + public double ElapsedFrameTime => underlyingClock.ElapsedFrameTime; + + public double FramesPerSecond => underlyingClock.FramesPerSecond; + + public FrameTimeInfo TimeInfo => underlyingClock.TimeInfo; + + public void ChangeSource(IClock source) => underlyingClock.ChangeSource(source); + + public IClock Source => underlyingClock.Source; + + public bool IsCoupled + { + get => underlyingClock.IsCoupled; + set => underlyingClock.IsCoupled = value; + } + + private const double transform_time = 300; + + public void SeekTo(double seekDestination) + { + if (IsRunning) + Seek(seekDestination); + else + transformSeekTo(seekDestination, transform_time, Easing.OutQuint); + } + + private void transformSeekTo(double seek, double duration = 0, Easing easing = Easing.None) + => this.TransformTo(this.PopulateTransform(new TransformSeek(), seek, duration, easing)); + + private double currentTime + { + get => underlyingClock.CurrentTime; + set => underlyingClock.Seek(value); + } + + private class TransformSeek : Transform + { + public override string TargetMember => nameof(currentTime); + + protected override void Apply(EditorClock clock, double time) => + clock.currentTime = Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + + protected override void ReadIntoStartValue(EditorClock clock) => StartValue = clock.currentTime; } } } diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index f3d1ec2cbb..59af88a049 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Edit.Timing selectedGroup.BindValueChanged(selected => { if (selected.NewValue != null) - clock.Seek(selected.NewValue.Time); + clock.SeekTo(selected.NewValue.Time); }); } From 866db629d6ce60b534e9082652c37c888c3cb42b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 18:23:24 +0900 Subject: [PATCH 04/20] Fix remaining test failures --- .../Visual/Editing/TestScenePlaybackControl.cs | 7 +++---- osu.Game.Tests/Visual/Editing/TimelineTestScene.cs | 14 +++++--------- osu.Game/Screens/Edit/EditorClock.cs | 5 +++++ .../Tests/Visual/PlacementBlueprintTestScene.cs | 3 ++- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs b/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs index 3af976cae0..6aa884a197 100644 --- a/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs @@ -4,8 +4,8 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components; using osuTK; @@ -17,9 +17,8 @@ namespace osu.Game.Tests.Visual.Editing [BackgroundDependencyLoader] private void load() { - var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; - Dependencies.CacheAs(clock); - Dependencies.CacheAs(clock); + var clock = new EditorClock { IsCoupled = false }; + Dependencies.CacheAs(clock); var playback = new PlaybackControl { diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index 01ef7e6170..2e7ccc8ad3 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -102,7 +102,9 @@ namespace osu.Game.Tests.Visual.Editing private class StartStopButton : OsuButton { - private IAdjustableClock adjustableClock; + [Resolved] + private EditorClock editorClock { get; set; } + private bool started; public StartStopButton() @@ -114,22 +116,16 @@ namespace osu.Game.Tests.Visual.Editing Action = onClick; } - [BackgroundDependencyLoader] - private void load(IAdjustableClock adjustableClock) - { - this.adjustableClock = adjustableClock; - } - private void onClick() { if (started) { - adjustableClock.Stop(); + editorClock.Stop(); Text = "Start"; } else { - adjustableClock.Start(); + editorClock.Start(); Text = "Stop"; } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index e5e47507f3..d2bb1c8984 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -37,6 +37,11 @@ namespace osu.Game.Screens.Edit TrackLength = trackLength; } + public EditorClock() + : this(new ControlPointInfo(), 1000, new BindableBeatDivisor()) + { + } + /// /// Seek to the closest snappable beat from a time. /// diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs index feecea473c..c3d74f21aa 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs @@ -8,6 +8,7 @@ using osu.Framework.Timing; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose; namespace osu.Game.Tests.Visual @@ -32,7 +33,7 @@ namespace osu.Game.Tests.Visual protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(new StopwatchClock()); + dependencies.CacheAs(new EditorClock()); return dependencies; } From 8b79e142257652c1914d5381f8942f4cf20c1ae6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 19:49:49 +0900 Subject: [PATCH 05/20] Fix remaining test regressions --- osu.Game.Tests/Visual/Editing/TimelineTestScene.cs | 5 ++--- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index 2e7ccc8ad3..fdb8781563 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -7,7 +7,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; @@ -69,7 +68,7 @@ namespace osu.Game.Tests.Visual.Editing private IBindable beatmap { get; set; } [Resolved] - private IAdjustableClock adjustableClock { get; set; } + private EditorClock editorClock { get; set; } public AudioVisualiser() { @@ -96,7 +95,7 @@ namespace osu.Game.Tests.Visual.Editing base.Update(); if (beatmap.Value.Track.IsLoaded) - marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length); + marker.X = (float)(editorClock.CurrentTime / beatmap.Value.Track.Length); } } diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index f3d1ec2cbb..f22d7291d9 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -7,7 +7,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; @@ -62,7 +61,7 @@ namespace osu.Game.Screens.Edit.Timing private IBindableList controlGroups; [Resolved] - private IFrameBasedClock clock { get; set; } + private EditorClock clock { get; set; } [Resolved] protected IBindable Beatmap { get; private set; } From 12d65f305f24cdfd8dc0792d94eb4c6c5fa2f020 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 22:11:55 +0900 Subject: [PATCH 06/20] Simplify and fix incorrect seeking --- osu.Game/Screens/Edit/EditorClock.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 214b45f654..dd934c10cd 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -87,15 +87,7 @@ namespace osu.Game.Screens.Edit private void seek(int direction, bool snapped, double amount = 1) { - double current = CurrentTime; - - // if a seek transform is active, use its end time instead of the reported current time. - var existingTransform = Transforms.OfType().FirstOrDefault(); - - // but only if the requested direction is in the same direction as the transform. - // this allows quick pivoting rather than resetting the transform for the first opposite direction movement. - if (existingTransform != null && Math.Sign(existingTransform.EndValue - current) == Math.Sign(direction)) - current = existingTransform.EndValue; + double current = CurrentTimeAccurate; if (amount <= 0) throw new ArgumentException("Value should be greater than zero", nameof(amount)); From 83f4ba107f6b97185c0487bb75e45516e73aa52e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 22:41:06 +0900 Subject: [PATCH 07/20] Fix defaults not being applied correctly to blueprints after StartTime is changed --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index e71ccc33a4..90a114bcdc 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -34,6 +34,8 @@ namespace osu.Game.Rulesets.Edit private readonly IBindable beatmap = new Bindable(); + private Bindable startTimeBindable; + [Resolved] private IPlacementHandler placementHandler { get; set; } @@ -55,7 +57,8 @@ namespace osu.Game.Rulesets.Edit EditorClock = clock; - ApplyDefaultsToHitObject(); + startTimeBindable = HitObject.StartTimeBindable.GetBoundCopy(); + startTimeBindable.BindValueChanged(_ => ApplyDefaultsToHitObject(), true); } /// From bc82c2d3b7b6995f77473ea9686f8404e16c3686 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 May 2020 10:44:53 +0900 Subject: [PATCH 08/20] Move drawable addition above event bindings --- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 9ba3e30445..10f0855e33 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -40,10 +40,10 @@ namespace osu.Game.Rulesets.Osu.Edit [BackgroundDependencyLoader] private void load() { + LayerBelowRuleset.Add(distanceSnapGridContainer = new Container { RelativeSizeAxes = Axes.Both }); + EditorBeatmap.SelectedHitObjects.CollectionChanged += (_, __) => updateDistanceSnapGrid(); EditorBeatmap.PlacementObject.ValueChanged += _ => updateDistanceSnapGrid(); - - LayerBelowRuleset.Add(distanceSnapGridContainer = new Container { RelativeSizeAxes = Axes.Both }); } protected override ComposeBlueprintContainer CreateBlueprintContainer() => new OsuBlueprintContainer(HitObjects); From a8dbfe279159b3157b573f99a125c1fd4eda9060 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 May 2020 10:57:17 +0900 Subject: [PATCH 09/20] Fix distance snap grid not disappearing when exiting playfield --- .../Edit/OsuHitObjectComposer.cs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 10f0855e33..62287574ea 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -86,10 +86,24 @@ namespace osu.Game.Rulesets.Osu.Edit distanceSnapGridContainer.Clear(); distanceSnapGridCache.Invalidate(); - if (BlueprintContainer.CurrentTool is SelectTool && !EditorBeatmap.SelectedHitObjects.Any()) - return; + switch (BlueprintContainer.CurrentTool) + { + case SelectTool _: + if (!EditorBeatmap.SelectedHitObjects.Any()) + return; - if ((distanceSnapGrid = createDistanceSnapGrid(EditorBeatmap.SelectedHitObjects)) != null) + distanceSnapGrid = createDistanceSnapGrid(EditorBeatmap.SelectedHitObjects); + break; + + default: + if (!CursorInPlacementArea) + return; + + distanceSnapGrid = createDistanceSnapGrid(Enumerable.Empty()); + break; + } + + if (distanceSnapGrid != null) { distanceSnapGridContainer.Add(distanceSnapGrid); distanceSnapGridCache.Validate(); From edc46d1dce0e8f82e924de8becdb30a787b71031 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Sat, 23 May 2020 16:18:55 +0200 Subject: [PATCH 10/20] Fix osu.Game.Benchmarks --- osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs | 6 +++--- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs b/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs index 394fd75488..a6b7c8fcdb 100644 --- a/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs +++ b/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs @@ -8,7 +8,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.IO; using osu.Game.IO.Archives; -using osu.Game.Resources; +using osu.Game.Tests.Resources; namespace osu.Game.Benchmarks { @@ -18,8 +18,8 @@ namespace osu.Game.Benchmarks public override void SetUp() { - using (var resources = new DllResourceStore(OsuResources.ResourceAssembly)) - using (var archive = resources.GetStream("Beatmaps/241526 Soleily - Renatus.osz")) + using (var resources = new DllResourceStore(typeof(TestResources).Assembly)) + using (var archive = resources.GetStream($"Resources/Archives/241526 Soleily - Renatus.osz")) using (var reader = new ZipArchiveReader(archive)) reader.GetStream("Soleily - Renatus (Gamu) [Insane].osu").CopyTo(beatmapStream); } diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 88fe8f1150..41e726e05c 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -13,6 +13,7 @@ + From de60d509e8ac00b882d091b099f9171dfb4081f3 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Sat, 23 May 2020 17:01:34 +0200 Subject: [PATCH 11/20] Remove redundant string interpolation to fix CI --- osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs b/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs index a6b7c8fcdb..1d207d04c7 100644 --- a/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs +++ b/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs @@ -19,7 +19,7 @@ namespace osu.Game.Benchmarks public override void SetUp() { using (var resources = new DllResourceStore(typeof(TestResources).Assembly)) - using (var archive = resources.GetStream($"Resources/Archives/241526 Soleily - Renatus.osz")) + using (var archive = resources.GetStream("Resources/Archives/241526 Soleily - Renatus.osz")) using (var reader = new ZipArchiveReader(archive)) reader.GetStream("Soleily - Renatus (Gamu) [Insane].osu").CopyTo(beatmapStream); } From c071fe61407440f6035d35f3fef2949036ad402e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 May 2020 13:44:11 +0900 Subject: [PATCH 12/20] Add the ability to export skins --- osu.Game/Beatmaps/BeatmapManager.cs | 23 --------------- osu.Game/Database/ArchiveModelManager.cs | 28 +++++++++++++++++++ .../Overlays/Settings/Sections/SkinSection.cs | 24 ++++++++++++++++ 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b286c054e9..f626b45e42 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -27,7 +27,6 @@ using osu.Game.Online.API.Requests; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; using Decoder = osu.Game.Beatmaps.Formats.Decoder; -using ZipArchive = SharpCompress.Archives.Zip.ZipArchive; namespace osu.Game.Beatmaps { @@ -66,7 +65,6 @@ namespace osu.Game.Beatmaps private readonly AudioManager audioManager; private readonly GameHost host; private readonly BeatmapOnlineLookupQueue onlineLookupQueue; - private readonly Storage exportStorage; public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null, WorkingBeatmap defaultBeatmap = null) @@ -83,7 +81,6 @@ namespace osu.Game.Beatmaps beatmaps.BeatmapRestored += b => beatmapRestored.Value = new WeakReference(b); onlineLookupQueue = new BeatmapOnlineLookupQueue(api, storage); - exportStorage = storage.GetStorageForDirectory("exports"); } protected override ArchiveDownloadRequest CreateDownloadRequest(BeatmapSetInfo set, bool minimiseDownloadSize) => @@ -214,26 +211,6 @@ namespace osu.Game.Beatmaps workingCache.Remove(working); } - /// - /// Exports a to an .osz package. - /// - /// The to export. - public void Export(BeatmapSetInfo set) - { - var localSet = QueryBeatmapSet(s => s.ID == set.ID); - - using (var archive = ZipArchive.Create()) - { - foreach (var file in localSet.Files) - archive.AddEntry(file.Filename, Files.Storage.GetStream(file.FileInfo.StoragePath)); - - using (var outputStream = exportStorage.GetStream($"{set}.osz", FileAccess.Write, FileMode.Create)) - archive.SaveTo(outputStream); - - exportStorage.OpenInNativeExplorer(); - } - } - private readonly WeakList workingCache = new WeakList(); /// diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 33b16cbaaf..3db367555f 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -22,6 +22,7 @@ using osu.Game.IO.Archives; using osu.Game.IPC; using osu.Game.Overlays.Notifications; using osu.Game.Utils; +using SharpCompress.Archives.Zip; using SharpCompress.Common; using FileInfo = osu.Game.IO.FileInfo; @@ -82,6 +83,8 @@ namespace osu.Game.Database // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) private ArchiveImportIPCChannel ipc; + private readonly Storage exportStorage; + protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) { ContextFactory = contextFactory; @@ -90,6 +93,8 @@ namespace osu.Game.Database ModelStore.ItemAdded += item => handleEvent(() => itemAdded.Value = new WeakReference(item)); ModelStore.ItemRemoved += item => handleEvent(() => itemRemoved.Value = new WeakReference(item)); + exportStorage = storage.GetStorageForDirectory("exports"); + Files = new FileStore(contextFactory, storage); if (importHost != null) @@ -369,6 +374,29 @@ namespace osu.Game.Database return item; }, cancellationToken, TaskCreationOptions.HideScheduler, import_scheduler).Unwrap(); + /// + /// Exports an item to an legacy (.zip based) package. + /// + /// The item to export. + public void Export(TModel item) + { + var retrievedItem = ModelStore.ConsumableItems.FirstOrDefault(s => s.ID == item.ID); + + if (retrievedItem == null) + throw new ArgumentException("Specified model count not be found", nameof(item)); + + using (var archive = ZipArchive.Create()) + { + foreach (var file in retrievedItem.Files) + archive.AddEntry(file.Filename, Files.Storage.GetStream(file.FileInfo.StoragePath)); + + using (var outputStream = exportStorage.GetStream($"{item}{HandledExtensions.First()}", FileAccess.Write, FileMode.Create)) + archive.SaveTo(outputStream); + + exportStorage.OpenInNativeExplorer(); + } + } + public void UpdateFile(TModel model, TFileModel file, Stream contents) { using (var usage = ContextFactory.GetForWrite()) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 94080f5592..a89f2c26c8 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Logging; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Skinning; @@ -34,13 +35,33 @@ namespace osu.Game.Overlays.Settings.Sections private IBindable> managerAdded; private IBindable> managerRemoved; + private SettingsButton exportButton; + + private Bindable currentSkin; + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { FlowContent.Spacing = new Vector2(0, 5); + Children = new Drawable[] { skinDropdown = new SkinSettingsDropdown(), + exportButton = new SettingsButton + { + Text = "Export selected skin", + Action = () => + { + try + { + skins.Export(skins.CurrentSkin.Value.SkinInfo); + } + catch (Exception) + { + Logger.Log("Could not export current skin", level: LogLevel.Error); + } + } + }, new SettingsSlider { LabelText = "Menu cursor size", @@ -81,6 +102,9 @@ namespace osu.Game.Overlays.Settings.Sections skinDropdown.Bindable = dropdownBindable; skinDropdown.Items = skins.GetAllUsableSkins().ToArray(); + currentSkin = skins.CurrentSkin.GetBoundCopy(); + currentSkin.BindValueChanged(skin => exportButton.Enabled.Value = skin.NewValue.SkinInfo.ID > 0); + // Todo: This should not be necessary when OsuConfigManager is databased if (skinDropdown.Items.All(s => s.ID != configBindable.Value)) configBindable.Value = 0; From f277b0c99f2a53f7b7bd92e0f748e1e206fe452c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 May 2020 22:30:56 +0900 Subject: [PATCH 13/20] Use better formatting for skin display (matching BeatmapMetadata) --- osu.Game/Skinning/SkinInfo.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index 6b9627188e..b9fe44ef3b 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -24,8 +24,6 @@ namespace osu.Game.Skinning public bool DeletePending { get; set; } - public string FullName => $"\"{Name}\" by {Creator}"; - public static SkinInfo Default { get; } = new SkinInfo { Name = "osu!lazer", @@ -34,6 +32,10 @@ namespace osu.Game.Skinning public bool Equals(SkinInfo other) => other != null && ID == other.ID; - public override string ToString() => FullName; + public override string ToString() + { + string author = Creator == null ? string.Empty : $"({Creator})"; + return $"{Name} {author}".Trim(); + } } } From 234fa2844574e81ac520b90974af0350b750f070 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 May 2020 22:34:31 +0900 Subject: [PATCH 14/20] Ensure export filename is valid --- osu.Game/Database/ArchiveModelManager.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 3db367555f..9fc1bfceb5 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -390,7 +390,7 @@ namespace osu.Game.Database foreach (var file in retrievedItem.Files) archive.AddEntry(file.Filename, Files.Storage.GetStream(file.FileInfo.StoragePath)); - using (var outputStream = exportStorage.GetStream($"{item}{HandledExtensions.First()}", FileAccess.Write, FileMode.Create)) + using (var outputStream = exportStorage.GetStream($"{getValidFilename(item.ToString())}{HandledExtensions.First()}", FileAccess.Write, FileMode.Create)) archive.SaveTo(outputStream); exportStorage.OpenInNativeExplorer(); @@ -738,5 +738,12 @@ namespace osu.Game.Database } #endregion + + private string getValidFilename(string filename) + { + foreach (char c in Path.GetInvalidFileNameChars()) + filename = filename.Replace(c, '_'); + return filename; + } } } From 904d17224f75260783a416170ce6b53ee1edd8c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 May 2020 23:09:38 +0900 Subject: [PATCH 15/20] Fix english --- osu.Game/Database/ArchiveModelManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 9fc1bfceb5..f21f708f95 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -375,7 +375,7 @@ namespace osu.Game.Database }, cancellationToken, TaskCreationOptions.HideScheduler, import_scheduler).Unwrap(); /// - /// Exports an item to an legacy (.zip based) package. + /// Exports an item to a legacy (.zip based) package. /// /// The item to export. public void Export(TModel item) @@ -383,7 +383,7 @@ namespace osu.Game.Database var retrievedItem = ModelStore.ConsumableItems.FirstOrDefault(s => s.ID == item.ID); if (retrievedItem == null) - throw new ArgumentException("Specified model count not be found", nameof(item)); + throw new ArgumentException("Specified model could not be found", nameof(item)); using (var archive = ZipArchive.Create()) { From 8ab65e4c5d3083682ea2fde406dbfcd229fca359 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 May 2020 23:15:24 +0900 Subject: [PATCH 16/20] Move implementation into own class --- .../Overlays/Settings/Sections/SkinSection.cs | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index a89f2c26c8..b84b9fec37 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -35,10 +35,6 @@ namespace osu.Game.Overlays.Settings.Sections private IBindable> managerAdded; private IBindable> managerRemoved; - private SettingsButton exportButton; - - private Bindable currentSkin; - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -47,21 +43,7 @@ namespace osu.Game.Overlays.Settings.Sections Children = new Drawable[] { skinDropdown = new SkinSettingsDropdown(), - exportButton = new SettingsButton - { - Text = "Export selected skin", - Action = () => - { - try - { - skins.Export(skins.CurrentSkin.Value.SkinInfo); - } - catch (Exception) - { - Logger.Log("Could not export current skin", level: LogLevel.Error); - } - } - }, + new ExportSkinButton(), new SettingsSlider { LabelText = "Menu cursor size", @@ -102,9 +84,6 @@ namespace osu.Game.Overlays.Settings.Sections skinDropdown.Bindable = dropdownBindable; skinDropdown.Items = skins.GetAllUsableSkins().ToArray(); - currentSkin = skins.CurrentSkin.GetBoundCopy(); - currentSkin.BindValueChanged(skin => exportButton.Enabled.Value = skin.NewValue.SkinInfo.ID > 0); - // Todo: This should not be necessary when OsuConfigManager is databased if (skinDropdown.Items.All(s => s.ID != configBindable.Value)) configBindable.Value = 0; @@ -141,5 +120,35 @@ namespace osu.Game.Overlays.Settings.Sections protected override DropdownMenu CreateMenu() => base.CreateMenu().With(m => m.MaxHeight = 200); } } + + private class ExportSkinButton : SettingsButton + { + [Resolved] + private SkinManager skins { get; set; } + + private Bindable currentSkin; + + [BackgroundDependencyLoader] + private void load() + { + Text = "Export selected skin"; + Action = export; + + currentSkin = skins.CurrentSkin.GetBoundCopy(); + currentSkin.BindValueChanged(skin => Enabled.Value = skin.NewValue.SkinInfo.ID > 0, true); + } + + private void export() + { + try + { + skins.Export(currentSkin.Value.SkinInfo); + } + catch (Exception e) + { + Logger.Log($"Could not export current skin: {e.Message}", level: LogLevel.Error); + } + } + } } } From b44beb413729bb40dc5294c194454ea0707ddf3e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 May 2020 15:40:25 +0900 Subject: [PATCH 17/20] Remove double resolution of EditorClock --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 1e0507fc0a..e2bb8b5995 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Edit /// protected readonly HitObject HitObject; - [Resolved] + [Resolved(canBeNull: true)] protected EditorClock EditorClock { get; private set; } private readonly IBindable beatmap = new Bindable(); @@ -85,9 +85,6 @@ namespace osu.Game.Rulesets.Edit PlacementActive = false; } - [Resolved(canBeNull: true)] - private EditorClock editorClock { get; set; } - /// /// Updates the position of this to a new screen-space position. /// @@ -95,7 +92,7 @@ namespace osu.Game.Rulesets.Edit public virtual void UpdatePosition(SnapResult snapResult) { if (!PlacementActive) - HitObject.StartTime = snapResult.Time ?? editorClock?.CurrentTime ?? Time.Current; + HitObject.StartTime = snapResult.Time ?? EditorClock?.CurrentTime ?? Time.Current; } /// From cd65fc860b56f7fb2132e547e93ab068e49b308b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 25 May 2020 16:15:55 +0900 Subject: [PATCH 18/20] Remove extra default application --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index e2bb8b5995..3541a78faa 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -56,8 +56,6 @@ namespace osu.Game.Rulesets.Edit { this.beatmap.BindTo(beatmap); - ApplyDefaultsToHitObject(); - startTimeBindable = HitObject.StartTimeBindable.GetBoundCopy(); startTimeBindable.BindValueChanged(_ => ApplyDefaultsToHitObject(), true); } From d09b579aeee7ca9ca75f78e3bc67754882f1800e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 25 May 2020 09:32:24 +0000 Subject: [PATCH 19/20] Bump DiffPlex from 1.6.1 to 1.6.2 Bumps [DiffPlex](https://github.com/mmanela/diffplex) from 1.6.1 to 1.6.2. - [Release notes](https://github.com/mmanela/diffplex/releases) - [Commits](https://github.com/mmanela/diffplex/commits) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 010ef8578a..dbaf0697a0 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -19,7 +19,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 88b0c7dd8a..664a629369 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -75,7 +75,7 @@ - + From c4665048dbd036ee6f492eb45f00bde4a38eedd7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 25 May 2020 09:34:26 +0000 Subject: [PATCH 20/20] Bump SharpCompress from 0.25.0 to 0.25.1 Bumps [SharpCompress](https://github.com/adamhathcock/sharpcompress) from 0.25.0 to 0.25.1. - [Release notes](https://github.com/adamhathcock/sharpcompress/releases) - [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.25...0.25.1) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index dbaf0697a0..d8feb4df24 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -27,7 +27,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 664a629369..6d74be5f85 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -81,7 +81,7 @@ - +