Beispiel #1
0
    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);
        }
    }