Beispiel #1
0
    public SpringSubComponentEditor(Editor editor) : base(editor)
    {
        name             = "Springs";
        springBodyEditor = (JelloSpringBodyEditor)editor;
        springBody       = (JelloSpringBody)springBodyEditor.serializedObject.targetObject;

        handlePositions = new Vector3[2];
        handleSizes     = new float[2];

        eShapeMatching      = springBodyEditor.serializedObject.FindProperty("mShapeMatchingOn");
        eShapeSpringK       = springBodyEditor.serializedObject.FindProperty("mShapeSpringK");
        eShapeSpringDamp    = springBodyEditor.serializedObject.FindProperty("mShapeSpringDamp");
        eEdgeSpringK        = springBodyEditor.serializedObject.FindProperty("mDefaultEdgeSpringK");
        eEdgeSpringDamp     = springBodyEditor.serializedObject.FindProperty("mDefaultEdgeSpringDamp");
        eInternalSpringK    = springBodyEditor.serializedObject.FindProperty("mDefaultInternalSpringK");
        eInternalSpringDamp = springBodyEditor.serializedObject.FindProperty("mDefaultInternalSpringDamp");
        eCustomSpringK      = springBodyEditor.serializedObject.FindProperty("mDefaultCustomSpringK");
        eCustomSpringDamp   = springBodyEditor.serializedObject.FindProperty("mDefaultCustomSpringDamp");
        eEdgeSprings        = springBodyEditor.serializedObject.FindProperty("mEdgeSprings");
        eInternalSprings    = springBodyEditor.serializedObject.FindProperty("mInternalSprings");
        eCustomSprings      = springBodyEditor.serializedObject.FindProperty("mCustomSprings");

        drawIndex            = editIndex = -1;
        newSpring            = null;
        newSubComponentState = AddSubComponentState.inactive;
    }
	public override void DrawEditorGUI ()
	{
		//springBodyEditor.serializedObject.Update();

		multiEditing = springBodyEditor.serializedObject.isEditingMultipleObjects;

		if(!multiEditing)
		{	
			if(GUILayout.Button(addSpringContent, EditorStyles.miniButton)) //TODO move this...
			{
				editIndex = -1;
				drawIndex = -1;
				newSpring = null;
				newSubComponentState = AddSubComponentState.initiated;
			}

			if(newSubComponentState != AddSubComponentState.inactive)
			{
				EditorGUILayout.HelpBox("Click near any Point Mass on the Jello Body" +
				                        "\nEsc to cancel", MessageType.Info);
			}


		}

		//TODO this might work better in a popup menu...
		if(springBody.SpringCount != 0) 
		{
			EditorGUI.indentLevel++;
			DrawShapeMatchingGUI();
			DrawEdgeSpringsGUI();
			DrawInternalSpringsGUI();
			DrawCustomSpringsGUI();
			EditorGUI.indentLevel--;
		}

		if(newSubComponentState != AddSubComponentState.inactive )
		{
			if(Event.current.isKey && Event.current.keyCode == KeyCode.Escape)
			{
				newSubComponentState = AddSubComponentState.inactive;
				mainEditor.Repaint();
			}
		}

		//springBodyEditor.serializedObject.ApplyModifiedProperties();
	}
Beispiel #3
0
    public override void DrawSceneGUI()
    {
        if (springBody == null || multiEditing)
        {
            return;
        }

        //draw the hovered over spring
        if (drawIndex != -1)
        {
            JelloSpring spring = springBody.getSpring(drawIndex);
            Vector3     posA;
            Vector3     posB;

            posA = springBody.transform.TransformPoint(springBody.Shape.getVertex(spring.pointMassA));
            posB = springBody.transform.TransformPoint(springBody.Shape.getVertex(spring.pointMassB));

            Handles.color = Color.magenta;

            if (spring.lengthMultiplier != 1f)
            {
                float   dist = Vector2.Distance(posA, posB) * spring.lengthMultiplier;
                Vector3 mid  = (posA + posB) * 0.5f;
                posA = mid + (mid - posA).normalized * dist * 0.5f;
                posB = mid + (mid - posB).normalized * dist * 0.5f;
            }

            Handles.DrawLine(posA, posB);
        }

        //TODO make it remember the selected spring?
        //draw the currently selected spring
        if (editIndex != -1 && editIndex < springBody.SpringCount)
        {
            JelloSpring spring = springBody.getSpring(editIndex);
            Handles.color = Color.cyan;

            Vector3[] globalHandlePositions = new Vector3[2];
            for (int i = 0; i < handlePositions.Length; i++)
            {
                globalHandlePositions[i] = springBody.transform.TransformPoint(handlePositions[i]);
            }
            CalculateHandleSizes(handlePositions);

            bool mouseUp = false;

            if (Event.current.type == EventType.mouseUp)
            {
                mouseUp = true;
            }

            for (int i = 0; i < handlePositions.Length; i++)
            {
                handlePositions[i] = springBody.transform.InverseTransformPoint(Handles.FreeMoveHandle(springBody.transform.TransformPoint(handlePositions[i]), Quaternion.identity, handleSizes[i], Vector3.zero, Handles.CircleCap));
            }
            //handlePositions[1] = springBody.transform.InverseTransformPoint( Handles.FreeMoveHandle(springBody.transform.TransformPoint(handlePositions[1]), Quaternion.identity, HandleUtility.GetHandleSize(handlePositions[1]) * 0.15f, Vector3.zero, Handles.CircleCap));

            Handles.color = Color.magenta;
            Handles.DrawLine(springBody.transform.TransformPoint(handlePositions[0]), springBody.transform.TransformPoint(handlePositions[1]));

            if (mouseUp)
            {
                if ((Vector2)handlePositions[0] != springBody.Shape.getVertex(spring.pointMassA))
                {
                    Vector2[] points = new Vector2[springBody.Shape.VertexCount];
                    for (int i = 0; i < springBody.Shape.VertexCount; i++)
                    {
                        points[i] = springBody.Shape.getVertex(i);
                    }

                    spring.pointMassA = JelloShapeTools.FindClosestVertexOnShape(handlePositions[0], points);

                    handlePositions[0] = springBody.Shape.getVertex(spring.pointMassA);

                    spring.length = Vector2.Distance(springBody.Shape.getVertex(spring.pointMassA), springBody.Shape.getVertex(spring.pointMassB));

                    EditorUtility.SetDirty(springBody);
                }

                if ((Vector2)handlePositions[1] != springBody.Shape.getVertex(spring.pointMassB))
                {
                    Vector2[] points = new Vector2[springBody.Shape.VertexCount];
                    for (int i = 0; i < springBody.Shape.VertexCount; i++)
                    {
                        points[i] = springBody.Shape.getVertex(i);
                    }

                    spring.pointMassB = JelloShapeTools.FindClosestVertexOnShape(handlePositions[1], points);

                    handlePositions[1] = springBody.Shape.getVertex(spring.pointMassB);

                    spring.length = Vector2.Distance(springBody.Shape.getVertex(spring.pointMassA), springBody.Shape.getVertex(spring.pointMassB));

                    EditorUtility.SetDirty(springBody);
                }
            }

            Vector3 posA = springBody.transform.TransformPoint(springBody.Shape.getVertex(spring.pointMassA));
            Vector3 posB = springBody.transform.TransformPoint(springBody.Shape.getVertex(spring.pointMassB));

            if (spring.lengthMultiplier != 1f)
            {
                float   dist = Vector2.Distance(posA, posB) * spring.lengthMultiplier;
                Vector3 mid  = (posA + posB) * 0.5f;
                posA = mid + (mid - posA).normalized * dist * 0.5f;
                posB = mid + (mid - posB).normalized * dist * 0.5f;
            }

            Handles.color = Color.blue;

            Handles.DrawLine(posA, posB);
        }

        if (newSubComponentState != AddSubComponentState.inactive)
        {
            if (Event.current.isKey && Event.current.keyCode == KeyCode.Escape)
            {
                newSubComponentState = AddSubComponentState.inactive;
            }


            int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);

            if (Event.current.type == EventType.Layout)
            {
                HandleUtility.AddDefaultControl(controlID);
            }

            Handles.color = Color.red;

            Vector3 pos   = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin;           //need where this ray intersects the zplane
            Plane   plane = new Plane(Vector3.forward, new Vector3(0, 0, springBody.transform.position.z));
            Ray     ray   = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
            float   dist  = 0f;
            plane.Raycast(ray, out dist);
            pos = ray.GetPoint(dist);
            Vector3 mousePosWorld = new Vector3(pos.x, pos.y, springBody.transform.position.z);

            if (newSubComponentState == AddSubComponentState.assignedFirst)
            {
                pos = springBody.transform.TransformPoint(springBody.Shape.getVertex(newSpring.pointMassA));
                Handles.CircleCap(3, pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.15f);
                Handles.DrawLine(pos, mousePosWorld);

                Handles.color = Color.blue;
                Handles.CircleCap(3, mousePosWorld, Quaternion.identity, HandleUtility.GetHandleSize(mousePosWorld) * 0.15f);

                if (Event.current.type == EventType.MouseUp)
                {
                    Vector2[] points = new Vector2[springBody.Shape.VertexCount];
                    for (int i = 0; i < springBody.Shape.VertexCount; i++)
                    {
                        points[i] = springBody.Shape.getVertex(i);
                    }

                    newSpring.pointMassB = JelloShapeTools.FindClosestVertexOnShape(springBody.transform.InverseTransformPoint(mousePosWorld), points);
                    newSpring.length     = Vector2.Distance(springBody.Shape.getVertex(newSpring.pointMassA), springBody.Shape.getVertex(newSpring.pointMassB));
                    newSpring.stiffness  = springBody.DefaultCustomSpringStiffness;
                    newSpring.damping    = springBody.DefaultCustomSpringDamping;

                    editIndex = springBody.SpringCount;
                    springBody.addCustomSpring(newSpring);
                    newSubComponentState = AddSubComponentState.inactive;

                    handlePositions[0] = springBody.Shape.getVertex(newSpring.pointMassA);
                    handlePositions[1] = springBody.Shape.getVertex(newSpring.pointMassB);

                    eCustomSprings.isExpanded   = true;
                    eEdgeSprings.isExpanded     = false;
                    eInternalSprings.isExpanded = false;

                    EditorUtility.SetDirty(springBody);
                }
            }
            if (newSubComponentState == AddSubComponentState.initiated)
            {
                Handles.CircleCap(3, mousePosWorld, Quaternion.identity, HandleUtility.GetHandleSize(mousePosWorld) * 0.15f);

                if (Event.current.type == EventType.MouseUp)
                {
                    Vector2[] points = new Vector2[springBody.Shape.VertexCount];
                    for (int i = 0; i < springBody.Shape.VertexCount; i++)
                    {
                        points[i] = springBody.Shape.getVertex(i);
                    }

                    newSpring            = new JelloSpring();
                    newSpring.pointMassA = JelloShapeTools.FindClosestVertexOnShape(springBody.transform.InverseTransformPoint(mousePosWorld), points);
                    newSubComponentState = AddSubComponentState.assignedFirst;
                }
            }

            SceneView.RepaintAll();
        }

        if (newSubComponentState != AddSubComponentState.inactive || editIndex != -1)
        {
            Handles.color = new Color(0.5f, 0.5f, 0.5f, 0.5f);

            for (int i = springBody.EdgeSpringCount; i < springBody.SpringCount; i++)
            {
                if (editIndex == i)
                {
                    continue;
                }
                Handles.DrawLine(springBody.transform.TransformPoint(springBody.Shape.getVertex(springBody.getSpring(i).pointMassA)), springBody.transform.TransformPoint(springBody.Shape.getVertex(springBody.getSpring(i).pointMassB)));
            }

            mainEditor.DrawPointMasses(springBody, false);
        }
    }
    public override void DrawSceneGUI()
    {
        if(springBody == null || multiEditing)
            return;

        //draw the hovered over spring
        if(drawIndex != -1)
        {
            JelloSpring spring = springBody.getSpring(drawIndex);
            Vector3 posA;
            Vector3 posB;

            posA = springBody.transform.TransformPoint(springBody.Shape.getVertex(spring.pointMassA));
            posB = springBody.transform.TransformPoint(springBody.Shape.getVertex(spring.pointMassB));

            Handles.color = Color.magenta;

            if(spring.lengthMultiplier != 1f)
            {
                float dist = Vector2.Distance(posA, posB) * spring.lengthMultiplier;
                Vector3 mid = (posA + posB) * 0.5f;
                posA = mid + (mid - posA).normalized * dist * 0.5f;
                posB = mid + (mid - posB).normalized * dist * 0.5f;
            }

            Handles.DrawLine(posA,posB);
        }

        //TODO make it remember the selected spring?
        //draw the currently selected spring
        if(editIndex != -1 && editIndex < springBody.SpringCount)
        {
            JelloSpring spring = springBody.getSpring(editIndex);
            Handles.color = Color.cyan;

            Vector3[] globalHandlePositions = new Vector3[2];
            for(int i = 0; i < handlePositions.Length; i++)
                globalHandlePositions[i] = springBody.transform.TransformPoint(handlePositions[i]);
            CalculateHandleSizes(handlePositions);

            bool mouseUp = false;

            if(Event.current.type == EventType.mouseUp)
                mouseUp = true;

            for(int i = 0; i < handlePositions.Length; i++)
                handlePositions[i] = springBody.transform.InverseTransformPoint( Handles.FreeMoveHandle(springBody.transform.TransformPoint(handlePositions[i]), Quaternion.identity, handleSizes[i], Vector3.zero, Handles.CircleCap));
            //handlePositions[1] = springBody.transform.InverseTransformPoint( Handles.FreeMoveHandle(springBody.transform.TransformPoint(handlePositions[1]), Quaternion.identity, HandleUtility.GetHandleSize(handlePositions[1]) * 0.15f, Vector3.zero, Handles.CircleCap));

            Handles.color = Color.magenta;
            Handles.DrawLine(springBody.transform.TransformPoint(handlePositions[0]), springBody.transform.TransformPoint(handlePositions[1]));

            if(mouseUp)
            {
                if((Vector2)handlePositions[0] != springBody.Shape.getVertex(spring.pointMassA))
                {
                    Vector2[] points = new Vector2[springBody.Shape.VertexCount];
                    for(int i = 0; i < springBody.Shape.VertexCount; i++)
                        points[i] = springBody.Shape.getVertex(i);

                    spring.pointMassA = JelloShapeTools.FindClosestVertexOnShape(handlePositions[0], points);

                    handlePositions[0] = springBody.Shape.getVertex(spring.pointMassA);

                    spring.length = Vector2.Distance(springBody.Shape.getVertex(spring.pointMassA), springBody.Shape.getVertex(spring.pointMassB));

                    EditorUtility.SetDirty(springBody);
                }

                if((Vector2)handlePositions[1] != springBody.Shape.getVertex(spring.pointMassB))
                {
                    Vector2[] points = new Vector2[springBody.Shape.VertexCount];
                    for(int i = 0; i < springBody.Shape.VertexCount; i++)
                        points[i] = springBody.Shape.getVertex(i);

                    spring.pointMassB = JelloShapeTools.FindClosestVertexOnShape(handlePositions[1], points);

                    handlePositions[1] = springBody.Shape.getVertex(spring.pointMassB);

                    spring.length = Vector2.Distance(springBody.Shape.getVertex(spring.pointMassA), springBody.Shape.getVertex(spring.pointMassB));

                    EditorUtility.SetDirty(springBody);
                }
            }

            Vector3 posA = springBody.transform.TransformPoint(springBody.Shape.getVertex(spring.pointMassA));
            Vector3 posB = springBody.transform.TransformPoint(springBody.Shape.getVertex(spring.pointMassB));

            if(spring.lengthMultiplier != 1f)
            {
                float dist = Vector2.Distance(posA, posB) * spring.lengthMultiplier;
                Vector3 mid = (posA + posB) * 0.5f;
                posA = mid + (mid - posA).normalized * dist * 0.5f;
                posB = mid + (mid - posB).normalized * dist * 0.5f;
            }

            Handles.color = Color.blue;

            Handles.DrawLine(posA,posB);
        }

        if(newSubComponentState != AddSubComponentState.inactive)
        {

            if(Event.current.isKey && Event.current.keyCode == KeyCode.Escape)
            {
                newSubComponentState = AddSubComponentState.inactive;
            }

            int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);

            if(Event.current.type == EventType.Layout)
                HandleUtility.AddDefaultControl(controlID);

            Handles.color = Color.red;

            Vector3 pos = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin; //need where this ray intersects the zplane
            Plane plane = new Plane(Vector3.forward, new Vector3(0, 0, springBody.transform.position.z));
            Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
            float dist = 0f;
            plane.Raycast(ray, out dist);
            pos = ray.GetPoint(dist);
            Vector3 mousePosWorld = new Vector3(pos.x, pos.y, springBody.transform.position.z);

            if(newSubComponentState == AddSubComponentState.assignedFirst)
            {
                pos = springBody.transform.TransformPoint(springBody.Shape.getVertex(newSpring.pointMassA));
                Handles.CircleCap(3, pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.15f);
                Handles.DrawLine( pos, mousePosWorld);

                Handles.color = Color.blue;
                Handles.CircleCap(3, mousePosWorld, Quaternion.identity, HandleUtility.GetHandleSize(mousePosWorld) * 0.15f);

                if(Event.current.type == EventType.MouseUp)
                {
                    Vector2[] points = new Vector2[springBody.Shape.VertexCount];
                    for(int i = 0; i < springBody.Shape.VertexCount; i++)
                        points[i] = springBody.Shape.getVertex(i);

                    newSpring.pointMassB = JelloShapeTools.FindClosestVertexOnShape(springBody.transform.InverseTransformPoint(mousePosWorld), points);
                    newSpring.length = Vector2.Distance(springBody.Shape.getVertex(newSpring.pointMassA), springBody.Shape.getVertex(newSpring.pointMassB));
                    newSpring.stiffness = springBody.DefaultCustomSpringStiffness;
                    newSpring.damping = springBody.DefaultCustomSpringDamping;

                    editIndex = springBody.SpringCount;
                    springBody.addCustomSpring(newSpring);
                    newSubComponentState = AddSubComponentState.inactive;

                    handlePositions[0] = springBody.Shape.getVertex(newSpring.pointMassA);
                    handlePositions[1] = springBody.Shape.getVertex(newSpring.pointMassB);

                    eCustomSprings.isExpanded = true;
                    eEdgeSprings.isExpanded = false;
                    eInternalSprings.isExpanded = false;

                    EditorUtility.SetDirty(springBody);
                }
            }
            if(newSubComponentState == AddSubComponentState.initiated)
            {
                Handles.CircleCap(3, mousePosWorld, Quaternion.identity, HandleUtility.GetHandleSize(mousePosWorld) * 0.15f);

                if(Event.current.type == EventType.MouseUp)
                {
                    Vector2[] points = new Vector2[springBody.Shape.VertexCount];
                    for(int i = 0; i < springBody.Shape.VertexCount; i++)
                        points[i] = springBody.Shape.getVertex(i);

                    newSpring = new JelloSpring();
                    newSpring.pointMassA = JelloShapeTools.FindClosestVertexOnShape(springBody.transform.InverseTransformPoint(mousePosWorld), points);
                    newSubComponentState = AddSubComponentState.assignedFirst;
                }
            }

            SceneView.RepaintAll();
        }

        if(newSubComponentState != AddSubComponentState.inactive || editIndex != -1)
        {
            Handles.color = new Color(0.5f, 0.5f, 0.5f, 0.5f);

            for(int i = springBody.EdgeSpringCount; i < springBody.SpringCount; i++)
            {
                if(editIndex == i)
                    continue;
                Handles.DrawLine(springBody.transform.TransformPoint(springBody.Shape.getVertex(springBody.getSpring(i).pointMassA)), springBody.transform.TransformPoint(springBody.Shape.getVertex(springBody.getSpring(i).pointMassB)));
            }

            mainEditor.DrawPointMasses(springBody, false);
        }
    }
    public override void DrawEditorGUI()
    {
        //springBodyEditor.serializedObject.Update();

        multiEditing = springBodyEditor.serializedObject.isEditingMultipleObjects;

        if(!multiEditing)
        {
            if(GUILayout.Button(addSpringContent, EditorStyles.miniButton)) //TODO move this...
            {
                editIndex = -1;
                drawIndex = -1;
                newSpring = null;
                newSubComponentState = AddSubComponentState.initiated;
            }

            if(newSubComponentState != AddSubComponentState.inactive)
            {
                EditorGUILayout.HelpBox("Click near any Point Mass on the Jello Body" +
                                        "\nEsc to cancel", MessageType.Info);
            }

        }

        //TODO this might work better in a popup menu...
        if(springBody.SpringCount != 0)
        {
            EditorGUI.indentLevel++;
            DrawShapeMatchingGUI();
            DrawEdgeSpringsGUI();
            DrawInternalSpringsGUI();
            DrawCustomSpringsGUI();
            EditorGUI.indentLevel--;
        }

        if(newSubComponentState != AddSubComponentState.inactive )
        {
            if(Event.current.isKey && Event.current.keyCode == KeyCode.Escape)
            {
                newSubComponentState = AddSubComponentState.inactive;
                mainEditor.Repaint();
            }
        }

        //springBodyEditor.serializedObject.ApplyModifiedProperties();
    }
    public SpringSubComponentEditor(Editor editor)
        : base(editor)
    {
        name = "Springs";
        springBodyEditor = (JelloSpringBodyEditor)editor;
        springBody = (JelloSpringBody)springBodyEditor.serializedObject.targetObject;

        handlePositions = new Vector3[2];
        handleSizes = new float[2];

        eShapeMatching = springBodyEditor.serializedObject.FindProperty("mShapeMatchingOn");
        eShapeSpringK = springBodyEditor.serializedObject.FindProperty("mShapeSpringK");
        eShapeSpringDamp = springBodyEditor.serializedObject.FindProperty("mShapeSpringDamp");
        eEdgeSpringK = springBodyEditor.serializedObject.FindProperty("mDefaultEdgeSpringK");
        eEdgeSpringDamp = springBodyEditor.serializedObject.FindProperty("mDefaultEdgeSpringDamp");
        eInternalSpringK = springBodyEditor.serializedObject.FindProperty("mDefaultInternalSpringK");
        eInternalSpringDamp = springBodyEditor.serializedObject.FindProperty("mDefaultInternalSpringDamp");
        eCustomSpringK = springBodyEditor.serializedObject.FindProperty("mDefaultCustomSpringK");
        eCustomSpringDamp = springBodyEditor.serializedObject.FindProperty("mDefaultCustomSpringDamp");
        eEdgeSprings = springBodyEditor.serializedObject.FindProperty("mEdgeSprings");
        eInternalSprings = springBodyEditor.serializedObject.FindProperty("mInternalSprings");
        eCustomSprings = springBodyEditor.serializedObject.FindProperty("mCustomSprings");

        drawIndex = editIndex = -1;
        newSpring = null;
        newSubComponentState = AddSubComponentState.inactive;
    }
    /// <summary>
    /// Clears every internal JelloPointMass.
    /// Will also clear every internal JelloSpring an any custom JelloSpring that is no longer valid.
    /// </summary>
    /// <param name="recenterBaseShape">If set to <c>true</c> recenter the JelloBody.Shape.</param>
    public override void clearInternalPointMasses(bool recenterBaseShape)
    {
        base.clearInternalPointMasses (recenterBaseShape);

        mInternalSprings = new JelloSpring[0];

        bool[] validity = new bool[mCustomSprings.Length];
        int num = 0;
        for(int i = 0; i < mCustomSprings.Length; i++)
        {
            if(mCustomSprings[i].pointMassA >= mEdgePointMasses.Length || mCustomSprings[i].pointMassB >= mEdgePointMasses.Length)
            {
                validity[i] = false;
            }
            else
            {
                validity[i] = true;
                num++;
            }
        }

        JelloSpring[] temp = new JelloSpring[num];
        num = 0;
        for(int i = 0; i < mCustomSprings.Length; i++)
        {
            if(validity[i])
            {
                temp[i - num] = mCustomSprings[i];
            }
            else
            {
                num++;
            }
        }

        mCustomSprings = temp;
    }
 /// <summary>
 /// Add multiple custom JelloSpring.
 /// </summary>
 /// <param name="springs">JelloSpring array to add to this JelloBody.</param>
 public void addCustomSprings(JelloSpring[] springs)
 {
     addSprings(springs, ref mCustomSprings);
 }
 /// <summary>
 /// Adds a custom JelloSpring.
 /// </summary>
 /// <param name="spring">The new JelloSpring to add.</param>
 public void addCustomSpring(JelloSpring spring)
 {
     addSpring(spring, ref mCustomSprings);
 }
    /// <summary>
    /// Removes the JelloSpring from the given JelloSpring array.
    /// </summary>
    /// <param name="spring">The JelloSpring to be removed.</param>
    /// <param name="removeFromArray">The JelloSpring array to remove the JelloSpring from.</param>
    private void removeSpring(JelloSpring spring, ref JelloSpring[] removeFromArray)
    {
        List<JelloSpring> tempSprings = new List<JelloSpring>();
        for(int i = 0; i < removeFromArray.Length; i++)
            if(spring != removeFromArray[i])
                tempSprings.Add (removeFromArray[i]);

        removeFromArray = tempSprings.ToArray();
    }
    /// <summary>
    /// Adds multiple JelloSpring objects with specified values.
    /// </summary>
    /// <param name="indices">
    /// The indices of the JelloPointMass that each JelloSpring will connect to
    /// Each JelloSpring uses two indices.
    /// </param>
    /// <param name="stiffness">The JelloSpring.stiffness of each JelloSpring to be added.</param>
    /// <param name="damping">The JelloSpring.damping of each JelloSpring to be added.</param>
    /// <param name="addToArray">The JelloSpring array to add each new JelloSpring to.</param>
    private void addSprings(int[] indices, float stiffness, float damping, ref JelloSpring[] addToArray)
    {
        JelloSpring[] newSprings = new JelloSpring[indices.Length / 2];
        //float dist = 0f;

        for(int i = 0; i < newSprings.Length; i ++)
        {
            //dist = Vector2.Distance(mBaseShape.getVertex( indices[ 2 * i ] ), mBaseShape.getVertex( indices[2 * i + 1] ));

            newSprings[i] = new JelloSpring(indices[2 * i], indices[2 * i + 1], 0f, stiffness, damping);
        }

        addSprings(newSprings, ref addToArray);
    }
    /// <summary>
    /// Adds one JelloSpring array to another.
    /// </summary>
    /// <param name="springs">JelloSpring array to be added.</param>
    /// <param name="addToArray">JelloSpring array to add to.</param>
    private void addSprings(JelloSpring[] springs, ref JelloSpring[] addToArray)
    {
        Vector2 posA;
        Vector2 posB;
        Vector2 diff;
        float dist;
        Vector2 mid;

        for(int i = 0; i < springs.Length; i++)
        {
            posA = mBaseShape.getVertex(springs[i].pointMassA);
            posB = mBaseShape.getVertex(springs[i].pointMassB);
            diff = posA - posB;
            dist = springs[i].length * Vector2.Distance(posA, posB) / Vector2.Distance (Vector2.zero, diff);
            mid = (posA + posB) * 0.5f;
            posA = mid + (mid - posA).normalized * dist * 0.5f;
            posB = mid + (mid - posB).normalized * dist * 0.5f;

            springs[i].scaledLength = Vector2.Distance
                (
                    Vector2.zero,
                    new Vector2
                    (
                        (posA.x - posB.x) * Scale.x,
                        (posA.y - posB.y) * Scale.y
                    )
                );
        }

        //create a temporary array of springs at the new size
        JelloSpring[] oldSprings = new JelloSpring[addToArray.Length];

        //add springs already in the array to the temp array
        for(int i = 0; i < addToArray.Length; i++)
            oldSprings[i] = addToArray[i];

        addToArray = new JelloSpring[oldSprings.Length + springs.Length];

        int a = 0;

        for(int i = 0; i < addToArray.Length; i++)
        {
            if(i < oldSprings.Length)
            {
                addToArray[i] = oldSprings[i];
            }
            else
            {
                addToArray[i] = springs[a];

                a++;
            }
        }
    }
    /// <summary>
    /// Adds a new JelloSpring to the JelloSpring array passed in.
    /// </summary>
    /// <param name="spring">JelloSpring to add.</param>
    /// <param name="addToArray">JelloSpring array to add the new JelloSpring to</param>
    private void addSpring(JelloSpring spring, ref JelloSpring[] addToArray)
    {
        if(spring == null || spring.pointMassA < 0 || spring.pointMassA >= mBaseShape.VertexCount || spring.pointMassB < 0 || spring.pointMassB >= mBaseShape.VertexCount)
            return;

        Vector2 posA = mBaseShape.getVertex(spring.pointMassA);
        Vector2 posB = mBaseShape.getVertex(spring.pointMassB);
        Vector2 diff = posA - posB;
        float dist = spring.length * Vector2.Distance(posA, posB) / Vector2.Distance (Vector2.zero, diff);
        Vector2 mid = (posA + posB) * 0.5f;

        mid = (posA + posB) * 0.5f;
        posA = mid + (mid - posA).normalized * dist * 0.5f;
        posB = mid + (mid - posB).normalized * dist * 0.5f;

        spring.scaledLength = Vector2.Distance
            (
                Vector2.zero,
                new Vector2
                (
                (posA.x - posB.x) * Scale.x,
                (posA.y - posB.y) * Scale.y
                )
                );

        //create a temporary array of springs at the new size
        JelloSpring[] oldSprings = new JelloSpring[addToArray.Length];

        //add springs already in the array to the temp array
        for(int i = 0; i < addToArray.Length; i++)
            oldSprings[i] = addToArray[i];

        addToArray = new JelloSpring[addToArray.Length + 1];

        for(int i = 0; i < oldSprings.Length; i++)
            addToArray[i] = oldSprings[i];

        addToArray[addToArray.Length - 1] = spring;
    }
    protected override void processSmartSetShape(List<int[]> indexPairs, JelloClosedShape shape, ShapeSettingOptions options, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
    {
        base.processSmartSetShape (indexPairs, shape, options, smartOptions);

        List<int[]> indexPairsQueue = new List<int[]>();
        List<JelloSpring> tempSprings = new  List<JelloSpring>();

        if((options & ShapeSettingOptions.RebuildEdgeSprings) == ShapeSettingOptions.RebuildEdgeSprings)
        {
            clearEdgeSprings();
            buildEdgeSprings();
        }
        else if((options & ShapeSettingOptions.ClearEdgeSprings) == ShapeSettingOptions.ClearEdgeSprings)
        {
            clearEdgeSprings();
        }
        else
        {

            //find the first common point to the two shapes
            int index = -1;
            for(int i = 0; i < shape.EdgeVertexCount; i++)
            {
                if(indexPairs[i][1] != -1)
                {
                    index = i;
                    break;
                }
            }

            if(index == -1)//in this case, there are no common points to this shape at all. we can just create new edge springs...
            {
                clearEdgeSprings();
                buildEdgeSprings();
            }
            else
            {
                while(indexPairsQueue.Count < shape.EdgeVertexCount)
                {
                    if(index >= shape.EdgeVertexCount)
                        index = 0;

                    indexPairsQueue.Add (indexPairs[index]);
                    index++;
                }

                //see if edge is intact...
                for(int i = 0; i < shape.EdgeVertexCount; i++)//using edge point mass length, because we only want the edge indices
                {
                    int next = i + 1 < shape.EdgeVertexCount ? i + 1 : 0;

                    //check if this edge is the same as the last.
                    if(indexPairsQueue[i][1] != -1) //old doesnt equal -1
                    {																				//then the next should equal this plus 1 or 0 if full wrap around?
                        if(indexPairsQueue[next][1] == (indexPairsQueue[i][1] + 1 < mBaseShape.EdgeVertexCount ? indexPairsQueue[i][1] + 1 : 0)) //our edge is preserved from the old shape, lets move our old spring into place...
                        {
                            bool found = false;
                            JelloSpring spring = null;

                            //first check the expected position.
                            if(indexPairsQueue[i][1] < mEdgeSprings.Length)
                                spring = mEdgeSprings[indexPairsQueue[i][1]];

                            if(spring != null && spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == indexPairsQueue[next][1])
                                found = true;

                            //if not in the expected position, check the rest of the positions...
                            if(!found)
                            {
                                for(int a = 0; a < mEdgeSprings.Length; a++)
                                {
                                    spring = mEdgeSprings[a];

                                    if(spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == indexPairsQueue[next][1])
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                            }

                            if(!found)//the spring could not be found, create a new one.
                            {
                                //float dist = Vector2.Distance(shape.EdgeVertices[indexPairsQueue[i][1]], shape.EdgeVertices[indexPairsQueue[next][1]]);
                                spring = new JelloSpring(indexPairsQueue[i][1], indexPairsQueue[next][1], 0f, DefaultEdgeSpringStiffness, DefaultEdgeSpringDamping);
                            }

                            spring.pointMassA = indexPairsQueue[i][0];
                            spring.pointMassB = indexPairsQueue[next][0];
                            tempSprings.Add(spring);
                        }
                        else
                        {
                            if(indexPairsQueue[next][1] == -1)//this is a new point.
                            {
                                //lets check if there is a spring here...
                                bool found = false;

                                //first check the expected position.
                                JelloSpring spring = null;
                                if(indexPairsQueue[i][1] < mEdgeSprings.Length)
                                    spring = mEdgeSprings[indexPairsQueue[i][1]];

                                if(spring != null && (spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == (spring.pointMassA == mBaseShape.EdgeVertexCount - 1 ? spring.pointMassA + 1 : 0)))
                                {
                                    found = true;
                                }

                                //we didnt find the spring in the expected position, lets look through the rest of the springs.
                                if(!found)
                                {
                                    for(int a = 0; a < mEdgeSprings.Length; a++)
                                    {
                                        spring = mEdgeSprings[a];

                                        if(spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == (spring.pointMassA == mBaseShape.EdgeVertexCount - 1 ? spring.pointMassA + 1 : 0))
                                        {
                                            found = true;
                                            break;
                                        }
                                    }
                                }

                                //no old spring found, lets create one...
                                if(!found)
                                {
                                    spring = new JelloSpring(indexPairsQueue[i][0], indexPairsQueue[next][0], 0f, DefaultEdgeSpringStiffness, DefaultEdgeSpringDamping);
                                }

                                spring.pointMassA = indexPairsQueue[i][0];
                                spring.pointMassB = indexPairsQueue[next][0];
                                //spring.length = Vector2.Distance(shape.EdgeVertices[spring.pointMassA], shape.EdgeVertices[spring.pointMassB]);

                                float multiplier = spring.lengthMultiplier;

                                //first assing spring to this one...
                                tempSprings.Add (spring);
                                //int nextnext = next + 1 < shape.EdgeVertexCount ? next + 1 : 0;

                                //now look through the rest of the points until i find a common point and create those springs in the image of this one...
                                for(int a = next; a < shape.EdgeVertexCount; a++)
                                {
                                    int nextnext = a + 1 < shape.EdgeVertexCount ? a + 1 : 0;

                                    spring = new JelloSpring(indexPairsQueue[a][0], indexPairsQueue[nextnext][0], 0f, spring.stiffness, spring.damping);
                                    //spring.length = Vector2.Distance(shape.EdgeVertices[spring.pointMassA], shape.EdgeVertices[spring.pointMassB]);
                                    spring.lengthMultiplier = multiplier;

                                    tempSprings.Add (spring);

                                    i++;

                                    if(indexPairsQueue[nextnext][1] != -1)
                                        break;
                                }

                            }
                            else//this is a vertex preserved from the old shape... in otherwords, there was a point mass deleted here.
                            {
                                //lets check if there is a spring here...
                                bool found = false;

                                //first check the expected position.
                                JelloSpring spring = null;
                                if(indexPairsQueue[i][1] < mEdgeSprings.Length)
                                    spring = mEdgeSprings[indexPairsQueue[i][1]];

                                if(spring != null && (spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == (spring.pointMassA == mBaseShape.EdgeVertexCount - 1 ? spring.pointMassA + 1 : 0)))
                                {
                                    found = true;
                                }

                                //we didnt find the spring in the expected position, lets look through the rest of the springs.
                                if(!found)
                                {
                                    for(int a = 0; a < mEdgeSprings.Length; a++)
                                    {
                                        spring = mEdgeSprings[a];

                                        if(spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == (spring.pointMassA == mBaseShape.EdgeVertexCount - 1 ? spring.pointMassA + 1 : 0))
                                        {
                                            found = true;
                                            break;
                                        }
                                    }
                                }

                                //no old spring found, lets create one...
                                if(!found)
                                {
                                    spring = new JelloSpring(indexPairsQueue[i][0], indexPairsQueue[next][0], 0f, DefaultEdgeSpringStiffness, DefaultEdgeSpringDamping);
                                }

                                spring.pointMassA = indexPairsQueue[i][0];
                                spring.pointMassB = indexPairsQueue[next][0];
                                //spring.length = Vector2.Distance(shape.EdgeVertices[spring.pointMassA], shape.EdgeVertices[spring.pointMassB]);

                                tempSprings.Add (spring);
                            }
                        }
                    }
                    else
                    {
                        JelloSpring spring = new JelloSpring(indexPairsQueue[i][0], indexPairsQueue[next][0], 0f, DefaultEdgeSpringStiffness, DefaultEdgeSpringDamping);
                        //spring.length = Vector2.Distance(shape.EdgeVertices[spring.pointMassA], shape.EdgeVertices[spring.pointMassB]);

                        tempSprings.Add (spring);
                    }
                }

                mEdgeSprings = new JelloSpring[tempSprings.Count];
                int indexOffset = 0;

                for(int i = 0; i < tempSprings.Count; i++)
                {
                    if(tempSprings[i].pointMassA == 0)
                    {
                        indexOffset = i;
                        break;
                    }
                }

                JelloSpring[] tempArray = new JelloSpring[tempSprings.Count];

                for(int i = 0; i < tempArray.Length; i++)
                {
                    int a = i + indexOffset;
                    if(a >= tempArray.Length)
                        a -= tempArray.Length;

                    tempArray[i] = tempSprings[a];
                }

                clearEdgeSprings();
                addSprings(tempArray, ref mEdgeSprings);
            }
        }

        if((options & ShapeSettingOptions.RebuildInternalSprings) == ShapeSettingOptions.RebuildInternalSprings)
        {
            clearInternalSprings();
            BuildInternalSprings();
        }
        else if((options & ShapeSettingOptions.ClearInternalSprings) == ShapeSettingOptions.ClearInternalSprings)
        {
            clearInternalSprings();
        }
        else if(mInternalSprings.Length > 0)
        {

            //now handle internal springs
            int[] tris = shape.Triangles;
            tempSprings.Clear();

            for(int i = 0; i < tris.Length; i+=3)
            {
                for(int t = 0; t < 3; t++)
                {
                    int r = t + 1 < 3 ? t + 1 : 0;

                    if(tris[ i + t ] < shape.EdgeVertexCount && tris[ i + r] < shape.EdgeVertexCount) //dont build edge springs
                    {
                        if(tris[ i + t ] != 0 && tris[ i + r ] != 0)
                        {
                            if(Mathf.Abs( tris[ i + t ] - tris[ i + r ] ) == 1)
                            {
                                continue;
                            }
                        }
                        else if(tris[ i + t ] == shape.EdgeVertexCount - 1 || tris[ i + r ] == shape.EdgeVertexCount - 1 || tris[ i + t ] == 1 || tris[ i + t ] == 1)
                        {
                            continue;
                        }
                    }

                    bool exists = false;
                    for(int a = 0; a < tempSprings.Count; a++)
                    {
                        if((tris[i + t] == tempSprings[a].pointMassA && tris[i + r] == tempSprings[a].pointMassB) || (tris[i + t] == tempSprings[a].pointMassB && tris[i + r] == tempSprings[a].pointMassA))
                        {
                            exists = true;
                            break;
                        }
                    }

                    if(exists)
                        continue;
                    else
                        tempSprings.Add
                            (
                                new JelloSpring
                                (
                                tris[i + t],
                                tris[i + r],
                                0f,
                                mDefaultInternalSpringK,
                                mDefaultInternalSpringDamp
                                )
                                );
                }
            }

            //now compare our new internal springs to our old internal springs...
            for(int i = 0; i < tempSprings.Count; i++)
            {
                JelloSpring spring = tempSprings[i];
                int pairA = -1;
                int pairB = -1;

                for(int a = 0; a < indexPairs.Count; a++)
                {
                    if(indexPairs[a][0] == spring.pointMassA)
                        pairA = a;
                    if(indexPairs[a][0] == spring.pointMassB)
                        pairB = a;

                    if(pairA != -1 && pairB != -1)
                        break;
                }

                if(pairA == -1 || pairB == -1)
                {
                    //this shouldnt be possible
                    continue;
                }

                //check if there is an old point assosiated with each spring end point
                if(indexPairs[pairA][1] != -1 && indexPairs[pairB][1] != -1)
                {
                    JelloSpring oldSpring;
                    for(int a = 0; a < mInternalSprings.Length; a++)
                    {
                        oldSpring = mInternalSprings[a];

                        if((oldSpring.pointMassA == indexPairs[pairA][1] && oldSpring.pointMassB  == indexPairs[pairB][1]) || (oldSpring.pointMassB == indexPairs[pairA][1] && oldSpring.pointMassA  == indexPairs[pairB][1]))
                        {
                            spring.damping = oldSpring.damping;
                            spring.lengthMultiplier = oldSpring.lengthMultiplier;
                            spring.stiffness = oldSpring.stiffness;
                        }
                    }
                }
            }

            //now set our new internal springs.
            clearInternalSprings();

            if(tempSprings.Count > 0)
                addSprings(tempSprings.ToArray(), ref mInternalSprings);
        }

        if((options & ShapeSettingOptions.ClearCustomSprings) == ShapeSettingOptions.ClearCustomSprings)
        {
            clearCustomSprings();
        }
        else
        {

            tempSprings.Clear();

            bool rebuildCustomSprings = (smartOptions & SmartShapeSettingOptions.RebuildInvalidatedCustomSprings) == SmartShapeSettingOptions.RebuildInvalidatedCustomSprings;

            //now handle custom springs
            for(int i = 0; i < mCustomSprings.Length; i++)
            {
                JelloSpring spring = mCustomSprings[i];

                int indexA = -1;
                int indexB = -1;

                for(int a = 0; a < indexPairs.Count; a++)
                {
                    if(spring.pointMassA == indexPairs[a][1])
                        indexA = indexPairs[a][0];
                    if(spring.pointMassB == indexPairs[a][1])
                        indexB = indexPairs[a][0];

                    if(indexA != -1 && indexB != -1)
                    {
                        break;
                    }
                }

                //here
                if(indexA == -1 || indexB == -1)
                {
                    if(rebuildCustomSprings)
                    {
                        Vector2[] fullShape = new Vector2[shape.VertexCount];
                        for(int c = 0; c < shape.VertexCount; c++)
                            fullShape[c] = shape.getVertex(c);

                        if(indexA == -1)
                        {
                            //rebuild the spring
                            Vector2 pos = mBaseShape.getVertex(spring.pointMassA);

                            int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, 2);

                            //check if any of the indices are already in use
                            for(int c = 0; c < closestIndices.Length; c++)
                            {
                                //already in use by index b
                                if(indexB == closestIndices[c])
                                    continue;

                                indexA = closestIndices[c];
                                break;
                            }
                        }
                        if(indexB == -1)
                        {
                            //rebuild the spring
                            Vector2 pos = mBaseShape.getVertex(spring.pointMassB);

                            int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, 2);

                            //check if any of the indices are already in use
                            for(int c = 0; c < closestIndices.Length; c++)
                            {
                                //already in use by index b
                                if(indexA == closestIndices[c])
                                    continue;

                                indexB = closestIndices[c];
                                break;
                            }
                        }
                    }
                    else
                    {
                        continue;
                    }
                }

                spring.pointMassA = indexA;
                spring.pointMassB = indexB;
                tempSprings.Add(spring);
            }

            clearCustomSprings();

            if(tempSprings.Count > 0)
                addSprings(tempSprings.ToArray(), ref mCustomSprings);
        }
    }
 /// <summary>
 /// Sets the internal JelloSpring array.
 /// </summary>
 /// <param name="springs">JelloSpring array to replace the current internal JelloSpring array.</param>
 public void setInternalSprings(JelloSpring[] springs)
 {
     mInternalSprings = springs;
 }
    /// <summary>
    /// Removes the JelloSpring from this JelloSpringBody.
    /// Will look at edge, internal, and custom JelloSpring objects.
    /// </summary>
    /// <param name="spring">JelloSpring to remove from this JelloSpringBody.</param>
    public void RemoveSpring(JelloSpring spring)
    {
        for(int i = 0; i < SpringCount; i++)
        {
            if(getSpring(i) == spring)
            {
                if(i < mEdgeSprings.Length)
                    removeSpring(spring, ref mEdgeSprings);
                else if(i < mEdgeSprings.Length + mInternalSprings.Length)
                    removeSpring(spring, ref mInternalSprings);
                else
                    removeSpring(spring, ref mCustomSprings);

                break;
            }
        }
    }