public static bool ParticleSelector(Vector3[] positions,
                                            bool[] selectionStatus,
                                            ObiParticleActorEditor.FaceCulling selectBackfaces,
                                            bool[] facingCamera)
        {
            Matrix4x4 cachedMatrix = Handles.matrix;

            int  controlID              = GUIUtility.GetControlID(particleSelectorHash, FocusType.Passive);
            int  selectedParticleIndex  = -1;
            bool selectionStatusChanged = false;

            // select vertex on mouse click:
            switch (Event.current.GetTypeForControl(controlID))
            {
            case EventType.MouseDown:

                if (Event.current.button != 0)
                {
                    break;
                }

                startPos = Event.current.mousePosition;
                marquee.Set(0, 0, 0, 0);

                // If the user is pressing shift, accumulate selection.
                if ((Event.current.modifiers & EventModifiers.Shift) == 0 && (Event.current.modifiers & EventModifiers.Alt) == 0)
                {
                    for (int i = 0; i < selectionStatus.Length; i++)
                    {
                        selectionStatus[i] = false;
                    }
                }

                // If the user is holding down control, dont allow selection of other objects and use marquee tool.
                if ((Event.current.modifiers & EventModifiers.Control) != 0)
                {
                    GUIUtility.hotControl = controlID;
                }

                float minSqrDistance = System.Single.MaxValue;

                for (int i = 0; i < positions.Length; i++)
                {
                    // skip not selectable particles:
                    switch (selectBackfaces)
                    {
                    case ObiParticleActorEditor.FaceCulling.Back: if (!facingCamera[i])
                        {
                            continue;
                        }
                        break;

                    case ObiParticleActorEditor.FaceCulling.Front: if (facingCamera[i])
                        {
                            continue;
                        }
                        break;
                    }

                    // get particle position in gui space:
                    Vector2 pos = HandleUtility.WorldToGUIPoint(positions[i]);

                    // get distance from mouse position to particle position:
                    float sqrDistance = Vector2.SqrMagnitude(startPos - pos);

                    // check if this particle is closer to the cursor that any previously considered particle.
                    if (sqrDistance < 100 && sqrDistance < minSqrDistance)              //magic number 100 = 10*10, where 10 is min distance in pixels to select a particle.
                    {
                        minSqrDistance        = sqrDistance;
                        selectedParticleIndex = i;
                    }
                }

                if (selectedParticleIndex >= 0)          // toggle particle selection status.

                {
                    selectionStatus[selectedParticleIndex] = !selectionStatus[selectedParticleIndex];
                    selectionStatusChanged = true;

                    // Prevent cloth deselection if we have selected a particle:
                    GUIUtility.hotControl = controlID;
                    Event.current.Use();
                }
                else if (Event.current.modifiers == EventModifiers.None)          // deselect all particles:
                {
                    for (int i = 0; i < selectionStatus.Length; i++)
                    {
                        selectionStatus[i] = false;
                    }

                    selectionStatusChanged = true;
                }

                break;

            case EventType.MouseMove:
                SceneView.RepaintAll();
                break;

            case EventType.MouseDrag:

                if (GUIUtility.hotControl == controlID)
                {
                    currentPos = Event.current.mousePosition;
                    if (!dragging && Vector2.Distance(startPos, currentPos) > 5)
                    {
                        dragging = true;
                    }
                    else
                    {
                        GUIUtility.hotControl = controlID;
                        Event.current.Use();
                    }

                    //update marquee rect:
                    float left   = Mathf.Min(startPos.x, currentPos.x);
                    float right  = Mathf.Max(startPos.x, currentPos.x);
                    float bottom = Mathf.Min(startPos.y, currentPos.y);
                    float top    = Mathf.Max(startPos.y, currentPos.y);

                    marquee = new Rect(left, bottom, right - left, top - bottom);
                }

                break;

            case EventType.MouseUp:

                if (GUIUtility.hotControl == controlID)
                {
                    dragging = false;

                    for (int i = 0; i < positions.Length; i++)
                    {
                        // skip not selectable particles:
                        switch (selectBackfaces)
                        {
                        case ObiParticleActorEditor.FaceCulling.Back: if (!facingCamera[i])
                            {
                                continue;
                            }
                            break;

                        case ObiParticleActorEditor.FaceCulling.Front: if (facingCamera[i])
                            {
                                continue;
                            }
                            break;
                        }

                        // get particle position in gui space:
                        Vector2 pos = HandleUtility.WorldToGUIPoint(positions[i]);

                        if (pos.x > marquee.xMin && pos.x < marquee.xMax && pos.y > marquee.yMin && pos.y < marquee.yMax)
                        {
                            selectionStatus[i]     = true;
                            selectionStatusChanged = true;
                        }
                    }

                    GUIUtility.hotControl = 0;
                    Event.current.Use();
                }

                break;

            case EventType.Repaint:

                Handles.matrix = Matrix4x4.identity;

                if (dragging)
                {
                    GUISkin oldSkin = GUI.skin;
                    GUI.skin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene);
                    Handles.BeginGUI();
                    GUI.Box(new Rect(marquee.xMin, marquee.yMin, marquee.width, marquee.height), "");
                    Handles.EndGUI();
                    GUI.skin = oldSkin;
                }

                Handles.matrix = cachedMatrix;

                break;
            }

            return(selectionStatusChanged);
        }
        public static bool ParticleBrush(Vector3[] positions,
                                         ObiParticleActorEditor.FaceCulling selectBackfaces,
                                         bool[] facingCamera,
                                         float radius,
                                         Action strokeStart,
                                         Action <List <ParticleStampInfo>, bool> particlesAffected,
                                         Action strokeEnd,
                                         Texture2D brushImage)
        {
            Matrix4x4 cachedMatrix = Handles.matrix;

            int  controlID = GUIUtility.GetControlID(particleBrushHash, FocusType.Passive);
            bool selectionStatusChanged = false;

            List <ParticleStampInfo> affectedParticles = new List <ParticleStampInfo>();

            switch (Event.current.GetTypeForControl(controlID))
            {
            case EventType.MouseDown:

                if (Event.current.button != 0 || (Event.current.modifiers & ~EventModifiers.Shift) != EventModifiers.None)
                {
                    break;
                }

                GUIUtility.hotControl = controlID;
                startPos = Event.current.mousePosition;

                for (int i = 0; i < positions.Length; i++)
                {
                    // skip not selectable particles:
                    switch (selectBackfaces)
                    {
                    case ObiParticleActorEditor.FaceCulling.Back: if (!facingCamera[i])
                        {
                            continue;
                        }
                        break;

                    case ObiParticleActorEditor.FaceCulling.Front: if (facingCamera[i])
                        {
                            continue;
                        }
                        break;
                    }

                    // get particle position in gui space:
                    Vector2 pos = HandleUtility.WorldToGUIPoint(positions[i]);

                    // get distance from mouse position to particle position:
                    float sqrDistance = Vector2.SqrMagnitude(startPos - pos);

                    if (sqrDistance < radius * radius)
                    {
                        affectedParticles.Add(new ParticleStampInfo(i, sqrDistance));
                    }
                }

                if (affectedParticles.Count > 0)
                {
                    selectionStatusChanged = true;
                    if (strokeStart != null)
                    {
                        strokeStart();
                    }
                    if (particlesAffected != null)
                    {
                        particlesAffected(affectedParticles, (Event.current.modifiers & EventModifiers.Shift) != 0);
                    }
                }

                Event.current.Use();

                break;

            case EventType.MouseMove:
                SceneView.RepaintAll();
                break;

            case EventType.MouseDrag:

                if (GUIUtility.hotControl == controlID)
                {
                    currentPos = Event.current.mousePosition;
                    dragging   = true;

                    for (int i = 0; i < positions.Length; i++)
                    {
                        // skip not selectable particles:
                        switch (selectBackfaces)
                        {
                        case ObiParticleActorEditor.FaceCulling.Back: if (!facingCamera[i])
                            {
                                continue;
                            }
                            break;

                        case ObiParticleActorEditor.FaceCulling.Front: if (facingCamera[i])
                            {
                                continue;
                            }
                            break;
                        }

                        // get particle position in gui space:
                        Vector2 pos = HandleUtility.WorldToGUIPoint(positions[i]);

                        // get distance from mouse position to particle position:
                        float sqrDistance = Vector2.SqrMagnitude(currentPos - pos);

                        if (sqrDistance < radius * radius)
                        {
                            affectedParticles.Add(new ParticleStampInfo(i, sqrDistance));
                        }
                    }

                    if (affectedParticles.Count > 0)
                    {
                        selectionStatusChanged = true;
                        if (particlesAffected != null)
                        {
                            particlesAffected(affectedParticles, (Event.current.modifiers & EventModifiers.Shift) != 0);
                        }
                    }

                    Event.current.Use();
                }

                break;

            case EventType.MouseUp:

                if (GUIUtility.hotControl == controlID)
                {
                    dragging = false;

                    GUIUtility.hotControl = 0;
                    Event.current.Use();
                    if (strokeEnd != null)
                    {
                        strokeEnd();
                    }
                }

                break;

            case EventType.Repaint:

                Handles.matrix = Matrix4x4.identity;

                Handles.BeginGUI();
                GUI.DrawTexture(new Rect(Event.current.mousePosition.x - radius,
                                         Event.current.mousePosition.y - radius,
                                         radius * 2,
                                         radius * 2), brushImage);
                Handles.EndGUI();

                Handles.matrix = cachedMatrix;

                break;
            }

            return(selectionStatusChanged);
        }