public override void OnInspectorGUI()
        {
            serializedObject.UpdateIfRequiredOrScript();

            Editor.DrawPropertiesExcluding(serializedObject, "m_Script");

            // Get the particle actor editor to retrieve selected particles:
            ObiParticleActorEditor[] editors = (ObiParticleActorEditor[])Resources.FindObjectsOfTypeAll(typeof(ObiParticleActorEditor));

            // If there's any particle actor editor active, we can show pin constraints:
            if (editors.Length > 0)
            {
                List <int> selectedPins = new List <int>();
                List <int> removedPins  = new List <int>();

                if (constraints.GetBatches().Count > 0)
                {
                    ObiPinConstraintBatch batch = (ObiPinConstraintBatch)constraints.GetBatches()[0];

                    // Get the list of pin constraints from the selected particles:
                    for (int i = 0; i < batch.ConstraintCount; i++)
                    {
                        int particleIndex = batch.pinIndices[i];

                        if (particleIndex >= 0 && particleIndex < ObiParticleActorEditor.selectionStatus.Length &&
                            ObiParticleActorEditor.selectionStatus[particleIndex])
                        {
                            selectedPins.Add(i);
                        }
                    }

                    if (selectedPins.Count > 0)
                    {
                        //Iterate over all constraints:
                        foreach (int i in selectedPins)
                        {
                            GUILayout.BeginVertical("box");

                            GUILayout.BeginHorizontal();

                            EditorGUI.BeginChangeCheck();
                            bool allowSceneObjects = !EditorUtility.IsPersistent(target);
                            batch.pinBodies[i] = EditorGUILayout.ObjectField("Pinned to:", batch.pinBodies[i], typeof(ObiCollider), allowSceneObjects) as ObiCollider;

                            // Calculate initial pin offset value after changing the rigidbody.
                            if (EditorGUI.EndChangeCheck() && batch.pinBodies[i] != null)
                            {
                                batch.pinOffsets[i] = batch.pinBodies[i].transform.InverseTransformPoint(constraints.Actor.GetParticlePosition(batch.pinIndices[i]));
                            }

                            Color oldColor = GUI.color;
                            GUI.color = Color.red;
                            if (GUILayout.Button("X", GUILayout.Width(30)))
                            {
                                // Mark this constraint to be removed outside of the loop.
                                removedPins.Add(i);
                                continue;
                            }
                            GUI.color = oldColor;

                            GUILayout.EndHorizontal();

                            batch.pinOffsets[i]         = EditorGUILayout.Vector3Field("Offset:", batch.pinOffsets[i]);
                            batch.pinBreakResistance[i] = EditorGUILayout.DelayedFloatField("Break Resistance:", batch.pinBreakResistance[i]);

                            GUILayout.EndVertical();
                        }
                    }
                    else
                    {
                        EditorGUILayout.HelpBox("No pin constraints for the selected particles.", MessageType.Info);
                    }

                    if (GUILayout.Button("Remove selected"))
                    {
                        for (int i = 0; i < batch.ConstraintCount; i++)
                        {
                            int particleIndex = batch.pinIndices[i];

                            if (particleIndex >= 0 && particleIndex < ObiParticleActorEditor.selectionStatus.Length &&
                                ObiParticleActorEditor.selectionStatus[particleIndex])
                            {
                                removedPins.Add(i);
                            }
                        }
                    }

                    if (GUILayout.Button("Add Pin Constraint"))
                    {
                        Undo.RecordObject(constraints, "Add pin constraints");

                        bool wasInSolver = constraints.InSolver;
                        constraints.RemoveFromSolver(null);

                        for (int i = 0; i < ObiParticleActorEditor.selectionStatus.Length; i++)
                        {
                            if (ObiParticleActorEditor.selectionStatus[i])
                            {
                                batch.AddConstraint(i, null, Vector3.zero, 0);
                            }
                        }

                        if (wasInSolver)
                        {
                            constraints.AddToSolver(null);
                        }
                    }

                    // Remove selected constraint outside of constraint listing loop:
                    if (removedPins.Count > 0)
                    {
                        Undo.RecordObject(constraints, "Remove pin constraints");

                        bool wasInSolver = constraints.InSolver;
                        constraints.RemoveFromSolver(null);

                        // Remove from last to first, to avoid throwing off subsequent indices:
                        foreach (int i in removedPins.OrderByDescending(i => i))
                        {
                            batch.RemoveConstraint(i);
                        }

                        if (wasInSolver)
                        {
                            constraints.AddToSolver(null);
                        }
                    }
                }
            }

            // Apply changes to the serializedProperty
            if (GUI.changed)
            {
                serializedObject.ApplyModifiedProperties();

                constraints.PushDataToSolver();
            }
        }