Substance 3D Painterにメニューを追加する

## 環境
* Windows
* Adobe Substance 3D Painter 10.1.2

## メニューを追加する

メニューを追加する方法として、ここではスタートアッププラグインで追加する方法を紹介します。

## スタートアッププラグインの配置先

プラグインの配置場所について説明します。
ユーザー用のプラグインのディレクトリのデフォルトの場所は下記になります。

```%USERPROFILE%\Documents\Adobe\Adobe Substance 3D Painter\python```

また環境変数 ```SUBSTANCE_PAINTER_PLUGINS_PATH``` を使用することで、任意のディレクトリをプラグインの検索パスに追加できます。

プラグインディレクトリについては3つのサブディレクトリ ```plugins```、```startup```、```modules``` があり、```startup``` ディレクトリに配置されたファイルはスタートアッププラグイン (起動時に読み込まれるプラグイン) として認識されます。
(サブディレクトリの詳細については [substance_painter_plugins](https://helpx.adobe.com/substance-3d-painter-python/api/plugins/substance-painter-plugins.html) に記載がありますので、そちらを参照してください。)


## スタートアッププラグインの記述方法

[Hello Plugin](https://helpx.adobe.com/substance-3d-painter-python/api/plugins/hello-plugin.html) のサンプルを例に説明します。

重要なのは下記3点です。
* start_plugin 関数
* close_plugin 関数
* エントリーポイント

### start_plugin 関数

プラグイン起動時に呼び出される関数です。この関数に起動時に実行したい処理を記述します。

### close_plugin 関数

プラグイン停止時に呼び出される関数です。Hello Pluginの例では追加されたウィジェットをクリーンアップする処理が記述されています。

### エントリーポイント

エントリーポイントで start_plugin 関数を呼び出します。

## プラグインのサンプル

### サンプルコード

以下のコードは説明のわかりやすさを重視したものです。コーディングのベストプラクティスを示したものではありませんのでご注意ください。

```python
from PySide6 import QtGui, QtWidgets

import substance_painter as sp

plugin_widgets = []


class SampleMenu(QtWidgets.QMenu):
    def __init__(self, title):
        super().__init__(title)

        action1 = QtGui.QAction("Action1", self)
        action1.triggered.connect(self.callback_action1)
        self.addAction(action1)

        action2 = QtGui.QAction("Action2", self)
        action2.triggered.connect(self.callback_action2)
        self.addAction(action2)

    def callback_action1(self):
        print("Action1")

    def callback_action2(self):
        print("Action2")


def start_plugin():
    menu = SampleMenu("Sample")
    sp.ui.add_menu(menu)
    plugin_widgets.append(menu)


def close_plugin():
    for widget in plugin_widgets:
        sp.ui.delete_ui_element(widget)
    plugin_widgets.clear()


if __name__ == "__main__":
    start_plugin()
```


![sp_menu_00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965005/8d0ca6e5-c513-4815-b277-5cfa9aca6777.jpeg)


### 説明

サンプルコードでポイントとなるのは ```start_plugin``` 関数で呼び出している ```ui.add_menu``` 関数のみです。
```ui.add_menu``` 関数は指定したメニューをメインウインドウに追加する関数で、引数として [PySide6.QtWidgets.QMenu](https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QMenu.html) を指定するだけでメニューを追加することができます。
サブメニューやコールバック関数の追加に関しては Qt for Python で実装するやり方と違いはありません。
ウィジェットのクリーンアップの処理については先に触れた [Hello Plugin](https://helpx.adobe.com/substance-3d-painter-python/api/plugins/hello-plugin.html) を参考に実装してください。


## 参考

* [Substance 3D Painter Python API](https://helpx.adobe.com/substance-3d-painter-python.html)
* [Environment variables](https://helpx.adobe.com/substance-3d-painter/pipeline-and-integration/configuration/environment-variables.html)
* [substance_painter_plugins](https://helpx.adobe.com/substance-3d-painter-python/api/plugins/substance-painter-plugins.html)
* [Hello Plugin](https://helpx.adobe.com/substance-3d-painter-python/api/plugins/hello-plugin.html)
* [ui module](https://helpx.adobe.com/substance-3d-painter-python/api/substance-painter/ui.html)
* [PySide6.QtWidgets.QMenu](https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QMenu.html)