public override void smartSetShape (JelloClosedShape shape, ShapeSettingOptions options = ShapeSettingOptions.None, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
	{
		base.smartSetShape (shape, options, smartOptions);
		
		mNormalList = new Vector2[mEdgePointMasses.Length];
		mEdgeLengthList = new float[mEdgePointMasses.Length];
	}
Beispiel #2
0
    protected virtual void processSmartSetShape(List<int[]> indexPairs, JelloClosedShape shape, ShapeSettingOptions options = ShapeSettingOptions.None, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
    {
        bool rebuildJoints = (smartOptions & SmartShapeSettingOptions.RebuildInvalidatedJoints) == SmartShapeSettingOptions.RebuildInvalidatedJoints;
        bool rebuildAttachPoints = (smartOptions & SmartShapeSettingOptions.RebuildInvalidatedAttachPoints) == SmartShapeSettingOptions.RebuildInvalidatedAttachPoints;

        if(mJoints != null)
        {

            //work with joints first...
            for(int i = 0; i < mJoints.Length; i++)
            {
                JelloJoint joint = mJoints[i];

                if(joint.bodyA == this)
                {
                    for(int a = 0; a < joint.affectedIndicesA.Length; a++)
                    {
                        //Vector2 point = joint .GetAnchorPointA(true);
                        bool found = false;

                        for(int b = 0; b < indexPairs.Count; b++)
                        {
                            if(joint.affectedIndicesA[a] == indexPairs[b][1])
                            {
                                joint.affectedIndicesA[a] = indexPairs[b][0];
                                found = true;
                                break;
                            }
                        }

                        if(!found)
                        {
                            if(rebuildJoints)
                            {
                                //rebuild the joint..
                                Vector2 pos = mBaseShape.getVertex(joint.affectedIndicesA[a]);
                                Vector2[] fullShape = new Vector2[shape.VertexCount];
                                for(int c = 0; c < shape.VertexCount; c++)
                                    fullShape[c] = shape.getVertex(c);

                                int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, joint.affectedIndicesA.Length);

                                bool assignedClosest = false;

                                //check if any of the indices are already in use
                                for(int c = 0; c < closestIndices.Length; c++)
                                {
                                    //joint.affectedindicesA[a] is the current one...
                                    //compare unchecked indices against their old position and compare checked indices against their new position.
                                    for(int d = 0; d < joint.affectedIndicesA.Length; d++)
                                    {
                                        //skip the index that we are currently working with.
                                        if(d == a)
                                            continue;

                                        if(d < a)//this index has been updated to the new shape so compare against indexPairs[index][0]
                                        {
                                            if(indexPairs[closestIndices[c]][0] == joint.affectedIndicesA[d])//in use
                                                continue;
                                        }
                                        else//d must be greater than a, so so this index is untouched and we should compare against indexPairs[index][1]
                                        {
                                            if(indexPairs[closestIndices[c]][1] == joint.affectedIndicesA[d])//in use
                                                continue;
                                        }

                                        //made it past the early continues, so the index must not be in use.
                                        joint.affectedIndicesA[a] = closestIndices[c];
                                        assignedClosest = true;
                                        break;
                                    }

                                    if(assignedClosest)
                                        break;
                                }

                                //dont forget to rebuild the joint!!!
                                Vector2[] affectedVertices = new Vector2[joint.affectedIndicesA.Length];
                                for(int q = 0; q < affectedVertices.Length; q++)
                                    affectedVertices[q] = shape.getVertex (joint.affectedIndicesA[q]);

                                joint.RebuildAnchor(joint.localAnchorA, true, true, joint.affectedIndicesA, affectedVertices);
                            }
                            else
                            {
                                //this joint is invalid and will be removed in the clear invalid subcomponents method.
                                mJoints[i] = null;
                                break;
                            }
                        }
                    }
                }
                else if(joint.bodyB == this)
                {

                    for(int a = 0; a < joint.affectedIndicesB.Length; a++)
                    {
                        bool found = false;

                        for(int b = 0; b < indexPairs.Count; b++)
                        {
                            if(joint.affectedIndicesB[a] == indexPairs[b][1])
                            {
                                joint.affectedIndicesB[a] = indexPairs[b][0];
                                found = true;
                                break;
                            }
                        }

                        if(!found)
                        {
                            if(rebuildJoints)
                            {
                                //rebuild the joint..
                                Vector2 pos = mBaseShape.getVertex(joint.affectedIndicesB[a]);
                                Vector2[] fullShape = new Vector2[shape.VertexCount];
                                for(int c = 0; c < shape.VertexCount; c++)
                                    fullShape[c] = shape.getVertex(c);

                                int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, joint.affectedIndicesB.Length);

                                bool assignedClosest = false;

                                //check if any of the indices are already in use
                                for(int c = 0; c < closestIndices.Length; c++)
                                {
                                    //joint.affectedindicesA[a] is the current one...
                                    //compare unchecked indices against their old position and compare checked indices against their new position.
                                    for(int d = 0; d < joint.affectedIndicesB.Length; d++)
                                    {
                                        //skip the index that we are currently working with.
                                        if(d == a)
                                            continue;

                                        if(d < a)//this index has been updated to the new shape so compare against indexPairs[index][0]
                                        {
                                            if(indexPairs[closestIndices[c]][0] == joint.affectedIndicesB[d])//in use
                                                continue;
                                        }
                                        else//d must be greater than a, so so this index is untouched and we should compare against indexPairs[index][1]
                                        {
                                            if(indexPairs[closestIndices[c]][1] == joint.affectedIndicesB[d])//in use
                                                continue;
                                        }

                                        //made it past the early continues, so the index must not be in use.
                                        joint.affectedIndicesB[a] = closestIndices[c];
                                        assignedClosest = true;
                                        break;
                                    }

                                    if(assignedClosest)
                                        break;
                                }

                                //dont forget to rebuild the joint!!!
                                Vector2[] affectedVertices = new Vector2[joint.affectedIndicesB.Length];
                                for(int q = 0; q < affectedVertices.Length; q++)
                                    affectedVertices[q] = shape.getVertex(joint.affectedIndicesB[q]);

                                joint.RebuildAnchor(joint.localAnchorB, false, true, joint.affectedIndicesB, affectedVertices);
                            }
                            else
                            {
                                //this joint is invalid and will be removed in the clear invalid subcomponents method.
                                mJoints[i] = null;
                                break;
                            }
                        }
                    }
                }
            }
        }

        if(mAttachPoints != null)
        {

            //handle attach points now
            for(int i = 0; i < mAttachPoints.Length; i++)
            {
                JelloAttachPoint attachPoint = mAttachPoints[i];

                for(int a = 0; a < attachPoint.affectedIndices.Length; a++)
                {
                    bool found = false;
                    for(int b = 0; b < indexPairs.Count; b++)
                    {
                        if(attachPoint.affectedIndices[a] == indexPairs[b][1])
                        {
                            attachPoint.affectedIndices[a] = indexPairs[b][0];
                            found = true;
                            break;
                        }
                    }

                    if(!found)
                    {
                        if(rebuildAttachPoints)
                        {
                            //rebuild the attach point..
                            Vector2 pos = mBaseShape.getVertex(attachPoint.affectedIndices[a]);
                            Vector2[] fullShape = new Vector2[shape.VertexCount];
                            for(int c = 0; c < shape.VertexCount; c++)
                                fullShape[c] = shape.getVertex(c);

                            int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, attachPoint.affectedIndices.Length);

                            bool assignedClosest = false;

                            //check if any of the indices are already in use
                            for(int c = 0; c < closestIndices.Length; c++)
                            {
                                //joint.affectedindicesA[a] is the current one...
                                //compare unchecked indices against their old position and compare checked indices against their new position.
                                for(int d = 0; d < attachPoint.affectedIndices.Length; d++)
                                {
                                    //skip the index that we are currently working with.
                                    if(d == a)
                                        continue;

                                    if(d < a)//this index has been updated to the new shape so compare against indexPairs[index][0]
                                    {
                                        if(indexPairs[closestIndices[c]][0] == attachPoint.affectedIndices[d])//in use
                                            continue;
                                    }
                                    else//d must be greater than a, so so this index is untouched and we should compare against indexPairs[index][1]
                                    {
                                        if(indexPairs[closestIndices[c]][1] == attachPoint.affectedIndices[d])//in use
                                            continue;
                                    }

                                    //made it past the early continues, so the index must not be in use.
                                    attachPoint.affectedIndices[a] = closestIndices[c];
                                    assignedClosest = true;
                                    break;
                                }

                                if(assignedClosest)
                                    break;
                            }

                            //all legs have been updated, not rebuild the attach point.
                            attachPoint.Rebuild(attachPoint.point, this, attachPoint.affectedIndices, true);
                        }
                        else
                        {
                            //this joint is invalid and will be removed in the clear invalid subcomponents method.
                            mAttachPoints[i] = null;
                            break;
                        }
                    }
                }
            }
        }
    }
Beispiel #3
0
    /// <summary>
    /// Smartly sets JelloBody.Shape to a new JelloClosedShape object.
    /// Make sure your JelloShape does not contain any duplicate points ( Use JelloShapeTools.RemoveDuplicates() ).
    /// This method will attemp to retain as much information as possible from the previous shape.
    /// The subcomponents that will be processed in order to try and retained are JelloPointMass, JelloJoint, JelloAttachPoint, and JelloSpring.
    /// </summary>
    /// <param name="shape">New JelloClosedShape.</param>
    /// <param name="options">ShapeSettingOptions for setting the JelloClosedShape.</param>
    /// <param name="smartOptions">SmartShapeSettingOptions for setting the JelloClosedShape.</param>
    public virtual void smartSetShape(JelloClosedShape shape, ShapeSettingOptions options = ShapeSettingOptions.None, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
    {
        //no need to run smart method if no shape yet assigned.
        if(mBaseShape == null)
        {
            setShape(shape, options);
            return;
        }

        setComponentReferences();

        //find common points between the old shape and the new one.
        List<int[]> indexPairs = new List<int[]>();

        //start with the edges...???
        for(int a = 0;  a < shape.EdgeVertexCount; a++)
        {
            bool found = false;
            for(int i = 0; i < mBaseShape.EdgeVertexCount; i++)
            {
                if(mBaseShape.EdgeVertices[i] == shape.EdgeVertices[a])
                {
                    indexPairs.Add (new int[2]{a, i});
                    found = true;
                    break;
                }
            }

            if(!found)
                indexPairs.Add (new int[2]{a, -1});
        }

        for(int a = 0;  a < shape.InternalVertexCount; a++)
        {
            bool found = false;
            for(int i = 0; i < mBaseShape.InternalVertexCount; i++)
            {
                if(mBaseShape.InternalVertices[i] == shape.InternalVertices[a])
                {
                    indexPairs.Add (new int[2]{a, i});
                    found = true;
                    break;
                }
            }

            if(!found)
                indexPairs.Add (new int[2]{a, -1});
        }

        bool movePointMasses = (options & ShapeSettingOptions.MovePointMasses) == ShapeSettingOptions.MovePointMasses;

        //reconfigure point masses
        JelloPointMass[] tempPointMasses = new JelloPointMass[shape.EdgeVertexCount];
        for(int i = 0; i < shape.EdgeVertexCount; i++)
        {
            //this is a new point, create a point mass here
            if(indexPairs[i][1] == -1)
            {
                Vector2 pos;

                if(movePointMasses)
                    pos =  myTransform.TransformPoint(shape.EdgeVertices[indexPairs[i][0]]);
                else
                    pos = Position;

                tempPointMasses[i] = new JelloPointMass(Mass, pos, this, false);
            }
            else//this point exists from the old shape, move that point mass into this index.
            {
                tempPointMasses[i] = mEdgePointMasses[indexPairs[i][1]];
            }
        }
        mEdgePointMasses = tempPointMasses;

        tempPointMasses = new JelloPointMass[shape.InternalVertexCount];
        for(int i = 0; i < shape.InternalVertexCount; i++)
        {
            //this is a new point, create a point mass here
            if(indexPairs[i + shape.EdgeVertexCount][1] == -1)
            {
                Vector2 pos;

                if(movePointMasses)
                    pos =  myTransform.TransformPoint(shape.InternalVertices[indexPairs[i + shape.EdgeVertexCount][0]]);
                else
                    pos = Position;

                tempPointMasses[i] = new JelloPointMass(Mass, pos, this, false);
            }
            else//this point exists from the old shape, move that point mass into this index.
            {
                tempPointMasses[i] = mInternalPointMasses[indexPairs[i + shape.EdgeVertexCount][1]];
            }
        }
        mInternalPointMasses = tempPointMasses;

        pivotOffset = JelloShapeTools.FindCenter(shape.EdgeVertices);

        //offset index pairs for internal points
        for(int i = 0;  i < shape.InternalVertexCount; i++)
        {
            indexPairs[shape.EdgeVertexCount + i][0] += shape.EdgeVertexCount;
            indexPairs[shape.EdgeVertexCount + i][1] += mBaseShape.EdgeVertexCount;
        }

        //		//TODO remove this? it seems a bit redundant...
        //		for(int i = 0; i < mEdgePointMasses.Length; i++)
        //			mEdgePointMasses[i].body = this;
        //		for(int i = 0; i < mInternalPointMasses.Length; i++)
        //			mInternalPointMasses[i].body = this;

        processSmartSetShape(indexPairs, shape, options, smartOptions);

        ClearInvalidSubComponents(); //this is joints and attach points....

        mBaseShape = shape;
    }
Beispiel #4
0
    /// <summary>
    /// At the given index, smartly remove the internal JelloPointMass from this JelloBody and the internal vertex from JelloBody.Shape.InternalVertices.
    /// Smartly means that most edits made to the JelloBody will be retained and is done via the JelloBody.smartSetShape() method.
    /// </summary>
    /// <param name="index">The index of internal JelloPointMass to be removed.</param>
    /// <param name="recenterBaseShape">Whether to recenter JelloBody.Shape.</param>
    /// <param name="options">ShapeSettingOptions on how Subcomponents should be modified as the JelloPointMass and JelloClosedShape vertex is removed.</param>
    /// <param name="smartOptions">SmartShapeSettingOptions on how Subcomponents should be modified as the JelloPointMass and JelloClosedShape vertex is removed.</param>
    public virtual void smartRemoveInternalPointMass(int index, bool recenterBaseShape, ShapeSettingOptions options = ShapeSettingOptions.None, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
    {
        if(index < 0 && index >= mInternalPointMasses.Length)
            return;

        Vector2[] tempItnernalVertices = new Vector2[mBaseShape.InternalVertexCount - 1];
        int a = 0;
        for(int i = 0; i < mBaseShape.InternalVertexCount; i++)
        {
            if(i != index)
            {
                tempItnernalVertices[a] = mBaseShape.InternalVertices[i];
                a++;
            }
        }

        JelloClosedShape newShape = new JelloClosedShape(mBaseShape.EdgeVertices, tempItnernalVertices, recenterBaseShape);

        smartSetShape(newShape, options, smartOptions);
    }
Beispiel #5
0
    /// <summary>
    /// Add an internal JelloPointMass to this JelloBody.
    /// This will also add an internal vertex to JelloBody.Shape.InternalVertices.
    /// Smartly means that most edits made to the JelloBody will be retained and is done via the JelloBody.smartSetShape() method.
    /// </summary>
    /// <param name="pointMass">The new JelloPointMass to add.</param>
    /// <param name="recenterBaseShape">Whether to recenter JelloBody.Shape.</param>
    /// <param name="options">ShapeSettingOptions on how Subcomponents should be modified as the JelloPointMass and JelloClosedShape vertex is added .</param>
    /// <param name="smartOptions">SmartShapeSettingOptions options on how Subcomponents should be modified as the JelloPointMass and JelloClosedShape vertex is added.</param>
    public void smartAddInternalPointMass(JelloPointMass pointMass, bool recenterBaseShape, ShapeSettingOptions options = ShapeSettingOptions.None, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
    {
        if(mBaseShape == null)
            return;

        JelloClosedShape newShape = new JelloClosedShape(mBaseShape.EdgeVertices, mBaseShape.InternalVertices, false);

        if(!newShape.addInternalVertex(pointMass.LocalPosition))
            return;

        newShape.finish(recenterBaseShape);

        smartSetShape(newShape, options, smartOptions);

        mInternalPointMasses[mInternalPointMasses.Length - 1] = pointMass;
    }
Beispiel #6
0
    /// <summary>
    /// Sets JelloBody.Shape to a new JelloClosedShape object.
    /// Make sure your JelloShape does not contain any duplicate points ( Use JelloShapeTools.RemoveDuplicates() ).
    /// This method will remove any existing JelloPointMass objects, and replace them with new ones if
    /// the new shape has a different JelloClosedShape.VertexCount than the previous one. In this case
    /// the JelloPointMass.Mass for each newly added JelloPointMass will be set to JelloBody.Mass. 
    /// Otherwise the JelloBody.Shape is just updated, not affecting the existing JelloPointMass objects other than thier positions.
    /// Any JelloJoint, JelloSpring, or AttachPoint made invalid by the new shape will be removed.
    /// </summary>
    /// <param name="shape">New JelloClosedShape.</param>
    /// <param name="options">ShapeSettingOptions for setting the JelloClosedShape.</param>
    /// 
    /// <dl class="example"><dt>Example</dt></dl>
    /// ~~~{.c}
    /// //Change the shape of the body to match the shape of the collider collided against
    /// JelloSpringBody springBody;
    /// 
    /// void OnTriggerEnter2D(Collider2D coll)
    /// {
    /// 	if(coll.GetType() == typeof(PolygonCollider2D))
    /// 	{
    /// 		PolygonCollider2D polyColl = (PolygonCollider2D)coll;
    /// 		
    /// 		JelloClosedShape shape = new JelloClosedShape(polyColl.points, true);
    /// 		
    /// 		springBody.setShape(shape, true);
    /// 	}
    /// }
    /// ~~~
    public virtual void setShape(JelloClosedShape shape, ShapeSettingOptions options = ShapeSettingOptions.None)
    {
        //TODO make this all work better...
        mBaseShape = shape;

        bool movePointMasses = (options & ShapeSettingOptions.MovePointMasses) == ShapeSettingOptions.MovePointMasses;

        setComponentReferences();

        if (mBaseShape.EdgeVertices.Length != mEdgePointMasses.Length)
        {
            Vector2 pos;
        //			JelloPointMass[] oldPointMasses = mPointMasses;
            mEdgePointMasses = new JelloPointMass[mBaseShape.EdgeVertices.Length];

            //how to make this work so that it doesnt move the point masses... what about mesh link options?
            for (int i = 0; i < mBaseShape.EdgeVertices.Length; i++)
            {
        //				if(i < oldPointMasses.Length)
        //				{
        //					mPointMasses[i] = oldPointMasses[i]; //retain as many of the original point masses?
        //
        //					if(movePointMasses)
        //						mPointMasses[i].Position = myTransform.TransformPoint(mBaseShape.EdgeVertices[i]);
        //				}
        //				else
        //				{
                    if(movePointMasses)
                        pos =  myTransform.TransformPoint(mBaseShape.EdgeVertices[i]);
                    else
                        pos = Position;

                    mEdgePointMasses[i] = new JelloPointMass(Mass, pos, this, false);
        //				}
            }
        }
        else if(movePointMasses)
        {
            for(int i = 0; i < EdgePointMassCount; i++)
                mEdgePointMasses[i].Position = myTransform.TransformPoint(mBaseShape.EdgeVertices[i]);
        }

        if (mBaseShape.InternalVertices.Length != mInternalPointMasses.Length)
        {
            Vector2 pos;
        //			JelloPointMass[] oldPointMasses = mInternalPointMasses;
            mInternalPointMasses = new JelloPointMass[mBaseShape.InternalVertices.Length];

            //how to make this work so that it doesnt move the point masses... what about mesh link options?
            for (int i = 0; i < mBaseShape.InternalVertices.Length; i++)
            {
        //				if(i < oldPointMasses.Length)
        //				{
        //					mInternalPointMasses[i] = oldPointMasses[i]; //retain as many of the original point masses?
        //
        //					if(movePointMasses)
        //						mInternalPointMasses[i].Position = myTransform.TransformPoint(mBaseShape.InternalVertices[i]);
        //				}
        //				else
        //				{
                    if(movePointMasses)
                        pos =  myTransform.TransformPoint(mBaseShape.InternalVertices[i]);
                    else
                        pos = Position;

                    mInternalPointMasses[i] = new JelloPointMass(Mass, pos, this, false);
        //				}
            }
        }
        else if(movePointMasses)
        {
            for(int i = 0; i < mInternalPointMasses.Length; i++)
                mInternalPointMasses[i].Position = myTransform.TransformPoint(mBaseShape.InternalVertices[i]);
        }

        pivotOffset = JelloShapeTools.FindCenter(mBaseShape.EdgeVertices);

        for(int i = 0; i < mEdgePointMasses.Length; i++)
            mEdgePointMasses[i].body = this;
        for(int i = 0; i < mInternalPointMasses.Length; i++)
            mInternalPointMasses[i].body = this;

        ClearInvalidSubComponents();
    }
    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);
        }
    }
 public override void smartSetShape(JelloClosedShape shape, ShapeSettingOptions options, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
 {
     base.smartSetShape (shape, options, smartOptions);
 }
    /// <summary>
    /// Set the JelloBody.Shape of this JelloBody to a new JelloClosedShape object.  This function 
    /// will remove any existing JelloPointMass objects, and replace them with new ones if
    /// the new JelloClosedShape has a different vertex count than the previous one.  In this case
    /// the JelloPointMass.Mass for each newly added JelloPointMass will be set to the JelloBody.Mass. Otherwise the JelloBody.Shape is just
    /// updated, not affecting any existing JelloPointMass other than by position.
    /// Any JelloJoint or AttachPoint made invalid by the new shape will be removed.
    /// If present, each internal JelloSpring will be removed and a new set will be built.
    /// If present, each custom spring will be removed.
    /// Will clear and replace every edge JelloSpring.
    /// Will update every JelloSpring rest length.
    /// </summary>
    /// <param name="shape">New JelloClosedShape to implement</param>
    /// <param name="options">ShapeSettingOptions for setting the JelloClosedShape.</param>
    public override void setShape(JelloClosedShape shape, ShapeSettingOptions options = ShapeSettingOptions.None)
    {
        base.setShape (shape, options);

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

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

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

        updateSpringDistances();
    }
    public override void smartSetShape(JelloClosedShape shape, ShapeSettingOptions options = ShapeSettingOptions.None, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
    {
        base.smartSetShape (shape, options, smartOptions);

        mNormalList = new Vector2[mEdgePointMasses.Length];
        mEdgeLengthList = new float[mEdgePointMasses.Length];
    }