diff --git a/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs b/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs index e14473c478..c8277af415 100644 --- a/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs +++ b/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils /// internal class FastRandom { - private const double uint_to_real = 1.0 / (uint.MaxValue + 1.0); + private const double int_to_real = 1.0 / (int.MaxValue + 1.0); private const uint int_mask = 0x7FFFFFFF; private const uint y = 842502087; private const uint z = 3579807591; @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils /// Generates a random double value within the range [0, 1). /// /// The random value. - public double NextDouble() => uint_to_real * NextUInt(); + public double NextDouble() => int_to_real * Next(); private uint bitBuffer; private int bitIndex = 32; diff --git a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/OsuHitObjectOverlayLayer.cs b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/OsuHitObjectOverlayLayer.cs new file mode 100644 index 0000000000..e0d1b34ca5 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/OsuHitObjectOverlayLayer.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Edit.Layers.Selection; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection +{ + public class OsuHitObjectOverlayLayer : HitObjectOverlayLayer + { + protected override HitObjectOverlay CreateOverlayFor(DrawableHitObject hitObject) + { + switch (hitObject) + { + case DrawableHitCircle circle: + return new HitCircleOverlay(circle); + case DrawableSlider slider: + return new SliderOverlay(slider); + } + + return base.CreateOverlayFor(hitObject); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/HitCircleOverlay.cs b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/HitCircleOverlay.cs new file mode 100644 index 0000000000..4e64783840 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/HitCircleOverlay.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Rulesets.Edit.Layers.Selection; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; + +namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays +{ + public class HitCircleOverlay : HitObjectOverlay + { + public HitCircleOverlay(DrawableHitCircle hitCircle) + : base(hitCircle) + { + Origin = Anchor.Centre; + + Position = hitCircle.Position; + Size = hitCircle.Size; + Scale = hitCircle.Scale; + + AddInternal(new RingPiece()); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderCircleOverlay.cs b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderCircleOverlay.cs new file mode 100644 index 0000000000..3c7f8a067b --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderCircleOverlay.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Rulesets.Edit.Layers.Selection; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using OpenTK; + +namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays +{ + public class SliderCircleOverlay : HitObjectOverlay + { + public SliderCircleOverlay(DrawableHitCircle sliderHead, DrawableSlider slider) + : this(sliderHead, sliderHead.Position, slider) + { + } + + public SliderCircleOverlay(DrawableSliderTail sliderTail, DrawableSlider slider) + : this(sliderTail, sliderTail.Position, slider) + { + } + + private readonly DrawableOsuHitObject hitObject; + + private SliderCircleOverlay(DrawableOsuHitObject hitObject, Vector2 position, DrawableSlider slider) + : base(hitObject) + { + this.hitObject = hitObject; + + Origin = Anchor.Centre; + + Position = position; + Size = slider.HeadCircle.Size; + Scale = slider.HeadCircle.Scale; + + AddInternal(new RingPiece()); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + } + + protected override void Update() + { + base.Update(); + + RelativeAnchorPosition = hitObject.RelativeAnchorPosition; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderOverlay.cs b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderOverlay.cs new file mode 100644 index 0000000000..a035a683e9 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderOverlay.cs @@ -0,0 +1,57 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Rulesets.Edit.Layers.Selection; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays +{ + public class SliderOverlay : HitObjectOverlay + { + private readonly SliderBody body; + private readonly DrawableSlider slider; + + public SliderOverlay(DrawableSlider slider) + : base(slider) + { + this.slider = slider; + + var obj = (Slider)slider.HitObject; + + InternalChildren = new Drawable[] + { + body = new SliderBody(obj) + { + AccentColour = Color4.Transparent, + PathWidth = obj.Scale * 64 + }, + new SliderCircleOverlay(slider.HeadCircle, slider), + new SliderCircleOverlay(slider.TailCircle, slider), + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + body.BorderColour = colours.Yellow; + } + + protected override void Update() + { + base.Update(); + + Position = slider.Position; + Size = slider.Size; + OriginPosition = slider.OriginPosition; + + // Need to cause one update + body.UpdateProgress(0); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index ae19706da3..70d49a6b4f 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Layers.Selection; using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Osu.Edit.Layers.Selection; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; @@ -29,5 +31,7 @@ namespace osu.Game.Rulesets.Osu.Edit }; protected override ScalableContainer CreateLayerContainer() => new ScalableContainer(OsuPlayfield.BASE_SIZE.X) { RelativeSizeAxes = Axes.Both }; + + protected override HitObjectOverlayLayer CreateHitObjectOverlayLayer() => new OsuHitObjectOverlayLayer(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index ede84e7737..f715ed075c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -23,6 +23,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly List components = new List(); public readonly DrawableHitCircle HeadCircle; + public readonly DrawableSliderTail TailCircle; + public readonly SliderBody Body; public readonly SliderBall Ball; @@ -33,7 +35,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Position = s.StackedPosition; - DrawableSliderTail tail; Container ticks; Container repeatPoints; @@ -54,8 +55,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AlwaysPresent = true, Alpha = 0 }, - HeadCircle = new DrawableHitCircle(s.HeadCircle) { Position = s.HeadCircle.Position - s.Position }, - tail = new DrawableSliderTail(s.TailCircle) { Position = s.TailCircle.Position - s.Position } + HeadCircle = new DrawableHitCircle(s.HeadCircle) { Position = s.TailCircle.Position - s.Position }, + TailCircle = new DrawableSliderTail(s.TailCircle) { Position = s.TailCircle.Position - s.Position } }; components.Add(Body); @@ -63,8 +64,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AddNested(HeadCircle); - AddNested(tail); - components.Add(tail); + AddNested(TailCircle); + components.Add(TailCircle); foreach (var tick in s.NestedHitObjects.OfType()) { @@ -170,7 +171,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => Body.ReceiveMouseInputAt(screenSpacePos); - public override Vector2 SelectionPoint => ToScreenSpace(Body.Position); + public override Vector2 SelectionPoint => ToScreenSpace(OriginPosition); public override Quad SelectionQuad => Body.PathDrawQuad; } } diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index a42dbeeb10..261c0be5eb 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -64,6 +64,10 @@ + + + + diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index 60ddff64ba..4926faa78c 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -6,10 +6,13 @@ using System.Collections.Generic; using osu.Framework.Allocation; using OpenTK; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Layers.Selection; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Edit; +using osu.Game.Rulesets.Osu.Edit.Layers.Selection; +using osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Tests.Beatmaps; @@ -21,7 +24,15 @@ namespace osu.Game.Tests.Visual { typeof(SelectionBox), typeof(SelectionLayer), - typeof(CaptureBox) + typeof(CaptureBox), + typeof(HitObjectComposer), + typeof(OsuHitObjectComposer), + typeof(HitObjectOverlayLayer), + typeof(OsuHitObjectOverlayLayer), + typeof(HitObjectOverlay), + typeof(HitCircleOverlay), + typeof(SliderOverlay), + typeof(SliderCircleOverlay) }; [BackgroundDependencyLoader] diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 1246127257..e6a51cc39b 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -4,14 +4,13 @@ using System; using System.Collections.Generic; using System.Linq; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit.Layers; using osu.Game.Rulesets.Edit.Layers.Selection; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.UI; @@ -50,13 +49,25 @@ namespace osu.Game.Rulesets.Edit return; } - ScalableContainer createLayerContainerWithContent(Drawable content) + HitObjectOverlayLayer hitObjectOverlayLayer = CreateHitObjectOverlayLayer(); + SelectionLayer selectionLayer = new SelectionLayer(rulesetContainer.Playfield); + + var layerBelowRuleset = new BorderLayer { - var container = CreateLayerContainer(); - container.Child = content; - layerContainers.Add(container); - return container; - } + RelativeSizeAxes = Axes.Both, + Child = CreateLayerContainer() + }; + + var layerAboveRuleset = CreateLayerContainer(); + layerAboveRuleset.Children = new Drawable[] + { + selectionLayer, // Below object overlays for input + hitObjectOverlayLayer, + selectionLayer.CreateProxy() // Proxy above object overlays for selections + }; + + layerContainers.Add(layerBelowRuleset); + layerContainers.Add(layerAboveRuleset); RadioButtonCollection toolboxCollection; InternalChild = new GridContainer @@ -82,17 +93,9 @@ namespace osu.Game.Rulesets.Edit RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - createLayerContainerWithContent(new Container - { - Name = "Border", - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderColour = Color4.White, - BorderThickness = 2, - Child = new Box { RelativeSizeAxes = Axes.Both, Alpha = 0, AlwaysPresent = true } - }), + layerBelowRuleset, rulesetContainer, - createLayerContainerWithContent(new SelectionLayer(rulesetContainer.Playfield)) + layerAboveRuleset } } }, @@ -103,6 +106,9 @@ namespace osu.Game.Rulesets.Edit } }; + selectionLayer.ObjectSelected += hitObjectOverlayLayer.AddOverlay; + selectionLayer.ObjectDeselected += hitObjectOverlayLayer.RemoveOverlay; + toolboxCollection.Items = new[] { new RadioButton("Select", () => setCompositionTool(null)) } .Concat( @@ -136,5 +142,10 @@ namespace osu.Game.Rulesets.Edit /// Creates a which provides a layer above or below the . /// protected virtual ScalableContainer CreateLayerContainer() => new ScalableContainer { RelativeSizeAxes = Axes.Both }; + + /// + /// Creates the which overlays selected s. + /// + protected virtual HitObjectOverlayLayer CreateHitObjectOverlayLayer() => new HitObjectOverlayLayer(); } } diff --git a/osu.Game/Rulesets/Edit/Layers/BorderLayer.cs b/osu.Game/Rulesets/Edit/Layers/BorderLayer.cs new file mode 100644 index 0000000000..54c30b8d89 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/BorderLayer.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Edit.Layers +{ + public class BorderLayer : Container + { + protected override Container Content => content; + private readonly Container content; + + public BorderLayer() + { + InternalChildren = new Drawable[] + { + new Container + { + Name = "Border", + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderColour = Color4.White, + BorderThickness = 2, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + }, + content = new Container { RelativeSizeAxes = Axes.Both } + }; + } + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectOverlay.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectOverlay.cs new file mode 100644 index 0000000000..543dd2cc54 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectOverlay.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + public class HitObjectOverlay : OverlayContainer + { + // ReSharper disable once NotAccessedField.Local + // This will be used later to handle drag movement, etc + private readonly DrawableHitObject hitObject; + + public HitObjectOverlay(DrawableHitObject hitObject) + { + this.hitObject = hitObject; + + State = Visibility.Visible; + } + + protected override void PopIn() => Alpha = 1; + protected override void PopOut() => Alpha = 0; + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectOverlayLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectOverlayLayer.cs new file mode 100644 index 0000000000..0b6e63d1fe --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectOverlayLayer.cs @@ -0,0 +1,53 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + public class HitObjectOverlayLayer : CompositeDrawable + { + private readonly Dictionary existingOverlays = new Dictionary(); + + public HitObjectOverlayLayer() + { + RelativeSizeAxes = Axes.Both; + } + + /// + /// Adds an overlay for a which adds movement support. + /// + /// The to create an overlay for. + public void AddOverlay(DrawableHitObject hitObject) + { + var overlay = CreateOverlayFor(hitObject); + if (overlay == null) + return; + + existingOverlays[hitObject] = overlay; + AddInternal(overlay); + } + + /// + /// Removes the overlay for a . + /// + /// The to remove the overlay for. + public void RemoveOverlay(DrawableHitObject hitObject) + { + if (!existingOverlays.TryGetValue(hitObject, out var existing)) + return; + + existing.Hide(); + existing.Expire(); + } + + /// + /// Creates a for a specific . + /// + /// The to create the overlay for. + protected virtual HitObjectOverlay CreateOverlayFor(DrawableHitObject hitObject) => null; + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index bda613f617..3895d34d7f 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -1,8 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -15,6 +17,16 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection { public class SelectionLayer : CompositeDrawable { + /// + /// Invoked when a is selected. + /// + public event Action ObjectSelected; + + /// + /// Invoked when a is deselected. + /// + public event Action ObjectDeselected; + private readonly Playfield playfield; public SelectionLayer(Playfield playfield) @@ -27,11 +39,11 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection private SelectionBox selectionBox; private CaptureBox captureBox; - private readonly List selectedHitObjects = new List(); + private readonly HashSet selectedHitObjects = new HashSet(); protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - clearSelection(); + DeselectAll(); return true; } @@ -74,24 +86,85 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection return true; } + /// + /// Selects a . + /// + /// The to select. + public void Select(DrawableHitObject hitObject) + { + if (!select(hitObject)) + return; + + clearCapture(); + finishSelection(); + } + + /// + /// Selects a without performing capture updates. + /// + /// The to select. + /// Whether was selected. + private bool select(DrawableHitObject hitObject) + { + if (!selectedHitObjects.Add(hitObject)) + return false; + + ObjectSelected?.Invoke(hitObject); + return true; + } + + /// + /// Deselects a . + /// + /// The to deselect. + public void Deselect(DrawableHitObject hitObject) + { + if (!deselect(hitObject)) + return; + + clearCapture(); + finishSelection(); + } + + /// + /// Deselects a without performing capture updates. + /// + /// The to deselect. + /// Whether the was deselected. + private bool deselect(DrawableHitObject hitObject) + { + if (!selectedHitObjects.Remove(hitObject)) + return false; + + ObjectDeselected?.Invoke(hitObject); + return true; + } + /// /// Deselects all selected s. /// - private void clearSelection() + public void DeselectAll() { + selectedHitObjects.ForEach(h => ObjectDeselected?.Invoke(h)); selectedHitObjects.Clear(); - captureBox?.Hide(); - captureBox?.Expire(); + + clearCapture(); } /// /// Selects all hitobjects that are present within the area of a . /// /// The selection . + // Todo: If needed we can severely reduce allocations in this method private void selectQuad(Quad screenSpaceQuad) { - foreach (var obj in playfield.HitObjects.Objects.Where(h => h.IsAlive && h.IsPresent && screenSpaceQuad.Contains(h.SelectionPoint))) - selectedHitObjects.Add(obj); + var expectedSelection = playfield.HitObjects.Objects.Where(h => h.IsAlive && h.IsPresent && screenSpaceQuad.Contains(h.SelectionPoint)).ToList(); + + var toRemove = selectedHitObjects.Except(expectedSelection).ToList(); + foreach (var obj in toRemove) + deselect(obj); + + expectedSelection.ForEach(h => select(h)); } /// @@ -100,11 +173,17 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// The to select at. private void selectPoint(Vector2 screenSpacePoint) { - var selected = playfield.HitObjects.Objects.Reverse().Where(h => h.IsAlive && h.IsPresent).FirstOrDefault(h => h.ReceiveMouseInputAt(screenSpacePoint)); - if (selected == null) + var target = playfield.HitObjects.Objects.Reverse().Where(h => h.IsAlive && h.IsPresent).FirstOrDefault(h => h.ReceiveMouseInputAt(screenSpacePoint)); + if (target == null) return; - selectedHitObjects.Add(selected); + select(target); + } + + private void clearCapture() + { + captureBox?.Hide(); + captureBox?.Expire(); } private void finishSelection() diff --git a/osu.Game/Rulesets/UI/ScalableContainer.cs b/osu.Game/Rulesets/UI/ScalableContainer.cs index 43ed770f77..9762828e7d 100644 --- a/osu.Game/Rulesets/UI/ScalableContainer.cs +++ b/osu.Game/Rulesets/UI/ScalableContainer.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.UI }); } - public class ScaledContainer : Container + private class ScaledContainer : Container { /// /// The value to scale the width of the content to match. diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index b91ff0d74b..3fcb885655 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -143,7 +143,7 @@ namespace osu.Game.Screens.Menu Alpha = 0.5f, Size = new Vector2(0.96f) }, - new BufferedContainer + new Container { AutoSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6d3746e30a..ee45bee80e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -352,7 +352,10 @@ + + +