protected virtual void processSmartSetShape(List<int[]> indexPairs, JelloClosedShape shape, ShapeSettingOptions options = ShapeSettingOptions.None, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None) { bool rebuildJoints = (smartOptions & SmartShapeSettingOptions.RebuildInvalidatedJoints) == SmartShapeSettingOptions.RebuildInvalidatedJoints; bool rebuildAttachPoints = (smartOptions & SmartShapeSettingOptions.RebuildInvalidatedAttachPoints) == SmartShapeSettingOptions.RebuildInvalidatedAttachPoints; if(mJoints != null) { //work with joints first... for(int i = 0; i < mJoints.Length; i++) { JelloJoint joint = mJoints[i]; if(joint.bodyA == this) { for(int a = 0; a < joint.affectedIndicesA.Length; a++) { //Vector2 point = joint .GetAnchorPointA(true); bool found = false; for(int b = 0; b < indexPairs.Count; b++) { if(joint.affectedIndicesA[a] == indexPairs[b][1]) { joint.affectedIndicesA[a] = indexPairs[b][0]; found = true; break; } } if(!found) { if(rebuildJoints) { //rebuild the joint.. Vector2 pos = mBaseShape.getVertex(joint.affectedIndicesA[a]); Vector2[] fullShape = new Vector2[shape.VertexCount]; for(int c = 0; c < shape.VertexCount; c++) fullShape[c] = shape.getVertex(c); int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, joint.affectedIndicesA.Length); bool assignedClosest = false; //check if any of the indices are already in use for(int c = 0; c < closestIndices.Length; c++) { //joint.affectedindicesA[a] is the current one... //compare unchecked indices against their old position and compare checked indices against their new position. for(int d = 0; d < joint.affectedIndicesA.Length; d++) { //skip the index that we are currently working with. if(d == a) continue; if(d < a)//this index has been updated to the new shape so compare against indexPairs[index][0] { if(indexPairs[closestIndices[c]][0] == joint.affectedIndicesA[d])//in use continue; } else//d must be greater than a, so so this index is untouched and we should compare against indexPairs[index][1] { if(indexPairs[closestIndices[c]][1] == joint.affectedIndicesA[d])//in use continue; } //made it past the early continues, so the index must not be in use. joint.affectedIndicesA[a] = closestIndices[c]; assignedClosest = true; break; } if(assignedClosest) break; } //dont forget to rebuild the joint!!! Vector2[] affectedVertices = new Vector2[joint.affectedIndicesA.Length]; for(int q = 0; q < affectedVertices.Length; q++) affectedVertices[q] = shape.getVertex (joint.affectedIndicesA[q]); joint.RebuildAnchor(joint.localAnchorA, true, true, joint.affectedIndicesA, affectedVertices); } else { //this joint is invalid and will be removed in the clear invalid subcomponents method. mJoints[i] = null; break; } } } } else if(joint.bodyB == this) { for(int a = 0; a < joint.affectedIndicesB.Length; a++) { bool found = false; for(int b = 0; b < indexPairs.Count; b++) { if(joint.affectedIndicesB[a] == indexPairs[b][1]) { joint.affectedIndicesB[a] = indexPairs[b][0]; found = true; break; } } if(!found) { if(rebuildJoints) { //rebuild the joint.. Vector2 pos = mBaseShape.getVertex(joint.affectedIndicesB[a]); Vector2[] fullShape = new Vector2[shape.VertexCount]; for(int c = 0; c < shape.VertexCount; c++) fullShape[c] = shape.getVertex(c); int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, joint.affectedIndicesB.Length); bool assignedClosest = false; //check if any of the indices are already in use for(int c = 0; c < closestIndices.Length; c++) { //joint.affectedindicesA[a] is the current one... //compare unchecked indices against their old position and compare checked indices against their new position. for(int d = 0; d < joint.affectedIndicesB.Length; d++) { //skip the index that we are currently working with. if(d == a) continue; if(d < a)//this index has been updated to the new shape so compare against indexPairs[index][0] { if(indexPairs[closestIndices[c]][0] == joint.affectedIndicesB[d])//in use continue; } else//d must be greater than a, so so this index is untouched and we should compare against indexPairs[index][1] { if(indexPairs[closestIndices[c]][1] == joint.affectedIndicesB[d])//in use continue; } //made it past the early continues, so the index must not be in use. joint.affectedIndicesB[a] = closestIndices[c]; assignedClosest = true; break; } if(assignedClosest) break; } //dont forget to rebuild the joint!!! Vector2[] affectedVertices = new Vector2[joint.affectedIndicesB.Length]; for(int q = 0; q < affectedVertices.Length; q++) affectedVertices[q] = shape.getVertex(joint.affectedIndicesB[q]); joint.RebuildAnchor(joint.localAnchorB, false, true, joint.affectedIndicesB, affectedVertices); } else { //this joint is invalid and will be removed in the clear invalid subcomponents method. mJoints[i] = null; break; } } } } } } if(mAttachPoints != null) { //handle attach points now for(int i = 0; i < mAttachPoints.Length; i++) { JelloAttachPoint attachPoint = mAttachPoints[i]; for(int a = 0; a < attachPoint.affectedIndices.Length; a++) { bool found = false; for(int b = 0; b < indexPairs.Count; b++) { if(attachPoint.affectedIndices[a] == indexPairs[b][1]) { attachPoint.affectedIndices[a] = indexPairs[b][0]; found = true; break; } } if(!found) { if(rebuildAttachPoints) { //rebuild the attach point.. Vector2 pos = mBaseShape.getVertex(attachPoint.affectedIndices[a]); Vector2[] fullShape = new Vector2[shape.VertexCount]; for(int c = 0; c < shape.VertexCount; c++) fullShape[c] = shape.getVertex(c); int[] closestIndices = JelloShapeTools.GetClosestIndices(pos, fullShape, attachPoint.affectedIndices.Length); bool assignedClosest = false; //check if any of the indices are already in use for(int c = 0; c < closestIndices.Length; c++) { //joint.affectedindicesA[a] is the current one... //compare unchecked indices against their old position and compare checked indices against their new position. for(int d = 0; d < attachPoint.affectedIndices.Length; d++) { //skip the index that we are currently working with. if(d == a) continue; if(d < a)//this index has been updated to the new shape so compare against indexPairs[index][0] { if(indexPairs[closestIndices[c]][0] == attachPoint.affectedIndices[d])//in use continue; } else//d must be greater than a, so so this index is untouched and we should compare against indexPairs[index][1] { if(indexPairs[closestIndices[c]][1] == attachPoint.affectedIndices[d])//in use continue; } //made it past the early continues, so the index must not be in use. attachPoint.affectedIndices[a] = closestIndices[c]; assignedClosest = true; break; } if(assignedClosest) break; } //all legs have been updated, not rebuild the attach point. attachPoint.Rebuild(attachPoint.point, this, attachPoint.affectedIndices, true); } else { //this joint is invalid and will be removed in the clear invalid subcomponents method. mAttachPoints[i] = null; break; } } } } } }
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); } }