次のサンプルは、ファイル トランスレータの使用法を示します。
polyExporter クラスは MPxFileTranslator から派生し、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; };
プラグインを初期化する場合、MFnPlugin を使用して新しいファイル トランスレータを登録する必要があります。registerFileTranslator メソッドには 6 個の引数が関連付けられています。後半 3 つの引数はオプションです。
このサンプルでは、引数 Rawtext がファイル トランスレータ名です。option1=1 引数には、トランスレータのオプション ボックスに使用するオプション文字列の既定値が含まれます。最後の引数はブーリアン型で、トランスレータ内部で MEL スクリプトを実行可能かどうかを定義します。この引数を true 値にすると、MGlobal::executeCommand メソッドを使用して MEL コマンドを実行できます。
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; }
トランスレータの除去は、MFnPlugin の deregisterFileTranslator() メソッドをコールして uninitializePlugin() で実行されます。
MStatus uninitializePlugin(MObject obj) { MStatus status; MFnPlugin plugin( obj ); status = plugin.deregisterFileTranslator("RawText"); if (!status) { status.perror("deregisterFileTranslator"); return status; } return status; }
ファイル トランスレータによってサポートされているファイル タイプをロードする場合は、reader() メソッドを実装する必要があります。
haveReadMethod() メソッドは、トランスレータが read メソッドを提供しているかどうかチェックします。LepTranslator クラス内では、reader() メソッドが存在するためこのメソッドは true を返します。
bool LepTranslator::haveReadMethod () const { return true; }
reader() メソッドはファイルの各ラインを読み取り、トランスレータが開けない場合 MS::kFailure を返します。トランスレータがファイル タイプを認識できない場合、このメソッドはそのファイルのデータをサポートするための新しいオブジェクトを MEL 経由で作成します。
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; }
ファイル トランスレータによってサポートされているファイル タイプを保存する場合は、writer() メソッドを実装する必要があります。
haveWriteMethod() メソッドは、トランスレータに write() メソッドが存在するかどうかチェックします。polyExporter クラス内では、writer() メソッドが実装されているためこのメソッドは true を返します。
bool polyExporter::haveWriteMethod() const { return true; }
writer() メソッドはスクリプト エディタを介してメッセージを提供し、ステータスを返して結果を示します。
このサンプルでは、データの保存時に許可されているのは、すべて書き出し(Export All)オプションと選択項目の書き出し(Export Selection)のみです。その他のオプションでは、スクリプト エディタに失敗メッセージが表示され、トランスレータが該当するファイル タイプを解釈できないことを示す MS:kFailure が返されます。お使いのプラグインで、独自の識別文字列を設定する必要があります。メソッドが成功した場合、トランスレータがサポートしているファイル タイプの新しいファイルとしてデータが保存されます。
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; }
このメソッドは通常、対象のファイルの拡張子がトランスレータにとって正しいものかどうかをチェックするのに使用します。
ファイルが検出されると identifyFile() メソッドがコールされ、適切に一致するトランスレータが見つかるまで各トランスレータが照会されます。このメソッドは、チェック中のファイルを示す MFileObject とファイルの内容の初期値を指すポインタ name を備えています。次の例では、このメソッドに渡された .anim 以外のすべてのファイル タイプに対して MS::kNotMyFileType が返されます。これは、このファイル タイプをトランスレータが解釈できないことを示します。それ以外の場合、ファイルはトランスレータによって解釈され、トランスレータ プラグインを経由して Maya で操作することができます。
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); }