#include <maya/MDagPath.h>
#include <maya/MDagPathArray.h>
#include <maya/MFileIO.h>
#include <maya/MFileObject.h>
#include <maya/MFnAttribute.h>
#include <maya/MFnCompoundAttribute.h>
#include <maya/MFnDagNode.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnPlugin.h>
#include <maya/MGlobal.h>
#include <maya/MItDag.h>
#include <maya/MItDependencyNodes.h>
#include <maya/MObjectArray.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MPxFileTranslator.h>
#include <maya/MString.h>
#include <maya/MStringArray.h>
#include <ctype.h>
#include <maya/MFStream.h>
#include <time.h>
{
public:
const char* buffer,
short size
) const override;
FileAccessMode mode
) override;
FileAccessMode mode
) override;
static void* creator();
static void setPluginName(
const MString& name);
protected:
void writeBrokenRefConnections(fstream& f);
void writeConnections(fstream& f);
void writeCreateNode(fstream& f,
const MObject& node);
void writeCreateNode(
);
void writeDagNodes(fstream& f);
void writeDefaultNodes(fstream& f);
void writeFileInfo(fstream& f);
void writeFooter(fstream& f,
const MString& fileName);
void writeHeader(fstream& f,
const MString& fileName);
void writeInstances(fstream& f);
void writeLockNode(fstream& f,
const MObject& node);
void writeNodeAttrs(fstream& f,
const MObject& node,
bool isSelected);
void writeNodeConnections(fstream& f,
const MObject& node);
void writeNonDagNodes(fstream& f);
void writeParent(
fstream& f,
bool addIt
);
void writePlugSizeHint(fstream& f,
const MPlug& plug);
void writeReferences(fstream& f);
void writeReferenceNodes(fstream& f);
void writeRefNodeParenting(fstream& f);
void writeRequirements(fstream& f);
void writeSelectNode(fstream& f,
const MObject& node);
void writeUnits(fstream& f);
private:
unsigned int fAttrFlag;
unsigned int fCreateFlag;
unsigned int fConnectionFlag;
};
MString maTranslator::fFileVersion =
"4.5ff01";
MString maTranslator::fExtension =
"pma";
MString maTranslator::fPluginName =
"";
MString maTranslator::fTranslatorName =
"Maya ASCII (via plugin)";
inline MString maTranslator::defaultExtension()
const
{ return fExtension; }
inline bool maTranslator::haveReadMethod() const
{ return false; }
inline bool maTranslator::haveWriteMethod() const
{ return true; }
inline void maTranslator::setPluginName(
const MString& name)
{ fPluginName = name; }
inline MString maTranslator::translatorName()
{ return fTranslatorName; }
void* maTranslator::creator()
{
return new maTranslator();
}
const MFileObject& file,
const char* buffer,
short bufferLen
) const
{
MString tagStr = comment(fTranslatorName);
if (bufferLen >= tagLen)
{
MString initialContents(buffer, bufferLen);
initialContents.split('\n', initialLines);
if (initialLines.
length() > 0)
{
if (((int)initialLines[0].length() >= tagLen)
&& (initialLines[0].substring(0, tagLen-1) == tagStr))
{
return kIsMyFileType;
}
}
}
else
{
int fileNameLen = fileName.
length();
int startOfExtension = fileName.rindex('.') + 1;
if ((startOfExtension > 0)
&& (startOfExtension < fileNameLen)
&& (fileName.substring(startOfExtension, fileNameLen) == fExtension))
{
return kIsMyFileType;
}
}
return kNotMyFileType;
}
)
{
if ((mode != kSaveAccessMode) && (mode != kExportAccessMode))
return MS::kNotImplemented;
if (!output.good()) return MS::kNotFound;
if (status)
if (status)
if (!status)
{
"Could not allocate three free node flags."
" Try unloading some other plugins."
);
return MS::kFailure;
}
{
nodeFn.setFlag(fCreateFlag, false);
nodeFn.setFlag(fAttrFlag, false);
nodeFn.setFlag(fConnectionFlag, false);
}
writeFileInfo(output);
writeReferences(output);
writeRequirements(output);
writeUnits(output);
writeDagNodes(output);
writeNonDagNodes(output);
writeDefaultNodes(output);
writeReferenceNodes(output);
writeConnections(output);
output.close();
return MS::kSuccess;
}
void maTranslator::writeHeader(fstream& f,
const MString& fileName)
{
time_t tempTime = time(NULL);
struct tm* curTime = localtime(&tempTime);
char formattedTime[100];
strftime(
formattedTime, sizeof(formattedTime), "%a, %b %e, %Y %r", curTime
);
f << comment(fTranslatorName).asChar() << " "
<< fFileVersion.asChar() << " scene" << endl;
f << comment(
"Name: ").asChar() << fileName.
asChar() << endl;
f << comment("Last modified: ").asChar() << formattedTime << endl;
}
void maTranslator::writeFileInfo(fstream& f)
{
{
unsigned numEntries = fileInfo.
length();
unsigned i;
for (i = 0; i < numEntries; i += 2)
{
f << "fileInfo " << quote(fileInfo[i]).asChar() << " "
<< quote(fileInfo[i+1]).asChar() << ";" << endl;
}
}
else
}
void maTranslator::writeReferences(fstream& f)
{
unsigned numRefs = files.
length();
unsigned i;
for (i = 0; i < numRefs; i++)
{
MString tempCmd =
"file -q -ns \"";
tempCmd += fileName + "\"";
{
refCmd += " -ns \"";
refCmd += nsName + "\"";
}
else
tempCmd = "file -q -dr \"";
tempCmd += fileName + "\"";
int isDeferred;
{
if (isDeferred) refCmd += " -dr 1";
}
else
tempCmd = "file -q -rfn \"";
tempCmd += fileName + "\"";
{
{
refCmd += " -rfn \"";
refCmd += refNode + "\"";
}
}
else
f << refCmd.
asChar() <<
" \"" << fileName.
asChar() <<
"\";" << endl;
}
}
void maTranslator::writeRequirements(fstream& f)
{
f << "requires maya \"" << fFileVersion.asChar() << "\";" << endl;
{
unsigned numPlugins = pluginsUsed.
length();
unsigned i;
for (i = 0; i < numPlugins; i += 2)
{
f << "requires " << quote(pluginsUsed[i]).asChar() << " "
<< quote(pluginsUsed[i+1]).asChar() << ";" << endl;
}
}
else
{
"Could not get list of plugins currently in use."
);
}
}
void maTranslator::writeUnits(fstream& f)
{
args += " -l " + result;
else
args += " -a " + result;
else
args += " -t " + result;
else
if (args != "")
{
f <<
"currentUnit" << args.
asChar() <<
";" << endl;
}
}
void maTranslator::writeDagNodes(fstream& f)
{
fParentingRequired.clear();
{
if (dagNodeFn.isFlagSet(fCreateFlag))
{
continue;
}
if (dagNodeFn.isDefaultNode()) continue;
if (!dagNodeFn.canBeWritten() && !dagNodeFn.isShared())
{
dagNodeFn.setFlag(fCreateFlag, true);
continue;
}
unsigned int numParents = dagNodeFn.parentCount();
if (dagNodeFn.isFromReferencedFile())
{
unsigned int i;
for (i = 0; i < numParents; i++)
{
MObject altParent = dagNodeFn.parent(i);
if (!altParentFn.isFromReferencedFile()
&& (altParentFn.object() != worldPath.
node()))
{
fParentingRequired.append(path);
break;
}
}
}
else
{
{
parentPath = path;
{
}
}
if (parentNodeFn.isFromReferencedFile())
{
unsigned i;
for (i = 0; i < numParents; i++)
{
if (dagNodeFn.parent(i) != parentNodeFn.object())
{
MObject altParent = dagNodeFn.parent(i);
if (!altParentFn.isFromReferencedFile()
&& !altParentFn.isFlagSet(fCreateFlag))
{
break;
}
}
}
if (i < numParents) continue;
writeCreateNode(f, path, worldPath);
fParentingRequired.append(path);
}
else
{
writeCreateNode(f, path, parentPath);
unsigned int i;
bool hasRefParents = false;
bool hasOtherNonRefParents = false;
for (i = 0; i < numParents; i++)
{
if (dagNodeFn.parent(i) != parentNodeFn.object())
{
MObject altParent = dagNodeFn.parent(i);
if (altParentFn.isFromReferencedFile())
hasRefParents = true;
else
hasOtherNonRefParents = true;
if (hasRefParents && hasOtherNonRefParents) break;
}
}
if (hasRefParents) fParentingRequired.append(path);
if (hasOtherNonRefParents)
{
fInstanceChildren.append(path);
fInstanceParents.append(parentPath);
}
}
writeNodeAttrs(f, path.
node(),
true);
writeLockNode(f, path.
node());
}
dagNodeFn.setFlag(fCreateFlag, true);
}
writeInstances(f);
}
void maTranslator::writeInstances(fstream& f)
{
unsigned int numInstancedNodes = fInstanceChildren.length();
unsigned int i;
for (i = 0; i < numInstancedNodes; i++)
{
unsigned int numParents = nodeFn.parentCount();
unsigned int p;
for (p = 0; p < numParents; p++)
{
if (nodeFn.parent(i) != fInstanceParents[i].node())
{
if (!parentFn.isFromReferencedFile())
{
writeParent(f, parentPath, fInstanceChildren[i], true);
}
}
}
}
fInstanceChildren.clear();
fInstanceParents.clear();
}
void maTranslator::writeParent(
)
{
f << "parent -s -nc -r ";
if (addIt) f << "-a ";
if (parent.
length() == 0) f <<
"-w ";
f << ";" << endl;
}
void maTranslator::writeNonDagNodes(fstream& f)
{
{
if (nodeFn.isDefaultNode())
{
fDefaultNodes.append(node);
}
else if (!nodeFn.isFromReferencedFile()
&& !nodeFn.isFlagSet(fCreateFlag))
{
if (nodeFn.canBeWritten() || nodeFn.isShared())
{
writeCreateNode(f, node);
writeNodeAttrs(f, node, true);
writeLockNode(f, node);
}
nodeFn.setFlag(fCreateFlag, true);
nodeFn.setFlag(fAttrFlag, true);
}
}
}
void maTranslator::writeDefaultNodes(fstream& f)
{
unsigned int numNodes = fDefaultNodes.length();
unsigned int i;
for (i = 0; i < numNodes; i++)
{
writeNodeAttrs(f, fDefaultNodes[i], false);
nodeFn.setFlag(fAttrFlag, true);
}
}
void maTranslator::writeNodeAttrs(
fstream& f,
const MObject& node,
bool isSelected
)
{
if (nodeFn.canBeWritten())
{
getAddAttrCmds(node, addAttrCmds);
getSetAttrCmds(node, setAttrCmds);
unsigned int numAddAttrCmds = addAttrCmds.
length();
unsigned int numSetAttrCmds = setAttrCmds.
length();
if (numAddAttrCmds + numSetAttrCmds > 0)
{
if (!isSelected) writeSelectNode(f, node);
unsigned int i;
for (i = 0; i < numAddAttrCmds; i++)
f << addAttrCmds[i].asChar() << endl;
for (i = 0; i < numSetAttrCmds; i++)
f << setAttrCmds[i].asChar() << endl;
}
}
}
void maTranslator::writeReferenceNodes(fstream& f)
{
writeRefNodeParenting(f);
{
if (nodeFn.isFromReferencedFile()
&& !nodeFn.isFlagSet(fAttrFlag))
{
writeNodeAttrs(f, node, false);
node, fBrokenConnSrcs, fBrokenConnDests, true, true
);
nodeFn.setFlag(fAttrFlag, true);
}
}
{
if (nodeFn.isFromReferencedFile()
&& !nodeFn.isFlagSet(fAttrFlag))
{
writeNodeAttrs(f, node, false);
node, fBrokenConnSrcs, fBrokenConnDests, true, true
);
nodeFn.setFlag(fAttrFlag, true);
}
}
}
void maTranslator::writeConnections(fstream& f)
{
writeBrokenRefConnections(f);
{
if (!dagNodeFn.isFlagSet(fConnectionFlag)
&& dagNodeFn.canBeWritten()
&& !dagNodeFn.isDefaultNode())
{
dagNodeFn.setFlag(fConnectionFlag, true);
}
}
{
if (!nodeFn.isFlagSet(fConnectionFlag)
&& nodeFn.canBeWritten()
&& !nodeFn.isDefaultNode())
{
writeNodeConnections(f, nodeIter.
thisNode());
nodeFn.
setFlag(fConnectionFlag,
true);
}
}
unsigned int numNodes = fDefaultNodes.length();
unsigned int i;
for (i = 0; i < numNodes; i++)
{
if (!nodeFn.isFlagSet(fConnectionFlag)
&& nodeFn.canBeWritten()
&& nodeFn.isDefaultNode())
{
writeNodeConnections(f, fDefaultNodes[i]);
nodeFn.setFlag(fConnectionFlag, true);
}
}
}
void maTranslator::writeBrokenRefConnections(fstream& f)
{
unsigned int numBrokenConnections = fBrokenConnSrcs.length();
unsigned int i;
for (i = 0; i < numBrokenConnections; i++)
{
f << "disconnectAttr \""
<< fBrokenConnSrcs[i].partialName(true).asChar()
<< "\" \""
<< fBrokenConnDests[i].partialName(true).asChar()
<< "\"";
MObject attr = fBrokenConnDests[i].attribute();
if (!attrFn.indexMatters()) f << " -na";
f << ";" << endl;
}
}
void maTranslator::writeNodeConnections(fstream& f,
const MObject& node)
{
nodeFn.getConnections(plugs);
unsigned int numBrokenConns = fBrokenConnSrcs.
length();
unsigned int numPlugs = plugs.
length();
unsigned int i;
for (i = 0; i < numPlugs; i++)
{
MPlug destPlug = plugs[i];
{
MObject srcNode = srcPlug[0].node();
if (!srcNodeFn.canBeWritten()) continue;
if (srcNodeFn.isDefaultNode() && nodeFn.isShared()) continue;
f << "connectAttr \"";
if (srcNodeFn.isDefaultNode()) f << ":";
f << srcPlug[0].partialName(true).asChar()
<< "\" \"";
if (nodeFn.isDefaultNode()) f << ":";
<< "\"";
if (srcNodeFn.isFromReferencedFile())
{
unsigned int j;
for (j = 0; j < numBrokenConns; j++)
{
if (fBrokenConnSrcs[j] == srcPlug[0])
{
f << " -rd \""
<< fBrokenConnDests[j].partialName(true).asChar()
<< "\"";
break;
}
}
}
if (!attrFn.indexMatters()) f << " -na";
f << ";" << endl;
}
}
}
void maTranslator::writeCreateNode(
)
{
f << "createNode " << nodeFn.typeName().asChar();
if (nodeFn.isShared()) f << " -s";
f << " -n \"" << nodeFn.name().asChar() << "\"";
f << ";" << endl;
}
void maTranslator::writeCreateNode(fstream& f,
const MObject& node)
{
f << "createNode " << nodeFn.typeName().asChar();
if (nodeFn.isShared()) f << " -s";
f << " -n \"" << nodeFn.name().asChar() << "\";" << endl;
}
void maTranslator::writeLockNode(fstream& f,
const MObject& node)
{
if (nodeFn.isLocked()) f << "lockNode;" << endl;
}
void maTranslator::writeSelectNode(fstream& f,
const MObject& node)
{
if (nodeFn.hasUniqueName())
nodeName = nodeFn.name();
else
{
if (!status)
{
+ "' has a non-unique name but claimes to not be a DAG node.\n"
+ "Using non-unique name."
);
nodeName = nodeFn.name();
}
else
nodeName = dagNodeFn.partialPathName();
}
f << "select -ne ";
if (nodeFn.isDefaultNode()) f << ":";
f << nodeName.
asChar() <<
";\n";
}
void maTranslator::writeRefNodeParenting(fstream& f)
{
unsigned int numNodes = fParentingRequired.length();
unsigned int i;
for (i = 0; i < numNodes; i++)
{
bool hasRefParents = false;
bool hasNonRefParents = false;
unsigned int numParents = nodeFn.parentCount();
unsigned int p;
for (p = 0; p < numParents; p++)
{
if (parentFn.isFromReferencedFile())
hasRefParents = true;
else
hasNonRefParents = true;
if (hasRefParents && hasNonRefParents) break;
}
bool alreadyHasFirstParent =
(nodeFn.isFromReferencedFile() ? hasRefParents : hasNonRefParents);
for (p = 0; p < numParents; p++)
{
if (parentFn.isFromReferencedFile() != nodeFn.isFromReferencedFile())
{
writeParent(
f, parentPath, fParentingRequired[i], alreadyHasFirstParent
);
alreadyHasFirstParent = true;
}
}
}
}
void maTranslator::writeFooter(fstream& f,
const MString& fileName)
{
f << comment(
" End of ").asChar() << fileName.
asChar() << endl;
}
{
unsigned int numAttrs = nodeFn.attributeCount();
unsigned int i;
for (i = 0; i < numAttrs; i++)
{
MObject attr = nodeFn.reorderedAttribute(i);
if (nodeFn.isNewAttribute(attr))
{
attrFn.parent(&status);
if (status == MS::kNotFound)
{
if (status)
{
cAttrFn.getAddAttrCmds(newCmds);
unsigned int numCommands = newCmds.
length();
unsigned int c;
for (c = 0; c < numCommands; c++)
{
if (newCmds[c] != "")
}
}
else
{
MString newCmd = attrFn.getAddAttrCmd();
if (newCmd !=
"") cmds.
append(newCmd);
}
}
}
}
}
{
unsigned int numAttrs = nodeFn.attributeCount();
unsigned int i;
for (i = 0; i < numAttrs; i++)
{
MObject attr = nodeFn.reorderedAttribute(i);
attrFn.parent(&status);
bool isChild = (status != MS::kNotFound);
if (!isChild && attrFn.isStorable() && attrFn.isWritable())
{
unsigned int numCommands = newCmds.
length();
unsigned int c;
for (c = 0; c < numCommands; c++)
{
if (newCmds[c] != "")
}
}
}
}
)
{
return MS::kNotImplemented;
}
{
result += text;
return result;
}
{
const char* cstr = str.
asChar();
int i;
for (i = 0; i < strLen; i++)
{
int c = cstr[i];
if (isprint(c))
{
switch (c)
{
case '"':
result += "\\\"";
break;
case '\\':
result += "\\\\";
break;
default:
result +=
MString((
const char*)&c, 1);
break;
}
}
else
{
switch (c)
{
case '\n':
result += "\\n";
break;
case '\t':
result += "\\t";
break;
case '\b':
result += "\\b";
break;
case '\r':
result += "\\r";
break;
case '\f':
result += "\\f";
break;
case '\v':
result += "\\v";
break;
case '\007':
result += "\\a";
break;
default:
{
char buff[5];
sprintf(buff, "\\%.3o", c);
}
}
}
}
result += "\"";
return result;
}
{
MFnPlugin plugin(obj, PLUGIN_COMPANY,
"1.0",
"Any");
maTranslator::setPluginName(plugin.name());
plugin.registerFileTranslator(
maTranslator::translatorName(),
NULL,
maTranslator::creator,
NULL,
NULL,
false
);
return MS::kSuccess;
}
{
plugin.deregisterFileTranslator(maTranslator::translatorName());
return MS::kSuccess;
}