Hey, i’ve recently started trying to work with multiple files after finding my one long script was becoming too hard to edit. I understand that it requires one main file (init) to import all the other ‘modules’, but apart from that i feel kind of lost on how i should be designing a multi-file script. The information on the BlenderWiki seems out of date as that solution didn’t work for me, and the Python wiki felt rather confusing, and didn’t seem to have much relevant information that applied directly to scripting Blender Plugins - i’ve had to use something like this to have the plugin successfully load:
from .update import *
from .user_interface import *
from .set_data import *
from .draw_stroke import *
from .edit_data import *
from .export_data import *
Using this, the UI loads and everything seems fine, but pretty much all the functions don’t work, as each module has lots of references to operators from other modules, or variables from init. Although I think the variables aren’t having any issues, despite including the above code format for importing modules into other modules, one module can’t find operators in another. How do other people structure their multi-file plugins?
(heres my current code in-case anyone wants to look at it - Download)
Thanks a lot for the info, this and your add-on has really cleared up how I need to organise it. I was aware the mass importing of classes from another file was frowned upon, but it was for testing purposes so I didn’t have to worry about using the right names before getting the multi-file script to work properly.
I’m currently having one more issue though that seems really odd. Ive listed the modules I need to register and unregister like this:
I don’t think you need that if statement theinit.py is going to call those register statements directly. But I have never seen that classes error before so I am not sure what to think…
I removed the if statement, but it didn’t change anything. As soon as this error occurs if I try to load the plugin again it just says that it fails, with no specific reason as to why it failed loading the module. I have to restart Blender at that point to check for the error again. Damn -.-
if "bpy" in locals():
import imp
imp.reload(mesh_bump)
imp.reload(face_inset_fillet)
imp.reload(mesh_bevel_witold)
imp.reload(mesh_filletplus)
imp.reload(mesh_normal_smooth)
imp.reload(mesh_polyredux)
imp.reload(mesh_vertex_chamfer)
imp.reload(mesh_mextrude_plus)
else:
from . import mesh_bump
from . import face_inset_fillet
from . import mesh_bevel_witold
from . import mesh_filletplus
from . import mesh_normal_smooth
from . import mesh_polyredux
from . import mesh_vertex_chamfer
from . import mesh_mextrude_plus
import bpy
then
# Define "Extras" menu
def menu_func(self, context):
self.layout.menu('VIEW3D_MT_edit_mesh_extras', icon='PLUGIN')
def register():
bpy.utils.register_module(__name__)
# Add "Extras" menu to the "Add Mesh" menu
bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_func)
def unregister():
bpy.utils.unregister_module(__name__)
# Remove "Extras" menu from the "Add Mesh" menu.
bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_func)
if __name__ == "__main__":
register()
although this works too:
# register the class
def register():
bpy.utils.register_module(__name__)
pass
def unregister():
bpy.utils.unregister_module(__name__)
pass
if __name__ == "__main__":
register()
I’ve also now tried clearing all of Blender’s files stored in the Application Library folder (on Mac OS X) to ensure nothing was conflicting with the plugin by accident, and it hasn’t changed the issue.
I’ll link the files here (Download). I tried using your suggestion too, but it also didn’t solve the initial bug i encountered, and the imp package is pending deprecation which is why i tried using Linusy’s code.
I had look deeper look, for some reason bpy.utils.register_module doesn’t work used like this. However if you use bpy.utils.register_class it does work, but then you need to make list of classes to register, silly but the editor does for me so… It would be nice to know why register_module fails in this scenario, maybe because the name is package.file ?
import importlib
modules = [ "properties", "user_interface",
"draw_stroke", "export_data", "events"]
imported_modules = []
if "bpy" in locals():
for im in imported_modules:
importlib.reload(im)
else:
for m in modules:
im = importlib.import_module(".{}".format(m), __package__)
imported_modules.append(im)
import bpy
def register():
for im in imported_modules:
if hasattr(im, 'register'):
im.register()
def unregister():
for im in imported_modules:
if hasattr(im, 'unregister'):
im.unregister()
I removed some import * also.
The addon might not work as this, but it does register.
Oh awesome Linusy, thanks! It does seem strange that it wouldn’t work, I honestly have no idea why it wouldn’t. This is extremely helpful though, I can finally start adding more features
Yeah, I see what you’ve done. I was honestly hoping id be able to avoid needing to import classes individually, but at least it works. The UI is broken, but it likely just needs some loose ends tied up from moving to a multi-file setup. tysm!
I hope somebody can shed a light on why register_module doesn’t work used like this, that class thing is really ugly… I have no clue right now.
I meant more that you should look at init.py
In terms of finding the root cause or the code you edited? I did check out and it now makes sense, ^^. The only other thing I’m currently having trouble with is refreshing the script inside Blender, as I edit it outside, as it doesn’t seem to respond at all, but it’s probably something stupid i’m doing with the setup e_e.