Skip to content

Commit

Permalink
Compose: Improve selection for overlapped notes
Browse files Browse the repository at this point in the history
  • Loading branch information
0thElement committed Apr 2, 2024
1 parent 6ac62f3 commit 43cc20f
Showing 1 changed file with 28 additions and 20 deletions.
48 changes: 28 additions & 20 deletions Assets/Scripts/Compose/Selection/SelectionService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using ArcCreate.Compose.Navigation;
using ArcCreate.Compose.Popups;
using ArcCreate.Compose.Timeline;
Expand Down Expand Up @@ -28,10 +29,10 @@ public class SelectionService : MonoBehaviour, ISelectionService
[SerializeField] private MarkerRange rangeSelectPreview;

private readonly HashSet<Note> selectedNotes = new HashSet<Note>();
private float latestSelectedDistance = 0;
private bool rangeSelected;
private readonly NoteRaycastHit[] hitResults = new NoteRaycastHit[32];
private readonly HashSet<Note> search = new HashSet<Note>();
private RaycastHitComparer hitComparer = new RaycastHitComparer();

public event Action<HashSet<Note>> OnSelectionChange;

Expand Down Expand Up @@ -336,27 +337,29 @@ private bool TryGetNoteUnderCursor(out Note note, SelectionMode selectionMode)
Ray ray = gameplayCamera.ScreenPointToRay(mousePosition);

int amount = NoteRaycaster.Raycast(ray, hitResults, 99999);
Array.Sort(hitResults, 0, amount, hitComparer);

if (TryGetNoteWithMinDistance(latestSelectedDistance, amount, out note, selectionMode))
{
return true;
}
else
{
return TryGetNoteWithMinDistance(0, amount, out note, selectionMode);
}
}
int length = Mathf.Min(hitResults.Length, amount);
int initialOffset = 0;
bool skipOne = false;

private bool TryGetNoteWithMinDistance(float distance, int amount, out Note note, SelectionMode selectionMode)
{
for (int i = 0; i < Mathf.Min(hitResults.Length, amount); i++)
if (selectionMode == SelectionMode.Any)
{
NoteRaycastHit hit = hitResults[i];

if (hit.HitDistance <= distance)
for (int i = 0; i < length; i++)
{
continue;
NoteRaycastHit hit = hitResults[i];
if (SelectedNotes.Contains(hit.Note))
{
initialOffset = i + 1;
skipOne = true;
}
}
}

int loopNum = skipOne ? length - 1 : length;
for (int i = 0; i < loopNum; i++)
{
NoteRaycastHit hit = hitResults[(i + initialOffset) % length];

if (hit.HitPoint.z >= Gameplay.Values.TrackLengthBackward
|| hit.HitPoint.z <= -Gameplay.Values.TrackLengthForward)
Expand Down Expand Up @@ -393,20 +396,17 @@ private bool TryGetNoteWithMinDistance(float distance, int amount, out Note note
switch (selectionMode)
{
case SelectionMode.Any:
latestSelectedDistance = hit.HitDistance;
return true;
case SelectionMode.Selected:
if (note.IsSelected)
{
latestSelectedDistance = hit.HitDistance;
return true;
}

break;
case SelectionMode.Deselected:
if (!note.IsSelected)
{
latestSelectedDistance = hit.HitDistance;
return true;
}

Expand Down Expand Up @@ -471,5 +471,13 @@ public class RequireSelectionAttribute : ContextRequirementAttribute

public override bool CheckRequirement() => Selection.Count > 0;
}

private class RaycastHitComparer : IComparer<NoteRaycastHit>
{
public int Compare(NoteRaycastHit x, NoteRaycastHit y)
{
return x.HitDistance.CompareTo(y.HitDistance);
}
}
}
}

0 comments on commit 43cc20f

Please sign in to comment.