animImportExport.cpp

//-
// ==========================================================================
// Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors.  All 
// rights reserved.
//
// The coded instructions, statements, computer programs, and/or related 
// material (collectively the "Data") in these files contain unpublished 
// information proprietary to Autodesk, Inc. ("Autodesk") and/or its 
// licensors, which is protected by U.S. and Canadian federal copyright 
// law and by international treaties.
//
// The Data is provided for use exclusively by You. You have the right 
// to use, modify, and incorporate this Data into other products for 
// purposes authorized by the Autodesk software license agreement, 
// without fee.
//
// The copyright notices in the Software and this entire statement, 
// including the above license grant, this restriction and the 
// following disclaimer, must be included in all copies of the 
// Software, in whole or in part, and all derivative works of 
// the Software, unless such copies or derivative works are solely 
// in the form of machine-executable object code generated by a 
// source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. 
// AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED 
// WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF 
// NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
// PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR 
// TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS 
// BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, 
// DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK 
// AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY 
// OR PROBABILITY OF SUCH DAMAGES.
//
// ==========================================================================
//+

//
//      File Name:      animImport.cc
//
//      Description:
//              Imports a .anim file into anim curves attached to the selected
//              Maya objects.
//

#include <stdlib.h>
#include <string.h>

#include <maya/MFStream.h>
#include <maya/MGlobal.h>
#include <maya/MString.h>
#include <maya/MFnPlugin.h>
#include <maya/MPxFileTranslator.h>

#include <maya/MSelectionList.h>

#include <maya/MFnAnimCurve.h>
#include <maya/MAnimCurveClipboard.h>
#include <maya/MAnimCurveClipboardItem.h>
#include <maya/MAnimCurveClipboardItemArray.h>

#include "animImportExport.h"
#include "animFileUtils.h"
#include "animImportExportStrings.h"

#if defined (OSMac_)
#       include <sys/param.h>
extern "C" int strcasecmp (const char *, const char *);
#endif
//-----------------------------------------------------------------------------
//      anim Importer
//-----------------------------------------------------------------------------

const char *const animImportOptionScript = "animImportOptions";
const char *const animImportDefaultOptions = 
        "targetTime=4;copies=1;option=replace;pictures=0;connect=0;";

// Register all strings used by the plugin C++ code
static MStatus registerMStringResources(void)
{
        MStringResource::registerString(kNothingSelected);
        MStringResource::registerString(kPasteFailed);
        MStringResource::registerString(kAnimCurveNotFound);            
        MStringResource::registerString(kInvalidAngleUnits);
        MStringResource::registerString(kInvalidLinearUnits);
        MStringResource::registerString(kInvalidTimeUnits);
        MStringResource::registerString(kInvalidVersion);
        MStringResource::registerString(kSettingToUnit);
        MStringResource::registerString(kMissingKeyword);
        MStringResource::registerString(kCouldNotReadAnim);
        MStringResource::registerString(kCouldNotCreateAnim);   
        MStringResource::registerString(kUnknownKeyword);
        MStringResource::registerString(kClipboardFailure);
        MStringResource::registerString(kSettingTanAngleUnit);
        MStringResource::registerString(kUnknownNode);
        MStringResource::registerString(kCouldNotKey);
        MStringResource::registerString(kMissingBrace);
        MStringResource::registerString(kCouldNotExport);
        return MS::kSuccess;
}



animImport::animImport()
: MPxFileTranslator()
{
}

animImport::~animImport()
{
}

void *animImport::creator()
{
        return new animImport();
}

MStatus animImport::reader(     const MFileObject& file,
                                                                const MString& options,
                                                                FileAccessMode mode)
{
        MStatus status = MS::kFailure;

        MString fileName = file.fullName();
#if defined (OSMac_)    
        char fname[MAXPATHLEN];
        strcpy (fname, fileName.asChar());
        ifstream animFile(fname);
#else
        ifstream animFile(fileName.asChar());
#endif
        //      Parse the options. The options syntax is in the form of
        //      "flag=val;flag1=val;flag2=val"
        //
        MString pasteFlags;
        if (options.length() > 0) {
                //      Set up the flags for the paste command.
                //
                const MString flagTargetTime("targetTime");
                const MString flagTime("time");
                const MString flagCopies("copies");
                const MString flagOption("option");
                const MString flagConnect("connect");

                MString copyValue;
                MString flagValue;
                MString connectValue;
                MString timeValue;

                //      Start parsing.
                //
                MStringArray optionList;
                MStringArray theOption;
                options.split(';', optionList);

                unsigned nOptions = optionList.length();
                for (unsigned i = 0; i < nOptions; i++) {

                        theOption.clear();
                        optionList[i].split('=', theOption);
                        if (theOption.length() < 1) {
                                continue;
                        }

                        if (theOption[0] == flagCopies && theOption.length() > 1) {
                                copyValue = theOption[1];;
                        } else if (theOption[0] == flagOption && theOption.length() > 1) {
                                flagValue = theOption[1];
                        } else if (theOption[0] == flagConnect && theOption.length() > 1) {
                                if (theOption[1].asInt() != 0) {
                                        connectValue += theOption[1];
                                }
                        } else if (theOption[0] == flagTime && theOption.length() > 1) {
                                timeValue += theOption[1];
                        } 
                }
        
                if (copyValue.length() > 0) {
                        pasteFlags += " -copies ";
                        pasteFlags += copyValue;
                        pasteFlags += " ";
                } 
                if (flagValue.length() > 0) {
                        pasteFlags += " -option \"";
                        pasteFlags += flagValue;
                        pasteFlags += "\" ";
                } 
                if (connectValue.length() > 0) {
                        pasteFlags += " -connect ";
                        pasteFlags += connectValue;
                        pasteFlags += " ";
                } 
                if (timeValue.length() > 0) {
                        bool useQuotes = !timeValue.isDouble();
                        pasteFlags += " -time ";
                        if (useQuotes) pasteFlags += "\"";
                        pasteFlags += timeValue;
                        if (useQuotes) pasteFlags += "\"";
                        pasteFlags += " ";
                } 
        }

        if (mode == kImportAccessMode) {
                status = importAnim(animFile, pasteFlags);
        }

        animFile.close();
        return status;
}

bool animImport::haveReadMethod() const
{
        return true;
}

bool animImport::haveWriteMethod() const
{
        return false;
}

bool animImport::canBeOpened() const
{
        return false;
}

MString animImport::defaultExtension() const
{
        return MString("anim");
}

MPxFileTranslator::MFileKind animImport::identifyFile(
                                                                const MFileObject& fileName,
                                                                const char* buffer,
                                                                short size) const
{
        const char *name = fileName.name().asChar();
        int   nameLength = (int)strlen(name);

        if ((nameLength > 5) && !strcasecmp(name+nameLength-5, ".anim")) {
                return kIsMyFileType;
        }

        //      Check the buffer to see if this contains the correct keywords
        //      to be a anim file.
        //
        if (strncmp(buffer, "animVersion", 11) == 0) {
                return kIsMyFileType;
        }

        return  kNotMyFileType;
}

MStatus 
animImport::importAnim(ifstream &animFile, const MString &pasteFlags)
{
        MStatus status = MS::kFailure;
        MAnimCurveClipboard::theAPIClipboard().clear();

        //      If the selection list is empty, there is nothing to import.
        //
        MSelectionList sList;
        MGlobal::getActiveSelectionList(sList);
        if (sList.isEmpty()) {
                MString msg = MStringResource::getString(kNothingSelected, status);
                MGlobal::displayError(msg);
                return (MS::kFailure);
        }

        if (MS::kSuccess != 
                        (status = fReader.readClipboard(animFile, 
                        MAnimCurveClipboard::theAPIClipboard()))) {

                return status;
        }

        if (MAnimCurveClipboard::theAPIClipboard().isEmpty()) {
                return (MS::kFailure);
        }

        MString command("pasteKey -cb api ");
        command += pasteFlags;

        int result;
        if (MS::kSuccess != (status =  
                MGlobal::executeCommand(command, result, false, true))) {
                MString msg = MStringResource::getString(kPasteFailed, status);
                MGlobal::displayError(msg);
                return status;
        }

        return status;
}

//-----------------------------------------------------------------------------
//      anim Exporter
//-----------------------------------------------------------------------------

const char *const animExportOptionScript = "animExportOptions";
const char *const animExportDefaultOptions = "precision=8;nodeNames=1;verboseUnits=0;whichRange=1;range=0:10;options=keys;hierarchy=none;controlPoints=0;shapes=1;helpPictures=0;useChannelBox=0;copyKeyCmd=";

const int kDefaultPrecision = 8;        //      float precision.

animExport::animExport()
: MPxFileTranslator()
{
}

animExport::~animExport()
{
}

void *animExport::creator()
{
        return new animExport();
}

MStatus animExport::writer(     const MFileObject& file,
                                                                const MString& options,
                                                                FileAccessMode mode)
{
        MStatus status = MS::kFailure;

#ifdef MAYA_EVAL_VERSION
        status = MS::kFailure;
        return status;
#endif

        MString fileName = file.fullName();
#if defined (OSMac_)
        char fname[MAXPATHLEN];
        strcpy (fname, fileName.asChar());
        ofstream animFile(fname);
#else
        ofstream animFile(fileName.asChar());
#endif
        //      Defaults.
        //
        MString copyFlags("copyKey -cb api -fea 1 ");
        int precision = kDefaultPrecision;
        bool nodeNames = true;
        bool verboseUnits = false;

        //      Parse the options. The options syntax is in the form of
        //      "flag=val;flag1=val;flag2=val"
        //
        MString exportFlags;
        if (options.length() > 0) {
                const MString flagPrecision("precision");
                const MString flagNodeNames("nodeNames");
                const MString flagVerboseUnits("verboseUnits");
                const MString flagCopyKeyCmd("copyKeyCmd");

                //      Start parsing.
                //
                MStringArray optionList;
                MStringArray theOption;
                options.split(';', optionList);

                unsigned nOptions = optionList.length();
                for (unsigned i = 0; i < nOptions; i++) {
                        theOption.clear();
                        optionList[i].split('=', theOption);
                        if (theOption.length() < 1) {
                                continue;
                        }

                        if (theOption[0] == flagPrecision && theOption.length() > 1) {
                                if (theOption[1].isInt()) {
                                        precision = theOption[1].asInt();
                                }
                        } else if (     theOption[0] == 
                                                flagNodeNames && theOption.length() > 1) {
                                if (theOption[1].isInt()) {
                                        nodeNames = (theOption[1].asInt()) ? true : false;
                                }
                        }
                        else if (theOption[0] == 
                                        flagVerboseUnits && theOption.length() > 1) {
                                if (theOption[1].isInt()) {
                                        verboseUnits = (theOption[1].asInt()) ? true : false;
                                }
                        } else if (     theOption[0] == 
                                                flagCopyKeyCmd && theOption.length() > 1) {

                                //      Replace any '>' characters with '"'. This is needed
                                //      since the file translator option boxes do not handle
                                //      escaped quotation marks.
                                //
                                const char *optStr = theOption[1].asChar();
                                size_t nChars = strlen(optStr);
                                char *copyStr = new char[nChars+1];

                                copyStr = strcpy(copyStr, optStr);
                                for (size_t j = 0; j < nChars; j++) {
                                        if (copyStr[j] == '>') {
                                                copyStr[j] = '"';
                                        }
                                }
                
                                copyFlags += copyStr;
                                delete copyStr;
                        }
                }
        }
        
        //      Set the precision of the ofstream.
        //
        animFile.precision(precision);

        status = exportSelected(animFile, copyFlags, nodeNames, verboseUnits);

        animFile.flush();
        animFile.close();

        return status;
}

bool animExport::haveReadMethod() const
{
        return false;
}

bool animExport::haveWriteMethod() const
{
#ifdef MAYA_EVAL_VERSION
        return false;
#else
        return true;
#endif
}

MString animExport::defaultExtension() const
{
        return MString("anim");
}

MPxFileTranslator::MFileKind animExport::identifyFile(
                                                                const MFileObject& fileName,
                                                                const char* buffer,
                                                                short size) const
{
        const char *name = fileName.name().asChar();
        int   nameLength = (int)strlen(name);

        if ((nameLength > 5) && !strcasecmp(name+nameLength-5, ".anim")) {
                return kIsMyFileType;
        }

        return  kNotMyFileType;
}

MStatus animExport::exportSelected(     ofstream &animFile, 
                                                                        MString &copyFlags,
                                                                        bool nodeNames /* false */,
                                                                        bool verboseUnits /* false */)
{
        MStatus status = MS::kFailure;

        //      If the selection list is empty, then there are no anim curves
        //      to export.
        //
        MSelectionList sList;
        MGlobal::getActiveSelectionList(sList);
        if (sList.isEmpty()) {
                MString msg = MStringResource::getString(kNothingSelected, status);
                MGlobal::displayError(msg);
                return (MS::kFailure);
        }

        //      Copy any anim curves to the API clipboard.
        //
        int result = 0;
        MString command(copyFlags);

        if (MS::kSuccess != (status = 
                MGlobal::executeCommand(command, result, false, true))) {
                MStatus stringStat;
                MString msg = MStringResource::getString(kAnimCurveNotFound, stringStat);
                MGlobal::displayError(msg);
                return status;
        }

        if (result == 0 || MAnimCurveClipboard::theAPIClipboard().isEmpty()) {
                MString msg = MStringResource::getString(kAnimCurveNotFound, status);
                MGlobal::displayError(msg);
                return (MS::kFailure);
        }

        if (MS::kSuccess != (   status = 
                                                        fWriter.writeClipboard(animFile, 
                                                        MAnimCurveClipboard::theAPIClipboard(),
                                                        nodeNames, verboseUnits))) {
                return (MS::kFailure);
        }

        return status;
}


MStatus initializePlugin(MObject obj)
{
        MStatus stat = MS::kFailure;
        MFnPlugin impPlugIn(obj, PLUGIN_COMPANY, "3.0", "Any");
        
        // This is done first, so the strings are available. 
        stat = impPlugIn.registerUIStrings(registerMStringResources, "animImportExportInitStrings");
        if (stat != MS::kSuccess)
        {
                stat.perror("registerUIStrings");
                return stat;
        }

        stat = impPlugIn.registerFileTranslator("animImport", "none",
                                                                                        animImport::creator,
                                                                                        (char *)animImportOptionScript,
                                                                                        (char *)animImportDefaultOptions, 
                                                                                        true);

        if (stat != MS::kSuccess) {
                return stat;
        }

        MFnPlugin expPlugIn(obj, PLUGIN_COMPANY, "3.0", "Any");
        stat = expPlugIn.registerFileTranslator("animExport", "",
                                                                                animExport::creator,
                                                                                (char *)animExportOptionScript,
                                                                                (char *)animExportDefaultOptions,
                                                                                true);

        return stat;
}

MStatus uninitializePlugin(MObject obj)
{
        MStatus stat = MS::kFailure;

        MFnPlugin impPlugIn(obj);
        stat = impPlugIn.deregisterFileTranslator("animImport");

        if (stat != MS::kSuccess) {
                return stat;
        }

        MFnPlugin expPlugIn(obj);
        stat = expPlugIn.deregisterFileTranslator("animExport");

        return stat;
}

Autodesk® Maya® 2009 © 1997-2008 Autodesk, Inc. All rights reserved. Generated with doxygen 1.5.6