Having trouble creating an Addon with multiple modules

I'm trying to put together an add-on that contains two operators. I've gotten each operator file to run properly independently, but I'm having trouble figuring out how to write an init.py file that would allow me to distribute them as a single add-on.

I've posted everything on Github. The three files aren't too long: https://github.com/blackears/blenderStairs/tree/master/src

I've read a few other threads, but nothing seems to work for me. How can I get my init.py to register my operators properly?

The add-on registration can be simplified using a register() and unregister() function per file that can be called by the __init__.py. You've already implemented these to test your operators, but they can be used for the full add-on as well. Therefore all you have to do is import the kitfoxStairs.py and kitfoxStairsCurved.py and then call their register() function in the __init__.py.

# Copyright 2019 Mark McKay
#
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#
# Unless required by applicable law or agreed to in writing, software
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and

bl_info = {
"name": "Curved Stairs Mesh Generator",
"description": "Adds new mesh builders for quickly creating staircases.",
"author": "Mark McKay",
"version": (1, 0),
"blender": (2, 80, 0),
"location": "View3D > Add > Mesh",
"wiki_url": "https://github.com/blackears/blenderStairs",
"tracker_url": "https://github.com/blackears/blenderStairs",
"support": "COMMUNITY",
}

import bpy
from .operators import kitfoxStairs
from .operators import kitfoxStairsCurved

def register():
kitfoxStairs.register()
kitfoxStairsCurved.register()

def unregister():
kitfoxStairs.unregister()
kitfoxStairsCurved.unregister()


If you want to reload modifications of your scripts when they have been imported before, then you need to replace the import statements

import bpy
from .operators import kitfoxStairs
from .operators import kitfoxStairsCurved


with the following code:

if "bpy" in locals():
import importlib
if "kitfoxStairs" in locals():
if "kitfoxStairsCurved" in locals():
else:
from .operators import kitfoxStairs
from .operators import kitfoxStairsCurved

import bpy


Scripts can be reloaded through F3 > Reload Scripts. Blender 2.8x doesn't have the F8 shortcut anymore, but you can add it to your keymap. Since Blender 2.83 this feature is available via the top bar menu Blender Icon > System > Reload Scripts.

Note: I've removed the if __name__ == "__main__": from the __init__.py since this doesn't work with relative imports.

There is an error in the menu_func of kitfoxStairsCurved.py. It should reference the AddStairsCurved class instead of AddStairs. The correct function is:

def menu_func(self, context):

• I've made the changes you suggested, but my module is still not loading. Worse, it seems to be failing silently without any meaningful error messages. I've pushed my updates to the repository. Nov 22 '19 at 13:25
• @kitfox works fine for me. Have you installed the add-on by zipping the src folder and then installing it through Edit > Preferences > Add-ons? Nov 22 '19 at 13:27
• I was trying to run it by trying to install the [code]__init__.py[/code] file as an addon. Zipping it first seemed to work. Is there a way to run it in an unzipped state? Also, what the best directory structure within the zip? Nov 22 '19 at 13:33
• If you don't want to .zip it, you could also create a new directory, e.g. kitfox, where Blender's add-ons are stored [blender version]/scripts/addons (replace the x with the actual version, e.g. 2.81) and copy the __init__.py and the modules into kitfox (or however you called the directory). Nov 22 '19 at 14:29

Basically for an addon, import as a module, call the modules register method to enable.

The folder your addon is in is the module name, eg mesh_stairs

The operators you have in the operators folder already have a register and unregister method. Can from ./operators import foo and in register call foo.register() (as answered by @RJG while I was dawdling along)

mesh_stairs/
__init__.py
operators/
__init__.py
foo.py
bar.py


Here is a method I played around with for bat_tools to manage a number of "addons" into one. Enabling / disabling addons for workspaces has prompted somewhat of a rethink.

Pretty generic. Using __all__ and globals. Could load any list or dict etc instead.

Script: mesh_stairs/operators/__init__.py

"""
BATTOOLS edit re stairs q.
"""

__all__ = []

def register_tools():
""" """
for name in __all__:
register_tool(globals()[name])

def register_tool(tool):
"""

:param tool:

"""
print("REGTOOLS", tool)
tool.register()

def unregister_tools():
""" """
for name in __all__:
unregister_tool(globals()[name])

def unregister_tool(tool):
"""

:param tool:

"""
print("UNREGTOOLS", tool)
tool.unregister()

""" """
__all__.clear()
import pkgutil

for m in pkgutil.iter_modules(__path__):
tool = __import__(m.name, globals(), level=1)
__all__.append(m.name)



Print in system console after enabling addon.

REGTOOLS <module 'mesh_stairs.operators.kitfoxStairs' from '/home/batfinger/.config/blender/2.82/scripts/addons/mesh_stairs/operators/kitfoxStairs.py'>


Script: mesh_stairs/__init__.py

bl_info = {
"name": "Curved Stairs Mesh Generator",
"description": "Adds new mesh builders for quickly creating staircases.",
"author": "Mark McKay",
"version": (1, 0),
"blender": (2, 80, 0),
"location": "View3D > Add > Mesh",
#    "warning": "", # used for warning icon and text in addons panel
"wiki_url": "https://github.com/blackears/blenderStairs",
"tracker_url": "https://github.com/blackears/blenderStairs",
"support": "COMMUNITY",