• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by svendkiloo · Jun 27, 2019 at 08:53 AM · editoreditor-scriptingprogrammingpropertydrawer

Why does my custom property drawer's DragAndDrop add items twice?

I've got a custom property drawer, with this code in it's OnGui:


 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
 {
     SerializedProperty serialisedList = property.FindPropertyRelative("_serialisedName");
     switch (Event.current.type)
     {
         case EventType.DragUpdated:
             DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
             Event.current.Use();
             break;
         case EventType.DragPerform:
             DragAndDrop.AcceptDrag();

             foreach (Object draggedObject in DragAndDrop.objectReferences)
             {
                 if (draggedObject is GameObject addedGameObject)
                 {
                     MyClass addedItem = addedGameObject.GetComponent<MyClass>();
                     if (addedItem != null)
                     {
                         int index = serialisedList.arraySize;
                         serialisedList.InsertArrayElementAtIndex(index);
                         serialisedList.GetArrayElementAtIndex(index).objectReferenceValue = addedItem;
                     }
                 }
             }

             break;
     }

This works perfectly when dragging an item onto the "frame" of the list (i.e. not onto an item slot in the list). However, if I drag an item onto an item in the list, the above code is executed, but the item is also added at the end of the list. Is there a way to either:


a) Detect that the drag is onto an item, and avoid executing the code above.

b) Somehow avoid that the item assignment is performed. I'm not sure what's causing that.


I would prefer solution a), as that would still allow assigning items to specific slots, effectively overwriting the existing entries, but b) would also be acceptable. The advantage of b) is that it's not as easy to accidentally overwrite an item, when you really meant to just add one. It would mean that dragging an item onto the list would always have the same effect, regardless of where it's dragged (but it would work differently from the standard lists).


EDIT: Also, if I drop elements onto other lists in the same component, it ALSO adds them to this list.

Comment

People who like this

0 Show 0
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image

Answer by Bunny83 · Jul 13, 2019 at 09:03 AM

You don't check the mouse position at all. So currently you should be able to drop your item anywhere in the inspector window, not only on your list. We don't know for what element you designed your property drawer for. A propertydrawer is meant to handle the drawing of that one SerializedProperty. You can't get access to other properties as you don't know where they are drawn inside the inspector. So it highly depends on how your actual serialized data looks like, to which property this drawer is attached to and how you draw the properties.


In any way you have to do this for the whole list and mask the events for the list / array header. You can do rect.Contains(Event.current.mousePosition) to see if the mouse is inside that rect. Keep in mind that you have to do this in both cases. So for DragUpdated to actually show the correct visual and in DragPerform to restrict the dropping to that area. But again, which rect you should use depends on which property this drawer belongs to. By default a single "line" has a height of 15 pixel which is provided in EditorGUIUtility.singleLineHeight.

Comment
svendkiloo

People who like this

1 Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Jul 13, 2019 at 09:22 AM 1
Share

For reference you may want to have a look at my IMGUI crash course

avatar image svendkiloo · Jul 15, 2019 at 07:05 AM 0
Share

OK, so I manually have to check the mouse position to know when the dragging is actually happening on my property's area. Oh, and moving the above code below the actual displaying seems to fix the adding-twice when dropping into an element :)

avatar image svendkiloo · Jul 15, 2019 at 07:23 AM 0
Share

(I've added another answer as well, just to put the code in, in case it's useful to anyone else)

avatar image

Answer by svendkiloo · Jul 15, 2019 at 07:14 AM

With the help from @Bunny83 and some trial and error I found this solution to both problems:


  1. Adding the check on mouse position against the rect of the property drawer.

  2. Moving the drag-handling code below the displaying code.


So, what I ended up with looks a bit like this:


 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
 {
     Rect position = originalPosition; // Saving the originalPosition value, as my displaying code updates position

 ... // I've left out the displaying code here

     SerializedProperty serialisedList = property.FindPropertyRelative("_serialisedName");
     if (originalPosition.Contains(Event.current.mousePosition))
     {
         switch (Event.current.type)
         {
             case EventType.DragUpdated:
                 DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                 Event.current.Use();
                 break;
             case EventType.DragPerform:
                 DragAndDrop.AcceptDrag();
                 foreach (Object draggedObject in DragAndDrop.objectReferences)
                 {
                     if (draggedObject is GameObject addedGameObject)
                     {
                         MyClass addedItem = addedGameObject.GetComponent<MyClass>();
                         if (addedItem != null)
                         {
                             int index = serialisedList.arraySize;
                             serialisedList.InsertArrayElementAtIndex(index);
                             serialisedList.GetArrayElementAtIndex(index).objectReferenceValue = addedItem;
                         }
                     }
                 }
                 break;
         }
     }
Comment
ClearRoseOfWar

People who like this

1 Show 0 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

160 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

How can I make function run in the editor only when I press a button in the inspector? 1 Answer

How to detect if project is Using new or Old Input System via code? 1 Answer

Why PropertyDrawers shared same values? 2 Answers

How to show type text in EditorGUI.ObjectField? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges