I've written a script and am trying to turn it into an addon. I've been trying to copy an existing addon which is working, but for some reason my variation isn't working.
I've created a directory that has an __init__.py in the root describing the addon and my script file in a subdirectory called ops. I then zip it into a zipfile. I then start a new Blender session, open the Preferences menu and install my addon. Everything seems to go well and I get the message
Modules Installed () from 'D:\\dev\\testDeploy\\modalDrawOperator.zip' into 'C:\\Users\\kitfox\\AppData\\Roaming\\Blender Foundation\\Blender\\2.91\\scripts\\addons'
However, my addon isn't then added to the list of the available addons. Why is this failing?
__init__.py:
bl_info = {
"name": "Normal Tool",
"description": "Run the example modal draw operator.",
"author": "Test",
"version": (1, 0),
"blender": (2, 80, 0),
"location": "View3D",
"category": "Generic"
}
if "bpy" in locals():
import importlib
if "modalDrawOperator" in locals():
importlib.reload(modalDrawOperator)
else:
from .ops import modalDrawOperator
import bpy
def register():
modalDrawOperator.register()
def unregister():
modalDrawOperator.unregister()
ops/modalDrawOperator.py:
(this is just copied from the examples in the script templates)
import bpy
import bgl
import blf
import gpu
from gpu_extras.batch import batch_for_shader
def draw_callback_px(self, context):
print("mouse points", len(self.mouse_path))
font_id = 0 # XXX, need to find out how best to get this.
# draw some text
blf.position(font_id, 15, 30, 0)
blf.size(font_id, 20, 72)
blf.draw(font_id, "Hello Word " + str(len(self.mouse_path)))
# 50% alpha, 2 pixel width line
shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
bgl.glEnable(bgl.GL_BLEND)
bgl.glLineWidth(2)
batch = batch_for_shader(shader, 'LINE_STRIP', {"pos": self.mouse_path})
shader.bind()
shader.uniform_float("color", (0.0, 0.0, 0.0, 0.5))
batch.draw(shader)
# restore opengl defaults
bgl.glLineWidth(1)
bgl.glDisable(bgl.GL_BLEND)
class ModalDrawOperator(bpy.types.Operator):
"""Draw a line with the mouse"""
bl_idname = "view3d.modal_operator"
bl_label = "Simple Modal View3D Operator"
def modal(self, context, event):
context.area.tag_redraw()
if event.type == 'MOUSEMOVE':
self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
elif event.type == 'LEFTMOUSE':
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'FINISHED'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.area.type == 'VIEW_3D':
# the arguments we pass the the callback
args = (self, context)
# Add the region OpenGL drawing callback
# draw in view space with 'POST_VIEW' and 'PRE_VIEW'
self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
self.mouse_path = []
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "View3D not found, cannot run operator")
return {'CANCELLED'}
def register():
bpy.utils.register_class(ModalDrawOperator)
def unregister():
bpy.utils.unregister_class(ModalDrawOperator)
if name == "main":
register()