既存のメニューを消してアドオンAのメニューを追加しつつ、同様のメニュークラスにappendで寄生している別アドオンBを保持する方法を紹介する。
もくじ
既存のメニューに追加する
def register(): bpy.types.VIEWLAYER_PT_layer.append(viewlayer_list_menu) def unregister(): bpy.types.VIEWLAYER_PT_layer.remove(viewlayer_list_menu)
追加したい既存のメニュークラス名に、"append"により自分のメニューを追加することができる。
prependで前に追加・apendで後に追加。
この場合は、既存のメニューはそのまま。単純に機能追加するアドオンであればこれでよい。
既存のメニューを置き換える
既存のメニューレイアウトを改善するようなアドオンは、既存のメニューを完全に置き換えたくなる。
bpy.types.CLASS名.draw = 置き換えたいメニュー関数
上記の方法より、すべての既存メニューを自分のメニューに置き換えることができる。
既存のメニューを戻せるように保持しておく
アドオンを無効化時に元のメニューに戻すことができるように、bpy.types.CLASS名.drawを代入して保持しておくとよい。
登録解除時に、同じように~.drawに保持しておいたメニューを代入する。
def update_viewlayer_list(self, context): try: prefs = bpy.context.preferences.addons[__name__.partition('.')[0]].preferences if prefs.use_viewlayer_list: bpy.types.VIEWLAYER_PT_layer.draw = viewlayer_list_menu else: bpy.types.VIEWLAYER_PT_layer.draw = keep_VIEWLAYER_PT_layer except: pass keep_VIEWLAYER_PT_layer = bpy.types.VIEWLAYER_PT_layer.draw def register(): update_viewlayer_list(None, bpy.context) def unregister(): try: bpy.types.VIEWLAYER_PT_layer.draw = keep_VIEWLAYER_PT_layer except: pass
他アドオンのメニューをそのままにする
既存のメニューを完全に置き換える方法では、同じメニュークラスにappendなどで登録している他のアドオンBのメニューまで消えてしまう。
競合したアドオンが自分のアドオンであれば、隠しプロパティをアドオンBの方に追加することで解決できる。
アドオンBに隠しプロパティを追加
アドオンB側にプロパティを追加し、updateでメニュー追加を実行する隠し機能を作っておく。
# アドオンB def update_vl_append_menu(self, context): bpy.types.VIEWLAYER_PT_layer.append(draw_buildenode_menu) class BUILDENODE_AddonPreferences(AddonPreferences): bl_idname = __name__ update_vl_append_menu : BoolProperty(update=update_vl_append_menu)
アドオンA側に、上記のプロパティを切り替える処理を追加する
メニューを空にする処理をした後に、上記で作ったプロパティを切り替えれば、そのメニューを保持することができる。
def update_viewlayer_list(self, context): try: prefs = bpy.context.preferences.addons[__name__.partition('.')[0]].preferences if prefs.use_viewlayer_list: bpy.types.VIEWLAYER_PT_layer.draw = viewlayer_list_menu if "build_export_node" in bpy.context.preferences.addons: bui_prefs = bpy.context.preferences.addons["build_export_node"].preferences bui_prefs.update_vl_append_menu = bool(not bui_prefs.update_vl_append_menu) else: bpy.types.VIEWLAYER_PT_layer.draw = keep_VIEWLAYER_PT_layer except: pass
その他
アドオンの登録順番は操作することができず、よって処理順番を操作することが難しい。
このような競合に対しては、再実行して上書きするような例外処理を作る他なさそう。