The following examples demonstrate the usage of file translators.
The polyExporter class inherits from MPxFileTranslator and defines a number of virtual methods such as writer().
class polyExporter:public MPxFileTranslator { public: polyExporter(); virtual ~polyExporter(); virtual MStatus writer (const MFileObject& file, const MString& optionsString, MPxFileTranslator::FileAccessMode mode); virtual bool haveWriteMethod () const; virtual bool haveReadMethod () const; virtual bool canBeOpened () const; virtual MString defaultExtension () const = 0; protected: virtual bool isVisible(MFnDagNode& fnDag, MStatus& status); virtual MStatus exportAll(ostream& os); virtual MStatus exportSelection(ostream& os); virtual void writeHeader(ostream& os); virtual void writeFooter(ostream& os); virtual MStatus processPolyMesh(const MDagPath dagPath, ostream& os); virtual polyWriter* createPolyWriter(const MDagPath dagPath, MStatus& status) = 0; };
You need to register the new File Translator with MFnPlugin when initializing the plug-in. There are six arguments associated with the registerFileTranslator method. The latter three arguments are optional.
In this example, the argument Rawtext is the file translator name. The option1=1 argument contains the default value of the options strings for the option box for the translator. The last argument is of boolean type that determines the ability for a translator to execute MEL scripts within the translator. A true value of this argument allows the MEL commands be executed through the MGlobal::executeCommand method.
MStatus initializePlugin(MObject obj) { MStatus status; MFnPlugin plugin(obj, "Autodesk", "4.5", "Any"); status = plugin.registerFileTranslator("RawText", "", polyRawExporter::creator, "", "option1=1", true); if (!status) { status.perror("registerFileTranslator"); return status; } return status; }
Removing the translator is done in the uninitializePlugin() through a call to the deregisterFileTranslator() method of MFnPlugin.
MStatus uninitializePlugin(MObject obj) { MStatus status; MFnPlugin plugin( obj ); status = plugin.deregisterFileTranslator("RawText"); if (!status) { status.perror("deregisterFileTranslator"); return status; } return status; }
You need to implement a reader() method if you wish to load a file type that is supported by your file translator.
The haveReadMethod() method checks if the translator provides a read method. In the LepTranslator class, the method returns true because the reader() method exists.
bool LepTranslator::haveReadMethod () const { return true; }
The reader() method reads each line of the file and returns a MS::kFailure if it cannot be opened by the translator. If a file type cannot be recognized by the translator, the method creates a new object via MEL to support the data in that file.
MStatus LepTranslator::reader ( const MFileObject& file, const MString& options, MPxFileTranslator::FileAccessMode mode) { #if defined (OSMac_) char nameBuffer[MAXPATHLEN]; strcpy (nameBuffer, file.fullName().asChar()); const MString fname(nameBuffer); #else const MString fname = file.fullName(); #endif MStatus rval(MS::kSuccess); const int maxLineSize = 1024; char buf[maxLineSize]; ifstream inputfile(fname.asChar(), ios::in); if (!inputfile) { // open failed cerr << fname << ": could not be opened for reading\n"; return MS::kFailure; } if (!inputfile.getline (buf, maxLineSize)) { cerr << "file " << fname << " contained no lines ... aborting\n"; return MS::kFailure; } if (0 != strncmp(buf, magic.asChar(), magic.length())) { cerr << "first line of file " << fname; cerr << " did not contain " << magic.asChar() << " ... aborting\n"; return MS::kFailure; } while (inputfile.getline (buf, maxLineSize)) { //processing each line of the file MString cmdString; cmdString.set(buf); if (!MGlobal::executeCommand(cmdString)) rval = MS::kFailure; } inputfile.close(); return rval; }
Lines of files are processed in order to add new objects to the model.
You need to include a writer() method if you want to save a file type that is supported by your translator.
The haveWriteMethod() method checks if the translator has a write method. In the polyExporter class, the method returns true because the writer() method is implemented.
bool polyExporter::haveWriteMethod() const { return true; }
The writer() method provides a message through the script editor and returns a status to indicate the results.
In this example, only ‘export all’ and ‘export selection’ options are allowed when trying to save data. Other options will result in the display of a failure message through the script editor and returns a MS:kFailure, which indicates that the file type cannot be understood by the translator. For your plug-in, you will have to set your own identifier string. If the method is successful, the data will be saved as a new file in a file type that is supported by the translator.
MStatus polyExporter::writer(const MFileObject& file, const MString& /*options*/, MPxFileTranslator::FileAccessMode mode) { #if defined (OSMac_) char nameBuffer[MAXPATHLEN]; strcpy (nameBuffer, file.fullName().asChar()); const MString fileName(nameBuffer); #else const MString fileName = file.fullName(); #endif ofstream newFile(fileName.asChar(), ios::out); if (!newFile) { MGlobal::displayError(fileName + ": could not be opened for reading"); return MS::kFailure; } newFile.setf(ios::unitbuf); writeHeader(newFile); if (MPxFileTranslator::kExportAccessMode == mode) { if (MStatus::kFailure == exportAll(newFile)) { return MStatus::kFailure; } } else if (MPxFileTranslator::kExportActiveAccessMode == mode) { if (MStatus::kFailure == exportSelection(newFile)) { return MStatus::kFailure; } } else { return MStatus::kFailure; } writeFooter(newFile); newFile.flush(); newFile.close(); MGlobal::displayInfo("Export to " + fileName + " successful!"); return MS::kSuccess; }
This method is typically used to check if the file extension of the file in question is the correct file type for the translator.
When a file is encountered, Maya calls the identifyFile() method and queries each translator until it finds an appropriate match. The method is given an MFileObject indicating the file being checked and a pointer name to the initial file contents. In this example below, any file types being passed to this method other than .anim will result in MS::kNotMyFileType being returned, which indicates that the translator cannot understand the file type. Otherwise, the file is understood by the translator and is able to operate in Maya through the translator plug-in.
MPxFileTranslator::MFileKind animExportUtil::identifyFile ( const MFileObject &file, const char * /*buffer*/, short /*size*/ ) const { const char *name = file.name().asChar(); int nameLength = (int)strlen(name); if ((nameLength > 5) && !strcasecmp(name+nameLength-5, ".anim")) { return (kIsMyFileType); } return (kNotMyFileType); }
The defaultExtension() method defines the default file extension of a translator and returns a string.
In this example, Maya calls the method and saves the file with a .raw file extension. Note that the period should not be included in the extension name.
The fileAccessMode() is an enum method that returns the type of file access mode that Maya is currently in. There are six types of file access modes in Maya.
In this example, the mode is kImportAccessMode, which is when Maya imports data into the scene.
if (mode == kImportAccessMode) { status = importAnim(animFile, pasteFlags); }