Пример #1
0
    // We should just modify the internal points then map them out at the end
    public override void Modify(MegaModifiers mc)
    {
        verts.CopyTo(sverts, 0);                // This should only blit totally untouched verts

        for (int i = 0; i < chanBank.Count; i++)
        {
            MegaMorphChan chan = chanBank[i];
            chan.UpdatePercent();

            float fChannelPercent = chan.Percent;

            // check for change since last frame on percent, if none just add in diff
            // Can we keep each chan delta then if not changed can just add it in
            if (fChannelPercent == chan.fChannelPercent)
            {
                MegaMorphTarget trg = chan.mTargetCache[chan.targ];

                for (int pointnum = 0; pointnum < trg.mompoints.Length; pointnum++)
                {
                    int p = trg.mompoints[pointnum].id;
                    int c = mapping[p].indices.Length;

                    Vector3 df = chan.diff[pointnum];

                    for (int m = 0; m < c; m++)
                    {
                        int index = mapping[p].indices[m];
                        sverts[index].x += df.x;
                        sverts[index].y += df.y;
                        sverts[index].z += df.z;
                    }
                }
            }
            else
            {
                chan.fChannelPercent = fChannelPercent;

                if (chan.mTargetCache != null && chan.mTargetCache.Count > 0 && chan.mActiveOverride)
                {
                    if (chan.mUseLimit || glUseLimit)
                    {
                        if (glUseLimit)
                        {
                            fChannelPercent = Mathf.Clamp(fChannelPercent, glMin, glMax);
                        }
                        else
                        {
                            fChannelPercent = Mathf.Clamp(fChannelPercent, chan.mSpinmin, chan.mSpinmax);
                        }
                    }

                    int   targ  = 0;
                    float alpha = 0.0f;

                    if (fChannelPercent < chan.mTargetCache[0].percent)
                    {
                        targ = 0;
                        //alpha = 0.0f;
                        alpha = (fChannelPercent - chan.mTargetCache[targ].percent) / (chan.mTargetCache[targ + 1].percent - chan.mTargetCache[targ].percent);
                        //Debug.Log("alpha " + alpha + " percent " + fChannelPercent);
                    }
                    else
                    {
                        int last = chan.mTargetCache.Count - 1;
                        if (fChannelPercent >= chan.mTargetCache[last].percent)
                        {
                            targ = last - 1;
                            //alpha = 1.0f;
                            alpha = (fChannelPercent - chan.mTargetCache[targ].percent) / (chan.mTargetCache[targ + 1].percent - chan.mTargetCache[targ].percent);
                        }
                        else
                        {
                            for (int t = 1; t < chan.mTargetCache.Count; t++)
                            {
                                if (fChannelPercent < chan.mTargetCache[t].percent)
                                {
                                    targ  = t - 1;
                                    alpha = (fChannelPercent - chan.mTargetCache[targ].percent) / (chan.mTargetCache[t].percent - chan.mTargetCache[targ].percent);
                                    //Debug.Log("alpha1 " + alpha + " percent1 " + fChannelPercent);
                                    break;
                                }
                            }
                        }
                    }

                    MegaMorphTarget trg = chan.mTargetCache[targ];
                    chan.targ = targ;
                    for (int pointnum = 0; pointnum < trg.mompoints.Length; pointnum++)
                    {
                        int p = trg.mompoints[pointnum].id;

                        // Save so if chan doesnt change we dont need to recalc
                        Vector3 df = trg.mompoints[pointnum].start;

                        df.x += trg.mompoints[pointnum].delta.x * alpha;
                        df.y += trg.mompoints[pointnum].delta.y * alpha;
                        df.z += trg.mompoints[pointnum].delta.z * alpha;

                        chan.diff[pointnum] = df;

                        for (int m = 0; m < mapping[p].indices.Length; m++)
                        {
                            int index = mapping[p].indices[m];
                            sverts[index].x += df.x;
                            sverts[index].y += df.y;
                            sverts[index].z += df.z;
                        }
                    }
                }
            }
        }
    }
Пример #2
0
    public void PrepareForMT(MegaModifiers mc, int cores)
    {
        if (setStart == null)
        {
            BuildMorphVertInfo(cores);
        }

        // cycle through channels, searching for ones to use
        mtmorphed = false;

        for (int i = 0; i < source.chanBank.Count; i++)
        {
            MegaMorphChan chan = source.chanBank[i];
            chan.UpdatePercent();

            //float fChannelPercent = Mathf.Clamp(chan.Percent, 0.0f, 100.0f);
            float fChannelPercent;

            if (chan.mUseLimit)
            {
                fChannelPercent = Mathf.Clamp(chan.Percent, chan.mSpinmin, chan.mSpinmax);
            }
            else
            {
                fChannelPercent = Mathf.Clamp(chan.Percent, 0.0f, 100.0f);
            }

            if (fChannelPercent != 0.0f || (fChannelPercent == 0.0f && chan.fChannelPercent != 0.0f))
            {
                chan.fChannelPercent = fChannelPercent;

                if (chan.mTargetCache != null && chan.mTargetCache.Count > 0 && chan.mActiveOverride)
                {
                    mtmorphed = true;

                    if (chan.mTargetCache.Count > 1)
                    {
                        int totaltargs = chan.mTargetCache.Count;                               // + 1;	// + 1;

                        chan.fProgression = chan.fChannelPercent;                               //Mathf.Clamp(fChannelPercent, 0.0f, 100.0f);
                        chan.segment      = 1;
                        while (chan.segment <= totaltargs && chan.fProgression >= chan.GetTargetPercent(chan.segment - 2))
                        {
                            chan.segment++;
                        }

                        if (chan.segment > totaltargs)
                        {
                            chan.segment = totaltargs;
                        }

                        chan.p4 = source.oPoints;

                        if (chan.segment == 1)
                        {
                            chan.p1 = source.oPoints;
                            chan.p2 = chan.mTargetCache[0].points;                              // mpoints
                            chan.p3 = chan.mTargetCache[1].points;
                        }
                        else
                        {
                            if (chan.segment == totaltargs)
                            {
                                int targnum = totaltargs - 1;

                                for (int j = 2; j >= 0; j--)
                                {
                                    targnum--;
                                    if (targnum == -2)
                                    {
                                        SetVerts(chan, j, source.oPoints);
                                    }
                                    else
                                    {
                                        SetVerts(chan, j, chan.mTargetCache[targnum + 1].points);
                                    }
                                }
                            }
                            else
                            {
                                int targnum = chan.segment;

                                for (int j = 3; j >= 0; j--)
                                {
                                    targnum--;
                                    if (targnum == -2)
                                    {
                                        SetVerts(chan, j, source.oPoints);
                                    }
                                    else
                                    {
                                        SetVerts(chan, j, chan.mTargetCache[targnum + 1].points);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        if (!mtmorphed)
        {
            for (int i = 0; i < verts.Length; i++)
            {
                sverts[i] = verts[i];
            }
        }
    }
Пример #3
0
    // oPoints whould be verts
    public override void Modify(MegaModifiers mc)
    {
        if (source == null)
        {
            return;
        }

        if (source.nonMorphedVerts != null && source.nonMorphedVerts.Length > 1)
        {
            ModifyCompressed(mc);
            return;
        }

        framenum++;
        mc.ChangeSourceVerts();

        float   fChannelPercent;
        Vector3 delt;

        // cycle through channels, searching for ones to use
        bool firstchan = true;
        bool morphed   = false;

        float min = 0.0f;
        float max = 100.0f;

        if (UseLimit)
        {
            min = Min;
            max = Max;
        }

        for (int i = 0; i < source.chanBank.Count; i++)
        {
            MegaMorphChan chan = source.chanBank[i];

            // This needs to be local chan list
            chan.UpdatePercent();

            if (UseLimit)
            {
                fChannelPercent = Mathf.Clamp(chan.Percent, min, max);                  //chan.mSpinmin, chan.mSpinmax);
            }
            else
            {
                if (chan.mUseLimit)
                {
                    fChannelPercent = Mathf.Clamp(chan.Percent, chan.mSpinmin, chan.mSpinmax);
                }
                else
                {
                    fChannelPercent = Mathf.Clamp(chan.Percent, 0.0f, 100.0f);
                }
            }

            if (fChannelPercent != 0.0f || (fChannelPercent == 0.0f && chan.fChannelPercent != 0.0f))
            {
                chan.fChannelPercent = fChannelPercent;

                if (chan.mTargetCache != null && chan.mTargetCache.Count > 0 && chan.mActiveOverride)                   //&& fChannelPercent != 0.0f )
                {
                    morphed = true;

                    if (chan.mUseLimit)                         //|| glUseLimit )
                    {
                    }

                    if (firstchan)
                    {
                        firstchan = false;
                        for (int pointnum = 0; pointnum < source.oPoints.Length; pointnum++)
                        {
                            dif[pointnum] = source.oPoints[pointnum];
                        }
                    }

                    if (chan.mTargetCache.Count == 1)
                    {
                        for (int pointnum = 0; pointnum < source.oPoints.Length; pointnum++)
                        {
                            delt = chan.mDeltas[pointnum];

                            dif[pointnum].x += delt.x * fChannelPercent;
                            dif[pointnum].y += delt.y * fChannelPercent;
                            dif[pointnum].z += delt.z * fChannelPercent;
                        }
                    }
                    else
                    {
                        int totaltargs = chan.mTargetCache.Count;                       // + 1;	// + 1;

                        float fProgression = fChannelPercent;                           //Mathf.Clamp(fChannelPercent, 0.0f, 100.0f);
                        int   segment      = 1;
                        while (segment <= totaltargs && fProgression >= chan.GetTargetPercent(segment - 2))
                        {
                            segment++;
                        }

                        if (segment > totaltargs)
                        {
                            segment = totaltargs;
                        }

                        p4 = source.oPoints;

                        if (segment == 1)
                        {
                            p1 = source.oPoints;
                            p2 = chan.mTargetCache[0].points;                                   // mpoints
                            p3 = chan.mTargetCache[1].points;
                        }
                        else
                        {
                            if (segment == totaltargs)
                            {
                                int targnum = totaltargs - 1;

                                for (int j = 2; j >= 0; j--)
                                {
                                    targnum--;
                                    if (targnum == -2)
                                    {
                                        SetVerts(j, source.oPoints);
                                    }
                                    else
                                    {
                                        SetVerts(j, chan.mTargetCache[targnum + 1].points);
                                    }
                                }
                            }
                            else
                            {
                                int targnum = segment;

                                for (int j = 3; j >= 0; j--)
                                {
                                    targnum--;
                                    if (targnum == -2)
                                    {
                                        SetVerts(j, source.oPoints);
                                    }
                                    else
                                    {
                                        SetVerts(j, chan.mTargetCache[targnum + 1].points);
                                    }
                                }
                            }
                        }

                        float targetpercent1 = chan.GetTargetPercent(segment - 3);
                        float targetpercent2 = chan.GetTargetPercent(segment - 2);

                        float top    = fProgression - targetpercent1;
                        float bottom = targetpercent2 - targetpercent1;
                        float u      = top / bottom;

                        {
                            for (int pointnum = 0; pointnum < source.oPoints.Length; pointnum++)
                            {
                                Vector3 vert = source.oPoints[pointnum];

                                float length;

                                Vector3 progession;

                                endpoint[0] = p1[pointnum];
                                endpoint[1] = p2[pointnum];
                                endpoint[2] = p3[pointnum];
                                endpoint[3] = p4[pointnum];

                                if (segment == 1)
                                {
                                    splinepoint[0] = endpoint[0];
                                    splinepoint[3] = endpoint[1];
                                    temppoint[1]   = endpoint[2] - endpoint[0];
                                    temppoint[0]   = endpoint[1] - endpoint[0];
                                    length         = temppoint[1].sqrMagnitude;

                                    if (length == 0.0f)
                                    {
                                        splinepoint[1] = endpoint[0];
                                        splinepoint[2] = endpoint[1];
                                    }
                                    else
                                    {
                                        splinepoint[2] = endpoint[1] - (Vector3.Dot(temppoint[0], temppoint[1]) * chan.mCurvature / length) * temppoint[1];
                                        splinepoint[1] = endpoint[0] + chan.mCurvature * (splinepoint[2] - endpoint[0]);
                                    }
                                }
                                else
                                {
                                    if (segment == totaltargs)
                                    {
                                        splinepoint[0] = endpoint[1];
                                        splinepoint[3] = endpoint[2];
                                        temppoint[1]   = endpoint[2] - endpoint[0];
                                        temppoint[0]   = endpoint[1] - endpoint[2];
                                        length         = temppoint[1].sqrMagnitude;

                                        if (length == 0.0f)
                                        {
                                            splinepoint[1] = endpoint[0];
                                            splinepoint[2] = endpoint[1];
                                        }
                                        else
                                        {
                                            splinepoint[1] = endpoint[1] - (Vector3.Dot(temppoint[1], temppoint[0]) * chan.mCurvature / length) * temppoint[1];
                                            splinepoint[2] = endpoint[2] + chan.mCurvature * (splinepoint[1] - endpoint[2]);
                                        }
                                    }
                                    else
                                    {
                                        temppoint[1]   = endpoint[2] - endpoint[0];
                                        temppoint[0]   = endpoint[1] - endpoint[0];
                                        length         = temppoint[1].sqrMagnitude;
                                        splinepoint[0] = endpoint[1];
                                        splinepoint[3] = endpoint[2];

                                        if (length == 0.0f)
                                        {
                                            splinepoint[1] = endpoint[0];
                                        }
                                        else
                                        {
                                            splinepoint[1] = endpoint[1] + (Vector3.Dot(temppoint[0], temppoint[1]) * chan.mCurvature / length) * temppoint[1];
                                        }

                                        temppoint[1] = endpoint[3] - endpoint[1];
                                        temppoint[0] = endpoint[2] - endpoint[1];
                                        length       = temppoint[1].sqrMagnitude;

                                        if (length == 0.0f)
                                        {
                                            splinepoint[2] = endpoint[1];
                                        }
                                        else
                                        {
                                            splinepoint[2] = endpoint[2] - (Vector3.Dot(temppoint[0], temppoint[1]) * chan.mCurvature / length) * temppoint[1];
                                        }
                                    }
                                }

                                MegaUtils.Bez3D(out progession, ref splinepoint, u);

                                dif[pointnum].x += progession.x - vert.x;                                       //delt;
                                dif[pointnum].y += progession.y - vert.y;                                       //delt;
                                dif[pointnum].z += progession.z - vert.z;                                       //delt;
                            }
                        }
                    }
                }
            }
        }

        if (morphed)
        {
            for (int i = 0; i < source.mapping.Length; i++)
            {
                sverts[i] = dif[source.mapping[i]];
            }
        }
        else
        {
            for (int i = 0; i < verts.Length; i++)
            {
                sverts[i] = verts[i];
            }
        }
    }
Пример #4
0
    public void ModifyCompressed(MegaModifiers mc)
    {
        framenum++;
        mc.ChangeSourceVerts();

        float   fChannelPercent;
        Vector3 delt;

        // cycle through channels, searching for ones to use
        bool firstchan = true;
        bool morphed   = false;

        for (int i = 0; i < source.chanBank.Count; i++)
        {
            MegaMorphChan chan  = source.chanBank[i];
            MegaMorphChan lchan = chanBank[i];                  // copy of source banks with out the vert data

            chan.UpdatePercent();

            if (chan.mUseLimit)
            {
                fChannelPercent = Mathf.Clamp(lchan.Percent, chan.mSpinmin, chan.mSpinmax);
            }
            else
            {
                fChannelPercent = Mathf.Clamp(lchan.Percent, 0.0f, 100.0f);
            }

            if (fChannelPercent != 0.0f || (fChannelPercent == 0.0f && chan.fChannelPercent != 0.0f))
            {
                chan.fChannelPercent = fChannelPercent;

                if (chan.mTargetCache != null && chan.mTargetCache.Count > 0 && chan.mActiveOverride)                   //&& fChannelPercent != 0.0f )
                {
                    morphed = true;

                    if (chan.mUseLimit)                         //|| glUseLimit )
                    {
                    }

                    // New bit
                    if (firstchan)
                    {
                        firstchan = false;
                        // Save a int array of morphedpoints and use that, then only dealing with changed info
                        for (int pointnum = 0; pointnum < source.morphedVerts.Length; pointnum++)
                        {
                            // this will change when we remove points
                            int p = source.morphedVerts[pointnum];
                            dif[p] = source.oPoints[p];                                 //morphedVerts[pointnum]];
                        }
                    }
                    // end new

                    if (chan.mTargetCache.Count == 1)
                    {
                        // Save a int array of morphedpoints and use that, then only dealing with changed info
                        for (int pointnum = 0; pointnum < source.morphedVerts.Length; pointnum++)
                        {
                            int p = source.morphedVerts[pointnum];
                            delt = chan.mDeltas[p];                             //morphedVerts[pointnum]];
                            //delt = chan.mDeltas[pointnum];	//morphedVerts[pointnum]];

                            dif[p].x += delt.x * fChannelPercent;
                            dif[p].y += delt.y * fChannelPercent;
                            dif[p].z += delt.z * fChannelPercent;
                        }
                    }
                    else
                    {
                        int totaltargs = chan.mTargetCache.Count;                       // + 1;	// + 1;

                        float fProgression = fChannelPercent;                           //Mathf.Clamp(fChannelPercent, 0.0f, 100.0f);
                        int   segment      = 1;
                        while (segment <= totaltargs && fProgression >= chan.GetTargetPercent(segment - 2))
                        {
                            segment++;
                        }

                        if (segment > totaltargs)
                        {
                            segment = totaltargs;
                        }

                        p4 = source.oPoints;

                        if (segment == 1)
                        {
                            p1 = source.oPoints;
                            p2 = chan.mTargetCache[0].points;                                   // mpoints
                            p3 = chan.mTargetCache[1].points;
                        }
                        else
                        {
                            if (segment == totaltargs)
                            {
                                int targnum = totaltargs - 1;

                                for (int j = 2; j >= 0; j--)
                                {
                                    targnum--;
                                    if (targnum == -2)
                                    {
                                        SetVerts(j, source.oPoints);
                                    }
                                    else
                                    {
                                        SetVerts(j, chan.mTargetCache[targnum + 1].points);
                                    }
                                }
                            }
                            else
                            {
                                int targnum = segment;

                                for (int j = 3; j >= 0; j--)
                                {
                                    targnum--;
                                    if (targnum == -2)
                                    {
                                        SetVerts(j, source.oPoints);
                                    }
                                    else
                                    {
                                        SetVerts(j, chan.mTargetCache[targnum + 1].points);
                                    }
                                }
                            }
                        }

                        float targetpercent1 = chan.GetTargetPercent(segment - 3);
                        float targetpercent2 = chan.GetTargetPercent(segment - 2);

                        float top    = fProgression - targetpercent1;
                        float bottom = targetpercent2 - targetpercent1;
                        float u      = top / bottom;

                        for (int pointnum = 0; pointnum < source.morphedVerts.Length; pointnum++)
                        {
                            int     p    = source.morphedVerts[pointnum];
                            Vector3 vert = source.oPoints[p];                                   //pointnum];

                            float length;

                            Vector3 progession;

                            endpoint[0] = p1[p];
                            endpoint[1] = p2[p];
                            endpoint[2] = p3[p];
                            endpoint[3] = p4[p];

                            if (segment == 1)
                            {
                                splinepoint[0] = endpoint[0];
                                splinepoint[3] = endpoint[1];
                                temppoint[1]   = endpoint[2] - endpoint[0];
                                temppoint[0]   = endpoint[1] - endpoint[0];
                                length         = temppoint[1].sqrMagnitude;

                                if (length == 0.0f)
                                {
                                    splinepoint[1] = endpoint[0];
                                    splinepoint[2] = endpoint[1];
                                }
                                else
                                {
                                    splinepoint[2] = endpoint[1] - (Vector3.Dot(temppoint[0], temppoint[1]) * chan.mCurvature / length) * temppoint[1];
                                    splinepoint[1] = endpoint[0] + chan.mCurvature * (splinepoint[2] - endpoint[0]);
                                }
                            }
                            else
                            {
                                if (segment == totaltargs)
                                {
                                    splinepoint[0] = endpoint[1];
                                    splinepoint[3] = endpoint[2];
                                    temppoint[1]   = endpoint[2] - endpoint[0];
                                    temppoint[0]   = endpoint[1] - endpoint[2];
                                    length         = temppoint[1].sqrMagnitude;

                                    if (length == 0.0f)
                                    {
                                        splinepoint[1] = endpoint[0];
                                        splinepoint[2] = endpoint[1];
                                    }
                                    else
                                    {
                                        splinepoint[1] = endpoint[1] - (Vector3.Dot(temppoint[1], temppoint[0]) * chan.mCurvature / length) * temppoint[1];
                                        splinepoint[2] = endpoint[2] + chan.mCurvature * (splinepoint[1] - endpoint[2]);
                                    }
                                }
                                else
                                {
                                    temppoint[1]   = endpoint[2] - endpoint[0];
                                    temppoint[0]   = endpoint[1] - endpoint[0];
                                    length         = temppoint[1].sqrMagnitude;
                                    splinepoint[0] = endpoint[1];
                                    splinepoint[3] = endpoint[2];

                                    if (length == 0.0f)
                                    {
                                        splinepoint[1] = endpoint[0];
                                    }
                                    else
                                    {
                                        splinepoint[1] = endpoint[1] + (Vector3.Dot(temppoint[0], temppoint[1]) * chan.mCurvature / length) * temppoint[1];
                                    }

                                    temppoint[1] = endpoint[3] - endpoint[1];
                                    temppoint[0] = endpoint[2] - endpoint[1];
                                    length       = temppoint[1].sqrMagnitude;

                                    if (length == 0.0f)
                                    {
                                        splinepoint[2] = endpoint[1];
                                    }
                                    else
                                    {
                                        splinepoint[2] = endpoint[2] - (Vector3.Dot(temppoint[0], temppoint[1]) * chan.mCurvature / length) * temppoint[1];
                                    }
                                }
                            }

                            MegaUtils.Bez3D(out progession, ref splinepoint, u);

                            dif[p].x += progession.x - vert.x;
                            dif[p].y += progession.y - vert.y;
                            dif[p].z += progession.z - vert.z;
                        }
                    }
                }
            }
        }

        if (morphed)
        {
            for (int i = 0; i < source.morphMappingFrom.Length; i++)
            {
                sverts[source.morphMappingTo[i]] = dif[source.morphMappingFrom[i]];
            }

            for (int i = 0; i < source.nonMorphMappingFrom.Length; i++)
            {
                sverts[source.nonMorphMappingTo[i]] = source.oPoints[source.nonMorphMappingFrom[i]];
            }
        }
        else
        {
            for (int i = 0; i < verts.Length; i++)
            {
                sverts[i] = verts[i];
            }
        }
    }
    public void PrepareForMT(MegaModifiers mc, int cores)
    {
        return;

        verts.CopyTo(sverts, 0);                // This should only blit totally untouched verts

        for (int i = 0; i < chanBank.Count; i++)
        {
            MegaMorphChan chan = chanBank[i];
            chan.UpdatePercent();

            float fChannelPercent = chan.Percent;

            // check for change since last frame on percent, if none just add in diff
            // Can we keep each chan delta then if not changed can just add it in
            if (fChannelPercent != chan.fChannelPercent)
            {
                chan.fProgression = fChannelPercent;

                if (chan.mTargetCache != null && chan.mTargetCache.Count > 0 && chan.mActiveOverride)
                {
                    if (chan.mUseLimit || glUseLimit)
                    {
                        if (glUseLimit)
                        {
                            fChannelPercent = Mathf.Clamp(fChannelPercent, glMin, glMax);
                        }
                        else
                        {
                            fChannelPercent = Mathf.Clamp(fChannelPercent, chan.mSpinmin, chan.mSpinmax);
                        }
                    }

                    int targ = 0;
                    chan.alpha = 0.0f;

                    if (fChannelPercent < chan.mTargetCache[0].percent)
                    {
                        targ       = 0;
                        chan.alpha = 0.0f;                              // need to calc correct alpha here, use first gap
                    }
                    else
                    {
                        int last = chan.mTargetCache.Count - 1;
                        if (fChannelPercent >= chan.mTargetCache[last].percent)
                        {
                            targ       = last - 1;
                            chan.alpha = 1.0f;                                  // need to calc correct alpha here, use first gap
                        }
                        else
                        {
                            for (int t = 1; t < chan.mTargetCache.Count; t++)
                            {
                                if (fChannelPercent < chan.mTargetCache[t].percent)
                                {
                                    targ       = t - 1;
                                    chan.alpha = (fChannelPercent - chan.mTargetCache[targ].percent) / (chan.mTargetCache[t].percent - chan.mTargetCache[targ].percent);
                                    break;
                                }
                            }
                        }
                    }

                    chan.targ = targ;
                }
            }
        }
    }