Hey guys
I am having some difficulty with a custom list which has selection and drag and drop support.
The problem:
- Select object “D” using the Hierarchy window.
- Position mouse pointer over object “A” within Test Window.
- Press and hold left mouse button.
- Notice that object “A” appears selected in both windows.
- Drag mouse downward to initiate drag and drop mode.
- Notice that selection immediately reverts to the pre-mouse-down state.
The video:
The code:
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class TestWindow : EditorWindow {
[MenuItem("Window/Test Window")]
private static void ShowWindow() {
GetWindow<TestWindow>("Test Window");
}
private static IEnumerable<TestBehaviour> GetObjectsInScene() {
return Resources.FindObjectsOfTypeAll(typeof(TestBehaviour))
.Where(r => r.hideFlags != HideFlags.NotEditable r.hideFlags != HideFlags.HideAndDontSave string.IsNullOrEmpty(AssetDatabase.GetAssetPath(r) ))
.Cast<TestBehaviour>()
.OrderBy(r => r.name);
}
private static Vector2 s_MouseAnchorPosition;
private static GUIStyle s_ListItemStyle;
private void OnGUI() {
if (s_ListItemStyle == null)
s_ListItemStyle = "PR Label";
GUILayout.Space(-10);
foreach (var obj in GetObjectsInScene()) {
int controlID = GUIUtility.GetControlID(FocusType.Passive);
var content = new GUIContent(obj.name);
Rect position = GUILayoutUtility.GetRect(content, s_ListItemStyle);
position.width = Screen.width;
switch (Event.current.GetTypeForControl(controlID)) {
case EventType.MouseDown:
if (Event.current.button == 0 position.Contains(Event.current.mousePosition)) {
GUIUtility.hotControl = controlID;
s_MouseAnchorPosition = Event.current.mousePosition;
// 1. Adjust selection on mouse down.
Selection.objects = new Object[] { obj.gameObject };
Event.current.Use();
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == controlID) {
// Has user initiated drag and drop by breaking the 6px threshold?
if (Vector2.Distance(s_MouseAnchorPosition, Event.current.mousePosition) > 6) {
GUIUtility.hotControl = 0;
// 2. Start drag and drop.
DragAndDrop.PrepareStartDrag();
DragAndDrop.objectReferences = new Object[] { obj };
DragAndDrop.StartDrag(obj.name);
}
Event.current.Use();
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == controlID) {
GUIUtility.hotControl = 0;
Event.current.Use();
}
break;
case EventType.Repaint:
s_ListItemStyle.Draw(position, content, focusedWindow == this, false, Selection.activeObject == obj.gameObject, false);
break;
}
}
}
private void OnSelectionChange() {
Repaint();
}
private void OnHierarchyChange() {
Repaint();
}
}
Notes:
- The problem occurs as soon as DragAndDrop.StartDrag is invoked.
- Attempting to immediately restore the selection after starting drag fails.
Any help at fixing this problem would be super useful!