示例#1
0
	public void CenterPivot(JelloBody t)
	{
		Vector2 center = new Vector2();

		t.polyCollider.points = JelloShapeTools.RemoveDuplicatePoints(t.polyCollider.points);
		t.Shape.changeVertices(t.polyCollider.points, t.Shape.InternalVertices);

				
		center = JelloShapeTools.FindCenter(t.Shape.EdgeVertices);//using vertices instead of collider.points because need of assigning entire array at once


		if(t.meshLink != null)
		{
			MonoBehaviour monoBehavior;
			if(t.meshLink.UpdatePivotPoint(center, out monoBehavior))
				EditorUtility.SetDirty(monoBehavior);
		}

		for(int i = 0; i < t.Shape.VertexCount; i++)
			t.Shape.setVertex(i, t.Shape.getVertex(i) - center);
		
		t.polyCollider.points = t.Shape.EdgeVertices;
		
		t.transform.position += (Vector3)JelloVectorTools.rotateVector(new Vector2(center.x * t.Scale.x, center.y * t.Scale.y), t.Angle);
		if(t.transform.childCount > 0)
			for(int i = 0; i < t.transform.childCount; i++)
				t.transform.GetChild(i).position -= (Vector3)center;

		if(t.JointCount > 0)
			for(int i = 0; i < t.JointCount; i++)
				t.GetJoint (i).localAnchorA -= center;

		if(t.AttachPointCount > 0)
			for(int i = 0; i < t.AttachPointCount; i++)
				t.GetAttachPoint(i).point -= center;
		
		t.updateGlobalShape(true);
		
		EditorUtility.SetDirty(t);

		pivot = Vector2.zero;
	}
	/// <summary>
	/// Flip the JelloClosedShape verticaly.
	/// </summary>
	/// 
	/// <dl class="example"><dt>Example</dt></dl>
	/// ~~~{.c}
	/// //turn a body around when it hits a ceiling
	/// 
	/// JelloBody body;
	/// void handleCollisionEnter(JelloCollisionManifold manifold)
	/// {
	/// 	if(manifold.GetOtherBody(body).gameObject.tag == "ceiling")
	/// 	{
	/// 		body.flipY();
	/// 		//also reverse movement direction
	/// 	}
	/// }
	/// ~~~
	public void flipY() //TODO check into this --> will i need to retriangulate? because mesh triangles may need to always be wound in a certain direction.
	{
		Vector2[] tempVertices = new  Vector2[mEdgeVertices.Length];
		
		for(int i = 0; i < mEdgeVertices.Length; i++)
		{																						
			mEdgeVertices[i] = new Vector2(mEdgeVertices[i].x, mEdgeVertices[i].y + 2 * (Center.x - mEdgeVertices[i].x));
			tempVertices[mEdgeVertices.Length - i - 1] = mEdgeVertices[i];
		}
		
		mEdgeVertices = tempVertices;


		tempVertices = new  Vector2[mInternalVertices.Length];
		
		for(int i = 0; i < mInternalVertices.Length; i++)
		{																						
			mInternalVertices[i] = new Vector2(mInternalVertices[i].x, mInternalVertices[i].y + 2 * (Center.x - mInternalVertices[i].x));
			tempVertices[mInternalVertices.Length - i - 1] = mInternalVertices[i];
		}
		
		mInternalVertices = tempVertices;

		if(winding == Winding.Clockwise)
		{
			winding = Winding.CounterClockwise;
		}
		else if(winding == Winding.CounterClockwise)
		{
			winding = Winding.Clockwise;
		}
		else
		{
			if(JelloShapeTools.HasClockwiseWinding(mEdgeVertices))
				winding = Winding.Clockwise;					
			else
				winding = Winding.CounterClockwise;
		}

		//finish ();
	}
	/// <summary>
	/// Finish adding vertices to this JeloClosedShape, and choose whether to convert into local space.
	/// JelloClosedShape.winding and JelloClosedShape.Triangles will be set.
	/// Make sure there are no duplicate points before calling this. use JelloShapeTools.RemoveDuplicatePoints().
	/// </summary>
	/// <param name="recenter">whether to convert the positions of the JelloClosedShape into local space.</param>
	/// 
	/// <dl class="example"><dt>Example</dt></dl>
	/// ~~~{.c}
	/// //Create a closed shape square
	/// JelloClosedShape shape = new JelloClosedShape();
	/// 
	/// shape.begin();
	/// 
	/// shape.addPoint(new Vector2(-1,1));	//top left
	/// shape.addPoint(new Vector2(-1,1));	//top right
	/// shape.addPoint(new Vector2(-1,1));	//bottom right
	/// shape.addPoint(new Vector2(-1,1));	//bottom left
	/// 	
	/// shape.finish();
	/// ~~~
    public void finish(bool recenter = true)
    {

		if(mInternalVertices != null && mInternalVertices.Length > 0)
		{
			//dont allow duplicate points
			mInternalVertices = JelloShapeTools.RemoveDuplicatePoints(mInternalVertices);

			//dont allow points outside of the perimiter
			for(int i = 0;  i < mInternalVertices.Length; i++)
			{
				if(!JelloShapeTools.Contains(mEdgeVertices, mInternalVertices[i]))
				{	
					mInternalVertices[i] = Vector2.one * Mathf.Infinity;
				}
			}
			//dont allow points on the perimiter. (this will also remove any null points)
			mInternalVertices = JelloShapeTools.RemovePointsOnPerimeter(mEdgeVertices, mInternalVertices);
		}

		mCenter = JelloShapeTools.FindCenter(mEdgeVertices);
        
		if (recenter)
        {	
            // now subtract this from each element, to get proper "local" coordinates.
            for (int i = 0; i < mEdgeVertices.Length; i++)
                mEdgeVertices[i] -= mCenter;
			if(mInternalVertices != null)
				for (int i = 0; i < mInternalVertices.Length; i++)
					mInternalVertices[i] -= mCenter;
        }

		if(JelloShapeTools.HasClockwiseWinding(mEdgeVertices))
			winding = Winding.Clockwise;
		else
			winding = Winding.CounterClockwise;



		Triangulate();
    }
	/// <summary>
	/// Change the positions of the vertices of the JelloClosedShape. Be sure to call JelloClosedShape.finish() after this.
	/// Will fail if number of vertices do not match.
	/// </summary>
	/// <param name="edgeVertices">The new edge vertex positions.</param>
	/// <param name="internalVertices">The new internal vertex positions.</param>
	/// 
	/// <dl class="example"><dt>Example</dt></dl>
	/// ~~~{.c}
	/// //create a closed shape in the form of a square and then change it into a rectangle
	/// Vector2[] square;
	/// Vector2[] rectangle;
	/// 
	/// JelloClosedShape shape = new JelloClosedShape(square);
	/// 
	/// shape.changeVertices(rectangle, new Vector2[0], true);
	/// ~~~
	public void changeVertices(Vector2[] edgeVertices, Vector2[] internalVertices)
	{
		if(edgeVertices.Length == mEdgeVertices.Length)
		{
			for(int i = 0 ; i < edgeVertices.Length; i++)
				mEdgeVertices[i] = edgeVertices[i];

			bool[] valid = new bool[internalVertices.Length];
			int num = 0;

			for(int i = 0 ; i < internalVertices.Length; i++)
			{
				if(JelloShapeTools.Contains(mEdgeVertices, internalVertices[i]))
				{
					valid[i] = true;
					num++;
				}
				else
				{
					valid[i] = false;
				}
			}

			mInternalVertices = new Vector2[num];

			num = 0;
			for(int i = 0 ; i < internalVertices.Length; i++)
			{
				if(valid[i])
				{
					mInternalVertices[num] = internalVertices[i];
					num++;
				}
			}
		}
		else
		{
			Debug.LogWarning("new vertices count less than current vertices count");
		}
	}
示例#5
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);
			}

	
		}

	}
示例#6
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();
	}
	//TODO draw some info for the other body as well? like an outline?
	public void DrawjointSceneGUI()
	{
		mainEditor.DrawPointMasses(body, false);

		Vector3 pos;
		
		//hovered over joint
		if(drawIndex >= 0 && drawIndex < body.JointCount && body.GetJoint(drawIndex).bodyA != null)
		{
			JelloJoint joint = body.GetJoint(drawIndex);

			Vector3 posA = body.transform.TransformPoint(joint.GetAnchorPointA(true));
			posA.z = body.transform.position.z;

			Handles.color = Color.magenta;
			for(int i = 0; i < joint.affectedIndicesA.Length; i++)
			{
				Handles.DrawLine(posA, body.transform.TransformPoint(body.Shape.getVertex(joint.affectedIndicesA[i])));
				Handles.DotCap(3, 
				               body.transform.TransformPoint(body.Shape.getVertex(joint.affectedIndicesA[i])), 
				               Quaternion.identity, 
				               HandleUtility.GetHandleSize(body.transform.TransformPoint(body.Shape.getVertex(joint.affectedIndicesA[i]))) * 0.05f);
			}
			Handles.color = Color.blue;
			Handles.DotCap(3, posA, Quaternion.identity, HandleUtility.GetHandleSize(posA) * 0.075f);

			Vector3 posB = joint.GetAnchorPointB(true);



			if(joint.TransformB !=  null)
			{
				posB = joint.TransformB.TransformPoint(posB);
				
				if(joint.bodyB != null)
				{
					if(joint.affectedIndicesB != null)
					{


						Handles.color = Color.magenta;
						for(int i = 0; i < body.GetJoint(drawIndex).affectedIndicesB.Length; i++)
						{
							Handles.DrawLine(posB, joint.bodyB.transform.TransformPoint(joint.bodyB.Shape.getVertex(joint.affectedIndicesB[i])));
							Handles.DotCap(3, 
							               joint.bodyB.transform.TransformPoint(joint.bodyB.Shape.getVertex(joint.affectedIndicesB[i])), 
							               Quaternion.identity, 
							               HandleUtility.GetHandleSize(joint.bodyB.transform.TransformPoint(joint.bodyB.Shape.getVertex(joint.affectedIndicesB[i]))) * 0.05f);
						}
						Handles.color = Color.blue;
					}
				}
				
				
			}
			
			Handles.DotCap(3, posB, Quaternion.identity, HandleUtility.GetHandleSize(posB) * 0.075f);
			
			Handles.color = Color.red;
			Handles.DrawLine(posA, posB);
		}
		
		//selected joint
		if(editIndex >= 0 && editIndex < body.JointCount && body.GetJoint(editIndex).affectedIndicesA != null)
		{	
			JelloJoint joint = body.GetJoint(editIndex);


			int num = 2 + joint.affectedIndicesA.Length;
			if(joint.TransformB != null && joint.bodyB != null)
				num += joint.affectedIndicesB.Length;

			//first get handle sizes...
			//need global handle positions
			Vector3[] globalHandlePositions = new Vector3[num];

			globalHandlePositions[0] = body.transform.TransformPoint(handlePositions[0]);
			for(int i = 0; i < joint.affectedIndicesA.Length; i++)
				globalHandlePositions[i + 2] = body.transform.TransformPoint(handlePositions[i + 2]);
			
			
			if(joint.TransformB != null)
			{
				globalHandlePositions[1] = joint.TransformB.TransformPoint(handlePositions[1]);

				if(joint.bodyB != null)
				{
					for(int i = 0; i < joint.affectedIndicesB.Length; i++)
					{
						globalHandlePositions[i + 2 + joint.affectedIndicesA.Length] = joint.TransformB.TransformPoint(handlePositions[i + 2 + joint.affectedIndicesA.Length]);
					}
				}
			}
			else
			{
				globalHandlePositions[1] = joint.globalAnchorB;
			}

			CalculateHandleSizes(globalHandlePositions);
			
			bool mouseUp = false;
			
			if(Event.current.type == EventType.mouseUp)
				mouseUp = true;
			
			Handles.color = Color.cyan;
			
			EditorGUI.BeginChangeCheck();
			handlePositions[0] = body.transform.InverseTransformPoint( Handles.FreeMoveHandle(body.transform.TransformPoint(handlePositions[0]), Quaternion.identity, handleSizes[0], Vector3.zero, Handles.CircleCap));
			if(EditorGUI.EndChangeCheck())
			{
				Vector2[] affectedPoints = new Vector2[joint.affectedIndicesA.Length];
				for(int i = 0; i < affectedPoints.Length; i++)
					affectedPoints[i] = body.Shape.getVertex(joint.affectedIndicesA[i]);
				
				joint.RebuildAnchor
					(
						handlePositions[0], 
						true, 
						true,
						joint.affectedIndicesA,
						affectedPoints
						);
				SetEditIndex(editIndex);

				EditorUtility.SetDirty(body);

				SceneView.RepaintAll();
			}

			for(int i = 0; i < joint.affectedIndicesA.Length; i++)
			{
				Handles.color = Color.blue;
				handlePositions[i + 2] = body.transform.InverseTransformPoint(Handles.FreeMoveHandle(body.transform.TransformPoint(handlePositions[i + 2]), 
				                                                                                Quaternion.identity, 
				                                                                                handleSizes[i + 2],
				                                                                                Vector3.zero,  
				                                                                                Handles.CircleCap));
				
				if(mouseUp)
				{
					if((Vector2)handlePositions[i + 2] != body.Shape.getVertex(joint.affectedIndicesA[i]))
					{
						Vector2[] points = new Vector2[body.Shape.VertexCount];
						for(int s = 0; s < body.Shape.VertexCount; s++)
							points[s] = body.Shape.getVertex(s);
						
						int index = JelloShapeTools.FindClosestVertexOnShape(handlePositions[i + 2], points);
						bool indexInUse = false;
						
						for(int u = 0; u < joint.affectedIndicesA.Length; u++)
							if(index == joint.affectedIndicesA[u])
								indexInUse = true;
						
						if(!indexInUse)
						{
							joint.affectedIndicesA[i] = index;
							
							Vector2[] affectedVertices = new Vector2[joint.affectedIndicesA.Length];
							for(int v = 0; v < affectedVertices.Length; v++)
								affectedVertices[v] = body.Shape.getVertex(joint.affectedIndicesA[v]); 
							
							handlePositions[i + 2] = body.Shape.getVertex(index);
							
							
							joint.RebuildAnchor(joint.localAnchorA, true, true, null, affectedVertices);

							Vector2 newPosition = Vector2.zero;
							for(int v = 0; v < affectedVertices.Length; v++)
								newPosition += affectedVertices[v] * joint.scalarsA[v];

							handlePositions[0] = newPosition;

							EditorUtility.SetDirty(body);

							SceneView.RepaintAll();
						}
						else
						{
							handlePositions[i + 2] = body.Shape.getVertex(joint.affectedIndicesA[i]);
						}
					}
				}
				
				Handles.color = Color.black;
				Handles.DrawLine(body.transform.TransformPoint(handlePositions[0]), body.transform.TransformPoint( handlePositions[i + 2]));
			}
			
			//other object's GUI
			Handles.color = Color.magenta;
			
			if(joint.TransformB != null)
			{
				EditorGUI.BeginChangeCheck();
				handlePositions[1] = joint.TransformB.InverseTransformPoint( Handles.FreeMoveHandle(joint.TransformB.TransformPoint(handlePositions[1]), Quaternion.identity, handleSizes[1], Vector3.zero, Handles.CircleCap));
				if(EditorGUI.EndChangeCheck())
				{
					Vector2[] affectedPoints = new Vector2[0];
					
					if(joint.bodyB != null)
					{
						affectedPoints = new Vector2[joint.affectedIndicesB.Length];
						for(int i = 0; i < affectedPoints.Length; i++)
							affectedPoints[i] = joint.bodyB.Shape.getVertex(joint.affectedIndicesB[i]);
					}
					
					joint.RebuildAnchor
						(
							handlePositions[1], 
							false,
							true,
							joint.affectedIndicesB,
							affectedPoints
							);
					
					SetEditIndex(editIndex);

					EditorUtility.SetDirty(body);

					SceneView.RepaintAll();
				}

				if(joint.bodyB != null && joint.affectedIndicesB != null)
				{	
					int numAffectedA = joint.affectedIndicesA.Length;
					for(int i = 0; i < joint.affectedIndicesB.Length; i++)
					{
						int offsetIndex = i + numAffectedA + 2;
						
						Handles.color = Color.red;
						handlePositions[offsetIndex] = joint.TransformB.InverseTransformPoint(Handles.FreeMoveHandle(joint.TransformB.TransformPoint(handlePositions[offsetIndex]), 
						                                                                                                  Quaternion.identity, 
						                                                                                                  handleSizes[offsetIndex], 
						                                                                                                  Vector3.zero, 
						                                                                                                  Handles.CircleCap));

						if(mouseUp)
						{
							if((Vector2)handlePositions[offsetIndex] != joint.bodyB.Shape.getVertex(joint.affectedIndicesB[i]))
							{
								Vector2[] points = new Vector2[joint.bodyB.Shape.VertexCount];
								for(int s = 0; s < joint.bodyB.Shape.VertexCount; s++)
									points[s] = joint.bodyB.Shape.getVertex(s);
								
								int index = JelloShapeTools.FindClosestVertexOnShape(handlePositions[offsetIndex], points);
								bool indexInUse = false;
								
								for(int u = 0; u < joint.affectedIndicesB.Length; u++)
									if(index == joint.affectedIndicesB[u])
										indexInUse = true;
								
								
								if(!indexInUse)
								{
									joint.affectedIndicesB[i] = index;
									
									Vector2[] affectedVertices = new Vector2[joint.affectedIndicesB.Length];
									for(int v = 0; v < affectedVertices.Length; v++)
										affectedVertices[v] = joint.bodyB.Shape.getVertex(joint.affectedIndicesB[v]); 
									
									handlePositions[offsetIndex] = joint.bodyB.Shape.getVertex(index);
									

									joint.RebuildAnchor(joint.localAnchorB, false, true, null, affectedVertices);

									Vector2 newPosition = Vector2.zero;
									for(int v = 0; v < affectedVertices.Length; v++)
										newPosition += affectedVertices[v] * joint.scalarsB[v];
									handlePositions[1] = newPosition;

									EditorUtility.SetDirty(body);

									SceneView.RepaintAll();
								}
								else
								{
									handlePositions[offsetIndex] = joint.bodyB.Shape.getVertex(joint.affectedIndicesB[i]);
								}
							}
						}
						
						Handles.color = Color.grey;
						Handles.DrawLine(joint.bodyB.transform.TransformPoint(handlePositions[1]), joint.bodyB.transform.TransformPoint( handlePositions[offsetIndex]));
					}
				}
				
				Handles.color = Color.yellow;
				Handles.DrawLine(joint.TransformA.TransformPoint(handlePositions[0]), joint.TransformB.TransformPoint(handlePositions[1]));
			}
			else
			{
				//TODO this should be handlepositions[1]???
				EditorGUI.BeginChangeCheck();
				joint.globalAnchorB = Handles.FreeMoveHandle(joint.globalAnchorB, Quaternion.identity, handleSizes[1], Vector3.zero, Handles.CircleCap);
				if(EditorGUI.EndChangeCheck())
				{
					EditorUtility.SetDirty(body);
				}
				Handles.color = Color.yellow;
				Handles.DrawLine(joint.TransformA.TransformPoint(handlePositions[0]), joint.globalAnchorB);
			}
		}
		
		//add new joint logic
		if(newSubComponentState == AddSubComponentState.initiated)
		{
			int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);
			
			if(Event.current.type == EventType.Layout)
				HandleUtility.AddDefaultControl(controlID);
			
			pos = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin; //need where this ray intersects the zplane
			Plane plane = new Plane(Vector3.forward, new Vector3(0, 0, body.transform.position.z));
			Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
			float dist = 0f;
			plane.Raycast(ray, out dist);
			pos = ray.GetPoint(dist);
			Vector3 mousePosWorld = new Vector3(pos.x, pos.y, body.transform.position.z);
			
			Handles.color = Color.blue;
			
			Handles.CircleCap(3, mousePosWorld, Quaternion.identity, HandleUtility.GetHandleSize(mousePosWorld) * 0.15f);
			
			if(Event.current.type == EventType.MouseUp)
			{
				body.AddJoint(new JelloJoint(body.transform, null, body.transform.InverseTransformPoint(mousePosWorld), Vector2.zero, true, true));
				newSubComponentState = AddSubComponentState.inactive;
				SetEditIndex(body.JointCount - 1);

				EditorUtility.SetDirty(body);
			}
			
			SceneView.RepaintAll();
		}
	}
示例#8
0
    public override void DrawSceneGUI()
    {
        if (springBody == null || multiEditing)
        {
            return;
        }

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

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

            Handles.color = Color.magenta;

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

            Handles.DrawLine(posA, posB);
        }

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

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

            bool mouseUp = false;

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

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

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

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

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

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

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

                    EditorUtility.SetDirty(springBody);
                }

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

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

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

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

                    EditorUtility.SetDirty(springBody);
                }
            }

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

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

            Handles.color = Color.blue;

            Handles.DrawLine(posA, posB);
        }

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


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

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

            Handles.color = Color.red;

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

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

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

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

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

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

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

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

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

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

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

            SceneView.RepaintAll();
        }

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

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

            mainEditor.DrawPointMasses(springBody, false);
        }
    }
	/// <summary>
	/// Processes the pull.
	/// </summary>
	/// <returns>IEnumerator.</returns>
	IEnumerator ProcessPull()
	{
		//Grab the closest point mass and process adjacent points.
		GrabPointMass();

		//could be true later if you are still pulling the body, but do not have a specific point grabbed.
		//this would happen if when you are holding down the mouse button, its position is within the jello body.
		bool waitingForNewGrab = false;

		//keep processing the pull as long as the mouse button is depressed.
		while(Input.GetMouseButton(0))
		{
//			if(requireGrounded && !grounded)
//				break;

			//wake up the body if its being grabbed.
			body.IsAwake = true;

			//find the mouses current position in world space.
			mousePosInWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);

			//If our mouse position is outside of the body's transformed base shape
			if(!JelloShapeTools.Contains(body.Shape.EdgeVertices, body.transform.InverseTransformPoint(mousePosInWorld)))
			{
				//if our mouse position was inside of the base shape last step, grab a new point mass.
				if(waitingForNewGrab)
				{
					GrabPointMass();
					waitingForNewGrab = false;
				}

				//the base shape position (local and global) respective to the selected point mass.
				Vector2 pt = body.Shape.EdgeVertices[pmIndex];
				Vector2 ptGlobal = (Vector2)body.transform.TransformPoint(pt);

				//if we want the body to rotate to align with the pull
				if(rotate)
				{
					//find the difference in angle between the two vector
					Vector2 dir1 = mousePosInWorld - body.Position; 																						//body position to mouse position
					Vector2 dir2 = (Vector2)body.transform.TransformPoint(body.Shape.EdgeVertices[pmIndex]) - body.Position; 	//body position to xformed base shape position
					float ang = Vector2.Angle(dir1, dir2);

					//correct our body angle only a bit at a time for smooth rotations.
					ang = Mathf.Clamp(ang, 0f, ang * rotateSpeed * Time.fixedDeltaTime);
					
					if(JelloVectorTools.CrossProduct(dir1, dir2) < 0f)
						ang *=  -1f;
					body.Angle -= ang;
				}
				else
				{
					//we dont want the body to rotate to align and will constrain the point mass to a cone.

					//find the two shape positions next to our selected shape position.
					Vector2 prev = body.Shape.EdgeVertices[pmIndex > 0 ? pmIndex - 1 : body.Shape.EdgeVertexCount - 1];
					Vector2 next = body.Shape.EdgeVertices[pmIndex + 1 < body.Shape.EdgeVertexCount ? pmIndex + 1: 0];

					//vectors to/from adjacent ponts
					Vector2 fromPrev = pt - prev;
					Vector2 toNext = next - pt;
					//normal created by adjacent vectors
					//this is the bisector of the angle created by the prev to pt to next vectors
					//and will be used as the bisector of the constraining cone.
					Vector2 ptNorm = JelloVectorTools.getPerpendicular(fromPrev + toNext);
					//correct normal direction by shape winding.
					ptNorm = body.Shape.winding == JelloClosedShape.Winding.Clockwise ? ptNorm : -ptNorm;

					//convert to global coordinates
					ptNorm = (Vector2)body.transform.TransformDirection(ptNorm);
					//find the angle between the our mouse and the bisector.
					float ang = Vector2.Angle (ptNorm, mousePosInWorld - ptGlobal);

					//if we exceed the constraint of the cone.
					if(ang > coneAngle * 0.5f) //0.5 because the bisector cuts the cone angle in half.
					{
						//find the vector representing the edge of the cone
						Vector2 limitVector;
						if(JelloVectorTools.CrossProduct (ptNorm, mousePosInWorld - ptGlobal) < 0f )//which side of the bisector are we on
							limitVector = JelloVectorTools.rotateVector(ptNorm, -coneAngle * 0.5f);
						else
							limitVector = JelloVectorTools.rotateVector(ptNorm, coneAngle * 0.5f);

						//move our position to the closest point on the limit vector. Handle max pull back at the same time.
						mousePosInWorld = JelloVectorTools.getClosestPointOnSegment(mousePosInWorld, ptGlobal, ptGlobal + limitVector.normalized * maxPullBack);
					}
				}

				//how far away from xformed base shape position we are.
				pullBackDistance = (mousePosInWorld - ptGlobal).sqrMagnitude;
				if(pullBackDistance != 0f)
				{
					//if we exceed the max pullback, set to the max pullback.
					if(pullBackDistance > maxPullBack * maxPullBack)
					{
						mousePosInWorld = ptGlobal + (mousePosInWorld - ptGlobal).normalized * maxPullBack; // still do this when angle is not right.
						pullBackDistance = maxPullBack * maxPullBack;
					}
				}

				//explicitly set the selected pointmass position and velocity.
				pointmass.Position = mousePosInWorld;
				pointmass.velocity = Vector2.zero;	
			}
			else//our mouse is down, but is inside the perimeter of the body.
			{
				ReleasePointMass();//release the selected point mass and restore its ajacent point masses
				waitingForNewGrab = true;//wait for a new grab. would occur if the mouse was dragged outside of the body again. 
			}
				
			//keep the body still while being pulled.
			body.Position = position;

			//sync up with fixed update
			yield return new WaitForFixedUpdate();
		}

		//mouse button has been released!
		//release the selected point mass.
		ReleasePointMass();
		//release the body and apply force if we had a point mass selected at the time.
		ReleaseBody(!waitingForNewGrab);
	}
	public void DrawAttachPointSceneGUI()
	{
		//TODO i have an error when reverting to prefab. If the handles are ind a different place, it sets dirty and messes up the seleced edit attach point.
		mainEditor.DrawPointMasses(body, false);

		Vector3 pos;
		
		//the attach point hovered over in the editor
		if(drawIndex >= 0 && drawIndex < body.AttachPointCount && body.GetAttachPoint(drawIndex).body != null)
		{
			pos = body.transform.TransformPoint(body.GetAttachPoint(drawIndex).point);

			Handles.color = Color.magenta;
			for(int i = 0; i < body.GetAttachPoint(drawIndex).affectedIndices.Length; i++)
			{
				Handles.DrawLine(pos, body.transform.TransformPoint(body.Shape.getVertex(body.GetAttachPoint(drawIndex).affectedIndices[i])));
				Handles.DotCap(3, 
				               body.transform.TransformPoint(body.Shape.getVertex(body.GetAttachPoint(drawIndex).affectedIndices[i])), 
				               Quaternion.identity, 
				               HandleUtility.GetHandleSize(body.transform.TransformPoint(body.Shape.getVertex(body.GetAttachPoint(drawIndex).affectedIndices[i]))) * 0.05f);
			}
			Handles.color = Color.blue;
			Handles.DotCap(3, pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.075f);
		}
		
		//the attach point currently selected in the editor
		if(editIndex != -1 && editIndex < body.AttachPointCount && body.GetAttachPoint(editIndex).body != null)
		{	
			//handle sizes
			int num = body.GetAttachPoint(editIndex).affectedIndices.Length + 1;
			Vector3[] globalHandlePositions = new Vector3[num];
			globalHandlePositions[0] = body.transform.TransformPoint(handlePositions[0]);
			for(int i = 0; i < body.GetAttachPoint(editIndex).affectedIndices.Length; i++)
				globalHandlePositions[i + 1] = body.transform.TransformPoint(handlePositions[i + 1]);

			CalculateHandleSizes(globalHandlePositions);

			bool mouseUp = false;
			
			if(Event.current.type == EventType.mouseUp)
				mouseUp = true;
			
			Handles.color = Color.green;
			EditorGUI.BeginChangeCheck();
			handlePositions[0] = body.transform.InverseTransformPoint( Handles.FreeMoveHandle(body.transform.TransformPoint(handlePositions[0]), Quaternion.identity, handleSizes[0], Vector3.zero, Handles.CircleCap));
			if(EditorGUI.EndChangeCheck())
			{
				body.GetAttachPoint(editIndex).Rebuild(handlePositions[0], body, body.GetAttachPoint(editIndex).affectedIndices);
				SetEditIndex(editIndex);

				EditorUtility.SetDirty(body);
				//modified in scene
			}
		
			Handles.color = Color.white;
			Handles.DotCap(3, body.transform.TransformPoint(handlePositions[0]), Quaternion.identity, handleSizes[0] * 0.5f);
			//start at one because the point occupies the first position.
			//for(int i = 1; i < handlePositions.Length; i++)
			for(int i = 1; i < body.GetAttachPoint(editIndex).affectedIndices.Length + 1; i++)
			{
				Handles.color = Color.blue;
				handlePositions[i] = body.transform.InverseTransformPoint( Handles.FreeMoveHandle(body.transform.TransformPoint(handlePositions[i]), Quaternion.identity, handleSizes[i], Vector3.zero, Handles.CircleCap));
			
				if(mouseUp)
				{
					if((Vector2)handlePositions[i] != body.Shape.getVertex(body.GetAttachPoint(editIndex).affectedIndices[i - 1]))
					{
						Vector2[] points = new Vector2[body.Shape.VertexCount];
						for(int s = 0; s < body.Shape.VertexCount; s++)
							points[s] = body.Shape.getVertex(s);
						
						int index = JelloShapeTools.FindClosestVertexOnShape(handlePositions[i], points);

						bool occupied = false;
						for(int n = 0; n < body.GetAttachPoint(editIndex).affectedIndices.Length; n++)
							if(index == body.GetAttachPoint(editIndex).affectedIndices[n])
								occupied = true;

						if(!occupied)
						{
							body.GetAttachPoint(editIndex).affectedIndices[i - 1] = index;
							
							handlePositions[i] = body.Shape.getVertex(index);
							
							body.GetAttachPoint(editIndex).Rebuild(body.GetAttachPoint(editIndex).point, body, body.GetAttachPoint(editIndex).affectedIndices);

							handlePositions[0] = body.GetAttachPoint(editIndex).point;

							EditorUtility.SetDirty(body);
						}
						else
						{
							handlePositions[i] = body.Shape.getVertex(body.GetAttachPoint(editIndex).affectedIndices[i - 1]);
						}
					}
				}

				Handles.color = Color.black;
				Handles.DrawLine(body.transform.TransformPoint(handlePositions[0]), body.transform.TransformPoint( handlePositions[i]));
			}
		}
		
		//logic to add a new attach point
		if(newSubComponentState == AddSubComponentState.initiated)
		{
			int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);
			
			if(Event.current.type == EventType.Layout)
				HandleUtility.AddDefaultControl(controlID);
			
			pos = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin; //need where this ray intersects the zplane
			Plane plane = new Plane(Vector3.forward, new Vector3(0, 0, body.transform.position.z));
			Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
			float dist = 0f;
			plane.Raycast(ray, out dist);
			pos = ray.GetPoint(dist);
			Vector3 mousePosWorld = new Vector3(pos.x, pos.y, body.transform.position.z);
			
			Handles.color = Color.blue;
			
			Handles.CircleCap(3, mousePosWorld, Quaternion.identity, HandleUtility.GetHandleSize(mousePosWorld) * 0.15f);
			
			if(Event.current.type == EventType.MouseUp)//TODO not working correctly...?
			{
				body.AddAttachPoint(new JelloAttachPoint(body.transform.InverseTransformPoint(mousePosWorld), body, true));
				newSubComponentState = AddSubComponentState.inactive;
				SetEditIndex(body.AttachPointCount - 1);

				EditorUtility.SetDirty(body);
			}
			
			SceneView.RepaintAll();
		}
	}
示例#11
0
	/// <summary>
	/// Set up the anchor.
	/// </summary>
	/// <returns>The anchor's position.</returns>
	/// <param name="xform">The Transform of the anchor.</param>
	/// <param name="anchor">The anchor point, local to the given Transform.</param>
	/// <param name="isAnchorA">Whether to set up the first anchor instead of the second.</param>
	/// <param name="useBaseShape">Whether to use JelloBody.Shape instead of its JelloPointMass objects. Has no effect if no JelloBody is attached to the Transform.</param>
	/// <param name="numPointsAffected">The number of PointMasses affected / affecting this anchor. Has no effect if no JelloBody is attached to the Transform.</param>
	public Vector2 SetupAnchor(Transform xform, Vector2 anchor, bool isAnchorA, bool useBaseShape, int numPointsAffected = 0)
	{
		if(isAnchorA)
			TransformA = xform;
		else
			TransformB = xform;

		if(xform == null)
		{
			if(isAnchorA)
			{
				affectedIndicesA = null;
				scalarsA = null;

				if(TransformB != null)
				{
					globalAnchorA = TransformB.TransformPoint(GetAnchorPointB(useBaseShape));
					return globalAnchorA;
				}
				else
				{
					return Vector2.zero;
				}
			}
			else
			{
				affectedIndicesB = null;
				scalarsB = null;

				if(TransformA != null)
				{
					globalAnchorB = TransformA.TransformPoint(GetAnchorPointA(useBaseShape));
					return globalAnchorB;
				}
				else
				{
					return Vector2.zero;
				}
			}


			//return Vector2.zero;
		}

		Vector2 returnPosition = anchor;

		if(numPointsAffected < 1)
			numPointsAffected = 2;
		else if(numPointsAffected > 3)
			numPointsAffected = 3;

		if(isAnchorA)
		{
			localAnchorA = anchor;

			if(bodyA != null)
			{
				Vector2[] shape = new Vector2[bodyA.Shape.VertexCount];
				if(useBaseShape) //TODO tighten this up a bit
				{
					for(int i = 0; i < shape.Length; i++)
						shape[i] = bodyA.Shape.getVertex(i);
				}
				else
				{
					for(int i = 0; i < bodyA.PointMassCount; i++)
						shape[i] = bodyA.getPointMass(i).Position;
				}

				Vector2 point = localAnchorA;
				if(!useBaseShape)
					point = xform.TransformPoint(point);

				if(numPointsAffected == 1)
				{
					affectedIndicesA = JelloShapeTools.GetClosestIndices(point, shape, 1);
					scalarsA = new float[1];
					scalarsA[0] = 1f;
					returnPosition = shape[affectedIndicesA[0]];
				}
				else if(numPointsAffected == 2)
				{
					Vector2 hit;
					affectedIndicesA = JelloShapeTools.FindClosestEdgeOnShape(point, shape);
					scalarsA = new float[2];
					JelloVectorTools.getClosestPointOnSegmentSquared (point, shape[affectedIndicesA[0]], shape[affectedIndicesA[1]], out hit, out scalarsA[1]);
					scalarsA[0] = 1 - scalarsA[1];
					returnPosition = shape[affectedIndicesA[0]] * scalarsA[0] + shape[affectedIndicesA[1]] * scalarsA[1]; 
				}
				else if(numPointsAffected == 3)
				{
					Vector2[] shapePerimeter = new Vector2[bodyA.EdgePointMassCount];
					if(useBaseShape)
					{
						shapePerimeter = bodyA.Shape.EdgeVertices;
					}
					else
					{
						for(int i = 0; i < shapePerimeter.Length; i++)
							shapePerimeter[i] = bodyA.getEdgePointMass(i).Position;
					}
					
					affectedIndicesA = JelloShapeTools.FindContainingTriangle(point, shape, shapePerimeter, bodyA.Shape.Triangles, out scalarsA);

					returnPosition = shape[affectedIndicesA[0]] * scalarsA[0] + shape[affectedIndicesA[1]] * scalarsA[1] + shape[affectedIndicesA[2]] * scalarsA[2];
				}

				if(!useBaseShape)
					returnPosition = mTransformA.InverseTransformPoint(returnPosition);
			}
		}
		else
		{
			localAnchorB = anchor;
			
			if(bodyB != null)
			{
				Vector2[] shape = new Vector2[bodyB.Shape.VertexCount];
				if(useBaseShape)
				{
					for(int i = 0; i < shape.Length; i++)
						shape[i] = bodyB.Shape.getVertex(i);
				}
				else
				{
					for(int i = 0; i < bodyB.PointMassCount; i++)
						shape[i] = bodyB.getPointMass(i).Position;
				}
			
				Vector2 point = localAnchorB;
				if(!useBaseShape)
					point = xform.TransformPoint(point);
				
				if(numPointsAffected == 1)
				{
					affectedIndicesB = JelloShapeTools.GetClosestIndices(point, shape, 1);
					scalarsB = new float[1];
					scalarsB[0] = 1f;
					returnPosition = shape[affectedIndicesB[0]] * scalarsB[0];
				}
				else if(numPointsAffected == 2)
				{
					Vector2 hit;
//					affectedIndicesB = JelloShapeTools.GetClosestIndices(point, shape, 2);
					affectedIndicesB = JelloShapeTools.FindClosestEdgeOnShape(point, shape);
					scalarsB = new float[2];
					JelloVectorTools.getClosestPointOnSegmentSquared (point, shape[affectedIndicesB[0]], shape[affectedIndicesB[1]], out hit, out scalarsB[1]);
					scalarsB[0] = 1 - scalarsB[1];
					returnPosition = shape[affectedIndicesB[0]] * scalarsB[0] + shape[affectedIndicesB[1]] * scalarsB[1];
				}
				else if(numPointsAffected == 3)
				{
					Vector2[] shapePerimeter = new Vector2[bodyB.EdgePointMassCount];
					if(useBaseShape)
					{
						shapePerimeter = bodyB.Shape.EdgeVertices;
					}
					else
					{
						for(int i = 0; i < shapePerimeter.Length; i++)
							shapePerimeter[i] = bodyB.getEdgePointMass(i).Position;
					}
					
					affectedIndicesB = JelloShapeTools.FindContainingTriangle(point, shape, shapePerimeter, bodyB.Shape.Triangles, out scalarsB);

					returnPosition = shape[affectedIndicesB[0]] * scalarsB[0] + shape[affectedIndicesB[1]] * scalarsB[1] + shape[affectedIndicesB[2]] * scalarsB[2];
				}

				if(!useBaseShape)
					returnPosition = mTransformB.InverseTransformPoint(returnPosition);}
		}

		return returnPosition;
	}
示例#12
0
	//anchor is local //vertices are local //have vector2 return?
	/// <summary>
	/// Rebuilds the anchor.
	/// </summary>
	/// <param name="anchor">The anchor (In local space).</param>
	/// <param name="isAnchorA">Whether to rebuild the first anchor as opposed to rebuilding the second anchor.</param>
	/// <param name="useBaseShape">Whether use JelloBody.Shape instead of JelloPointMass.Position. Has no effect if Transform has no JelloBody attached.</param>
	/// <param name="affectedIndices">The indices of the affected / affecting JelloPointMass objects. Has no effect if Transform has no JelloBody attached.</param>
	/// <param name="affectedVertices">The positions (in local space) of the affected / affecting JelloPointMass objects. Has no effect if Transform has no JelloBody attached.</param>
	public void RebuildAnchor(Vector2 anchor, bool isAnchorA, bool useBaseShape, int[] affectedIndices = null, Vector2[] affectedVertices = null)
	{
		//Vector2 point;

		if(isAnchorA)
		{
			localAnchorA = anchor;

			if(mTransformA == null)
				return;

			if(bodyA != null)
			{
				if(affectedIndices == null)
					affectedIndices = affectedIndicesA;
				else
					affectedIndicesA = affectedIndices;

				if(affectedVertices == null)//grab from point mass positions?
				{
					if(useBaseShape)
					{
						affectedVertices = new Vector2[affectedIndicesA.Length];
						for(int i = 0; i < affectedIndicesA.Length; i++)
							affectedVertices[i] = bodyA.Shape.getVertex(affectedIndicesA[i]);
					}
					else
					{
						affectedVertices = new Vector2[affectedIndicesA.Length];
						for(int i = 0; i < affectedIndicesA.Length; i++)
							affectedVertices[i] = bodyA.getPointMass(affectedIndicesA[i]).LocalPosition;
					}
				}

				if(affectedIndices != null)
				{
					if(affectedIndices.Length == 1)
					{
						scalarsA = new float[1];
						scalarsA[0] = 1f;
					}
					else if(affectedIndices.Length == 2)
					{
						Vector2 hit;

						scalarsA = new float[2];
						JelloVectorTools.getClosestPointOnSegmentSquared (localAnchorA, affectedVertices[0], affectedVertices[1], out hit, out scalarsA[1]);
						scalarsA[0] = 1 - scalarsA[1];
					}
					else if(affectedIndices.Length == 3)
					{
						scalarsA = JelloShapeTools.GetBarycentricCoords(localAnchorA, affectedVertices);
					}
				}
			}
		}
		else
		{
			localAnchorB = anchor;
			
			if(mTransformB == null)
				return;
			
			if(bodyB != null)
			{
				if(affectedIndices == null)
					affectedIndices = affectedIndicesB;
				else
					affectedIndicesB = affectedIndices;
				
				if(affectedVertices == null)//grab from point mass positions?
				{
					if(useBaseShape)
					{
						affectedVertices = new Vector2[affectedIndicesB.Length];
						for(int i = 0; i < affectedIndicesB.Length; i++)
							affectedVertices[i] = bodyB.Shape.getVertex(affectedIndicesB[i]);
					}
					else
					{
						affectedVertices = new Vector2[affectedIndicesB.Length];
						for(int i = 0; i < affectedIndicesB.Length; i++)
							affectedVertices[i] = bodyB.getPointMass(affectedIndicesB[i]).LocalPosition;
					}
				}
				
				if(affectedIndices != null)
				{
					if(affectedIndices.Length == 1)
					{
						scalarsB = new float[1];
						scalarsB[0] = 1f;
					}
					else if(affectedIndices.Length == 2)
					{
						Vector2 hit;
						
						scalarsB = new float[2];
						JelloVectorTools.getClosestPointOnSegmentSquared (localAnchorB, affectedVertices[0], affectedVertices[1], out hit, out scalarsB[1]);
						scalarsB[0] = 1 - scalarsB[1];
					}
					else if(affectedIndices.Length == 3)
					{
						scalarsB = JelloShapeTools.GetBarycentricCoords(localAnchorB, affectedVertices);
					}
				}
			}
		}
	}
示例#13
0
    /// <summary>
    /// Rebuild this JelloAttachPoint.
    /// </summary>
    /// <param name="attachPoint">The point (local to the JelloAttachPoint.body) at which to attach the JelloAttachPoint.AttachedTransform.</param>
    /// <param name="jelloBody">The JelloBody to to be attached to.</param>
    /// <param name="indices">The JelloPointMass Indices. Should have a length of 1, 2, or 3.</param>
    /// <param name="useBaseShape">Whether to use the  JelloBody.Shape positions (instead of JelloPointMass.Position) when building the JelloAttachPoint.</param>
    public void Rebuild(Vector2 attachPoint, JelloBody jelloBody, int[] indices, bool useBaseShape = true)
    {
        body      = jelloBody;
        transform = body.transform;

        if (indices == null)
        {
            if (affectedIndices == null)
            {
                Rebuild(attachPoint, jelloBody, useBaseShape);
                return;
            }
            else
            {
                indices = affectedIndices;
            }
        }
        else if (indices.Length > 4)
        {
            affectedIndices = new int[3];
            for (int i = 0; i < 3; i++)
            {
                affectedIndices[i] = indices[i];
            }
        }
        else
        {
            affectedIndices = indices;
        }

        Vector2[] verts = new Vector2[3];

        if (useBaseShape)
        {
            for (int i = 0; i < affectedIndices.Length; i++)
            {
                verts[i] = body.Shape.getVertex(affectedIndices[i]);
            }
        }
        else
        {
            attachPoint = transform.TransformPoint(attachPoint);
            for (int i = 0; i < affectedIndices.Length; i++)
            {
                verts[i] = body.getPointMass(affectedIndices[i]).Position;
            }
        }

        if (affectedIndices.Length == 1)
        {
            scalars    = new float[1];
            scalars[0] = 1f;
        }
        else if (affectedIndices.Length == 2)
        {
            Vector2 hit;

            scalars = new float[2];
            JelloVectorTools.getClosestPointOnSegmentSquared(attachPoint, verts[0], verts[1], out hit, out scalars[1]);
            scalars[0] = 1 - scalars[1];
        }
        else if (affectedIndices.Length == 3)
        {
            scalars = JelloShapeTools.GetBarycentricCoords(attachPoint, verts);
        }

        //throw into for loop...
        point = Vector2.zero;
        for (int i = 0; i < affectedIndices.Length; i++)
        {
            point += scalars[i] * verts[i];
        }

        if (!useBaseShape)
        {
            point = transform.InverseTransformPoint(point);
        }

        if (mAttachedTransform != null)
        {
            Vector3 newPos = transform.TransformPoint(point);
            newPos.z = mAttachedTransform.position.z;
            mAttachedTransform.position = newPos;
        }
    }
示例#14
0
    /// <summary>
    /// Rebuild this JelloAttachPoint.
    /// </summary>
    /// <param name="attachPoint">The point (local to the JelloAttachPoint.body) at which to attach the JelloAttachPoint.AttachedTransform.</param>
    /// <param name="jelloBody">The JelloBody to to be attached to.</param>
    /// <param name="useBaseShape">Whether to use the  JelloBody.Shape positions (instead of JelloPointMass.Position) when building the JelloAttachPoint.</param>
    /// <param name="numLegs">Number of JelloPointMass objects to use as "legs" (use 1, 2, or 3).</param>
    public void Rebuild(Vector2 attachPoint, JelloBody jelloBody, bool useBaseShape = true, int numLegs = 0)
    {
        body      = jelloBody;
        transform = body.transform;

        if (numLegs != 0)
        {
            if (numLegs < 0)
            {
                numLegs = 1;
            }
            if (numLegs > 3)
            {
                numLegs = 3;
            }

            affectedIndices = new int[numLegs];
        }
        else if (affectedIndices == null || affectedIndices.Length == 0 || affectedIndices.Length > 3)
        {
            affectedIndices = new int[2];            //default to 3?
        }
        Vector2[] shape = new Vector2[body.Shape.VertexCount];
        if (useBaseShape)
        {
            for (int i = 0; i < shape.Length; i++)
            {
                shape[i] = body.Shape.getVertex(i);
            }
        }
        else
        {
            attachPoint = transform.TransformPoint(attachPoint);

            for (int i = 0; i < shape.Length; i++)
            {
                shape[i] = body.getPointMass(i).Position;
            }
        }

        if (affectedIndices.Length == 1)
        {
            affectedIndices = JelloShapeTools.GetClosestIndices(attachPoint, shape, 1);
            scalars         = new float[1];
            scalars[0]      = 1f;
        }
        else if (affectedIndices.Length == 2)
        {
            Vector2 hit;
            affectedIndices = JelloShapeTools.FindClosestEdgeOnShape(attachPoint, shape);
            scalars         = new float[2];
            JelloVectorTools.getClosestPointOnSegmentSquared(attachPoint, shape[affectedIndices[0]], shape[affectedIndices[1]], out hit, out scalars[1]);
            scalars[0] = 1 - scalars[1];
        }
        else if (affectedIndices.Length == 3)
        {
            Vector2[] shapePerimeter = new Vector2[body.EdgePointMassCount];
            if (useBaseShape)
            {
                shapePerimeter = body.Shape.EdgeVertices;
            }
            else
            {
                for (int i = 0; i < shapePerimeter.Length; i++)
                {
                    shapePerimeter[i] = body.getEdgePointMass(i).Position;
                }
            }

            affectedIndices = JelloShapeTools.FindContainingTriangle(attachPoint, shape, shapePerimeter, body.Shape.Triangles, out scalars);
        }

        point = Vector2.zero;
        for (int i = 0; i < affectedIndices.Length; i++)
        {
            point += shape[affectedIndices[i]] * scalars[i];
        }


        if (!useBaseShape)
        {
            point = transform.InverseTransformPoint(point);
        }

        if (mAttachedTransform != null)
        {
            Vector3 newPos = transform.TransformPoint(point);
            newPos.z = mAttachedTransform.position.z;
            mAttachedTransform.position = newPos;
        }
    }