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
	public void DrawPointMasses(JelloBody body, bool editable)
	{
		Handles.color = new Color(0.75f, 0.75f, 0.2f, 0.5f);
		
		for(int i = 0; i < body.Shape.EdgeVertexCount; i++)
		{
			Vector2 pos = body.transform.TransformPoint (body.Shape.EdgeVertices[i]);
			if(editable)
			{
				int hot = GUIUtility.hotControl;
				
				Handles.FreeMoveHandle(pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.075f, Vector3.zero, Handles.DotCap);
				if(GUIUtility.hotControl != hot)
				{
					if(currentSubEditor == 1)//point mass editor!
					{
						subEditors[currentSubEditor].SetEditIndex(i);
						Repaint();
					}
				}
			}
			else
			{
				Handles.color = new Color(0.5f, 0.5f, 0.5f, 0.5f);
				Handles.DotCap(3, pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.075f);
			}
		}

		for(int i = 0; i < body.Shape.InternalVertexCount; i++)
		{
			Handles.color = new Color(0.75f, 0f, 0.75f, 0.5f);
			Vector2 pos = body.transform.TransformPoint (body.Shape.InternalVertices[i]);
			
			if(editable)
			{
				int hot = GUIUtility.hotControl;

				EditorGUI.BeginChangeCheck();
				pos = Handles.FreeMoveHandle(pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.075f, Vector3.zero, Handles.DotCap);
				if(EditorGUI.EndChangeCheck())
				{
					if(!JelloShapeTools.Contains(body.Shape.EdgeVertices, body.transform.InverseTransformPoint(pos)) || JelloShapeTools.PointOnPerimeter(body.Shape.EdgeVertices, body.transform.InverseTransformPoint(pos)))
					{
						JelloClosedShape newShape = new JelloClosedShape(body.Shape.EdgeVertices, null, false);

						for(int a = 0; a < body.Shape.InternalVertexCount; a++)
						{
							//dont add this point
							if(a == i)
								continue;

							newShape.addInternalVertex(body.Shape.InternalVertices[a]);
						}

						newShape.finish(false);

						body.smartSetShape(newShape, JelloBody.ShapeSettingOptions.MovePointMasses, smartShapeSettingOptions);

						EditorUtility.SetDirty(body);
						GUIUtility.hotControl = 0;
						subEditors[currentSubEditor].SetEditIndex(-1);
						Repaint();
						break;
					}

					body.Shape.changeInternalVertexPosition(i, body.transform.InverseTransformPoint(pos));
					body.Shape.finish(false);

					EditorUtility.SetDirty(body);

				}
				if(GUIUtility.hotControl != hot && GUIUtility.hotControl != 0)
				{

					if(currentSubEditor == 1)//point mass editor!
					{
						subEditors[currentSubEditor].SetEditIndex(i + body.EdgePointMassCount);
						Repaint();
					}
				}
			}
			else
			{
				Handles.color = new Color(0.5f, 0.5f, 0.5f, 0.5f);
				Handles.DotCap(3, pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.075f);
			}

	
		}

	}
Beispiel #3
0
	//todo add onenable and ondisable events to body.
	public virtual void DrawEditorGUI()
	{
		//check polycollider vs pointmasscount
		if(!Application.isPlaying) //TODO have this be handled by a class that extends the polycollider and recognises changes?
		{
			for(int b = 0; b < targets.Length; b++)
			{
				JelloBody body = (JelloBody)targets[b];
				body.setComponentReferences();
				body.polyCollider.points = JelloShapeTools.RemoveDuplicatePoints(body.polyCollider.points);


				JelloClosedShape shape = new JelloClosedShape(body.polyCollider.points, null, false);

				if(body.Shape != null)
				{
					for(int i = 0; i < body.Shape.InternalVertexCount; i++)
						shape.addInternalVertex(body.Shape.InternalVertices[i]);

					shape.finish(false);
				}

				if(shape.EdgeVertexCount != body.Shape.EdgeVertexCount || shape.InternalVertexCount != body.Shape.InternalVertexCount)
					body.smartSetShape(shape, JelloBody.ShapeSettingOptions.MovePointMasses, smartShapeSettingOptions);
				else
					body.setShape(shape, JelloBody.ShapeSettingOptions.MovePointMasses); 

				//will i need to do this for constraints as well?
				for(int i = 0; i < body.AttachPointCount; i++)
				{
					body.GetAttachPoint(i).UpdateEditorMode();
				}
			}
		}
		
		serializedObject.Update();
		
		EditorGUI.showMixedValue = eMass.hasMultipleDifferentValues;
		EditorGUI.BeginChangeCheck();
		EditorGUILayout.PropertyField(eMass, massContent);
		if(EditorGUI.EndChangeCheck())
		{
			for(int i = 0; i < serializedObject.targetObjects.Length; i++)
			{
				JelloBody b = (JelloBody)serializedObject.targetObjects[i];
				b.Mass = eMass.floatValue;
			}
			serializedObject.UpdateIfDirtyOrScript();
		}
		EditorGUI.showMixedValue = false;

		if(!tar.IsStatic)
		{	
			EditorGUILayout.BeginHorizontal();
			
			EditorGUI.showMixedValue =  eAffectedByGravity.hasMultipleDifferentValues;
			EditorGUILayout.PropertyField(eAffectedByGravity, useGravContent);
			EditorGUI.showMixedValue = false;
				
			EditorGUILayout.EndHorizontal();
			
			if(eAffectedByGravity.boolValue)
			{
				EditorGUI.indentLevel++;
				EditorGUI.showMixedValue = eOverrideGravity.hasMultipleDifferentValues;
				EditorGUILayout.PropertyField(eOverrideGravity, overrideGravContent);
				EditorGUI.showMixedValue = false;
				
				if(eOverrideGravity.boolValue)
				{
					EditorGUI.indentLevel++;
					EditorGUI.showMixedValue = eGravity.hasMultipleDifferentValues;
					EditorGUILayout.PropertyField(eGravity, customGravContent);
					EditorGUI.showMixedValue = false;
					EditorGUI.indentLevel--;
				}
				EditorGUI.indentLevel--;
			}
			
			EditorGUI.showMixedValue = eKinematic.hasMultipleDifferentValues;
			EditorGUILayout.PropertyField(eKinematic, kinematicContent);
			EditorGUI.showMixedValue = false;
		}
		
		EditorGUI.showMixedValue = eTrigger.hasMultipleDifferentValues;
		EditorGUILayout.PropertyField(eTrigger, triggerContent);
		EditorGUI.showMixedValue = false;

		EditorGUI.showMixedValue = eAwake.hasMultipleDifferentValues;
		EditorGUILayout.PropertyField(eAwake, awakeContent);
		EditorGUI.showMixedValue = false;
		
		if(tar.meshLink == null || tar.meshLink.canModifyPivotPoint)
		{
			EditorGUI.indentLevel++;
			EditorGUILayout.BeginHorizontal();


			SerializedProperty ePivotOffset = serializedObject.FindProperty("pivotOffset");
			GUIStyle pivotStyle = new GUIStyle(EditorStyles.foldout);
			if(ePivotOffset.prefabOverride)
				pivotStyle.fontStyle = FontStyle.Bold;

			showPivot = EditorGUILayout.Foldout(showPivot, pivotFoldoutContent, pivotStyle);
			
			if(GUILayout.Button(centerPivotContent, EditorStyles.miniButton))
			{
				Undo.RecordObjects(serializedObject.targetObjects, "Center Pivot");
				for(int i = 0; i < serializedObject.targetObjects.Length; i++)
				{
					JelloBody jb = (JelloBody)serializedObject.targetObjects[i];
					Undo.RecordObject(jb.gameObject.transform, "Center Pivot transform");
					if(jb.meshLink != null)
					{
						Undo.RecordObject(jb.meshLink, "Center Pivot mesh");
						Undo.RecordObject(jb.polyCollider, "Center Pivot collider");
						Undo.RecordObject(jb.GetComponent<Renderer>(), "Center Pivot renderer");
						Undo.RecordObject(jb.meshLink.LinkedMeshFilter, "Center Pivot filter");
					}
				}

				for(int i = 0; i < serializedObject.targetObjects.Length; i++)
				{
					JelloBody bod = (JelloBody)serializedObject.targetObjects[i];
					CenterPivot(bod);
					EditorUtility.SetDirty(bod.gameObject);
					EditorUtility.SetDirty(bod.meshLink);
					//serializedObject.UpdateIfDirtyOrScript();
				}
				SceneView.RepaintAll();
			}
			
			EditorGUILayout.EndHorizontal();

			if(showPivot)
			{
				if(!serializedObject.isEditingMultipleObjects)
				{
					pivot = EditorGUILayout.Vector2Field("Position", pivot);
					
					if(pivot != Vector2.zero)
					{
						EditorGUILayout.BeginHorizontal();	
					
						if(GUILayout.Button(applyPivotContent, EditorStyles.miniButton))
						{
							JelloBody jb = (JelloBody)serializedObject.targetObject;
							Undo.RecordObject(jb, "Change Pivot");
							Undo.RecordObject(jb.gameObject.transform, "Change Pivot transform");
							if(jb.meshLink != null)
							{
								Undo.RecordObject(jb.meshLink, "Change Pivot mesh");
								Undo.RecordObject(jb.polyCollider, "Change Pivot collider");
								Undo.RecordObject(jb.GetComponent<Renderer>(), "Change Pivot renderer");
								Undo.RecordObject(jb.meshLink.LinkedMeshFilter, "Change Pivot filter");
							}

							ChangePivot(tar);
							EditorUtility.SetDirty(tar.gameObject);
							EditorUtility.SetDirty(tar.meshLink);
//							serializedObject.UpdateIfDirtyOrScript();
						}
						if(GUILayout.Button(cancelPivotContent, EditorStyles.miniButton))
							pivot = Vector2.zero;
						
						
						SceneView.RepaintAll();
						EditorGUILayout.EndHorizontal();
					}
				}
				else
				{
					EditorGUILayout.HelpBox("Pivot Points may only be centered when multiple Game Objects are selected", MessageType.Info);
				}
						
			}
			EditorGUI.indentLevel--;
		}

		serializedObject.ApplyModifiedProperties();
	}
Beispiel #4
0
    //TODO make sure any/all of this is precomputed in editor.
    void Awake()
    {
        myTransform = transform;
        polyCollider = (PolygonCollider2D)GetComponent<Collider2D>();

        //HACK this is to handle how ragespline keeps recreating the polygon collider with duplicate points
        if(meshLink != null && meshLink.meshLinkType == MeshLink.MeshLinkType.RageSplineMeshLink)
        {
            Vector2[] points = JelloShapeTools.RemoveDuplicatePoints(polyCollider.points);
            if(polyCollider.points.Length != points.Length)
                polyCollider.points = points;
        }

        //set pointmass positions to polygoncollider positions
        if(polyCollider.points.Length != mEdgePointMasses.Length)
        {
            JelloClosedShape shape = new JelloClosedShape(polyCollider.points, mBaseShape != null ? mBaseShape.InternalVertices : null, false);
            setShape(shape, ShapeSettingOptions.MovePointMasses);
        }
        else
        {
            Shape.changeVertices(polyCollider.points, Shape.InternalVertices);
            setShape(mBaseShape, ShapeSettingOptions.MovePointMasses);
        }

        Scale = Scale;
    }
Beispiel #5
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 #6
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 #7
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 #8
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 #9
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();
    }
Beispiel #13
0
    public void DrawPointMasses(JelloBody body, bool editable)
    {
        Handles.color = new Color(0.75f, 0.75f, 0.2f, 0.5f);

        for(int i = 0; i < body.Shape.EdgeVertexCount; i++)
        {
            Vector2 pos = body.transform.TransformPoint (body.Shape.EdgeVertices[i]);
            if(editable)
            {
                int hot = GUIUtility.hotControl;

                Handles.FreeMoveHandle(pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.075f, Vector3.zero, Handles.DotCap);
                if(GUIUtility.hotControl != hot)
                {
                    if(currentSubEditor == 1)//point mass editor!
                    {
                        subEditors[currentSubEditor].SetEditIndex(i);
                        Repaint();
                    }
                }
            }
            else
            {
                Handles.color = new Color(0.5f, 0.5f, 0.5f, 0.5f);
                Handles.DotCap(3, pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.075f);
            }
        }

        for(int i = 0; i < body.Shape.InternalVertexCount; i++)
        {
            Handles.color = new Color(0.75f, 0f, 0.75f, 0.5f);
            Vector2 pos = body.transform.TransformPoint (body.Shape.InternalVertices[i]);

            if(editable)
            {
                int hot = GUIUtility.hotControl;

                EditorGUI.BeginChangeCheck();
                pos = Handles.FreeMoveHandle(pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.075f, Vector3.zero, Handles.DotCap);
                if(EditorGUI.EndChangeCheck())
                {
                    if(!JelloShapeTools.Contains(body.Shape.EdgeVertices, body.transform.InverseTransformPoint(pos)) || JelloShapeTools.PointOnPerimeter(body.Shape.EdgeVertices, body.transform.InverseTransformPoint(pos)))
                    {
                        JelloClosedShape newShape = new JelloClosedShape(body.Shape.EdgeVertices, null, false);

                        for(int a = 0; a < body.Shape.InternalVertexCount; a++)
                        {
                            //dont add this point
                            if(a == i)
                                continue;

                            newShape.addInternalVertex(body.Shape.InternalVertices[a]);
                        }

                        newShape.finish(false);

                        body.smartSetShape(newShape, JelloBody.ShapeSettingOptions.MovePointMasses, smartShapeSettingOptions);

                        EditorUtility.SetDirty(body);
                        GUIUtility.hotControl = 0;
                        subEditors[currentSubEditor].SetEditIndex(-1);
                        Repaint();
                        break;
                    }

                    body.Shape.changeInternalVertexPosition(i, body.transform.InverseTransformPoint(pos));
                    body.Shape.finish(false);

                    EditorUtility.SetDirty(body);

                }
                if(GUIUtility.hotControl != hot && GUIUtility.hotControl != 0)
                {

                    if(currentSubEditor == 1)//point mass editor!
                    {
                        subEditors[currentSubEditor].SetEditIndex(i + body.EdgePointMassCount);
                        Repaint();
                    }
                }
            }
            else
            {
                Handles.color = new Color(0.5f, 0.5f, 0.5f, 0.5f);
                Handles.DotCap(3, pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.075f);
            }

        }
    }
Beispiel #14
0
    //todo add onenable and ondisable events to body.
    public virtual void DrawEditorGUI()
    {
        //check polycollider vs pointmasscount
        if(!Application.isPlaying) //TODO have this be handled by a class that extends the polycollider and recognises changes?
        {
            for(int b = 0; b < targets.Length; b++)
            {
                JelloBody body = (JelloBody)targets[b];
                body.setComponentReferences();
                body.polyCollider.points = JelloShapeTools.RemoveDuplicatePoints(body.polyCollider.points);

                JelloClosedShape shape = new JelloClosedShape(body.polyCollider.points, null, false);

                if(body.Shape != null)
                {
                    for(int i = 0; i < body.Shape.InternalVertexCount; i++)
                        shape.addInternalVertex(body.Shape.InternalVertices[i]);

                    shape.finish(false);
                }

                if(shape.EdgeVertexCount != body.Shape.EdgeVertexCount || shape.InternalVertexCount != body.Shape.InternalVertexCount)
                    body.smartSetShape(shape, JelloBody.ShapeSettingOptions.MovePointMasses, smartShapeSettingOptions);
                else
                    body.setShape(shape, JelloBody.ShapeSettingOptions.MovePointMasses);

                //will i need to do this for constraints as well?
                for(int i = 0; i < body.AttachPointCount; i++)
                {
                    body.GetAttachPoint(i).UpdateEditorMode();
                }
            }
        }

        serializedObject.Update();

        EditorGUI.showMixedValue = eMass.hasMultipleDifferentValues;
        EditorGUI.BeginChangeCheck();
        EditorGUILayout.PropertyField(eMass, massContent);
        if(EditorGUI.EndChangeCheck())
        {
            for(int i = 0; i < serializedObject.targetObjects.Length; i++)
            {
                JelloBody b = (JelloBody)serializedObject.targetObjects[i];
                b.Mass = eMass.floatValue;
            }
            serializedObject.UpdateIfDirtyOrScript();
        }
        EditorGUI.showMixedValue = false;

        if(!tar.IsStatic)
        {
            EditorGUILayout.BeginHorizontal();

            EditorGUI.showMixedValue =  eAffectedByGravity.hasMultipleDifferentValues;
            EditorGUILayout.PropertyField(eAffectedByGravity, useGravContent);
            EditorGUI.showMixedValue = false;

            EditorGUILayout.EndHorizontal();

            if(eAffectedByGravity.boolValue)
            {
                EditorGUI.indentLevel++;
                EditorGUI.showMixedValue = eOverrideGravity.hasMultipleDifferentValues;
                EditorGUILayout.PropertyField(eOverrideGravity, overrideGravContent);
                EditorGUI.showMixedValue = false;

                if(eOverrideGravity.boolValue)
                {
                    EditorGUI.indentLevel++;
                    EditorGUI.showMixedValue = eGravity.hasMultipleDifferentValues;
                    EditorGUILayout.PropertyField(eGravity, customGravContent);
                    EditorGUI.showMixedValue = false;
                    EditorGUI.indentLevel--;
                }
                EditorGUI.indentLevel--;
            }

            EditorGUI.showMixedValue = eKinematic.hasMultipleDifferentValues;
            EditorGUILayout.PropertyField(eKinematic, kinematicContent);
            EditorGUI.showMixedValue = false;
        }

        EditorGUI.showMixedValue = eTrigger.hasMultipleDifferentValues;
        EditorGUILayout.PropertyField(eTrigger, triggerContent);
        EditorGUI.showMixedValue = false;

        EditorGUI.showMixedValue = eAwake.hasMultipleDifferentValues;
        EditorGUILayout.PropertyField(eAwake, awakeContent);
        EditorGUI.showMixedValue = false;

        if(tar.meshLink == null || tar.meshLink.canModifyPivotPoint)
        {
            EditorGUI.indentLevel++;
            EditorGUILayout.BeginHorizontal();

            SerializedProperty ePivotOffset = serializedObject.FindProperty("pivotOffset");
            GUIStyle pivotStyle = new GUIStyle(EditorStyles.foldout);
            if(ePivotOffset.prefabOverride)
                pivotStyle.fontStyle = FontStyle.Bold;

            showPivot = EditorGUILayout.Foldout(showPivot, pivotFoldoutContent, pivotStyle);

            if(GUILayout.Button(centerPivotContent, EditorStyles.miniButton))
            {
                Undo.RecordObjects(serializedObject.targetObjects, "Center Pivot");
                for(int i = 0; i < serializedObject.targetObjects.Length; i++)
                {
                    JelloBody jb = (JelloBody)serializedObject.targetObjects[i];
                    Undo.RecordObject(jb.gameObject.transform, "Center Pivot transform");
                    if(jb.meshLink != null)
                    {
                        Undo.RecordObject(jb.meshLink, "Center Pivot mesh");
                        Undo.RecordObject(jb.polyCollider, "Center Pivot collider");
                        Undo.RecordObject(jb.GetComponent<Renderer>(), "Center Pivot renderer");
                        Undo.RecordObject(jb.meshLink.LinkedMeshFilter, "Center Pivot filter");
                    }
                }

                for(int i = 0; i < serializedObject.targetObjects.Length; i++)
                {
                    JelloBody bod = (JelloBody)serializedObject.targetObjects[i];
                    CenterPivot(bod);
                    EditorUtility.SetDirty(bod.gameObject);
                    EditorUtility.SetDirty(bod.meshLink);
                    //serializedObject.UpdateIfDirtyOrScript();
                }
                SceneView.RepaintAll();
            }

            EditorGUILayout.EndHorizontal();

            if(showPivot)
            {
                if(!serializedObject.isEditingMultipleObjects)
                {
                    pivot = EditorGUILayout.Vector2Field("Position", pivot);

                    if(pivot != Vector2.zero)
                    {
                        EditorGUILayout.BeginHorizontal();

                        if(GUILayout.Button(applyPivotContent, EditorStyles.miniButton))
                        {
                            JelloBody jb = (JelloBody)serializedObject.targetObject;
                            Undo.RecordObject(jb, "Change Pivot");
                            Undo.RecordObject(jb.gameObject.transform, "Change Pivot transform");
                            if(jb.meshLink != null)
                            {
                                Undo.RecordObject(jb.meshLink, "Change Pivot mesh");
                                Undo.RecordObject(jb.polyCollider, "Change Pivot collider");
                                Undo.RecordObject(jb.GetComponent<Renderer>(), "Change Pivot renderer");
                                Undo.RecordObject(jb.meshLink.LinkedMeshFilter, "Change Pivot filter");
                            }

                            ChangePivot(tar);
                            EditorUtility.SetDirty(tar.gameObject);
                            EditorUtility.SetDirty(tar.meshLink);
        //							serializedObject.UpdateIfDirtyOrScript();
                        }
                        if(GUILayout.Button(cancelPivotContent, EditorStyles.miniButton))
                            pivot = Vector2.zero;

                        SceneView.RepaintAll();
                        EditorGUILayout.EndHorizontal();
                    }
                }
                else
                {
                    EditorGUILayout.HelpBox("Pivot Points may only be centered when multiple Game Objects are selected", MessageType.Info);
                }

            }
            EditorGUI.indentLevel--;
        }

        serializedObject.ApplyModifiedProperties();
    }
    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];
    }