#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
const char *const animImportOptionScript = "animImportOptions";
const char *const animImportDefaultOptions =
"targetTime=4;copies=1;option=replace;pictures=0;connect=0;";
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
MString pasteFlags;
if (options.length() > 0) {
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;
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;
}
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();
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;
}
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;
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
MString copyFlags("copyKey -cb api -fea 1 ");
int precision = kDefaultPrecision;
bool nodeNames = true;
bool verboseUnits = false;
MString exportFlags;
if (options.length() > 0) {
const MString flagPrecision("precision");
const MString flagNodeNames("nodeNames");
const MString flagVerboseUnits("verboseUnits");
const MString flagCopyKeyCmd("copyKeyCmd");
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) {
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;
}
}
}
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 ©Flags,
bool nodeNames ,
bool verboseUnits )
{
MStatus status = MS::kFailure;
MSelectionList sList;
MGlobal::getActiveSelectionList(sList);
if (sList.isEmpty()) {
MString msg = MStringResource::getString(kNothingSelected, status);
MGlobal::displayError(msg);
return (MS::kFailure);
}
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");
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;
}