public static PickingObject PickGameObject(Vector2 mousePosition) { s_RetainHashes = true; var enumerator = GetAllOverlapping(mousePosition).GetEnumerator(); if (!enumerator.MoveNext()) { return(PickingObject.Empty); } PickingObject topmost = enumerator.Current; var pickingBase = topmost.TryGetComponent(out Transform trs) ? HandleUtility.FindSelectionBaseForPicking(trs) : null; // Selection base is only interesting if it's not the topmost PickingObject selectionBase = new PickingObject(pickingBase); PickingObject first = selectionBase.target == null ? topmost : selectionBase; int topmostHash = topmost.GetHashCode(); int prefixHash = topmostHash; if (Selection.activeObject == null) { // Nothing selected // Return selection base if it exists, otherwise topmost game object s_PreviousTopmostHash = topmostHash; s_PreviousPrefixHash = prefixHash; return(first); } if (topmostHash != s_PreviousTopmostHash) { // Topmost game object changed // Return selection base if exists and is not already selected, otherwise topmost game object s_PreviousTopmostHash = topmostHash; s_PreviousPrefixHash = prefixHash; return(Selection.activeObject == selectionBase.target ? topmost : first); } s_PreviousTopmostHash = topmostHash; // Pick potential selection base before topmost game object if (Selection.activeObject == selectionBase.target) { if (prefixHash == s_PreviousPrefixHash) { return(topmost); } s_PreviousPrefixHash = prefixHash; return(selectionBase); } s_ActiveObjectFilter.Clear(); s_ActiveObjectFilter.Add((PickingObject)Selection.activeObject); // Check if active game object will appear in selection stack PickingObject picked = HandleUtility.PickObject(mousePosition, false, null, s_ActiveObjectFilter); if (picked == ((PickingObject)Selection.activeObject)) { // Advance enumerator to active game object while (enumerator.Current != ((PickingObject)Selection.activeObject)) { if (!enumerator.MoveNext()) { s_PreviousPrefixHash = topmostHash; return(first); // Should not occur } UpdateHash(ref prefixHash, enumerator.Current); } } if (prefixHash != s_PreviousPrefixHash) { // Prefix hash changed, start over s_PreviousPrefixHash = topmostHash; return(first); } // Move on to next game object if (!enumerator.MoveNext()) { s_PreviousPrefixHash = topmostHash; return(first); // End reached, start over } UpdateHash(ref prefixHash, enumerator.Current); if (enumerator.Current == selectionBase) { // Skip selection base if (!enumerator.MoveNext()) { s_PreviousPrefixHash = topmostHash; return(first); // End reached, start over } UpdateHash(ref prefixHash, enumerator.Current); } s_PreviousPrefixHash = prefixHash; return(enumerator.Current); }
static void UpdateHash(ref int hash, PickingObject obj) { hash = unchecked (hash * 33 + obj.GetHashCode()); }