在 Blender 開發 Addon 時載入自己的 Module
前言
由於需要從 Blender 匯出自製遊戲引擎的格式,所以就需要開發 Addon ,但由於要支援的規格越來越多,所以程式碼就越來越多,全部都塞在一個檔案寫起來並不是很舒服,之前不拆成其它 Module 來載入是因為找不到方法來載入,官方並沒有提供載入 Module 的範例,但最近在 Valve 的 Source 引擎提供給 Blender 的 Addon 裡發現它可以載入自己的 Module ,所以就來研究是如何做的,在此做個紀錄。
內容
Valve 的 Source 引擎提供給 Blender 的 Addon 可以在 [ steamreview.org ] Blender Source Tools 下載。在研究中發現以前從沒想過把 Addon 裝起來跟直接在 Blender 的文字介面有何不同,所以總是在文字介面裡做實驗,所以 Import 自己的 Module 總是會失敗,但我看了 Valve 提供的 Addon ,裡面遽然可以直接 Import 自己的 Module ,本以為事情解決了,但發現一些小毛病!如果在安裝的環境下開發,當程式被修改時, Blender 並不會去 Reload 它,這裡我找到兩種方法來 Reload ,一種是直接用 Blender 的操作介面來 Reload ,如下圖
![]() |
Reload Addon 在 Blender 的介面 |
這個方法很簡潔,但不知為什麼每次 Reload 時會小小的頓一下,所以我個人比較建議第二種方法。第二種方法是利用 Addon 的啟動按鍵來 Reload ,如下圖
![]() |
利用 Addon 的起用來 Reload |
這個方法有個麻煩, 只是單純的利用關閉後再啟用會發現其實它不會被 Relaod ,但如果主程式(__init__.py)的修改日期有變動時,它就會 Reload,這種 Reload 操作會負責一點,但可以確定只 Reload 這個 Addon。解決了不會 Reload 後又發現當自己的 Module 被修改時,也不會 Reload! Reload 似乎只針對主程式(__init__.py),所以需要在主程式增加 Reload 自己的 Module ,這段程式碼我在 Valve 的 Addon 裡找到了如下
# Python doesn't reload package sub-modules at the same time as __init__.py! import importlib, sys for filename in [ f for f in os.listdir(os.path.dirname(os.path.realpath(__file__))) if f.endswith(".py") ]: if filename == os.path.basename(__file__): continue module = sys.modules.get("{}.{}".format(__name__,filename[:-3])) if module: importlib.reload(module) # clear out any scene update funcs hanging around, e.g. after a script reload from bpy.app.handlers import depsgraph_update_pre, depsgraph_update_post for func in depsgraph_update_post: if func.__module__.startswith(__name__): depsgraph_update_post.remove(func)
要在主程式裡加這段才可以 Reload 自己的 Module 。完整的範例程式碼如下
__init__.py
bl_info = { "name": "My export addon", "author": "Hosee", "version": (1, 0, 0), "blender": (2, 80, 0), "category": "Import-Export", "location": "", "wiki_url": "", "tracker_url": "", "description": "My custom export addon." } # import bpy, os from bpy_extras.io_utils import ExportHelper from bpy.props import StringProperty, BoolProperty, EnumProperty from bpy.types import Operator #follow code from Valve # Python doesn't reload package sub-modules at the same time as __init__.py! import importlib, sys for filename in [ f for f in os.listdir(os.path.dirname(os.path.realpath(__file__))) if f.endswith(".py") ]: if filename == os.path.basename(__file__): continue module = sys.modules.get("{}.{}".format(__name__,filename[:-3])) if module: importlib.reload(module) # clear out any scene update funcs hanging around, e.g. after a script reload from bpy.app.handlers import depsgraph_update_pre, depsgraph_update_post for func in depsgraph_update_post: if func.__module__.startswith(__name__): depsgraph_update_post.remove(func) # #import my module from . import utility # class ExportSomeData(Operator, ExportHelper): bl_idname = "export_test.something" bl_label = "Export something" filename_ext = ".txt" filter_glob: StringProperty( default="*.txt", options={'HIDDEN'}, maxlen=255, # Max internal buffer length, longer would be clamped. ) use_setting: BoolProperty( name="Example Boolean", description="Example Tooltip", default=True, ) type: EnumProperty( name="Example Enum", description="Choose between two items", items=( ('OPT_A', "First Option", "Description one"), ('OPT_B', "Second Option", "Description two"), ), default='OPT_A', ) def execute(self, context): utility.do_something() return {"FINISHED"} # Only needed if you want to add into a dynamic menu def menu_func_export(self, context): self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator") def register(): bpy.utils.register_class(ExportSomeData) bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): bpy.utils.unregister_class(ExportSomeData) bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) if __name__ == "__main__": register()
utility.py
def do_something(): print('Do something')
完整的程式碼可以在 [ Gitlab ] basic_export_addon 下載。
雖然照著上述的做法就可以載入自己的 Module ,但還是有些麻煩,如修改後要測試要經過 Reload 才能看到結果,或是修改後如果要搭配版本管理(Version control)時,要把修改的那一份(Blender 安裝的資料夾)複製到版本管理(Version control)才能 Commit ,這些麻煩目前還找不到方法解決,如果解決了會再寫一篇。
參考資料
[ steamreview.org ] Blender Source Tools
沒有留言:
張貼留言