Python + MaxScriptのツール開発入門(Max2020版)その8

2021年9月3日

 前回はツール本体のクラスについて、コンストラクタの実装を行いました。今回はそのシグナルの接続先として指定した実行メソッドを書いていきましょう。

ツール本体のクラスを作る 2

実行メソッドを仮実装する

 コンストラクタのコネクトのところで書いた内容と整合が取れるような名前でメソッドを実装します。もちろん、先にメソッドを書いてから、最後にコンストラクタ内のコネクト処理を追記するという順序で作業しても何ら問題ありません。

 まずは仮の内容で実装しましょう。

    def doGridCopy(self):
        print("doGridCopy")

 こんな感じで、とりあえずメソッド名を出力するだけの内容で実装します。

 今回のツールでは今のところこれしかメソッドが無いので、ひとまずこれだけで構いません。このメソッドを実際に書き込む前に、呼び出し側のコードを書いてしまい、動作をテストできるようにしておきましょう。

呼び出し側の関数を用意する

 GridCopyクラスの実装は一旦置いておき、このクラスを呼び出してツールを起動する部分を先に実装しましょう。これを用意することで、GridCopyクラスのテストが行えるようになります。

 呼び出し側の関数はmainという名前で、GridCopyクラスの実装と同じレベル(インデントが同じレベル)に書きます。ひとまず、GridCopyに渡すためのファイルパスを受け取り、それを出力する関数として実装してみましょう。

class GridCopy(QtWidgets.QDialog, UI.Ui_Dialog):
    def __init__(self, parent, f_path):
        super(GridCopy, self).__init__(parent)
        self.setupUi(self)
        # プロパティ
        self.f_path = f_path
        # シグナルとスロットのコネクト
        self.btn_exec.clicked.connect(self.doGridCopy)
    def doGridCopy(self):
        print("doGridCopy")
def main(f_path):
    print(f_path)

 こんな風になります。main関数を書いた位置に注目してください。GridCopyクラスの定義と同じレベルに書きます。インデントを下げてしまうとGridCopyクラスのメソッドになってしまうので注意してください。

エントリポイントを用意する

 ここでは呼び出しの関数を慣例的にmainという名前で実装していますが、この名前は何でも構いません。C言語のようなエントリポイントは必ずmain()というような決まりはありません。

 逆に、mainという関数を作ってもこれが自動的にエントリポイントにはなりません。そのため、エントリポイント(起動時に実行される関数)として動作させるにはそのような記述を明示的に書く必要があります。

if __name__ == "__main__":
    main(os.path.dirname(os.path.abspath(__file__)))

 こんな風に書きます。main()に渡す引数はケースバイケースです。重要なのはこの条件式です。

__name__という特殊な変数は、このファイルが呼び出された場所を格納しています。Pythonのファイルはそれ自体が実行されるケースのほかに、他のPythonファイルからインポートされる、という使い方をされることもあります。このような、どこから使われたのかを識別するための仕組みとして、__name__という変数が用意されています。

 Pythonのファイルが直接実行された場合(python.exeの引数として渡された場合)には、この__name__の値が"__main__"という文字列になります。このことを利用して、そのファイルが直接実行されたのか、他のファイルからインポートされたのかを判断しているわけです。

 このifブロックの中でmain()を呼ぶことで、main()をエントリポイントとして使うことができるようになります。

 今回は「このPythonファイルの置かれているディレクトリのパス」をmain()に引数として渡しています。main()はその受け取った内容をprintで出力しています。

実行してみる

 ここまでで一度実行してみましょう。

 実行前に動作を想像してみると、

  1. 3dsmax2020からgridCopy.pyファイルを実行する
  2. ファイルを直接実行するのでエントリポイントとしてmain()が呼ばれる
  3. main()は受け取った文字列(gridCopy.pyファイルの置いてあるディレクトリのパス)を表示する

という風になるはずです。では実行してみます。任意のフォルダにgridCopy.pyを保存し、3dsmax2020のスクリプト→スクリプトを起動から実行します。

「スクリプトを起動」のダイアログボックスでは、デフォルトではMaxScriptのファイルしか見えません。Pythonファイルを見るには、「ファイルの種類」のプルダウンからPythonに切り替える必要があります。

 実行すると以下のように、スクリプトリスナーに実行したPythonファイルが入っているフォルダのパスが表示されます。

まとめ

  • ツールクラスの実行メソッドはとりあえず仮の状態で書いておく
  • ツールクラスを呼び出す関数を用意する
  • __name__が"__main__"かどうかを見ることで、そのファイルが直接実行されたかどうかが識別できる
  • __name__が"__main__"の時に任意の関数を呼び出すようにしておくと、その関数が事実上のエントリポイントとして動作するようになる