public override void SetEditIndex(int index) { JelloJoint joint = body.GetJoint(index); editIndex = index; int numA = joint.affectedIndicesA.Length; handlePositions[0] = handlePositions[1] = Vector2.zero; for(int i = 0; i < numA; i++) { handlePositions[i + 2] = body.Shape.getVertex(joint.affectedIndicesA[i]); handlePositions[0] += handlePositions[i + 2] * joint.scalarsA[i]; } if(joint.TransformB != null) { if(joint.bodyB != null) { for(int i = 0; i < joint.affectedIndicesB.Length; i++) { handlePositions[numA + i + 2] = joint.bodyB.Shape.getVertex(joint.affectedIndicesB[i]); handlePositions[1] += handlePositions[numA + i + 2] * joint.scalarsB[i]; } } else { handlePositions[1] = joint.localAnchorB; } } }
/// <summary> /// Processes the collision event. /// </summary> /// <param name="jelloCollision">Jello collision.</param> private void ProcessCollisionEvent(JelloCollision jelloCollision) { if(!stickAtPoints && !stickAtEdges) return; //loop through each contact and see if a joint exists. //if not, create the joint. for(int i = 0; i < jelloCollision.contacts.Length; i++) { JelloContact contact = jelloCollision.contacts[i]; bool skip = true; if(stickAtPoints && body == contact.bodyA) skip = false; if(stickAtEdges && body == contact.bodyB) skip = false; if(skip) continue; bool found = false; //see if this joint already exists for(int c = joints.Count - 1; c >= 0; c--) { JelloJoint joint = joints[c]; //remove joints that have been destroyed if(joint.destroyed) { joints.Remove(joint); continue; } //i only want to know if there is a joint between the two bodies and if the point or edge is already taken. //should only need to use transform...? if(joint.TransformA != contact.transformA && joint.TransformB != contact.transformA) continue; if(joint.TransformA != contact.transformB && joint.TransformB != contact.transformB) continue; //at this point we know that they share the same transforms. //we also know that one of the bodies is the body that this script is attached to. if(contact.bodyA != null) { if(stickAtPoints && joint.bodyA == contact.bodyA) //this matters if i am alowing point joints { if(joint.affectedIndicesA.Length != 1) //joint bodya has multiple anchors { continue; } else if(joint.affectedIndicesA[0] != contact.bodyApm) //joint bodyA has a single anchor and is not the same { continue; } } //where am i handling rigidbodies or even static bodies?? if(stickAtEdges && joint.bodyB != null) { if(joint.bodyB == contact.bodyA)//this matters if i am allowing edge joints { if(joint.affectedIndicesB.Length != 1) { continue; } else if(joint.affectedIndicesB[0] != contact.bodyApm) { continue; } } } } if(contact.bodyB != null) { if(stickAtEdges && joint.bodyA == contact.bodyB) { if(joint.affectedIndicesA.Length != 2) { continue; } else { if(joint.affectedIndicesA[0] != contact.bodyBpmA && joint.affectedIndicesA[0] != contact.bodyBpmB) { continue; } if(joint.affectedIndicesA[1] != contact.bodyBpmA && joint.affectedIndicesA[1] != contact.bodyBpmB) { continue; } if(joint.bodyB != null) { if(joint.affectedIndicesB.Length != 1) { continue; } else if(joint.affectedIndicesB[0] != contact.bodyApm) { continue; } } } } if(stickAtPoints && joint.bodyB != null) { if(joint.bodyB == contact.bodyB) { if(joint.affectedIndicesB.Length != 2) { continue; } else { if(joint.affectedIndicesB[0] != contact.bodyBpmA && joint.affectedIndicesB[0] != contact.bodyBpmB) { continue; } if(joint.affectedIndicesB[1] != contact.bodyBpmA && joint.affectedIndicesB[1] != contact.bodyBpmB) { continue; } if(joint.bodyA != null) { if(joint.affectedIndicesA.Length != 1) { continue; } else if(joint.affectedIndicesA[0] != contact.bodyApm) { continue; } } //else check if ra is the same? } } } } //must be the same found = true; break; } if(!found)//joint Doesn't exist, so create it! { if(!stickAtPoints && contact.transformA == transform) continue; if(!stickAtEdges && contact.transformB == transform) continue; JelloJoint joint = new JelloJoint(); joint.TransformA = contact.transformA; joint.localAnchorA = joint.TransformA.InverseTransformPoint(contact.hitPoint); if(joint.bodyA != null) { int[] indices = new int[1]; Vector2[] vertices = new Vector2[1]; indices[0] = contact.bodyApm; vertices[0] = contact.bodyA.getPointMass(indices[0]).LocalPosition; joint.RebuildAnchor(contact.transformA.InverseTransformPoint(contact.hitPoint), true, false, indices, vertices); } joint.TransformB = contact.transformB; joint.localAnchorB = joint.TransformB.InverseTransformPoint(contact.hitPoint); if(contact.bodyB != null) { int[] indices = new int[2]; Vector2[] vertices = new Vector2[2]; indices[0] = contact.bodyBpmA; indices[1] = contact.bodyBpmB; vertices[0] = contact.bodyB.getPointMass(indices[0]).LocalPosition; vertices[1] = contact.bodyB.getPointMass(indices[1]).LocalPosition; joint.RebuildAnchor(joint.localAnchorB, false, false, indices, vertices); } joint.breakable = true; joint.breakVelocity = breakVelocity; body.AddJoint (joint); joints.Add(joint); } } }
//TODO make alternative method sigantures. /// <summary> /// Add a JelloJoint to this JelloBody. /// </summary> /// <param name="joint">The JelloJoint to add.</param> public void AddJoint(JelloJoint joint) { if(mJoints == null) mJoints = new JelloJoint[0]; for(int i = 0; i < mJoints.Length; i++) { if(mJoints[i] == joint) return; } bool rigidB = joint.bodyB == null && joint.rigidbodyB != null; bool rigidA = joint.bodyA == null && joint.rigidbodyA != null; //only check for similar if a rigidbody if(rigidB || rigidA) { bool similar = false; //add similar to a list? List<JelloJoint> similarJoints = new List<JelloJoint>(); for(int i = 0; i < mJoints.Length; i++) { similar = false; if(rigidB) { if(joint.TransformB == mJoints[i].TransformB) { similar = true; } else if(joint.TransformB == mJoints[i].TransformA) { similar = true; } } else if(rigidA) { if(joint.TransformA == mJoints[i].TransformA) { similar = true; } else if(joint.TransformA == mJoints[i].TransformB) { similar = true; } } if(similar) similarJoints.Add (mJoints[i]); } for(int i = 0; i < similarJoints.Count; i++) { similarJoints[i].numSimilar = similarJoints.Count + 1; } joint.numSimilar = similarJoints.Count + 1; } JelloJoint[] oldJoints = mJoints; mJoints = new JelloJoint[mJoints.Length + 1]; for(int i =0; i < oldJoints.Length; i++) { mJoints[i] = oldJoints[i]; } mJoints[mJoints.Length - 1] = joint; if(Application.isPlaying) World.addJoint(joint); }
/// <summary> /// Remove a JelloJoint from this JelloBody. /// </summary> /// <param name="joint">The JelloJoint to remove.</param> public void RemoveJoint(JelloJoint joint) { bool contains = false; List<JelloJoint> tempJoints = new List<JelloJoint>(); for(int i = 0; i < mJoints.Length; i++) { if(joint != mJoints[i]) { tempJoints.Add (mJoints[i]); } else { //do something contains = true; } } if(!contains) return; mJoints = tempJoints.ToArray(); bool rigidB = joint.bodyB == null && joint.rigidbodyB != null; bool rigidA = joint.bodyA == null && joint.rigidbodyA != null; //only check for similar if a rigidbody if(rigidB || rigidA) { bool similar = false; //add similar to a list? List<JelloJoint> similarJoints = new List<JelloJoint>(); for(int i = 0; i < mJoints.Length; i++) { similar = false; if(rigidB) { if(joint.TransformB == mJoints[i].TransformB) { similar = true; } else if(joint.TransformB == mJoints[i].TransformA) { similar = true; } } else if(rigidA) { if(joint.TransformA == mJoints[i].TransformA) { similar = true; } else if(joint.TransformA == mJoints[i].TransformB) { similar = true; } } if(similar) similarJoints.Add (mJoints[i]); } for(int i = 0; i < similarJoints.Count; i++) { similarJoints[i].numSimilar = similarJoints.Count; } joint.numSimilar = similarJoints.Count; } if(Application.isPlaying && !applicationIsQuitting) World.removeJoint(joint); }
//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(); } }
public virtual void DrawEditJointGUI() //TODO have some sort of snap all? and/or refresh all? { SerializedProperty eJoint = eJoints.GetArrayElementAtIndex(editIndex); SerializedProperty eBreakable = eJoint.FindPropertyRelative("breakable"); SerializedProperty eVelocity = eJoint.FindPropertyRelative("breakVelocity"); SerializedProperty eTransformB = eJoint.FindPropertyRelative("mTransformB"); SerializedProperty eGlobalAnchorB = eJoint.FindPropertyRelative("globalAnchorB"); SerializedProperty eLocalAnchorA = eJoint.FindPropertyRelative("localAnchorA"); SerializedProperty eIndicesA = eJoint.FindPropertyRelative("affectedIndicesA"); SerializedProperty eScalarsA = eJoint.FindPropertyRelative("scalarsA"); SerializedProperty eLocalAnchorB = eJoint.FindPropertyRelative("localAnchorB"); SerializedProperty eIndicesB = eJoint.FindPropertyRelative("affectedIndicesB"); SerializedProperty eScalarsB = eJoint.FindPropertyRelative("scalarsB"); JelloJoint joint = body.GetJoint(editIndex); EditorGUILayout.PropertyField(eBreakable, breakableContent); if(eBreakable.boolValue) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(eVelocity, jointBreakVelocityContent); EditorGUI.indentLevel--; } //TODO make anchor point bold GUIStyle anchorAStyle = new GUIStyle(EditorStyles.label); if(eIndicesA.prefabOverride || eScalarsA.prefabOverride || eLocalAnchorA.prefabOverride) anchorAStyle.fontStyle = FontStyle.Bold; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Anchor Point", anchorAStyle); //TODO have toggle to always snap??? how would this work with multiple objects? if(GUILayout.Button(snapJointContent)) { if(eTransformB.objectReferenceValue != null) { joint.TransformB.position -= joint.TransformB.TransformPoint(handlePositions[1]) - joint.TransformA.TransformPoint(handlePositions[0]); } else { eGlobalAnchorB.vector2Value = body.transform.TransformPoint(joint.GetAnchorPointA(true)); SceneView.RepaintAll(); } //EditorUtility.SetDirty(body); //? } EditorGUILayout.EndHorizontal(); GUIStyle localStyleA = new GUIStyle(EditorStyles.label); if(eIndicesA.prefabOverride || eScalarsA.prefabOverride || eLocalAnchorA.prefabOverride) localStyleA.fontStyle = FontStyle.Bold; EditorGUI.indentLevel++; EditorGUILayout.LabelField("Local Position", handlePositions[0].ToString(), localStyleA); string text = ""; for(int i = 0; i < joint.affectedIndicesA.Length; i++) text += joint.affectedIndicesA[i].ToString() + ", "; GUIStyle indicesStyleA = new GUIStyle(EditorStyles.label); if(eIndicesA.prefabOverride) indicesStyleA.fontStyle = FontStyle.Bold; GUIContent anchorIndicesContent = new GUIContent("Anchored Indices"); EditorGUILayout.LabelField(anchorIndicesContent, indicesStyleA); EditorGUI.indentLevel++; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(text, indicesStyleA); if(GUILayout.Button(removeJointLegContent) && joint.affectedIndicesA.Length > 1) { joint.SetupAnchor(body.transform, joint.GetAnchorPointA(true), true, true, joint.affectedIndicesA.Length - 1); SetEditIndex(editIndex); EditorUtility.SetDirty(body); SceneView.RepaintAll(); } if(GUILayout.Button(addJointLegContent) && joint.affectedIndicesA.Length < 3) { joint.SetupAnchor(body.transform, joint.GetAnchorPointA(true), true, true, joint.affectedIndicesA.Length + 1); SetEditIndex(editIndex); EditorUtility.SetDirty(body); SceneView.RepaintAll(); } EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel--; EditorGUI.indentLevel--; GUIStyle xformStyleB = new GUIStyle(EditorStyles.label); if(eTransformB.prefabOverride) xformStyleB.fontStyle = FontStyle.Bold; EditorGUILayout.LabelField("Connected Transform", xformStyleB); EditorGUI.indentLevel++; EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(eTransformB, new GUIContent()); if(EditorGUI.EndChangeCheck()) { Vector2 point = Vector2.zero; Transform xformB = (Transform)eTransformB.objectReferenceValue; if(xformB.collider2D != null) { Vector2 anchorPositionA = body.transform.TransformPoint(handlePositions[0]); if(xformB.collider2D.OverlapPoint(anchorPositionA)) point = xformB.InverseTransformPoint(anchorPositionA); } joint.SetupAnchor((Transform)eTransformB.objectReferenceValue, point, false, true); SetEditIndex(editIndex); EditorUtility.SetDirty(body); mainEditor.serializedObject.UpdateIfDirtyOrScript(); SceneView.RepaintAll(); } EditorGUI.indentLevel--; EditorGUILayout.BeginHorizontal(); GUIStyle anchorStyleB = new GUIStyle(EditorStyles.label); if(eTransformB.prefabOverride || eIndicesB.prefabOverride || eScalarsB.prefabOverride || eLocalAnchorB.prefabOverride || eGlobalAnchorB.prefabOverride) anchorStyleB.fontStyle = FontStyle.Bold; EditorGUILayout.LabelField("Anchor Point", anchorStyleB); if(GUILayout.Button(snapJointContent)) { if(eTransformB.objectReferenceValue != null) { joint.TransformA.position -= joint.TransformA.TransformPoint(handlePositions[0]) - joint.TransformB.TransformPoint(handlePositions[1]); } else { joint.TransformA.position -= joint.TransformA.TransformPoint(handlePositions[0]) - (Vector3)joint.globalAnchorB; } EditorUtility.SetDirty(body); } EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel++; if(eTransformB.objectReferenceValue != null) { GUIStyle positionStyleB = new GUIStyle(EditorStyles.label); if(eIndicesB.prefabOverride || eScalarsB.prefabOverride || eLocalAnchorB.prefabOverride) positionStyleB.fontStyle = FontStyle.Bold; EditorGUILayout.LabelField("Local Position", handlePositions[1].ToString(), positionStyleB); if(joint.bodyB != null) { text = ""; for(int i = 0; i < joint.affectedIndicesB.Length; i++) text += joint.affectedIndicesB[i].ToString() + ", "; GUIStyle indicesStyleB = new GUIStyle(EditorStyles.label); if(eIndicesB.prefabOverride) indicesStyleB.fontStyle = FontStyle.Bold; EditorGUILayout.LabelField("Anchored Indices", indicesStyleB); EditorGUI.indentLevel++; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(text, indicesStyleB); if(GUILayout.Button(removeJointLegContent) && joint.affectedIndicesB.Length > 1) { joint.SetupAnchor(joint.TransformB, joint.GetAnchorPointB(true), false, true, joint.affectedIndicesB.Length - 1); SetEditIndex(editIndex); EditorUtility.SetDirty(body); SceneView.RepaintAll(); } if(GUILayout.Button(addJointLegContent) && joint.affectedIndicesA.Length < 3) { joint.SetupAnchor(joint.TransformB, joint.GetAnchorPointB(true), false, true, joint.affectedIndicesB.Length + 1); SetEditIndex(editIndex); EditorUtility.SetDirty(body); SceneView.RepaintAll(); } EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel--; } EditorGUI.indentLevel--; } else { EditorGUILayout.PropertyField(eGlobalAnchorB, jointAnchorBcontent); } EditorGUI.indentLevel--; }
/// <summary> /// Add a JelloJoint to the JelloWorld. /// </summary> /// <param name="joint">The JelloJoint to be added.</param> public void addJoint(JelloJoint joint) { //exit if this body is already here if (mJoints.Contains(joint)) return; mJoints.Add(joint); }
/// <summary> /// Remove the JelloJoint from the JelloWorld. /// </summary> /// <param name="joint">The JelloJoint to remove.</param> public void removeJoint(JelloJoint joint) { if (mJoints.Contains(joint)) { mJoints.Remove(joint); if(joint.bodyA != null) joint.bodyA.RemoveJoint(joint); if(joint.bodyB != null) joint.bodyB.RemoveJoint(joint); } }
/// <summary> /// Processes the collision event. /// </summary> /// <param name="jelloCollision">Jello collision.</param> private void ProcessCollisionEvent(JelloCollision jelloCollision) { if (!stickAtPoints && !stickAtEdges) { return; } //loop through each contact and see if a joint exists. //if not, create the joint. for (int i = 0; i < jelloCollision.contacts.Length; i++) { JelloContact contact = jelloCollision.contacts[i]; bool skip = true; if (stickAtPoints && body == contact.bodyA) { skip = false; } if (stickAtEdges && body == contact.bodyB) { skip = false; } if (skip) { continue; } bool found = false; //see if this joint already exists for (int c = joints.Count - 1; c >= 0; c--) { JelloJoint joint = joints[c]; //remove joints that have been destroyed if (joint.destroyed) { joints.Remove(joint); continue; } //i only want to know if there is a joint between the two bodies and if the point or edge is already taken. //should only need to use transform...? if (joint.TransformA != contact.transformA && joint.TransformB != contact.transformA) { continue; } if (joint.TransformA != contact.transformB && joint.TransformB != contact.transformB) { continue; } //at this point we know that they share the same transforms. //we also know that one of the bodies is the body that this script is attached to. if (contact.bodyA != null) { if (stickAtPoints && joint.bodyA == contact.bodyA) //this matters if i am alowing point joints { if (joint.affectedIndicesA.Length != 1) //joint bodya has multiple anchors { continue; } else if (joint.affectedIndicesA[0] != contact.bodyApm) //joint bodyA has a single anchor and is not the same { continue; } } //where am i handling rigidbodies or even static bodies?? if (stickAtEdges && joint.bodyB != null) { if (joint.bodyB == contact.bodyA) //this matters if i am allowing edge joints { if (joint.affectedIndicesB.Length != 1) { continue; } else if (joint.affectedIndicesB[0] != contact.bodyApm) { continue; } } } } if (contact.bodyB != null) { if (stickAtEdges && joint.bodyA == contact.bodyB) { if (joint.affectedIndicesA.Length != 2) { continue; } else { if (joint.affectedIndicesA[0] != contact.bodyBpmA && joint.affectedIndicesA[0] != contact.bodyBpmB) { continue; } if (joint.affectedIndicesA[1] != contact.bodyBpmA && joint.affectedIndicesA[1] != contact.bodyBpmB) { continue; } if (joint.bodyB != null) { if (joint.affectedIndicesB.Length != 1) { continue; } else if (joint.affectedIndicesB[0] != contact.bodyApm) { continue; } } } } if (stickAtPoints && joint.bodyB != null) { if (joint.bodyB == contact.bodyB) { if (joint.affectedIndicesB.Length != 2) { continue; } else { if (joint.affectedIndicesB[0] != contact.bodyBpmA && joint.affectedIndicesB[0] != contact.bodyBpmB) { continue; } if (joint.affectedIndicesB[1] != contact.bodyBpmA && joint.affectedIndicesB[1] != contact.bodyBpmB) { continue; } if (joint.bodyA != null) { if (joint.affectedIndicesA.Length != 1) { continue; } else if (joint.affectedIndicesA[0] != contact.bodyApm) { continue; } } //else check if ra is the same? } } } } //must be the same found = true; break; } if (!found) //joint Doesn't exist, so create it! { if (!stickAtPoints && contact.transformA == transform) { continue; } if (!stickAtEdges && contact.transformB == transform) { continue; } JelloJoint joint = new JelloJoint(); joint.TransformA = contact.transformA; joint.localAnchorA = joint.TransformA.InverseTransformPoint(contact.hitPoint); if (joint.bodyA != null) { int[] indices = new int[1]; Vector2[] vertices = new Vector2[1]; indices[0] = contact.bodyApm; vertices[0] = contact.bodyA.getPointMass(indices[0]).LocalPosition; joint.RebuildAnchor(contact.transformA.InverseTransformPoint(contact.hitPoint), true, false, indices, vertices); } joint.TransformB = contact.transformB; joint.localAnchorB = joint.TransformB.InverseTransformPoint(contact.hitPoint); if (contact.bodyB != null) { int[] indices = new int[2]; Vector2[] vertices = new Vector2[2]; indices[0] = contact.bodyBpmA; indices[1] = contact.bodyBpmB; vertices[0] = contact.bodyB.getPointMass(indices[0]).LocalPosition; vertices[1] = contact.bodyB.getPointMass(indices[1]).LocalPosition; joint.RebuildAnchor(joint.localAnchorB, false, false, indices, vertices); } joint.breakable = true; joint.breakVelocity = breakVelocity; body.AddJoint(joint); joints.Add(joint); } } }