Mayaの拡張機能開発における Mac / Windows の差異

この記事は [Maya アドベントカレンダー 2018](https://qiita.com/advent-calendar/2018/maya) 7日目の記事です。

さて、大抵の Maya 開発の現場では、Windows 環境に統一されて業務が行われているかと思います。自分は長らく Mac でプログラムをしてきたのと、その他いろいろな都合で Maya （を含む3D関連の仕事全般） の業務を Mac で行っています。しかし、拡張機能の開発時には、余計なトラブルを防ぐためにも基本的には Mac は切り捨ててしまって、 Windows のみ対応する仕様としてしまうのが良いとは思っています。結局動作検証で Windowsマシン は使いますし。 

そんな感じではありますが、世の中のどこかで需要があるかもしれないので、せっかく知見を得た Maya での Mac (クロスプラットフォーム) 拡張機能開発時に注意すべき点、および関連するその他tips、を、ここにまとめたいと思います。Mac よりも Linuxでの作注意点の方が需要があるかもしれませんね。

※ 下記内容は主に Maya2017 で確認した内容に基づくものです。 あまり検証されていませんが、Maya2015 / Maya2018 でも同じ挙動ではあるようです。

## mel の文字コードが違う
まず立ちはだかるのはこれです。Windows では shift-jis、Mac では utf8 が期待される文字コードです。異なった文字コードで mel プログラムを動作させた場合、文字化けを起こすだけならまだよく、windows で utf8 の mel コードを実行した場合、scriptの読込時にランタイムエラーになったりします。これに対して自分が取っている解決策は、作成した拡張機能の提供前に`シェルスクリプトで文字コード変換をかける`、です。nkf や iconv を使っています。

下記はnkfを使った変換シェルスクリプト (bash) の例です。

```bash
# Windows 用に mel コード を shift-jis に変換する
find . -type f -name "*.mel" -exec nkf -s --overwrite {} \;
```

```bash
# mac 用に mel コード を utf8 に変換する
find . -type f -name "*.mel" -exec nkf -w --overwrite {} \;
```

## python コードの文字コードは utf8 で統一可能
python コードにおいては、文字コードを utf8 で統一させる事ができます。今後 python3 への移行する事も踏まえ、コードの先頭で

```python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division
```
このような宣言をしてしまうのが良いかと思います。 (`unicode_literals` のインポート以降は文字コードとは関係ないですが。)

ここで、一つ注意すべき点があります。python コードから mel コードを実行するような場合です。

```python
pm.mel.eval('print("こんにちわ ");')
```

このようなコードがランタイムエラーになってしまう事があるので、(UTF8コードとして mel が実行されてしまう)、日本語文字列は mel 側に記述する、そもそも日本語を使わないなどの対応が必要になります。shift-jis で python を記述するという回避方法もあるかもしれませんが、自分は試したことはないです。逆も然りで、mel から python の呼び出し時にも日本語文字列に注意が必要です。

## 改行コードが違う
改行コードは Mac の LF と Windows の CRLF で差異があります。しかし、これは特に問題を起こさないようなので、自分としては特に対応は入れていません。(上記の mel 文字コードのコンバート時に合わせて改行コードの変換をかけることは可能です。)また、ファイルごとに改行コードが混在しても平気です。
python / mel 共に、プログラム中で改行を扱う場合は `\n` (LF)を使います。これで Mac / Windows 共に改行が出力されます。

## ma ファイルの文字コードが異なる
mel と同様に　Maya ascii 形式の保存ファイルも文字コードの問題を起こします。UTF8 で保存された ma ファイルは  Windowsで読み込み時にランタイムエラーになります。対応方法としては Maya バイナリで保存する、日本語を使わない、maファイルも文字コード変換をかける、になります。自分はできる限りバイナリ形式で保存をするようにしています。（TA業務 では ascii 形式の方が扱いやすいのですが。）

## ユーザディレクトリの場所が異なる
Windows では `マイドキュメント/maya/` 以下に様々なファイルが保存されますが、Mac ではこれが２箇所に分散します。シーンファイルやレンダリング結果などは、Windows と似たように `ドキュメント/maya/`以下に保存されますが、env など設定ファイルは `/Users/ユーザー名/Library/Preferences/Autodesk/maya/` という位置に保存されています。手作業で何かする場合も、プログラムで扱う場合も混乱しがちです。
 
## パスの区切り文字が違う
Windows では `\`、Mac では`/`です。Pythonの標準モジュールには、os.path モジュールがあり、これを利用すると OS が利用する適切な区切り文字を使ってくれて安心、、だと思っていましたが罠がありました。QT5 (PySide２) の ダイアログでユーザがディレクトリを選択した場合など、OS 設定のものとは異なる区切り文字でパスが取得できる事がありました。気にせずパス文字列操作を行なっていると、２つのパス区切文字が混ざってしまったりします。解決策としては、Maya では `/` 
 の区切り文字を Windows でも扱ってくれるので、パス文字列を使う直前（およびパス文字列取得時）に `\` を全て `/` に置換するのが一番楽ではないかなと思います。

## PySide の挙動が違う
PySide2(最近さらに QT for pythonに名前が変わったとか？)での話です。Qt/PySide は、マルチプラットフォーム対応したUI キットなので、どの OS でもほぼ同じ挙動を取ることを期待していたのですが、実際はそうでもないようです。特に目立ったのは、ウィンドウの前面/背面の制御周りです。QT で作ったウィンドウが Maya ウィンドウの背面に入らないよう、`MayaQWidgetDockableMixin` を継承したり `siboken` を利用したりするのは広く行われている対応かと思いますが、自分が試した限りは両者の対応とも Mac では無効でした。同じコードを Windows で動かすと、正しくウインドウが前面に表示されるようになりますが、Mac では背面に入ったままです。ちょっと記憶が怪しいですが、最大化の挙動も異なる部分があったように思います。 その他、細かい挙動ずれを修正する努力も行いましたが、なかなか費用対効果に合わず捕手も難しくなってしまうので、QT の UI に関しては Windows で使いやすい状態である事を担保すれば、その他は気にせずともよし、というスタンスで製作する事にしました。この辺りは Maya のバージョンや PySideのバージョンでだいぶ変わりそうですね。

なお、自分の制作では、PySide/ PySide2 の差異を吸収するため、[Qt.py](https://github.com/mottosso/Qt.py) を利用しています。こちらのバージョンによっても挙動が変わるかもしれません。

# まとめ
まだあったかもしれませんが、まとめきる前にカレンダーの担当日になってしまいました。とはいえ大きな所はこんなものだと思います。プログラマ側の都合でいえば、できる限り日本語は使わない方が良いです。しかし作成した拡張機能の利用者側が英語表記を嫌う場合もあるので難しい所ですね。（なお、この記事にはまとめませんが、自分の制作物では表示言語の多国籍対応も行なっています。これを行うと python コード上からは日本語を締め出すことができます。)

以上、どこかでこの記事が役に立つことがあれば幸いです。

＃ 明日の投稿は sho7noka さんの `Maya らしい マイクロインタラクション でツールを作る` です。楽しみですね！（遅れて更新らしいです）