Exemplo n.º 1
0
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            EditorGUI.BeginProperty(position, label, property);
            position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

            SerializedProperty valueProperty      = property.FindPropertyRelative("_value");
            SerializedProperty tagLibraryProperty = property.FindPropertyRelative("_tagLibrary");

            position.height = 16;
            tagLibraryProperty.objectReferenceValue = EditorGUI.ObjectField(position, tagLibraryProperty.objectReferenceValue, typeof(ImpactTagLibraryBase), false);

            position.y     += 18;
            position.height = 16;

            ImpactTagLibraryBase tagLibrary = tagLibraryProperty.objectReferenceValue as ImpactTagLibraryBase;

            if (tagLibrary != null)
            {
                ImpactTagNameList tagNames = new ImpactTagNameList(ImpactTagLibraryConstants.TagCount);
                ImpactEditorUtilities.GetTagNames(tagLibrary, ref tagNames);

                ImpactEditorUtilities.TagDropdown(property, valueProperty, tagNames, position);
            }
            else
            {
                valueProperty.intValue = EditorGUI.IntField(position, valueProperty.intValue);
            }

            EditorGUI.EndProperty();
        }
        private void drawTagMaskFilter(SerializedProperty filterProperty, GUIContent label)
        {
            EditorGUILayout.BeginHorizontal();

            SerializedProperty tagMaskProperty = filterProperty.FindPropertyRelative("TagMask");
            SerializedProperty exactProperty   = filterProperty.FindPropertyRelative("ExactMatch");

            ImpactEditorUtilities.TagMaskPropertyEditor(tagMaskProperty, label, tagNames);
            exactProperty.boolValue = EditorGUILayout.ToggleLeft(new GUIContent("Exact", "Should the tags exactly match the specified tags?"), exactProperty.boolValue, GUILayout.Width(60));

            EditorGUILayout.EndHorizontal();
        }
Exemplo n.º 3
0
        public override void OnInspectorGUI()
        {
            EditorGUI.BeginChangeCheck();

            EditorGUILayout.LabelField("Particle Properties", EditorStyles.boldLabel);

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(new GUIContent("Particle Prefab", "The particle prefab to use."), GUILayout.Width(180));
            interaction.ParticlePrefab = EditorGUILayout.ObjectField(interaction.ParticlePrefab, typeof(ImpactParticles), false) as ImpactParticles;
            EditorGUILayout.EndHorizontal();

            if (interaction.ParticlePrefab == null)
            {
                EditorGUILayout.HelpBox("You must assign an Particle Prefab for this interaction.", MessageType.Error);
            }

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(new GUIContent("Is Particle Looped", "Is the particle prefab looped?"), GUILayout.Width(180));
            interaction.IsParticleLooped = EditorGUILayout.Toggle(interaction.IsParticleLooped);
            EditorGUILayout.EndHorizontal();

            ImpactEditorUtilities.Separator();

            EditorGUILayout.LabelField("Interaction Properties", EditorStyles.boldLabel);

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(new GUIContent("Minimum Velocity", "The minimum velocity magnitude required to show particles."), GUILayout.Width(180));
            interaction.MinimumVelocity = EditorGUILayout.FloatField(interaction.MinimumVelocity);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(new GUIContent("Collision Normal Influence", "How much the collision normal should influence the calculated intensity."), GUILayout.Width(180));
            interaction.CollisionNormalInfluence = EditorGUILayout.Slider(interaction.CollisionNormalInfluence, 0, 1);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Separator();

            interaction.EmitOnCollision = EditorGUILayout.ToggleLeft(new GUIContent("Emit On Collision", "Should particles be emitted on single collisions?"), interaction.EmitOnCollision);
            interaction.EmitOnSlide     = EditorGUILayout.ToggleLeft(new GUIContent("Emit On Slide", "Should particles be emitted when sliding?"), interaction.EmitOnSlide);
            interaction.EmitOnRoll      = EditorGUILayout.ToggleLeft(new GUIContent("Emit On Roll", "Should particles be emitted when rolling?"), interaction.EmitOnRoll);

            GUI.enabled = !interaction.IsParticleLooped && (interaction.EmitOnSlide || interaction.EmitOnRoll);

            interaction.EmissionInterval     = ImpactEditorUtilities.RangeEditor(interaction.EmissionInterval, new GUIContent("Emission Interval (Min/Max)", "The interval at which particles should be emitted when sliding or rolling."));
            interaction.EmissionIntervalType = (InteractionIntervalType)EditorGUILayout.EnumPopup(new GUIContent("Interval Type", "Whether the Emission Interval is defined in Time (seconds) or Distance."), interaction.EmissionIntervalType);

            GUI.enabled = true;

            if (EditorGUI.EndChangeCheck())
            {
                EditorUtility.SetDirty(interaction);
            }
        }
Exemplo n.º 4
0
        public override void OnInspectorGUI()
        {
            EditorGUI.BeginChangeCheck();

            drawAudioProperties();

            ImpactEditorUtilities.Separator();

            drawInteractionProperties();

            if (EditorGUI.EndChangeCheck())
            {
                EditorUtility.SetDirty(interaction);
            }
        }
        private void drawInteractionsList()
        {
            EditorGUILayout.BeginHorizontal();

            EditorGUILayout.LabelField("Interaction Sets", EditorStyles.boldLabel);

            GUILayout.FlexibleSpace();

            if (GUILayout.Button("New"))
            {
                ImpactMaterialInteractionSet newInteractionSet = new ImpactMaterialInteractionSet();
                newInteractionSet.Name = "New Interaction Set";
                material.AddInteractionSet(newInteractionSet);
                interactionFoldouts.Add(true);

                EditorUtility.SetDirty(target);
            }

            if (GUILayout.Button("Clear"))
            {
                if (EditorUtility.DisplayDialog("Clear All Interaction Sets", "Are you sure you want to remove all Interaction Sets? This cannot be undone.", "Yes", "No"))
                {
                    material.ClearInteractionSets();
                    EditorUtility.SetDirty(target);
                }
            }

            EditorGUILayout.EndHorizontal();

            if (material.InteractionSetCount == 0)
            {
                EditorGUILayout.HelpBox("No Interaction Sets have been added.", MessageType.Info);
            }
            else
            {
                EditorGUILayout.Separator();

                for (int i = 0; i < Mathf.Min(interactionSetsProperty.arraySize, material.InteractionSetCount); i++)
                {
                    drawInteractionSet(interactionSetsProperty.GetArrayElementAtIndex(i), material[i], i);
                }

                EditorGUILayout.Separator();

                ImpactEditorUtilities.TagMaskPropertyEditor(fallbackTagsMaskProperty, new GUIContent("Fallback Tags", "Tags that will be used if the input tags are unknown."), tagNames);
            }
        }
        private void drawInteractionSet(SerializedProperty interactionSetProperty, ImpactMaterialInteractionSet interactionSet, int index)
        {
            bool removed = false;

            EditorGUILayout.BeginHorizontal();

            SerializedProperty nameProperty = interactionSetProperty.FindPropertyRelative("_name");
            SerializedProperty includeTagsFilterProperty = interactionSetProperty.FindPropertyRelative("_includeTagsFilter");
            SerializedProperty excludeTagsFilterProperty = interactionSetProperty.FindPropertyRelative("_excludeTagsFilter");

            interactionFoldouts[index] = EditorGUILayout.Foldout(interactionFoldouts[index], new GUIContent(nameProperty.stringValue, ""), true);

            Color originalColor = GUI.color;

            GUI.color = warningColor;
            if (GUILayout.Button(new GUIContent("X", "Remove"), GUILayout.Width(20), GUILayout.Height(15)))
            {
                material.RemoveInteractionSet(index);
                interactionFoldouts.RemoveAt(index);
                removed = true;
                EditorUtility.SetDirty(target);
            }
            GUI.color = originalColor;

            EditorGUILayout.EndHorizontal();

            if (!removed && interactionFoldouts[index])
            {
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                EditorGUILayout.BeginVertical();

                GUILayout.Space(2);

                EditorGUILayout.PropertyField(nameProperty, new GUIContent("Name", "A human-readable name for the interaction set."));

                EditorGUILayout.Separator();

                EditorGUILayout.LabelField("Filters", EditorStyles.boldLabel);

                drawTagMaskFilter(includeTagsFilterProperty, new GUIContent("Include Tags", "Tags that, when present, will cause this interaction set to be used."));
                drawTagMaskFilter(excludeTagsFilterProperty, new GUIContent("Exclude Tags", "Tags that, when present, will cause this interaction set to be ignored."));

                ImpactEditorUtilities.Separator();

                drawInteractionsList(interactionSet);
            }
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            EditorGUILayout.PropertyField(tagLibraryProperty, new GUIContent("Tag Library", "The Tag Library to use for displaying tag names."));
            updateTagNames();

            if (material.TagLibrary == null)
            {
                EditorGUILayout.HelpBox(ImpactTagLibraryConstants.TagLibraryNotFoundErrorMessage, MessageType.Info);
            }

            ImpactEditorUtilities.TagMaskPropertyEditor(materialTagsMaskProperty, new GUIContent("Material Tags", "The tags that apply to this material."), tagNames);

            ImpactEditorUtilities.Separator();

            drawInteractionsList();

            serializedObject.ApplyModifiedProperties();
        }
Exemplo n.º 8
0
        private void drawInteractionProperties()
        {
            EditorGUILayout.LabelField("Interaction Properties", EditorStyles.boldLabel);

            interaction.VelocityRange = ImpactEditorUtilities.RangeEditor(interaction.VelocityRange, new GUIContent("Velocity Range (Min/Max)", "The velocity magnitude range to use when calculating collision intensity."));

            EditorGUILayout.Separator();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(new GUIContent("Collision Normal Influence", "How much the normal should affect the intensity."), GUILayout.Width(180));
            interaction.CollisionNormalInfluence = EditorGUILayout.Slider("", interaction.CollisionNormalInfluence, 0, 1);
            EditorGUILayout.EndHorizontal();

            interaction.ScaleVolumeWithVelocity = EditorGUILayout.ToggleLeft(new GUIContent("Scale Volume With Velocity", "Should volume be scaled based on the velocity?"), interaction.ScaleVolumeWithVelocity);

            if (interaction.ScaleVolumeWithVelocity)
            {
                EditorGUI.indentLevel++;

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField(new GUIContent("Volume Scale Curve", ""), GUILayout.Width(150));
                interaction.VelocityVolumeScaleCurve = EditorGUILayout.CurveField("", interaction.VelocityVolumeScaleCurve);
                EditorGUILayout.EndHorizontal();

                EditorGUI.indentLevel--;
            }

            EditorGUILayout.Separator();

            interaction.RandomPitchRange  = ImpactEditorUtilities.RangeEditor(interaction.RandomPitchRange, new GUIContent("Pitch Randomness (Min/Max)", "Random multiplier for the pitch."));
            interaction.RandomVolumeRange = ImpactEditorUtilities.RangeEditor(interaction.RandomVolumeRange, new GUIContent("Volume Randomness (Min/Max)", "Random multiplier for the volume."));

            EditorGUILayout.Separator();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(new GUIContent("Slide Velocity Pitch Modifier", "How much to increase the pitch as sliding and rolling velocity increases."), GUILayout.Width(180));
            interaction.SlideVelocityPitchMultiplier = EditorGUILayout.Slider("", interaction.SlideVelocityPitchMultiplier, 0, 1);
            EditorGUILayout.EndHorizontal();
        }
        public override void OnInspectorGUI()
        {
            EditorGUILayout.Separator();

            EditorGUILayout.LabelField("Terrain", EditorStyles.boldLabel);
            terrain.Terrain = EditorGUILayout.ObjectField(new GUIContent("", "The Terrain this object is associated with."), terrain.Terrain, typeof(Terrain), true) as Terrain;

            if (terrain.Terrain == null)
            {
                EditorGUILayout.HelpBox("Assign a Terrain to begin editing Terrain Materials.", MessageType.Info);
            }
            else
            {
                ImpactEditorUtilities.Separator();

                drawTerrainLayersList();
            }

            if (GUI.changed)
            {
                EditorUtility.SetDirty(terrain);
            }
        }
Exemplo n.º 10
0
        public override void OnInspectorGUI()
        {
            configurationManager = target as ImpactManager;
            serializedObject.Update();

            EditorGUILayout.Separator();

            EditorGUILayout.LabelField("General", EditorStyles.boldLabel);

            doProperty(physicsInteractionsLimit, new GUIContent("Physics Interactions Limit", "The maximum number of interactions generated by the built-in physics triggers that can be processed in a single fixed update. 0 = No limit."));
            doProperty(interactionResultBufferSize, new GUIContent("Interaction Result Buffer Size", "The size of the buffer array used to retrieve interaction results. This will be the maximum number of interaction results that can be produced by a single interaction."));
            doProperty(activeContinuousInteractions, new GUIContent("Max Active Continuous Interactions", "The maximum number of continuous interactions (i.e. sliding and rolling) that can be active at the same time."));
            doProperty(materialCompositionBufferSize, new GUIContent("Material Composition Buffer Size", "The size of the buffer array used to retrieve material composition results. This will be the maximum number of materials that can be returned when using material composition."));

            EditorGUILayout.Separator();

            doProperty(dontDestroyOnLoad, new GUIContent("Don't Destroy On Load", "Should the manager persist across scene loads?"));
            doProperty(setAsActiveInstance, new GUIContent("Set as Active Instance", "Should the manager be set as the active ImpactManager instance on Awake?"));

            ImpactEditorUtilities.Separator();

            EditorGUILayout.LabelField("Material Mapping", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(useMaterialMapping, new GUIContent("Use Material Mapping", "Use the Physics Material to Impact Material mapping feature?"));

            EditorGUILayout.HelpBox("Use Material Mapping to map from Physics Materials to Impact Materials so that you don't have to add Impact Object components to every object. This works best for static objects.", MessageType.Info);

            GUI.enabled = useMaterialMapping.boolValue;

            EditorGUILayout.Separator();

            //3D physic material mappings
            physicMaterialMappingFoldout = EditorGUILayout.Foldout(physicMaterialMappingFoldout, "Physic Material Mappings (3D Physics)");

            if (physicMaterialMappingFoldout)
            {
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);

                GUILayout.Space(2);

                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();

                if (GUILayout.Button("New"))
                {
                    physicMaterialMapping.arraySize++;
                }

                if (GUILayout.Button("Clear"))
                {
                    if (EditorUtility.DisplayDialog("Clear All Physic Material Mappings", "Are you sure you want to remove all Physic Material  Mappings? This cannot be undone.", "Yes", "No"))
                    {
                        physicMaterialMapping.ClearArray();
                    }
                }

                EditorGUILayout.EndHorizontal();

                if (physicMaterialMapping.arraySize == 0)
                {
                    EditorGUILayout.HelpBox("No Physic Material mappings have been created.", MessageType.Info);
                }
                else
                {
                    EditorGUILayout.Separator();

                    for (int i = 0; i < physicMaterialMapping.arraySize; i++)
                    {
                        SerializedProperty mapping        = physicMaterialMapping.GetArrayElementAtIndex(i);
                        SerializedProperty physicMaterial = mapping.FindPropertyRelative("PhysicMaterial");
                        SerializedProperty impactMaterial = mapping.FindPropertyRelative("ImpactMaterial");

                        EditorGUILayout.BeginHorizontal();

                        EditorGUILayout.PropertyField(physicMaterial, new GUIContent());
                        EditorGUILayout.LabelField("→", GUILayout.Width(20));
                        EditorGUILayout.PropertyField(impactMaterial, new GUIContent());

                        Color originalColor = GUI.color;
                        GUI.color = warningColor;
                        if (GUILayout.Button(new GUIContent("X", "Remove"), GUILayout.Width(20), GUILayout.Height(15)))
                        {
                            physicMaterialMapping.DeleteArrayElementAtIndex(i);
                        }
                        GUI.color = originalColor;

                        EditorGUILayout.EndHorizontal();
                    }
                }

                GUILayout.Space(2);

                EditorGUILayout.EndVertical();
            }

            //2D physic material mappings
            physicsMaterial2DMappingFoldout = EditorGUILayout.Foldout(physicsMaterial2DMappingFoldout, "Physics Material 2D Mappings (2D Physics)");

            if (physicsMaterial2DMappingFoldout)
            {
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);

                GUILayout.Space(2);

                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();

                if (GUILayout.Button("New"))
                {
                    physicsMaterial2DMapping.arraySize++;
                }

                if (GUILayout.Button("Clear"))
                {
                    if (EditorUtility.DisplayDialog("Clear All Physic Material Mappings", "Are you sure you want to remove all Physic Material  Mappings? This cannot be undone.", "Yes", "No"))
                    {
                        physicsMaterial2DMapping.ClearArray();
                    }
                }

                EditorGUILayout.EndHorizontal();

                if (physicsMaterial2DMapping.arraySize == 0)
                {
                    EditorGUILayout.HelpBox("No Physics Material 2D mappings have been created.", MessageType.Info);
                }
                else
                {
                    EditorGUILayout.Separator();

                    for (int i = 0; i < physicsMaterial2DMapping.arraySize; i++)
                    {
                        SerializedProperty mapping        = physicsMaterial2DMapping.GetArrayElementAtIndex(i);
                        SerializedProperty physicMaterial = mapping.FindPropertyRelative("PhysicsMaterial2D");
                        SerializedProperty impactMaterial = mapping.FindPropertyRelative("ImpactMaterial");

                        EditorGUILayout.BeginHorizontal();

                        EditorGUILayout.PropertyField(physicMaterial, new GUIContent());
                        EditorGUILayout.LabelField("→", GUILayout.Width(20));
                        EditorGUILayout.PropertyField(impactMaterial, new GUIContent());

                        Color originalColor = GUI.color;
                        GUI.color = warningColor;
                        if (GUILayout.Button(new GUIContent("X", "Remove"), GUILayout.Width(20), GUILayout.Height(15)))
                        {
                            physicsMaterial2DMapping.DeleteArrayElementAtIndex(i);
                        }
                        GUI.color = originalColor;

                        EditorGUILayout.EndHorizontal();
                    }
                }

                GUILayout.Space(2);

                EditorGUILayout.EndVertical();
            }

            GUI.enabled = true;

            serializedObject.ApplyModifiedProperties();
        }
Exemplo n.º 11
0
        private void drawAudioProperties()
        {
            EditorGUILayout.LabelField("Audio Clips", EditorStyles.boldLabel);

            EditorGUILayout.BeginVertical(EditorStyles.helpBox);

            if (interaction.CollisionAudioClips.Count == 0)
            {
                EditorGUILayout.Separator();

                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                EditorGUILayout.LabelField("No Collision Audio Clips have been added.", GUILayout.Width(250));
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.Separator();
            }
            else
            {
                GUILayout.Space(2);

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField(new GUIContent("Audio Clip Selection Mode", "Should audio clips be chosen based on Velocity or be chosen Randomly?"));
                interaction.CollisionAudioSelectionMode = (ImpactAudioInteraction.CollisionAudioClipSelectionMode)EditorGUILayout.EnumPopup(interaction.CollisionAudioSelectionMode);
                EditorGUILayout.EndHorizontal();

                for (int i = 0; i < interaction.CollisionAudioClips.Count; i++)
                {
                    EditorGUILayout.BeginHorizontal();

                    if (interaction.CollisionAudioSelectionMode == ImpactAudioInteraction.CollisionAudioClipSelectionMode.Velocity)
                    {
                        EditorGUILayout.LabelField((i + 1) + ")", GUILayout.Width(20));
                    }
                    else
                    {
                        GUILayout.Space(5);
                    }

                    interaction.CollisionAudioClips[i] = EditorGUILayout.ObjectField(interaction.CollisionAudioClips[i], typeof(AudioClip), false) as AudioClip;

                    Color originalColor = GUI.color;
                    GUI.color = warningColor;
                    if (GUILayout.Button(new GUIContent("X", "Remove"), GUILayout.Width(18), GUILayout.Height(15)))
                    {
                        interaction.CollisionAudioClips.RemoveAt(i);
                        i--;
                    }
                    GUI.color = originalColor;

                    EditorGUILayout.EndHorizontal();
                }

                GUILayout.Space(2);
            }

            EditorGUILayout.HelpBox("You can drag-and-drop Audio Clips here to add them.", MessageType.Info);

            EditorGUILayout.EndVertical();

            //Drag and drop
            Rect listRect = GUILayoutUtility.GetLastRect();

            string[] paths;
            bool     drop = ImpactEditorUtilities.DragAndDropArea(listRect, out paths);

            if (drop && paths != null)
            {
                for (int i = 0; i < paths.Length; i++)
                {
                    AudioClip a = AssetDatabase.LoadAssetAtPath <AudioClip>(paths[i]);
                    if (a != null)
                    {
                        interaction.CollisionAudioClips.Add(a);
                    }
                }
            }

            EditorGUILayout.BeginHorizontal();

            GUILayout.FlexibleSpace();

            if (GUILayout.Button("Add Collision Audio Clip"))
            {
                interaction.CollisionAudioClips.Add(null);
            }

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Separator();

            interaction.SlideAudioClip = EditorGUILayout.ObjectField(new GUIContent("Slide Audio", "The AudioClip to play when sliding."), interaction.SlideAudioClip, typeof(AudioClip), false) as AudioClip;
            interaction.RollAudioClip  = EditorGUILayout.ObjectField(new GUIContent("Roll Audio", "The AudioClip to play when rolling."), interaction.RollAudioClip, typeof(AudioClip), false) as AudioClip;

            EditorGUILayout.Separator();

            interaction.AudioSourceTemplate = EditorGUILayout.ObjectField(new GUIContent("Audio Source Template", "The audio source whose properties will be used when playing sounds from this interaction."), interaction.AudioSourceTemplate, typeof(ImpactAudioSourceBase), false) as ImpactAudioSourceBase;

            if (interaction.AudioSourceTemplate == null)
            {
                EditorGUILayout.HelpBox("You must assign an Audio Source Template for sounds to play for this interaction.", MessageType.Error);
            }
        }
Exemplo n.º 12
0
 private void updateTagNames()
 {
     ImpactEditorUtilities.GetTagNames(material.TagLibrary, ref tagNames);
 }
Exemplo n.º 13
0
        private void drawInteractionsList(ImpactMaterialInteractionSet interactionSet)
        {
            EditorGUILayout.LabelField("Interactions", EditorStyles.boldLabel);

            for (int i = 0; i < interactionSet.InteractionCount; i++)
            {
                EditorGUILayout.BeginHorizontal();

                interactionSet[i] = EditorGUILayout.ObjectField(interactionSet[i], typeof(ImpactInteractionBase), false) as ImpactInteractionBase;

                Color originalColor = GUI.color;
                GUI.color = warningColor;
                if (GUILayout.Button(new GUIContent("X", "Remove"), GUILayout.Width(20), GUILayout.Height(15)))
                {
                    interactionSet.RemoveInteraction(i);
                    EditorUtility.SetDirty(target);
                }
                GUI.color = originalColor;

                EditorGUILayout.EndHorizontal();
            }

            EditorGUILayout.HelpBox("You can drag-and-drop Interactions here to add them.", MessageType.Info);

            GUILayout.Space(2);
            EditorGUILayout.EndVertical();

            //Drag and drop
            Rect listRect = GUILayoutUtility.GetLastRect();

            string[] paths;
            bool     drop = ImpactEditorUtilities.DragAndDropArea(listRect, out paths);

            if (drop && paths != null)
            {
                for (int i = 0; i < paths.Length; i++)
                {
                    ImpactInteractionBase a = AssetDatabase.LoadAssetAtPath <ImpactInteractionBase>(paths[i]);
                    if (a != null)
                    {
                        interactionSet.AddInteraction(a);
                    }
                }
                EditorUtility.SetDirty(target);
            }

            EditorGUILayout.BeginHorizontal();

            GUILayout.FlexibleSpace();

            if (GUILayout.Button("Add Interaction"))
            {
                interactionSet.AddInteraction(null);
                EditorUtility.SetDirty(target);
            }

            EditorGUILayout.EndHorizontal();

            GUILayout.Space(2);

            EditorGUILayout.EndVertical();
        }