- Main Page
- Related Pages
- Modules
- Classes
- Examples

# flipUVCmd.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
    //
    // Use of this software is subject to the terms of the Autodesk
    // license agreement provided at the time of installation or download,
    // or which otherwise accompanies this software in either electronic
    // or hard copy form.
    // ==========================================================================
    //+

    //
    // File: flipUVCmd.cpp
    //
    // MEL Command: flipUV
    //

    #include <flipUVCmd.h>

    #include <maya/MIOStream.h>
    #include <maya/MSyntax.h>
    #include <maya/MArgDatabase.h>
    #include <maya/MIntArray.h>
    #include <maya/MFloatArray.h>
    #include <maya/MFnMesh.h>

    // Flags for this command
    static const char * horizFlag           = "-h";
    static const char * horizFlagLong       = "-horizontal";
    static const char * globalFlag          = "-fg";
    static const char * globalFlagLong      = "-flipGlobal";
    static const char * extendFlag          = "-es";
    static const char * extendFlagLong      = "-extendToShell";

    const char * flipUVCmd::cmdName = "flipUV";
    //
    flipUVCmd::flipUVCmd() :
        horizontal(false),
        extendToShell(false),
        flipGlobal(false)
    {}

    //
    flipUVCmd::~flipUVCmd() {}

    //
    // Method to create a flipUVCmd object
    void *flipUVCmd::creator() { return new flipUVCmd; }

    //
    // Add additionnal flags for this command. The default setting of the
    // syntax is done in the base class.
    MSyntax flipUVCmd::newSyntax ()
    {
        MStatus status;

        // Get the base class syntax, and append to it.
        MSyntax syntax = MPxPolyTweakUVCommand::newSyntax();

        status = syntax.addFlag(horizFlag, horizFlagLong, MSyntax::kBoolean);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        status = syntax.addFlag(globalFlag, globalFlagLong, MSyntax::kBoolean);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        status = syntax.addFlag(extendFlag, extendFlagLong, MSyntax::kBoolean);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        return syntax;
    }

    //
    // Read the values of the additionnal flags for this command.
    MStatus flipUVCmd::parseSyntax (MArgDatabase &argData)
    {
        MStatus status;

        // Get the flag values, otherwise the default values are used.

        if (argData.isFlagSet(horizFlag)) {
            status = argData.getFlagArgument(horizFlag, 0, horizontal);
            CHECK_MSTATUS_AND_RETURN_IT(status);
        }

        if (argData.isFlagSet(globalFlag)) {
            status = argData.getFlagArgument(globalFlag, 0, flipGlobal);
            CHECK_MSTATUS_AND_RETURN_IT(status);
        }

        if (argData.isFlagSet(extendFlag)) {
            status = argData.getFlagArgument(extendFlag, 0, extendToShell);
            CHECK_MSTATUS_AND_RETURN_IT(status);
        }

        return MS::kSuccess;
    }

    //
    // Change the UVS for the given selection on this mesh object.
    //
    MStatus flipUVCmd::getTweakedUVs(
        const MObject & meshObj,                    // Object
        MIntArray & uvList,                     // UVs to move
        MFloatArray & uPos,                     // Moved UVs
        MFloatArray & vPos )                    // Moved UVs
    {
        MStatus status;
        unsigned int i;
        MFloatArray uArray;
        MFloatArray vArray;

        MFnMesh mesh( meshObj );

        // Read all UVs from the poly object
        status = mesh.getUVs(uArray, vArray);
        CHECK_MSTATUS_AND_RETURN_IT(status);

        unsigned int nbUvShells = 1;
        MIntArray uvShellIds;
        if ((!flipGlobal) || extendToShell)
        {
            // First, extract the UV shells.
            status = mesh.getUvShellsIds(uvShellIds, nbUvShells);
            CHECK_MSTATUS_AND_RETURN_IT(status);
        }

        if (extendToShell)
        {
            // Find all shells that have at least a selected UV.
            bool *selected = new bool[nbUvShells];
            for (i = 0 ; i<nbUvShells ; i++)
                selected[i] = false;

            for (i = 0 ; i<uvList.length() ; i++)
            {
                int indx = uvList[i];
                selected[uvShellIds[indx]] = true;
            }

            // Now recompute a new list of UVs to modify.

            unsigned int numUvs = mesh.numUVs();
            unsigned int numSelUvs = 0;

            // Preallocate a buffer, large enough to hold all Ids. This
            // prevents multiple reallocation from happening when growing
            // the array.
            uvList.setLength(numUvs);

            for (i = 0 ; i<numUvs ; i++)
            {
                if (selected[uvShellIds[i]])
                    uvList[numSelUvs++] = i;
            }

            // clamp the array to the proper size.
            uvList.setLength(numSelUvs);

            delete [] selected;
        }

        // For global flips, just pretend there is only one shell
        if (flipGlobal) nbUvShells = 1;

        float *minMax = new float[nbUvShells*4];

        for (i = 0 ; i<nbUvShells ; i++)
        {
            minMax[4*i+0] =  1e30F;             // Min U
            minMax[4*i+1] =  1e30F;             // Min V
            minMax[4*i+2] = -1e30F;             // Max U
            minMax[4*i+3] = -1e30F;             // Max V
        }

        // Get the bounding box of the UVs, for each shell if flipGlobal
        // is true, or for the whole selection if false.
        for (i = 0 ; i<uvList.length() ; i++)
        {
            int indx = uvList[i];
            int shellId = 0;
            if (!flipGlobal) shellId = uvShellIds[indx];

            if (uArray[indx] < minMax[4*shellId+0])
                minMax[4*shellId+0] = uArray[indx];
            if (vArray[indx] < minMax[4*shellId+1])
                minMax[4*shellId+1] = vArray[indx];
            if (uArray[indx] > minMax[4*shellId+2])
                minMax[4*shellId+2] = uArray[indx];
            if (vArray[indx] > minMax[4*shellId+3])
                minMax[4*shellId+3] = vArray[indx];
        }

        // Adjust the size of the output arrays
        uPos.setLength(uvList.length());
        vPos.setLength(uvList.length());

        for (i = 0 ; i<uvList.length() ; i++)
        {
            int shellId = 0;
            int indx = uvList[i];
            if (!flipGlobal) shellId = uvShellIds[indx];

            // Flip U or V along the bounding box center.
            if (horizontal)
            {
                uPos[i] = minMax[4*shellId+0] + minMax[4*shellId+2] -
                    uArray[indx];
                vPos[i] = vArray[indx];
            }
            else
            {
                uPos[i] = uArray[indx];
                vPos[i] = minMax[4*shellId+1] + minMax[4*shellId+3] -
                    vArray[indx];
            }
        }

        delete [] minMax;

        return MS::kSuccess;
    }