Blender2.8以降で消えたメニュー項目を復活させる

この記事はQiita版 Blender Advent Calendar 2020の空欄になっていた３日の記事を埋める記事として投稿します
https://qiita.com/advent-calendar/2020/blender

-----------------------------
2020年はBlender2.8の最初の長期サポート版が出たこともあって
Blender2.7系から2.8以降への移行が進んだ年でした。

Blender2.8以降では機能自体は変わっていないものの、
メニューの表示位置が移動したものがいくつかあります。

例えば編集モードの　辺メニューや面メニューの一部もそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/904b677e-482f-0d3f-7854-a13c8a261eb6.png)
2.79では 辺メニューの***辺ループ***や***辺リング***等の選択関連　面メニューの***法線***関連が重複してメニューにあったのが
2.80以降では　それぞれ選択メニュー　ノーマルメニュー　内のみになって辺メニューや面メニューから消えています
スッキリしたのはいいのですが　***ショートカット主体で覚えている人***には煩雑になりました

そこで　アドオン機能を使って　メニュー内に項目を復活させたいと思います
## サンプルアドオン
まずはサンプルコードから

```py:y_add_menu_item.py
bl_info = {
    "name": "add menu item",
    "author": "y",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "View3D ",
    "description": "2.8で整理されたメニューを追加する",
    "warning": "",
    "support": "COMMUNITY",
    "wiki_url": "",
    "tracker_url": "",
    "category": "User Interface"
}
import bpy
# 辺メニューの追加項目
def draw_edge_item(self, context):
    layout = self.layout
    layout.separator() # 区切り線
    # 辺ループを選択
    layout.operator("mesh.loop_multi_select", text="Edge Loops").ring = False
    # 辺リングを選択
    layout.operator("mesh.loop_multi_select", text="Edge Rings").ring = True
# 面メニューの追加項目
def draw_face_item(self, context):
    layout = self.layout
    layout.separator() # 区切り線
    #反転
    layout.operator("mesh.flip_normals", text="Flip")
def register():
    # 辺メニューに項目を追加
    bpy.types.VIEW3D_MT_edit_mesh_edges.append(draw_edge_item)
    # 面メニューに項目を追加
    bpy.types.VIEW3D_MT_edit_mesh_faces.append(draw_face_item)

def unregister():
    # 辺メニューから項目を削除
    bpy.types.VIEW3D_MT_edit_mesh_edges.remove(draw_edge_item)
    # 面メニューから項目を削除
    bpy.types.VIEW3D_MT_edit_mesh_faces.remove(draw_face_item)

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

辺メニューの***辺ループ***　***辺リング***　の選択　と　面メニューの***反転***をメニューに追加します


ファイルに保存して、プリファレンスのアドオンの項目のインストールからファイルを指定して読み込みます。
サポートレベルをTEESTINGにしているので　上のタブで***テスト中***を選択しないと一覧には出ないので注意してください。


## 自分好みの項目を追加する手順
サンプルの項目に限らず　メニュー項目を好みのメニューに追加したいという場合があるでしょうから
手順を解説しておきます。

まず　プリファレンスの***開発者用オプション***をオンにして　ワークスペースを***Scripting***に変更しておきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/3ebf8d0f-fc40-a24a-28b6-84bf4f6a0dc4.png)
Blenderのメニューやパネルのレイアウトに関わる部分はPythonで記述されています。
このPythonコードを見ることで　メニューの描画のコマンド等を調べることができます

開発者用オプションがオンの状態でメニュー項目等を右クリックすると「ソースを編集」という項目が追加されていて
実行すると　テキストエディッタ上にUIを設定するPyhtonファイルのクリック項目の行が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/35e10bb5-f352-9850-4e83-2dbfc95f47c4.png)
（ワークスペース上にテキストエディッタがない状態だとエラーが出るだけです）


今回の場合　***メッシュ***の***エディットモード***の***メッシュ***メニューのソースを表示させてみました
フォーカスのある行では　メニューを描画するためのクラスが呼び出されているのですが
```layout.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower())```
となっていて　ちょっと何が何だか分からないですね

これは編集中のオブジェクトによってメニューの項目を変化させるようになっています
（今の場合　オブジェクトのタイプは'MESH'でこの場合.lower() で小文字の'mesh'の文字列にしています）
とりあえず　ファイル内の　VIEW3D_MT_edit_　で始まるクラスを検索してみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/661ae59c-facd-b6a2-b8a1-1e82dd0edced.png)
今回のコードでは3559行目から　メニューの内容を描画するクラスでdraw()関数に処理が書かれているようです
実際のメニューのキャプチャーと比べてみると、例えば
```layout.menu("VIEW3D_MT_transform")```
は***トランスフォーム***のサブメニューを表示されるもののようです

今回は　***ノーマル***のサブメニューの内容を使いたいので
VIEW3D_MT_edit_mesh_normals のクラスをさらに探せばよさそうです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/c4c5048e-a02f-d3d0-1761-724bf4b21157.png)
今回欲しかったのは***反転***のみだったので
```layout.operator("mesh.flip_normals", text="Flip")```
の部分だけでよさそうです

後はサンプルのように　クラスのdraw()関数と同様の描画を指定する関数を作って
登録したいメニュー項目のクラスに　描画の関数を.append()するだけです。

もし　自分好みにメニュー項目を追加したいと思った時には　この方法も試してみてください