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> /// Grabs the point mass. /// </summary> public void GrabPointMass() { //i am now pulling the body. pulling = true; //clear old values from last pull adjacentPointMasses.Clear(); oldMultipliers.Clear(); //set the position to lock it in place while pulling the body position = body.Position; //get the closest point mass to the mouse positions and cache some information about it. mousePosInWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition); pmIndex = body.getClosestPointMass(mousePosInWorld, false); //only grab edge point masses pointmass = body.getEdgePointMass(pmIndex); oldMultipliers.Add (pointmass.shapeMatchingMultiplier); pointmass.shapeMatchingMultiplier = 0f; adjacentPointMasses.Add (pointmass); //Set the body to kinematic to keep it in place while pulling. body.IsKinematic = true; int adjIndex = 0; int numFromStart = 0; //grab adjacent point masses further in the array. for(int i = pmIndex; i < pmIndex + numAdjacentPoints; i++) { adjIndex = i > body.EdgePointMassCount - 1 ? i - body.EdgePointMassCount : i; if(adjIndex > body.EdgePointMassCount - 1 || adjacentPointMasses.Contains(body.getEdgePointMass(adjIndex))) continue; //cache the point mass info and modify the shape matching values by how close it is to the grabbed point mass adjacentPointMasses.Add (body.getEdgePointMass(adjIndex)); oldMultipliers.Add(body.getEdgePointMass(adjIndex).shapeMatchingMultiplier); numFromStart++; body.getEdgePointMass(adjIndex).shapeMatchingMultiplier = numFromStart / (numAdjacentPoints + 1 + adjacentDropoff); } numFromStart = 0; //grab adjacent point masses before the current index in the array. for(int i = pmIndex; i > pmIndex - numAdjacentPoints; i--) { adjIndex = i < 0 ? i + body.EdgePointMassCount: i; if(adjIndex < 0 || adjacentPointMasses.Contains(body.getEdgePointMass(adjIndex))) continue; //cache the point mass info and modify the shape matching values by how close it is to the grabbed point mass adjacentPointMasses.Add (body.getEdgePointMass(adjIndex)); oldMultipliers.Add(body.getEdgePointMass(adjIndex).shapeMatchingMultiplier); numFromStart++; body.getEdgePointMass(adjIndex).shapeMatchingMultiplier = numFromStart / (numAdjacentPoints + 1 + adjacentDropoff); } //find any internal point masses connected to the selected point mass (via spring) and cache/modify its shape matching multiplier. for(int i = 0; i < body.SpringCount; i++) { if(body.getSpring(i).pointMassA == pmIndex || body.getSpring(i).pointMassB == pmIndex) { if(body.getSpring(i).pointMassA >= body.EdgePointMassCount) { adjacentPointMasses.Add (body.getPointMass(body.getSpring(i).pointMassA)); oldMultipliers.Add (body.getPointMass(body.getSpring(i).pointMassA).shapeMatchingMultiplier); body.getPointMass(body.getSpring(i).pointMassA).shapeMatchingMultiplier = 1 / (2 + adjacentDropoff); } else if(body.getSpring(i).pointMassB >= body.EdgePointMassCount) { adjacentPointMasses.Add (body.getPointMass(body.getSpring(i).pointMassB)); oldMultipliers.Add (body.getPointMass(body.getSpring(i).pointMassB).shapeMatchingMultiplier); body.getPointMass(body.getSpring(i).pointMassB).shapeMatchingMultiplier = 1 / (2 + adjacentDropoff); } } } }