#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;
                    FileAccessMode mode
                );
                    FileAccessMode mode
                );
    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))
    
    
    
    
    
    
    
    if (status)
    if (status)
    if (!status)
    {
            "Could not allocate three free node flags."
            "  Try unloading some other plugins."
        );
    }
    
    
    
    {
        nodeFn.setFlag(fCreateFlag, false);
        nodeFn.setFlag(fAttrFlag, false);
        nodeFn.setFlag(fConnectionFlag, false);
    }
    
    
    
    writeHeader(output, file.
name());
    writeFileInfo(output);
    writeReferences(output);
    writeRequirements(output);
    writeUnits(output);
    writeDagNodes(output);
    writeNonDagNodes(output);
    writeDefaultNodes(output);
    writeReferenceNodes(output);
    writeConnections(output);
    writeFooter(output, file.
name());
    output.close();
}
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())
        {
            writeNodeConnections(f, dagIter.
item());
            dagNodeFn.setFlag(fConnectionFlag, true);
        }
    }
    
    
    
    {
        if (!nodeFn.isFlagSet(fConnectionFlag)
        &&  nodeFn.canBeWritten()
        &&  !nodeFn.isDefaultNode())
        {
            writeNodeConnections(f, nodeIter.
item());
            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)
                {
                    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);
        
        
        
        
        
        
        if (!isChild && attrFn.isStorable() && attrFn.isWritable())
        {
            
            
            
            
            
            
            
            unsigned int    numCommands = newCmds.
length();
 
            unsigned int    c;
            for (c = 0; c < numCommands; c++)
            {
                if (newCmds[c] != "")
            }
        }
    }
}
)
{
}
{
    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
    );
}
{
    plugin.deregisterFileTranslator(maTranslator::translatorName());
}