Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite editor selections to better handle selection and movement logic #2329

Merged
merged 51 commits into from Apr 6, 2018

Conversation

smoogipoo
Copy link
Contributor

@smoogipoo smoogipoo commented Mar 29, 2018

Fixes #2211
Fixes hitobjects not moving on drag.

It'd be a good idea to go through this in code, rather than looking at the diff, since most of everything besides HitObjectMask doesn't work the same way anymore.

The general idea behind this is that we need the masks to handle mouse down events, as they need to handle the drag (mousedown -> drag immediately).

I've rewritten the editor selections to use HitObjectMask events, as there are some 3-4 different components that handle/trigger selections in different ways.

  1. All selections/deselections now propagate through HitObjectMask.Select()/HitObjectMask.Deselect().
  2. Components that react to changes in the selection bind to the masks' Selected/Deselected events, and track them/change their states locally.
  3. SelectionBox renamed to Selection (with an internal box), and now handles all single-click-selection + drag-movement logic.
  4. DragBox now handles all drag input locally. It triggers Select/Deselect on the masks it needs to.
  5. DragBox handles the display of itself.
  6. Selection handles the display of its box itself.
  7. Selection handles movement of selections.

Note that the HitObjectMaskLayer.Select() and HitObjectMaskLayer.Deselect() methods have been removed. We'll probably want these back in the future, but it's too early for them. They'd be easy to implement anyway ^^.

The general idea here is that we need the masks to handle mouse down events, as they need to handle the drag (mousedown -> drag immediately).

I've rewritten the editor selections to use events, as there are some 3 different components that handle/trigger selections in different ways.

1. All selections/deselections now propagate through `HitObjectMask.Select()`/`HitObjectMask.Deselect()`.
2. Components that react to changes in the selection bind to the masks' `Selected`/`Deselected` events, and track them/change their states locally.
3. Masks provide a `SingleSelectionRequested` event which is invoked on the mouse-down event. Various components bind to this event to perform state changes locally in this scenario.
4. `DragBox` now handles all drag input locally. It triggers `Select`/`Deselect` on the masks it needs to.
5. `SelectionBox` handles the display of itself locally.
6. `SelectionBox` handles movement of groups of masks locally.
7. `HitObjectMasks` handles movement of itself locally.
@smoogipoo
Copy link
Contributor Author

Also this has allowed us to move the SelectionPoint/SelectionQuad stuff from DrawableHitObject to HitObjectMask, no more pollution of hitobjects with editor stuff :D/

@peppy peppy changed the title Selectionlayer rewrite SelectionLayer rewrite Mar 30, 2018
@smoogipoo smoogipoo changed the title SelectionLayer rewrite Rewrite editor selections to better handle selection and movement logic Apr 2, 2018
/// <summary>
/// A box that handles and displays drag selection for a collection of <see cref="HitObjectMask"/>s.
/// </summary>
public class DragBox : CompositeDrawable

This comment was marked as off-topic.

box.Position = topLeft;
box.Size = bottomRight - topLeft;

foreach (var mask in maskContainer.AliveMasks)

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

@@ -24,14 +25,22 @@ public class HitObjectMask : VisibilityContainer
/// </summary>
public event Action<HitObjectMask> Deselected;

/// <summary>
/// Invoked when this <see cref="HitObjectMask"/> has rqeuested selection.

This comment was marked as off-topic.

/// <summary>
/// The <see cref="DrawableHitObject"/> which this <see cref="HitObjectMask"/> applies to.
/// </summary>
public readonly DrawableHitObject HitObject;

protected override bool ShouldBeAlive => HitObject.IsAlive || State == Visibility.Visible;
public override bool RemoveWhenNotAlive => false;
public override bool HandleMouseInput => HitObject.IsPresent;

public override bool HandleMouseInput => ShouldBeAlive;

This comment was marked as off-topic.

This comment was marked as off-topic.

{
this.maskContainer = maskContainer;

this.performSelection = performSelection;

This comment was marked as off-topic.

@@ -33,23 +33,29 @@ private void load()
{
maskContainer = new MaskContainer();

selectionBox = composer.CreateSelectionBox(maskContainer);
maskSelection = composer.CreateSelectionBox(maskContainer);

This comment was marked as off-topic.

@@ -22,17 +23,25 @@ public class MaskContainer : Container<HitObjectMask>
/// </summary>
public event Action<HitObjectMask> MaskDeselected;

public event Action<HitObjectMask> MaskSelectionRequested;

This comment was marked as off-topic.

{
// todo: remove this

This comment was marked as off-topic.

@@ -63,39 +63,23 @@ private void load(OsuColour colours)

#region User Input Handling

// Only handle input on selectable or selected masks
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => selectableMasks.Reverse().Concat(selectedMasks).Any(m => m.ReceiveMouseInputAt(screenSpacePos));
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true;

This comment was marked as off-topic.


DeselectAll();
selectableMasks.Reverse().First(m => m.ReceiveMouseInputAt(state.Mouse.NativeState.Position)).Select();
protected override bool OnDragStart(InputState state) => handleInput(state);

This comment was marked as off-topic.

public void DeselectAll() => selectedMasks.ToList().ForEach(m => m.Deselect());
private void onSelectionRequested(HitObjectMask mask)
{
if (GetContainingInputManager().CurrentState.Keyboard.ControlPressed)

This comment was marked as off-topic.

Copy link
Contributor Author

@smoogipoo smoogipoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good apart from 2 more comments.

return false;
selectionRequested = false;

if (State == SelectionState.NotSelected && !selectionRequested)

This comment was marked as off-topic.

{
if (mask.IsSelected)
return;

This comment was marked as off-topic.

@smoogipoo
Copy link
Contributor Author

Input is no longer ordered correctly: https://streamable.com/3e8lo

@smoogipoo
Copy link
Contributor Author

This feels weird: https://streamable.com/kcvwy Click+dragging on a mask that is not selected but rests on top of a selected mask will transfer the selection to the clicked mask. Regressed by the previous change.

@smoogipoo
Copy link
Contributor Author

Looks good to me

peppy
peppy previously approved these changes Apr 6, 2018
@peppy peppy merged commit b91f538 into ppy:master Apr 6, 2018
@smoogipoo smoogipoo deleted the selectionlayer-rewrite branch June 15, 2018 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants