public SpringSubComponentEditor(Editor editor) : base(editor) { name = "Springs"; springBodyEditor = (JelloSpringBodyEditor)editor; springBody = (JelloSpringBody)springBodyEditor.serializedObject.targetObject; handlePositions = new Vector3[2]; handleSizes = new float[2]; eShapeMatching = springBodyEditor.serializedObject.FindProperty("mShapeMatchingOn"); eShapeSpringK = springBodyEditor.serializedObject.FindProperty("mShapeSpringK"); eShapeSpringDamp = springBodyEditor.serializedObject.FindProperty("mShapeSpringDamp"); eEdgeSpringK = springBodyEditor.serializedObject.FindProperty("mDefaultEdgeSpringK"); eEdgeSpringDamp = springBodyEditor.serializedObject.FindProperty("mDefaultEdgeSpringDamp"); eInternalSpringK = springBodyEditor.serializedObject.FindProperty("mDefaultInternalSpringK"); eInternalSpringDamp = springBodyEditor.serializedObject.FindProperty("mDefaultInternalSpringDamp"); eCustomSpringK = springBodyEditor.serializedObject.FindProperty("mDefaultCustomSpringK"); eCustomSpringDamp = springBodyEditor.serializedObject.FindProperty("mDefaultCustomSpringDamp"); eEdgeSprings = springBodyEditor.serializedObject.FindProperty("mEdgeSprings"); eInternalSprings = springBodyEditor.serializedObject.FindProperty("mInternalSprings"); eCustomSprings = springBodyEditor.serializedObject.FindProperty("mCustomSprings"); drawIndex = editIndex = -1; newSpring = null; newSubComponentState = AddSubComponentState.inactive; }
public override void DrawEditorGUI () { //springBodyEditor.serializedObject.Update(); multiEditing = springBodyEditor.serializedObject.isEditingMultipleObjects; if(!multiEditing) { if(GUILayout.Button(addSpringContent, EditorStyles.miniButton)) //TODO move this... { editIndex = -1; drawIndex = -1; newSpring = null; newSubComponentState = AddSubComponentState.initiated; } if(newSubComponentState != AddSubComponentState.inactive) { EditorGUILayout.HelpBox("Click near any Point Mass on the Jello Body" + "\nEsc to cancel", MessageType.Info); } } //TODO this might work better in a popup menu... if(springBody.SpringCount != 0) { EditorGUI.indentLevel++; DrawShapeMatchingGUI(); DrawEdgeSpringsGUI(); DrawInternalSpringsGUI(); DrawCustomSpringsGUI(); EditorGUI.indentLevel--; } if(newSubComponentState != AddSubComponentState.inactive ) { if(Event.current.isKey && Event.current.keyCode == KeyCode.Escape) { newSubComponentState = AddSubComponentState.inactive; mainEditor.Repaint(); } } //springBodyEditor.serializedObject.ApplyModifiedProperties(); }
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); } }
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); } }
public override void DrawEditorGUI() { //springBodyEditor.serializedObject.Update(); multiEditing = springBodyEditor.serializedObject.isEditingMultipleObjects; if(!multiEditing) { if(GUILayout.Button(addSpringContent, EditorStyles.miniButton)) //TODO move this... { editIndex = -1; drawIndex = -1; newSpring = null; newSubComponentState = AddSubComponentState.initiated; } if(newSubComponentState != AddSubComponentState.inactive) { EditorGUILayout.HelpBox("Click near any Point Mass on the Jello Body" + "\nEsc to cancel", MessageType.Info); } } //TODO this might work better in a popup menu... if(springBody.SpringCount != 0) { EditorGUI.indentLevel++; DrawShapeMatchingGUI(); DrawEdgeSpringsGUI(); DrawInternalSpringsGUI(); DrawCustomSpringsGUI(); EditorGUI.indentLevel--; } if(newSubComponentState != AddSubComponentState.inactive ) { if(Event.current.isKey && Event.current.keyCode == KeyCode.Escape) { newSubComponentState = AddSubComponentState.inactive; mainEditor.Repaint(); } } //springBodyEditor.serializedObject.ApplyModifiedProperties(); }
/// <summary> /// Clears every internal JelloPointMass. /// Will also clear every internal JelloSpring an any custom JelloSpring that is no longer valid. /// </summary> /// <param name="recenterBaseShape">If set to <c>true</c> recenter the JelloBody.Shape.</param> public override void clearInternalPointMasses(bool recenterBaseShape) { base.clearInternalPointMasses (recenterBaseShape); mInternalSprings = new JelloSpring[0]; bool[] validity = new bool[mCustomSprings.Length]; int num = 0; for(int i = 0; i < mCustomSprings.Length; i++) { if(mCustomSprings[i].pointMassA >= mEdgePointMasses.Length || mCustomSprings[i].pointMassB >= mEdgePointMasses.Length) { validity[i] = false; } else { validity[i] = true; num++; } } JelloSpring[] temp = new JelloSpring[num]; num = 0; for(int i = 0; i < mCustomSprings.Length; i++) { if(validity[i]) { temp[i - num] = mCustomSprings[i]; } else { num++; } } mCustomSprings = temp; }
/// <summary> /// Add multiple custom JelloSpring. /// </summary> /// <param name="springs">JelloSpring array to add to this JelloBody.</param> public void addCustomSprings(JelloSpring[] springs) { addSprings(springs, ref mCustomSprings); }
/// <summary> /// Adds a custom JelloSpring. /// </summary> /// <param name="spring">The new JelloSpring to add.</param> public void addCustomSpring(JelloSpring spring) { addSpring(spring, ref mCustomSprings); }
/// <summary> /// Removes the JelloSpring from the given JelloSpring array. /// </summary> /// <param name="spring">The JelloSpring to be removed.</param> /// <param name="removeFromArray">The JelloSpring array to remove the JelloSpring from.</param> private void removeSpring(JelloSpring spring, ref JelloSpring[] removeFromArray) { List<JelloSpring> tempSprings = new List<JelloSpring>(); for(int i = 0; i < removeFromArray.Length; i++) if(spring != removeFromArray[i]) tempSprings.Add (removeFromArray[i]); removeFromArray = tempSprings.ToArray(); }
/// <summary> /// Adds multiple JelloSpring objects with specified values. /// </summary> /// <param name="indices"> /// The indices of the JelloPointMass that each JelloSpring will connect to /// Each JelloSpring uses two indices. /// </param> /// <param name="stiffness">The JelloSpring.stiffness of each JelloSpring to be added.</param> /// <param name="damping">The JelloSpring.damping of each JelloSpring to be added.</param> /// <param name="addToArray">The JelloSpring array to add each new JelloSpring to.</param> private void addSprings(int[] indices, float stiffness, float damping, ref JelloSpring[] addToArray) { JelloSpring[] newSprings = new JelloSpring[indices.Length / 2]; //float dist = 0f; for(int i = 0; i < newSprings.Length; i ++) { //dist = Vector2.Distance(mBaseShape.getVertex( indices[ 2 * i ] ), mBaseShape.getVertex( indices[2 * i + 1] )); newSprings[i] = new JelloSpring(indices[2 * i], indices[2 * i + 1], 0f, stiffness, damping); } addSprings(newSprings, ref addToArray); }
/// <summary> /// Adds one JelloSpring array to another. /// </summary> /// <param name="springs">JelloSpring array to be added.</param> /// <param name="addToArray">JelloSpring array to add to.</param> private void addSprings(JelloSpring[] springs, ref JelloSpring[] addToArray) { Vector2 posA; Vector2 posB; Vector2 diff; float dist; Vector2 mid; for(int i = 0; i < springs.Length; i++) { posA = mBaseShape.getVertex(springs[i].pointMassA); posB = mBaseShape.getVertex(springs[i].pointMassB); diff = posA - posB; dist = springs[i].length * Vector2.Distance(posA, posB) / Vector2.Distance (Vector2.zero, diff); mid = (posA + posB) * 0.5f; posA = mid + (mid - posA).normalized * dist * 0.5f; posB = mid + (mid - posB).normalized * dist * 0.5f; springs[i].scaledLength = Vector2.Distance ( Vector2.zero, new Vector2 ( (posA.x - posB.x) * Scale.x, (posA.y - posB.y) * Scale.y ) ); } //create a temporary array of springs at the new size JelloSpring[] oldSprings = new JelloSpring[addToArray.Length]; //add springs already in the array to the temp array for(int i = 0; i < addToArray.Length; i++) oldSprings[i] = addToArray[i]; addToArray = new JelloSpring[oldSprings.Length + springs.Length]; int a = 0; for(int i = 0; i < addToArray.Length; i++) { if(i < oldSprings.Length) { addToArray[i] = oldSprings[i]; } else { addToArray[i] = springs[a]; a++; } } }
/// <summary> /// Adds a new JelloSpring to the JelloSpring array passed in. /// </summary> /// <param name="spring">JelloSpring to add.</param> /// <param name="addToArray">JelloSpring array to add the new JelloSpring to</param> private void addSpring(JelloSpring spring, ref JelloSpring[] addToArray) { if(spring == null || spring.pointMassA < 0 || spring.pointMassA >= mBaseShape.VertexCount || spring.pointMassB < 0 || spring.pointMassB >= mBaseShape.VertexCount) return; Vector2 posA = mBaseShape.getVertex(spring.pointMassA); Vector2 posB = mBaseShape.getVertex(spring.pointMassB); Vector2 diff = posA - posB; float dist = spring.length * Vector2.Distance(posA, posB) / Vector2.Distance (Vector2.zero, diff); Vector2 mid = (posA + posB) * 0.5f; mid = (posA + posB) * 0.5f; posA = mid + (mid - posA).normalized * dist * 0.5f; posB = mid + (mid - posB).normalized * dist * 0.5f; spring.scaledLength = Vector2.Distance ( Vector2.zero, new Vector2 ( (posA.x - posB.x) * Scale.x, (posA.y - posB.y) * Scale.y ) ); //create a temporary array of springs at the new size JelloSpring[] oldSprings = new JelloSpring[addToArray.Length]; //add springs already in the array to the temp array for(int i = 0; i < addToArray.Length; i++) oldSprings[i] = addToArray[i]; addToArray = new JelloSpring[addToArray.Length + 1]; for(int i = 0; i < oldSprings.Length; i++) addToArray[i] = oldSprings[i]; addToArray[addToArray.Length - 1] = spring; }
protected override void processSmartSetShape(List<int[]> indexPairs, JelloClosedShape shape, ShapeSettingOptions options, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None) { base.processSmartSetShape (indexPairs, shape, options, smartOptions); List<int[]> indexPairsQueue = new List<int[]>(); List<JelloSpring> tempSprings = new List<JelloSpring>(); if((options & ShapeSettingOptions.RebuildEdgeSprings) == ShapeSettingOptions.RebuildEdgeSprings) { clearEdgeSprings(); buildEdgeSprings(); } else if((options & ShapeSettingOptions.ClearEdgeSprings) == ShapeSettingOptions.ClearEdgeSprings) { clearEdgeSprings(); } else { //find the first common point to the two shapes int index = -1; for(int i = 0; i < shape.EdgeVertexCount; i++) { if(indexPairs[i][1] != -1) { index = i; break; } } if(index == -1)//in this case, there are no common points to this shape at all. we can just create new edge springs... { clearEdgeSprings(); buildEdgeSprings(); } else { while(indexPairsQueue.Count < shape.EdgeVertexCount) { if(index >= shape.EdgeVertexCount) index = 0; indexPairsQueue.Add (indexPairs[index]); index++; } //see if edge is intact... for(int i = 0; i < shape.EdgeVertexCount; i++)//using edge point mass length, because we only want the edge indices { int next = i + 1 < shape.EdgeVertexCount ? i + 1 : 0; //check if this edge is the same as the last. if(indexPairsQueue[i][1] != -1) //old doesnt equal -1 { //then the next should equal this plus 1 or 0 if full wrap around? if(indexPairsQueue[next][1] == (indexPairsQueue[i][1] + 1 < mBaseShape.EdgeVertexCount ? indexPairsQueue[i][1] + 1 : 0)) //our edge is preserved from the old shape, lets move our old spring into place... { bool found = false; JelloSpring spring = null; //first check the expected position. if(indexPairsQueue[i][1] < mEdgeSprings.Length) spring = mEdgeSprings[indexPairsQueue[i][1]]; if(spring != null && spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == indexPairsQueue[next][1]) found = true; //if not in the expected position, check the rest of the positions... if(!found) { for(int a = 0; a < mEdgeSprings.Length; a++) { spring = mEdgeSprings[a]; if(spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == indexPairsQueue[next][1]) { found = true; break; } } } if(!found)//the spring could not be found, create a new one. { //float dist = Vector2.Distance(shape.EdgeVertices[indexPairsQueue[i][1]], shape.EdgeVertices[indexPairsQueue[next][1]]); spring = new JelloSpring(indexPairsQueue[i][1], indexPairsQueue[next][1], 0f, DefaultEdgeSpringStiffness, DefaultEdgeSpringDamping); } spring.pointMassA = indexPairsQueue[i][0]; spring.pointMassB = indexPairsQueue[next][0]; tempSprings.Add(spring); } else { if(indexPairsQueue[next][1] == -1)//this is a new point. { //lets check if there is a spring here... bool found = false; //first check the expected position. JelloSpring spring = null; if(indexPairsQueue[i][1] < mEdgeSprings.Length) spring = mEdgeSprings[indexPairsQueue[i][1]]; if(spring != null && (spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == (spring.pointMassA == mBaseShape.EdgeVertexCount - 1 ? spring.pointMassA + 1 : 0))) { found = true; } //we didnt find the spring in the expected position, lets look through the rest of the springs. if(!found) { for(int a = 0; a < mEdgeSprings.Length; a++) { spring = mEdgeSprings[a]; if(spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == (spring.pointMassA == mBaseShape.EdgeVertexCount - 1 ? spring.pointMassA + 1 : 0)) { found = true; break; } } } //no old spring found, lets create one... if(!found) { spring = new JelloSpring(indexPairsQueue[i][0], indexPairsQueue[next][0], 0f, DefaultEdgeSpringStiffness, DefaultEdgeSpringDamping); } spring.pointMassA = indexPairsQueue[i][0]; spring.pointMassB = indexPairsQueue[next][0]; //spring.length = Vector2.Distance(shape.EdgeVertices[spring.pointMassA], shape.EdgeVertices[spring.pointMassB]); float multiplier = spring.lengthMultiplier; //first assing spring to this one... tempSprings.Add (spring); //int nextnext = next + 1 < shape.EdgeVertexCount ? next + 1 : 0; //now look through the rest of the points until i find a common point and create those springs in the image of this one... for(int a = next; a < shape.EdgeVertexCount; a++) { int nextnext = a + 1 < shape.EdgeVertexCount ? a + 1 : 0; spring = new JelloSpring(indexPairsQueue[a][0], indexPairsQueue[nextnext][0], 0f, spring.stiffness, spring.damping); //spring.length = Vector2.Distance(shape.EdgeVertices[spring.pointMassA], shape.EdgeVertices[spring.pointMassB]); spring.lengthMultiplier = multiplier; tempSprings.Add (spring); i++; if(indexPairsQueue[nextnext][1] != -1) break; } } else//this is a vertex preserved from the old shape... in otherwords, there was a point mass deleted here. { //lets check if there is a spring here... bool found = false; //first check the expected position. JelloSpring spring = null; if(indexPairsQueue[i][1] < mEdgeSprings.Length) spring = mEdgeSprings[indexPairsQueue[i][1]]; if(spring != null && (spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == (spring.pointMassA == mBaseShape.EdgeVertexCount - 1 ? spring.pointMassA + 1 : 0))) { found = true; } //we didnt find the spring in the expected position, lets look through the rest of the springs. if(!found) { for(int a = 0; a < mEdgeSprings.Length; a++) { spring = mEdgeSprings[a]; if(spring.pointMassA == indexPairsQueue[i][1] && spring.pointMassB == (spring.pointMassA == mBaseShape.EdgeVertexCount - 1 ? spring.pointMassA + 1 : 0)) { found = true; break; } } } //no old spring found, lets create one... if(!found) { spring = new JelloSpring(indexPairsQueue[i][0], indexPairsQueue[next][0], 0f, DefaultEdgeSpringStiffness, DefaultEdgeSpringDamping); } spring.pointMassA = indexPairsQueue[i][0]; spring.pointMassB = indexPairsQueue[next][0]; //spring.length = Vector2.Distance(shape.EdgeVertices[spring.pointMassA], shape.EdgeVertices[spring.pointMassB]); tempSprings.Add (spring); } } } else { JelloSpring spring = new JelloSpring(indexPairsQueue[i][0], indexPairsQueue[next][0], 0f, DefaultEdgeSpringStiffness, DefaultEdgeSpringDamping); //spring.length = Vector2.Distance(shape.EdgeVertices[spring.pointMassA], shape.EdgeVertices[spring.pointMassB]); tempSprings.Add (spring); } } mEdgeSprings = new JelloSpring[tempSprings.Count]; int indexOffset = 0; for(int i = 0; i < tempSprings.Count; i++) { if(tempSprings[i].pointMassA == 0) { indexOffset = i; break; } } JelloSpring[] tempArray = new JelloSpring[tempSprings.Count]; for(int i = 0; i < tempArray.Length; i++) { int a = i + indexOffset; if(a >= tempArray.Length) a -= tempArray.Length; tempArray[i] = tempSprings[a]; } clearEdgeSprings(); addSprings(tempArray, ref mEdgeSprings); } } if((options & ShapeSettingOptions.RebuildInternalSprings) == ShapeSettingOptions.RebuildInternalSprings) { clearInternalSprings(); BuildInternalSprings(); } else if((options & ShapeSettingOptions.ClearInternalSprings) == ShapeSettingOptions.ClearInternalSprings) { clearInternalSprings(); } else if(mInternalSprings.Length > 0) { //now handle internal springs int[] tris = shape.Triangles; tempSprings.Clear(); for(int i = 0; i < tris.Length; i+=3) { for(int t = 0; t < 3; t++) { int r = t + 1 < 3 ? t + 1 : 0; if(tris[ i + t ] < shape.EdgeVertexCount && tris[ i + r] < shape.EdgeVertexCount) //dont build edge springs { if(tris[ i + t ] != 0 && tris[ i + r ] != 0) { if(Mathf.Abs( tris[ i + t ] - tris[ i + r ] ) == 1) { continue; } } else if(tris[ i + t ] == shape.EdgeVertexCount - 1 || tris[ i + r ] == shape.EdgeVertexCount - 1 || tris[ i + t ] == 1 || tris[ i + t ] == 1) { continue; } } bool exists = false; for(int a = 0; a < tempSprings.Count; a++) { if((tris[i + t] == tempSprings[a].pointMassA && tris[i + r] == tempSprings[a].pointMassB) || (tris[i + t] == tempSprings[a].pointMassB && tris[i + r] == tempSprings[a].pointMassA)) { exists = true; break; } } if(exists) continue; else tempSprings.Add ( new JelloSpring ( tris[i + t], tris[i + r], 0f, mDefaultInternalSpringK, mDefaultInternalSpringDamp ) ); } } //now compare our new internal springs to our old internal springs... for(int i = 0; i < tempSprings.Count; i++) { JelloSpring spring = tempSprings[i]; int pairA = -1; int pairB = -1; for(int a = 0; a < indexPairs.Count; a++) { if(indexPairs[a][0] == spring.pointMassA) pairA = a; if(indexPairs[a][0] == spring.pointMassB) pairB = a; if(pairA != -1 && pairB != -1) break; } if(pairA == -1 || pairB == -1) { //this shouldnt be possible continue; } //check if there is an old point assosiated with each spring end point if(indexPairs[pairA][1] != -1 && indexPairs[pairB][1] != -1) { JelloSpring oldSpring; for(int a = 0; a < mInternalSprings.Length; a++) { oldSpring = mInternalSprings[a]; if((oldSpring.pointMassA == indexPairs[pairA][1] && oldSpring.pointMassB == indexPairs[pairB][1]) || (oldSpring.pointMassB == indexPairs[pairA][1] && oldSpring.pointMassA == indexPairs[pairB][1])) { spring.damping = oldSpring.damping; spring.lengthMultiplier = oldSpring.lengthMultiplier; spring.stiffness = oldSpring.stiffness; } } } } //now set our new internal springs. clearInternalSprings(); if(tempSprings.Count > 0) addSprings(tempSprings.ToArray(), ref mInternalSprings); } if((options & ShapeSettingOptions.ClearCustomSprings) == ShapeSettingOptions.ClearCustomSprings) { clearCustomSprings(); } else { tempSprings.Clear(); bool rebuildCustomSprings = (smartOptions & SmartShapeSettingOptions.RebuildInvalidatedCustomSprings) == SmartShapeSettingOptions.RebuildInvalidatedCustomSprings; //now handle custom springs for(int i = 0; i < mCustomSprings.Length; i++) { JelloSpring spring = mCustomSprings[i]; int indexA = -1; int indexB = -1; for(int a = 0; a < indexPairs.Count; a++) { if(spring.pointMassA == indexPairs[a][1]) indexA = indexPairs[a][0]; if(spring.pointMassB == indexPairs[a][1]) indexB = indexPairs[a][0]; if(indexA != -1 && indexB != -1) { break; } } //here if(indexA == -1 || indexB == -1) { if(rebuildCustomSprings) { Vector2[] fullShape = new Vector2[shape.VertexCount]; for(int c = 0; c < shape.VertexCount; c++) fullShape[c] = shape.getVertex(c); if(indexA == -1) { //rebuild the spring Vector2 pos = mBaseShape.getVertex(spring.pointMassA); int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, 2); //check if any of the indices are already in use for(int c = 0; c < closestIndices.Length; c++) { //already in use by index b if(indexB == closestIndices[c]) continue; indexA = closestIndices[c]; break; } } if(indexB == -1) { //rebuild the spring Vector2 pos = mBaseShape.getVertex(spring.pointMassB); int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, 2); //check if any of the indices are already in use for(int c = 0; c < closestIndices.Length; c++) { //already in use by index b if(indexA == closestIndices[c]) continue; indexB = closestIndices[c]; break; } } } else { continue; } } spring.pointMassA = indexA; spring.pointMassB = indexB; tempSprings.Add(spring); } clearCustomSprings(); if(tempSprings.Count > 0) addSprings(tempSprings.ToArray(), ref mCustomSprings); } }
/// <summary> /// Sets the internal JelloSpring array. /// </summary> /// <param name="springs">JelloSpring array to replace the current internal JelloSpring array.</param> public void setInternalSprings(JelloSpring[] springs) { mInternalSprings = springs; }
/// <summary> /// Removes the JelloSpring from this JelloSpringBody. /// Will look at edge, internal, and custom JelloSpring objects. /// </summary> /// <param name="spring">JelloSpring to remove from this JelloSpringBody.</param> public void RemoveSpring(JelloSpring spring) { for(int i = 0; i < SpringCount; i++) { if(getSpring(i) == spring) { if(i < mEdgeSprings.Length) removeSpring(spring, ref mEdgeSprings); else if(i < mEdgeSprings.Length + mInternalSprings.Length) removeSpring(spring, ref mInternalSprings); else removeSpring(spring, ref mCustomSprings); break; } } }