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

Add support for dragging and dropping multiple scene files on lists (& other collections) #85

Open
JoaoMagal opened this issue Dec 21, 2023 · 7 comments
Assignees
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@JoaoMagal
Copy link

JoaoMagal commented Dec 21, 2023

The issue:

The package doesn't allow populating a List of SceneReferences with multiple scene files in the inspector (via box selecting multiple files and dragging and dropping in the component's inspector).

Expected behavior:

Dragging and dropping multiple scene files into an list of SceneReferences should allow populating that list with the dropped files.

Steps to reproduce:

  1. Open Unity with any project containing the package
  2. Create an empty object and add a script to it
  3. Inside that script, add a variable of type List<SceneReference>;
  4. Back in the Unity inspector, select multiple scene files and try dragging them into the newly-created List variable; This should not be possible, even though it "would" be expected (as it is a pretty common QoL improvement)

Other

sceneRef_issue.mp4
@starikcetin
Copy link
Owner

This can be a bit tricky, but I'll see what we can do.

@starikcetin starikcetin self-assigned this Dec 22, 2023
@starikcetin starikcetin added the enhancement New feature or request label Dec 22, 2023
@JoaoMagal
Copy link
Author

JoaoMagal commented Dec 22, 2023

Fortunately, Unity does provide some tools for working with drag and drop on the editor - here's a link to the DragAndDrop class docs.

From what I've read, you can't implement PropertyDrawer scripts directy to generic classes such as List<>, which makes things even more complicated (in a personal project I'm using a wrapper for the list, and a drawer script for that wrapper). Don't know what happens to the list drawer if you implement the DragAndDrop operations directly to the SceneReference drawer script though.

Most implementations I've seen iterate over the DragAndDrop.objectReferences variable, casting and adding objects to the list in question, but you don't have access to the list inside the PropertDrawer script, so that's another issue too.

The drag and drop logic (probably) will look something like this:

public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
    if (position.Contains(Event.current.mousePosition))
    {
        if (Event.current.type == EventType.DragUpdated
        || Event.current.type == EventType.DragPerform)
        {
            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;

            if (Event.current.type == EventType.DragPerform)
            {
                 DragAndDrop.AcceptDrag();

                 foreach (Object draggedObj in DragAndDrop.objectReferences)
                 {
                     Debug.Log(draggedObj as SceneAsset);
                     // From here do whatever you want with the draggedObj.
                 }
             }
             Event.current.Use();
        }
    }
}

@starikcetin
Copy link
Owner

I could not devise a pretty way to do this consistently. I am leaving the issue open until I devise a good approach, or someone smarter than me decides to take a stab at it. I am happy to accept PRs.

@starikcetin starikcetin added the help wanted Extra attention is needed label Dec 23, 2023
@starikcetin starikcetin pinned this issue Dec 23, 2023
@JoaoMagal
Copy link
Author

JoaoMagal commented Dec 23, 2023

I'll take a swing at it pretty soon enough. I got my editor script working on instancing my wrapper classes, so I'll see if I can work around making a property drawer for List<SceneReference> types, and adapting my script to the package. Did you happen to find anything about that (making drawers for lists)?

@starikcetin
Copy link
Owner

starikcetin commented Dec 23, 2023

I'll take a swing at it pretty soon enough. I got my editor script working on instancing my wrapper classes, so I'll see if I can work around making a property drawer for List<SceneReference> types, and adapting my script to the package. Did you happen to find anything about that (making drawers for lists)?

Let me run you through what I have thought of so far. I rejected all the options in my head for the reasons given:

  1. A dummy wrapper class SceneReferenceList : List<SceneReference> to be used instead of List<SceneReference>. Then we would write a property drawer for the wrapper. This is the sanest option, but has the obvious drawback of introducing another type to the hierarchy.
  2. Custom editor for UnityEngine.Object. This has the very high risk of colliding with other custom editors.
  3. Tapping into Unity's internals with reflection or IL patching. This is very brittle and dangerous.
  4. Doing it in the existing SceneReference property drawer as you suggested. This has a couple of issues. First is we don't have a way to access the drawing rect of the list header, we can only approximate it. Second, if the list doesn't already have any SceneReferences in it, then the property drawer doesn't even run, which is inconsistent behavior.

As far as I know, it is not possible to overwrite List drawing with property drawers, but that might have changed since the last time I tried it.

@JoaoMagal
Copy link
Author

Gonna give a go at 4; I was flirting around with the constants in EditorGUIUtility (singeLineHeight, standardVerticalSpacing and so on) and with the idea of getting the list via the serialized object. If I come up with something, I'll open up a PR.

@Ale1
Copy link
Contributor

Ale1 commented Feb 27, 2024

I took a stab at this and reached the same conclusion as @starikcetin; i.e that there seems to be no elegant way of doing this without a (a) wrapper on List, or (b) dangerous touching of shared classes like Object or ReorderableLists or (c) forcing property drawers to do something it was not meant to do, potentially breaking things in unexpected ways or inconsistent behaviour between unity versions.

IMHO, best solution might be to paste a link to an example in the documentation to a blob with code to a custom inspector that implements this functionality via an approach similar to: https://gist.github.com/bzgeb/3800350. That way users that need it can create their own inspector.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants