チュートリアル / 読んで触ってよくわかる!Mayaを使いこなす為のAtoZ
第90回:Mayaのファイルパス解決のルール
- Maya
- ゲーム
- コラム
- スクリプト・API
- チュートリアル
- 学生・初心者
- 映画・TV
ファイルリファレンスにしてもテクスチャにしても、ファイルパスが指定した場所から変わってしまうことがあります。
パスを修正するフリーのツールや「Windows > General Editors > File Path Editor」を使っていつでも修正できますが、そもそもなぜパスが変わってしまうのか、気になりませんか?
今回はMayaがどのようにファイルパスを解決しているかご紹介します。
ファイルパス解決のルール
今は昔、Maya 2009でパスの解決方法や順序が変更されています。2009以降では次のように解決しています。
1)パスの完全一致を試す。
2)ディレクトリマップを使用した場合を試す。(dirmapを使用している場合。dirmapの説明は後ほど)
3)リファレンスマッピングを試す。(リファレンスが見つからないときに出るダイアログで指定したパスをチェック)
4)プロジェクトからの相対パスとして試す。(パスにスラッシュが二つ「//」のところがあれば、そこ区切った後ろ側が相対パス)
5)ベースネームだけで一致を試す。(ファイル名だけ抜き出し、プロジェクト内でファイル種類に応じた場所を見に行く。)
6)…。
…というようなルールです。
ドキュメントのどこにも書いてない気がしますが、どこにも書いてないです。多分。
さっきコードを見て確認したので今も変わりないはずですが、動きが違うようだったら教えてください。コッソリと。
ここで重要なのは「絶対パスが優先される」という事実なのです。
プロジェクトを設定してシーンを開いても、プロジェクト内のファイルを見に行くのは4段階目のチェックなのです。
このルールだと、次のようなことが起こりがちです。
問題が起こるパターン:プロジェクトのコピー
次のような操作はよく行われることだと思いますが、知らず知らずのうちにパスが入れ替わってしまいます。
1)プロジェクトをセットして、シーンを作成します。
2)プロジェクト内のテクスチャ・リファレンスを指定すると、保存したファイルには「//(\\)」の記述がある絶対パスが保存されます。
例:D:/myProject//sourceimages/tekito.png
この「//」の手前までが現在のプロジェクトまでのパス、後ろが相対パスということです。
3)プロジェクトを別の場所に「コピー」します。
4)コピー先を現在のプロジェクトをとして設定。シーンを開きます。
シーンを開く時に次のようにパスが解決されます。
・絶対パスとして、ファイルが有るか確認を始める。(1)
→ プロジェクトをコピーしたので、元々の場所に依然としてファイルが存在する。
→ 絶対パス先にファイルが有る。
→ 現在のプロジェクト外のファイルのため、絶対パスとして保存される。(//が削除される)(2)
例:D:/myProject/sourceimages/tekito.png
以後、絶対パスとなってしまう。相対パスに戻せない…。
この時もし、コピーではなく移動していれば、次のような挙動となり問題は起きません。
・絶対パス先を見に行っても、ファイルが存在しない。(移動しているため)(1)
・次の段階として、相対パスの場所を見に行く。
→ プロジェクト内にファイルを見つける。(2)
以後も相対パスのままとなる。
もしシーンを開けば、コピー先のプロジェクトのパスとして相対パスになります。(下の図ではprojA//a.pngがprojB//a.pngになります。)
ファイルサーバーにプロジェクトをコピーしてアップロードする時も、ローカルドライブにテクスチャやリファレンスのファイルが残っている時は注意が必要です。
コピーしたシーンを開かなければ、パスが書き換わることもないので問題ないです。
が、「ちょっと手直しが必要なので、アップロードしたシーンを直接開いて編集しちゃえ。てへっ。」とかやると、ローカルのファイルへのパスが、絶対パスに変換されてしまいます。そして他の人が開くと、「ファイルが見つからない」となります。
まあ、結局のところ確実なのは、次のように作業することです。
・ プロジェクトは必ず移動にする。(→ちょっと嫌だ。)
・ コピーしたプロジェクトは開かず、元のプロジェクトを開いて編集する。
・ Maya ASCIIで保存しておいて、何かツールでしっかり相対パスとして書き換える。(ふつうにテキストの置き換えをします。)
例:D:/testProj//sourceimages/tekito.pngという文字列を見つけて、sourceimages/tekito.pngにする。
ファイルリファレンスは相対パスをサポートしていないので(動いている気もしなくもないですが)、「$myPath」という感じで環境変数を設定して、それでどうにかします。
詳しくは「ファイル リファレンス用にファイルを管理する > ファイル パス」
https://help.autodesk.com/view/MAYAUL/2022/JPN/?guid=GUID-7BF2FD1A-3521-4292-89C2-2D388B686F7F
パスを変えるために、ファイル保存後のコールバックを設定する
プログラムを書けるなら、シーンを保存した後にコードを実行できますので、そのタイミングでファイルを書き換える方法があります。
MSceneMessage::addCallbackでkAfterSave(File > Save(Save As)実行後)としてコールバックを設定します。
保存後のmaに対して、パスを検索して相対パス化します。
たとえば次の様に、保存後にコールバックを呼んで、新しいファイル名を取得することが出来ます。
import maya.cmds as cmds
import maya.OpenMaya as OM
def convertPathCallback(*args):
filePath = cmds.file(q=1, expandName=1)
print ('Saved to:', filePath)
# filePathのファイルを開いて、何らかの文字列変換の処理を行う。ここでは割愛してます。。。
id = OM.MSceneMessage.addCallback(OM.MSceneMessage.kAfterSave, convertPathCallback)
#OM.MMessage.removeCallback(id)
dirmapコマンドの使い方と影響
dirmapコマンドを使うと、特定のパスを別のパスにマッピング出来ます。
指定する元パス、新しいパスはどちらも絶対パスで指定します。フォルダは「/」で区切る必要があります。
プロジェクトを移動する、または全く違う環境に持っていくときに、パスを指定し直すのに利用できます。
シーンを開くときにdirmapの設定が使用され、新しいパスにマッピングされます。
そのシーンを保存すると新しいパスで保存されるため、以後はdirmapを使わなくても大丈夫です。
常にdirmapを有効にするには、userSetup.melなどで毎回設定するようにします。
たとえば次のように実行します。
dirmap -m "D:/user1/projectA/textures" "D:/user2/projectB/textures";
次に、dirmapを有効にしてからパスを指定すると、新しいパスにマッピングされた文字列が返ります。
dirmap -en true;
dirmap -convertDirectory "D:/user1/projectA/textures/character/skin.psd";
// Result: D:/user2/projectB/textures/character/skin.psd //
この設定は、Mayaがパスの解決をする際に使用されます。
パスの指定に//が影響します。
もし保存してあるパスに//が含まれているようでしたら、マッピング対象のパスにも//を含めるようにします。
dirmap -en true;
dirmap -m "D:/user1/project//sourceimages" "D:/project/sourceimages";
dirmap -convertDirectory "D:/user1/project//sourceimages/grass.tga";
// Result: D:/project/sourceimages/grass.tga //
filePathEditorコマンドの使い方
filePathEditorコマンドを使うと、シーン内のノードに設定してあるファイルパスを簡単に操作出来ます。
// 今開いているシーンで使っているテクスチャやリファレンスファイルの参照先のディレクトリをリストにして照会します。
string $dirs[] = `filePathEditor -q -listDirectories ""`;
// Result: D:/samples/relativePathTest/sceneSample/scenes D:/samples/relativePathTest/sceneSample/sourceimages //
// 指定したディレクトリ内で、シーンで使っているファイルがあれば、そのファイル名とアトリビュート名を返します。
string $list[] = `filePathEditor -q -withAttribute -listFiles $dirs[0]`;
// Result: noise.tga file1.fileTextureName //
// 指定したアトリビュートのパスを書き変えます。-repathで指定したパスに置き換えます。
// 相対パスを指定する場合は、-fで強制的にパスを変更するようにします。
// -previewでプレビューモードとして実行します。パス書き換え後にファイルが存在するかどうか確認します。
string $test[] = `filePathEditor -preview -f -repath "sourceimages/" $list[1]`;
if ( $test[1] ){
filePathEditor -f -repath "sourceimage/" $list[1];
print("Repath as relative path:" + $list[1] + "\n");
}
まとめ
いかがでしょうか?Mayaでのパスの解決方法はこんな感じになっています。
挙動がわかれば対処もやりやすくなると思いますので、ぜひ参考にしてください。
朗報!Maya 2022.4、Maya 2023 以降の仕様が相対パスに優しくなりました!!
「絶対ファイル パスの前に相対ファイル パスを解決する新しい optionVar」として、ファイル パスの解決方法をコントロールする 2 つの新しい optionVars が用意されています。
詳しくはヘルプドキュメントをご確認下さい。
https://help.autodesk.com/view/MAYAUL/2022/JPN/?guid=Maya_ReleaseNotes_2022_4_release_notes_html
簡単に説明すると、次のオプションを設定すると、パス解決の方法が変更されます。
optionVar -q fileResolverResolveExactAfterRelative; // default 0.
optionVar -q fileResolverStrictRelativePaths; // default 0.
// プロジェクトからの相対パスでテストして、あとから絶対パスでテスト。
optionVar -iv fileResolverResolveExactAfterRelative 1;
// プロジェクトからの相対パスのテストのみ行う。絶対パスのところにファイルがあっても、見つからないという扱い。
optionVar -iv fileResolverStrictRelativePaths 1;