Last active
July 6, 2019 15:14
-
-
Save batFINGER/4eee7c1a03746c65f2611c70a9f2e2ba to your computer and use it in GitHub Desktop.
"addon submodules"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bl_info = { | |
"name": "Example Addon Preferences", | |
"author": "Your Name Here", | |
"version": (1, 0), | |
"blender": (2, 65, 0), | |
"location": "SpaceBar Search -> Addon Preferences Example", | |
"description": "Example Addon", | |
"warning": "", | |
"wiki_url": "", | |
"tracker_url": "", | |
"category": "Object"} | |
sub_modules_names = ( | |
"submod1", | |
"submod2", | |
"submod3", | |
) | |
sub_modules = {submod:__import__(__package__ + "." + submod, {}, {}, submod) for submod in sub_modules_names} | |
#sub_modules.sort(key=lambda mod: (mod.bl_info['category'], mod.bl_info['name'])) | |
def _get_pref_class(mod): | |
import inspect | |
for obj in vars(mod).values(): | |
if inspect.isclass(obj) and issubclass(obj, AddonPreferences): | |
if hasattr(obj, 'bl_idname'):# and obj.bl_idname == mod.__name__: | |
return obj | |
return None | |
import bpy | |
from bpy.types import Operator, AddonPreferences | |
from bpy.props import StringProperty, IntProperty, BoolProperty | |
class OBJECT_OT_addon_prefs_example(Operator): | |
"""Display example preferences""" | |
bl_idname = "object.addon_prefs_example" | |
bl_label = "Addon Preferences Example" | |
bl_options = {'REGISTER', 'UNDO'} | |
def execute(self, context): | |
user_preferences = context.user_preferences | |
addon_prefs = user_preferences.addons[__name__].preferences | |
info = ("Path: %s, Number: %d, Boolean %r" % | |
(addon_prefs.filepath, addon_prefs.number, addon_prefs.boolean)) | |
self.report({'INFO'}, info) | |
print(info) | |
return {'FINISHED'} | |
from bpy.types import PropertyGroup | |
from bpy.props import PointerProperty | |
''' | |
submods = {"submod1": ExampleAddonPreferences, | |
"submod2": ExampleAddonPreferences2} | |
''' | |
def draw_info(module, mod, layout, info, context): | |
colsub = layout # TODO FIX | |
if mod.expand: | |
if info["description"]: | |
split = colsub.row().split(percentage=0.15) | |
split.label(text="Description:") | |
split.label(text=info["description"]) | |
if info["location"]: | |
split = colsub.row().split(percentage=0.15) | |
split.label(text="Location:") | |
split.label(text=info["location"]) | |
if module: | |
split = colsub.row().split(percentage=0.15) | |
split.label(text="File:") | |
split.label(text=module.__file__, translate=False) | |
if info["author"]: | |
split = colsub.row().split(percentage=0.15) | |
split.label(text="Author:") | |
split.label(text=info["author"], translate=False) | |
if info["version"]: | |
split = colsub.row().split(percentage=0.15) | |
split.label(text="Version:") | |
split.label(text='.'.join(str(x) for x in info["version"]), translate=False) | |
if info["warning"]: | |
split = colsub.row().split(percentage=0.15) | |
split.label(text="Warning:") | |
split.label(text=' ' + info["warning"], icon='ERROR') | |
tot_row = bool(info["wiki_url"]) # + bool(user_addon) | |
if tot_row: | |
split = colsub.row().split(percentage=0.15) | |
split.label(text="Internet:") | |
if info["wiki_url"]: | |
split.operator("wm.url_open", text="Documentation", icon='HELP').url = info["wiki_url"] | |
split.operator("wm.url_open", text="Report a Bug", icon='URL').url = info.get( | |
"tracker_url", | |
"https://developer.blender.org/maniphest/task/edit/form/2") | |
def draw(self, context): | |
layout = self.layout | |
for k, module in sub_modules.items(): | |
info = getattr(module, "bl_info", {}) | |
mod = getattr(self, k) | |
box = layout.box() | |
row = box.row(align=True) | |
row.prop(mod, "expand", icon='TRIA_DOWN' if mod.expand else 'TRIA_RIGHT', icon_only=True, emboss=False) | |
row.prop(mod, "enable", icon='CHECKBOX_HLT' if mod.enable else 'CHECKBOX_DEHLT', icon_only=True, emboss=False) | |
sub = row.row() | |
sub.enabled = mod.enable | |
sub.label(info["description"]) | |
if mod.expand: | |
col = box.column() | |
draw_info(module, mod, col, info, context) | |
if mod.enable and mod.expand and mod.has_prefs: | |
box.label("Preferences:") | |
modbox = box.box() | |
mod.layout = modbox | |
mod.draw(context) | |
subaddonprefs = { | |
"bl_idname": "test_module", | |
"draw": draw, | |
} | |
def register_submodule(submod): | |
mod = sub_modules.get(submod) | |
def register(self, context): | |
if mod is None: | |
return None | |
if self.enable: | |
sub_modules[submod].register() | |
print("%s.register()" % submod) | |
else: | |
print("%s.unregister()" % submod) | |
sub_modules[submod].unregister() | |
return None | |
return register | |
classes = [] | |
def create_addon_prefs(): | |
for submod, mod in sub_modules.items(): | |
prefsclass = _get_pref_class(mod) | |
print("XXX", prefsclass) | |
#print("PREFCLASS", prefsclass) | |
props = {} | |
props["enable"] = BoolProperty(update=register_submodule(submod), default=True) | |
props["expand"] = BoolProperty(update=register_submodule(submod), default=False) | |
props["has_prefs"] = prefsclass is not None | |
if prefsclass: | |
props.update({k:v for k,v in vars(prefsclass).items() if not k.startswith("__")}) | |
#props = {"xx": IntProperty()} | |
# enable disable | |
preferences = type("%sPreferences" % submod, (PropertyGroup,), props) | |
#classes.append(preferences) | |
bpy.utils.register_class(preferences) | |
classes.append(preferences) | |
subaddonprefs[submod] = PointerProperty(type=preferences) | |
# ok an addon prefs made up of all the classes. | |
return type("AddonPrefs", (AddonPreferences,), subaddonprefs) | |
# Registration | |
from bpy.app.handlers import persistent | |
@persistent | |
def handle_registration(dummy): | |
print("Register the submodules based on prefs") | |
if dummy: | |
#enable disable addons from prefs | |
addon = bpy.context.user_preferences.addons.get(__name__) | |
print(addon) | |
if addon is None: | |
bpy.app.handlers.scene_update_post.remove(handle_registration) | |
return None | |
prefs = addon.preferences | |
for submod, module in sub_modules.items(): | |
print(prefs) | |
mod = getattr(prefs, submod, None) | |
if not mod: | |
continue | |
if getattr(mod, "enable", False) and hasattr(module, "register"): | |
try: | |
module.register() | |
print("%s.register()" % submod) | |
except RuntimeError: | |
print(RuntimeError) | |
return None | |
bpy.app.handlers.scene_update_post.remove(handle_registration) | |
return None | |
def register(): | |
classes.clear() | |
print("REGISTER") | |
addonprefs = create_addon_prefs() | |
bpy.utils.register_class(OBJECT_OT_addon_prefs_example) | |
try: | |
bpy.utils.register_class(addonprefs) | |
except ValueError: | |
print(ValueError) | |
classes.extend([OBJECT_OT_addon_prefs_example, addonprefs]) | |
print(classes) | |
bpy.app.handlers.scene_update_post.append(handle_registration) | |
#bpy.app.handlers.load_post.append(handle_registration) | |
def unregister(): | |
print("UNREG CLASSES", classes) | |
for cls in classes: | |
print("UNREG", cls, hasattr(cls, "bl_rna")) | |
try: | |
bpy.utils.unregister_class(cls) | |
except RuntimeError: | |
print(RuntimeError) | |
for mod in sub_modules.values(): | |
try: | |
mod.unregister() | |
except RuntimeError: | |
print(RuntimeError) | |
#bpy.app.handlers.load_post.remove(handle_registration) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bl_info = { | |
"name": "Snap Menu: Key: 'Ctrl Shift Tab'", | |
"description": "Snap Modes", | |
"author": "Antony Riakiotakis, Sebastian Koenig", | |
"version": (0, 1, 0), | |
"blender": (2, 77, 0), | |
"location": "Ctrl Shift Tab", | |
"warning": "", | |
"wiki_url": "", | |
"category": "3d View" | |
} | |
import bpy | |
from bpy.types import ( | |
Menu, | |
Operator, | |
AddonPreferences | |
) | |
from bpy.props import * #lazy hack | |
class ExampleAddonPreferences2(AddonPreferences): | |
bl_idname = __name__ | |
filepath = StringProperty( | |
name="Example File Path", | |
subtype='FILE_PATH', | |
) | |
number = IntProperty( | |
name="Example Number", | |
default=4, | |
) | |
boolean = BoolProperty( | |
name="Example Boolean", | |
default=False, | |
) | |
def draw(self, context): | |
layout = self.layout | |
layout.label(text="This is a preferences view for our addon again") | |
layout.prop(self, "filepath") | |
layout.prop(self, "number") | |
layout.prop(self, "boolean") | |
# Pie Snap Mode - . key | |
class VIEW3D_PIE_snap_of(Menu): | |
bl_label = "Snapping" | |
bl_idname = "view3d.snap_of" | |
def draw(self, context): | |
layout = self.layout | |
toolsettings = context.tool_settings | |
pie = layout.menu_pie() | |
pie.prop(toolsettings, "snap_element", expand=True) | |
pie.prop(toolsettings, "use_snap") | |
classes = [ | |
VIEW3D_PIE_snap_of | |
] | |
addon_keymaps = [] | |
def register(): | |
for cls in classes: | |
bpy.utils.register_class(cls) | |
wm = bpy.context.window_manager | |
if wm.keyconfigs.addon: | |
# Align | |
km = wm.keyconfigs.addon.keymaps.new(name='Object Non-modal') | |
kmi = km.keymap_items.new('wm.call_menu_pie', 'TAB', 'PRESS', ctrl=True, shift=True) | |
kmi.properties.name = "view3d.snap_of" | |
addon_keymaps.append((km, kmi)) | |
def unregister(): | |
for cls in classes: | |
print(cls) | |
bpy.utils.unregister_class(cls) | |
wm = bpy.context.window_manager | |
kc = wm.keyconfigs.addon | |
if kc: | |
km = kc.keymaps['Object Non-modal'] | |
for kmi in km.keymap_items: | |
if kmi.idname == 'wm.call_menu_pie': | |
if kmi.properties.name == "view3d.snap_of": | |
km.keymap_items.remove(kmi) | |
if __name__ == "__main__": | |
register() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bl_info = { | |
"name": "Shade Menu: Key: 'Z key'", | |
"description": "View Modes", | |
"author": "Antony Riakiotakis, Sebastian Koenig", | |
"version": (0, 1, 0), | |
"blender": (2, 77, 0), | |
"location": "Z key", | |
"warning": "", | |
"wiki_url": "", | |
"category": "3d View" | |
} | |
import bpy | |
from bpy.types import ( | |
Menu, | |
Operator, | |
AddonPreferences | |
) | |
from bpy.props import * #lazy hack | |
class ExampleAddonPreferences(AddonPreferences): | |
bl_idname = __name__ | |
filepath = StringProperty( | |
name="Example File Path", | |
subtype='FILE_PATH', | |
) | |
number = IntProperty( | |
name="Example Number", | |
default=4, | |
) | |
boolean = BoolProperty( | |
name="Example Boolean", | |
default=False, | |
) | |
def draw(self, context): | |
layout = self.layout | |
layout.label(text="This is a preferences view for our addon") | |
layout.prop(self, "filepath") | |
layout.prop(self, "number") | |
layout.prop(self, "boolean") | |
# Pie Shade Mode - Z | |
class VIEW3D_PIE_shade_of(Menu): | |
bl_label = "Shade" | |
bl_idname = "pie.shade_of" | |
def draw(self, context): | |
layout = self.layout | |
pie = layout.menu_pie() | |
pie.prop(context.space_data, "viewport_shade", expand=True) | |
if context.active_object: | |
if(context.mode == 'EDIT_MESH'): | |
pie.operator("MESH_OT_faces_shade_smooth") | |
pie.operator("MESH_OT_faces_shade_flat") | |
else: | |
pie.operator("OBJECT_OT_shade_smooth") | |
pie.operator("OBJECT_OT_shade_flat") | |
classes = [ | |
VIEW3D_PIE_shade_of, | |
] | |
addon_keymaps = [] | |
def register(): | |
for cls in classes: | |
bpy.utils.register_class(cls) | |
wm = bpy.context.window_manager | |
if wm.keyconfigs.addon: | |
# Align | |
km = wm.keyconfigs.addon.keymaps.new(name='Object Non-modal') | |
kmi = km.keymap_items.new('wm.call_menu_pie', 'Z', 'PRESS') | |
kmi.properties.name = "pie.shade_of" | |
addon_keymaps.append((km, kmi)) | |
def unregister(): | |
for cls in classes: | |
bpy.utils.unregister_class(cls) | |
wm = bpy.context.window_manager | |
kc = wm.keyconfigs.addon | |
if kc: | |
km = kc.keymaps['Object Non-modal'] | |
for kmi in km.keymap_items: | |
if kmi.idname == 'wm.call_menu_pie': | |
if kmi.properties.name == "pie.shade_of": | |
km.keymap_items.remove(kmi) | |
if __name__ == "__main__": | |
register() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Screen shot.