diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index ddf6cd0f57..abe8be530a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public partial class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler, IHasContextMenu where T : OsuHitObject, IHasPath { - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; // allow context menu to appear outside of the playfield. + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; // allow context menu to appear outside the playfield. internal readonly Container> Pieces; @@ -196,6 +196,7 @@ private void onControlPointsChanged(object sender, NotifyCollectionChangedEventA if (allowSelection) d.RequestSelection = selectionRequested; + d.ControlPoint.Changed += controlPointChanged; d.DragStarted = DragStarted; d.DragInProgress = DragInProgress; d.DragEnded = DragEnded; @@ -209,6 +210,8 @@ private void onControlPointsChanged(object sender, NotifyCollectionChangedEventA foreach (var point in e.OldItems.Cast()) { + point.Changed -= controlPointChanged; + foreach (var piece in Pieces.Where(p => p.ControlPoint == point).ToArray()) piece.RemoveAndDisposeImmediately(); } @@ -217,6 +220,8 @@ private void onControlPointsChanged(object sender, NotifyCollectionChangedEventA } } + private void controlPointChanged() => updateCurveMenuItems(); + protected override bool OnClick(ClickEvent e) { if (Pieces.Any(piece => piece.IsHovered)) @@ -318,6 +323,13 @@ protected override bool OnKeyDown(KeyDownEvent e) } } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + foreach (var p in Pieces) + p.ControlPoint.Changed -= controlPointChanged; + } + private void selectionRequested(PathControlPointPiece piece, MouseButtonEvent e) { if (e.Button == MouseButton.Left && inputManager.CurrentState.Keyboard.ControlPressed) @@ -328,7 +340,7 @@ private void selectionRequested(PathControlPointPiece piece, MouseButtonEvent /// /// Attempts to set all selected control point pieces to the given path type. - /// If that would fail, try to change the path such that it instead succeeds + /// If that fails, try to change the path such that it instead succeeds /// in a UX-friendly way. /// /// The path type we want to assign to the given control point piece. @@ -371,6 +383,8 @@ private void updatePathTypeOfSelectedPieces(PathType? type) private int draggedControlPointIndex; private HashSet selectedControlPoints; + private List curveTypeItems; + public void DragStarted(PathControlPoint controlPoint) { dragStartPositions = hitObject.Path.ControlPoints.Select(point => point.Position).ToArray(); @@ -467,7 +481,7 @@ public MenuItem[] ContextMenuItems var splittablePieces = selectedPieces.Where(isSplittable).ToList(); int splittableCount = splittablePieces.Count; - List curveTypeItems = new List(); + curveTypeItems = new List(); if (!selectedPieces.Contains(Pieces[0])) { @@ -505,25 +519,39 @@ public MenuItem[] ContextMenuItems () => DeleteSelected()) ); + updateCurveMenuItems(); + return menuItems.ToArray(); + + CurveTypeMenuItem createMenuItemForPathType(PathType? type) => new CurveTypeMenuItem(type, _ => updatePathTypeOfSelectedPieces(type)); } } - private MenuItem createMenuItemForPathType(PathType? type) + private void updateCurveMenuItems() { - int totalCount = Pieces.Count(p => p.IsSelected.Value); - int countOfState = Pieces.Where(p => p.IsSelected.Value).Count(p => p.ControlPoint.Type == type); + foreach (var item in curveTypeItems.OfType()) + { + int totalCount = Pieces.Count(p => p.IsSelected.Value); + int countOfState = Pieces.Where(p => p.IsSelected.Value).Count(p => p.ControlPoint.Type == item.PathType); - var item = new TernaryStateRadioMenuItem(type?.Description ?? "Inherit", MenuItemType.Standard, _ => updatePathTypeOfSelectedPieces(type)); + if (countOfState == totalCount) + item.State.Value = TernaryState.True; + else if (countOfState > 0) + item.State.Value = TernaryState.Indeterminate; + else + item.State.Value = TernaryState.False; + } + } - if (countOfState == totalCount) - item.State.Value = TernaryState.True; - else if (countOfState > 0) - item.State.Value = TernaryState.Indeterminate; - else - item.State.Value = TernaryState.False; + private class CurveTypeMenuItem : TernaryStateRadioMenuItem + { + public readonly PathType? PathType; - return item; + public CurveTypeMenuItem(PathType? pathType, Action action) + : base(pathType?.Description ?? "Inherit", MenuItemType.Standard, action) + { + PathType = pathType; + } } } }