animImportExport/animImportExport.cpp

animImportExport/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(kAnimCurveNotFound);
MStringResource::registerString(kInvalidAngleUnits);
MStringResource::registerString(kInvalidLinearUnits);
MStringResource::registerString(kInvalidTimeUnits);
MStringResource::registerString(kCouldNotReadAnim);
MStringResource::registerString(kCouldNotCreateAnim);
MStringResource::registerString(kClipboardFailure);
MStringResource::registerString(kSettingTanAngleUnit);
return MS::kSuccess;
}
animImport::animImport()
{
}
animImport::~animImport()
{
}
void *animImport::creator()
{
return new animImport();
}
MStatus animImport::reader( const MFileObject& file,
const MString& options,
FileAccessMode mode)
{
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;
}
animImport::importAnim(ifstream &animFile, const MString &pasteFlags)
{
// If the selection list is empty, there is nothing to import.
//
if (sList.isEmpty()) {
MString msg = MStringResource::getString(kNothingSelected, status);
return (MS::kFailure);
}
if (MS::kSuccess !=
(status = fReader.readClipboard(animFile,
return status;
}
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);
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()
{
}
animExport::~animExport()
{
}
void *animExport::creator()
{
return new animExport();
}
MStatus animExport::writer( const MFileObject& file,
const MString& options,
FileAccessMode mode)
{
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
{
return true;
}
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 */)
{
// If the selection list is empty, then there are no anim curves
// to export.
//
if (sList.isEmpty()) {
MString msg = MStringResource::getString(kNothingSelected, status);
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);
return status;
}
if (result == 0 || MAnimCurveClipboard::theAPIClipboard().isEmpty()) {
MString msg = MStringResource::getString(kAnimCurveNotFound, status);
return (MS::kFailure);
}
if (MS::kSuccess != ( status =
fWriter.writeClipboard(animFile,
nodeNames, verboseUnits))) {
return (MS::kFailure);
}
return status;
}
MStatus initializePlugin(MObject obj)
{
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)
{
MFnPlugin impPlugIn(obj);
stat = impPlugIn.deregisterFileTranslator("animImport");
if (stat != MS::kSuccess) {
return stat;
}
MFnPlugin expPlugIn(obj);
stat = expPlugIn.deregisterFileTranslator("animExport");
return stat;
}