From 43cc20f26f549d6ac0586d93c405adfc577d2382 Mon Sep 17 00:00:00 2001 From: 0thElement Date: Wed, 3 Apr 2024 01:14:30 +0900 Subject: [PATCH] Compose: Improve selection for overlapped notes --- .../Compose/Selection/SelectionService.cs | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/Assets/Scripts/Compose/Selection/SelectionService.cs b/Assets/Scripts/Compose/Selection/SelectionService.cs index 1d80f706..ebfd8c9e 100644 --- a/Assets/Scripts/Compose/Selection/SelectionService.cs +++ b/Assets/Scripts/Compose/Selection/SelectionService.cs @@ -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; @@ -28,10 +29,10 @@ public class SelectionService : MonoBehaviour, ISelectionService [SerializeField] private MarkerRange rangeSelectPreview; private readonly HashSet selectedNotes = new HashSet(); - private float latestSelectedDistance = 0; private bool rangeSelected; private readonly NoteRaycastHit[] hitResults = new NoteRaycastHit[32]; private readonly HashSet search = new HashSet(); + private RaycastHitComparer hitComparer = new RaycastHitComparer(); public event Action> OnSelectionChange; @@ -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) @@ -393,12 +396,10 @@ 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; } @@ -406,7 +407,6 @@ private bool TryGetNoteWithMinDistance(float distance, int amount, out Note note case SelectionMode.Deselected: if (!note.IsSelected) { - latestSelectedDistance = hit.HitDistance; return true; } @@ -471,5 +471,13 @@ public class RequireSelectionAttribute : ContextRequirementAttribute public override bool CheckRequirement() => Selection.Count > 0; } + + private class RaycastHitComparer : IComparer + { + public int Compare(NoteRaycastHit x, NoteRaycastHit y) + { + return x.HitDistance.CompareTo(y.HitDistance); + } + } } } \ No newline at end of file