Pose library: fix asset creation operator poll when no object active
[blender-addons.git] / space_view3d_pie_menus / __init__.py
bloba1f761b5f3fedbecd9b2ff2fcf83fb4c7fd56904
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # Contributed to by meta-androcto, pitiwazou, chromoly, italic, kc98
5 import bpy
6 from bpy.props import (
7 BoolProperty,
8 PointerProperty,
10 from bpy.types import (
11 PropertyGroup,
12 AddonPreferences,
16 bl_info = {
17 "name": "3D Viewport Pie Menus",
18 "author": "meta-androcto",
19 "version": (1, 3, 0),
20 "blender": (2, 80, 0),
21 "description": "Pie Menu Activation",
22 "location": "Addons Preferences",
23 "warning": "",
24 "doc_url": "{BLENDER_MANUAL_URL}/addons/interface/viewport_pies.html",
25 "category": "Interface"
28 sub_modules_names = (
29 "pie_modes_menu",
30 "pie_views_numpad_menu",
31 "pie_sculpt_menu",
32 "pie_origin",
33 "pie_manipulator_menu",
34 "pie_shading_menu",
35 "pie_align_menu",
36 "pie_delete_menu",
37 "pie_apply_transform_menu",
38 "pie_select_menu",
39 "pie_animation_menu",
40 "pie_save_open_menu",
41 "pie_editor_switch_menu",
42 "pie_defaults_menu",
43 "pie_proportional_menu",
47 sub_modules = [__import__(__package__ + "." + submod, {}, {}, submod) for submod in sub_modules_names]
48 sub_modules.sort(key=lambda mod: (mod.bl_info['category'], mod.bl_info['name']))
51 def _get_pref_class(mod):
52 import inspect
54 for obj in vars(mod).values():
55 if inspect.isclass(obj) and issubclass(obj, PropertyGroup):
56 if hasattr(obj, 'bl_idname') and obj.bl_idname == mod.__name__:
57 return obj
60 def get_addon_preferences(name=''):
61 """Acquisition and registration"""
62 addons = bpy.context.preferences.addons
63 if __name__ not in addons: # wm.read_factory_settings()
64 return None
65 addon_prefs = addons[__name__].preferences
66 if name:
67 if not hasattr(addon_prefs, name):
68 for mod in sub_modules:
69 if mod.__name__.split('.')[-1] == name:
70 cls = _get_pref_class(mod)
71 if cls:
72 prop = PointerProperty(type=cls)
73 create_property(PIEToolsPreferences, name, prop)
74 bpy.utils.unregister_class(PIEToolsPreferences)
75 bpy.utils.register_class(PIEToolsPreferences)
76 return getattr(addon_prefs, name, None)
77 else:
78 return addon_prefs
81 def create_property(cls, name, prop):
82 if not hasattr(cls, '__annotations__'):
83 cls.__annotations__ = dict()
84 cls.__annotations__[name] = prop
87 def register_submodule(mod):
88 mod.register()
89 mod.__addon_enabled__ = True
92 def unregister_submodule(mod):
93 if mod.__addon_enabled__:
94 mod.unregister()
95 mod.__addon_enabled__ = False
97 prefs = get_addon_preferences()
98 name = mod.__name__.split('.')[-1]
99 if hasattr(PIEToolsPreferences, name):
100 delattr(PIEToolsPreferences, name)
101 if prefs:
102 bpy.utils.unregister_class(PIEToolsPreferences)
103 bpy.utils.register_class(PIEToolsPreferences)
104 if name in prefs:
105 del prefs[name]
108 class PIEToolsPreferences(AddonPreferences):
109 bl_idname = __name__
111 def draw(self, context):
112 layout = self.layout
114 for mod in sub_modules:
115 mod_name = mod.__name__.split('.')[-1]
116 info = mod.bl_info
117 column = layout.column()
118 box = column.box()
120 # first stage
121 expand = getattr(self, 'show_expanded_' + mod_name)
122 icon = 'TRIA_DOWN' if expand else 'TRIA_RIGHT'
123 col = box.column()
124 row = col.row()
125 sub = row.row()
126 sub.context_pointer_set('addon_prefs', self)
127 op = sub.operator('wm.context_toggle', text='', icon=icon,
128 emboss=False)
129 op.data_path = 'addon_prefs.show_expanded_' + mod_name
130 sub.label(text='{}: {}'.format(info['category'], info['name']))
131 sub = row.row()
132 sub.alignment = 'RIGHT'
133 if info.get('warning'):
134 sub.label(text='', icon='ERROR')
135 sub.prop(self, 'use_' + mod_name, text='')
137 # The second stage
138 if expand:
139 if info.get('description'):
140 split = col.row().split(factor=0.15)
141 split.label(text='Description:')
142 split.label(text=info['description'])
143 if info.get('location'):
144 split = col.row().split(factor=0.15)
145 split.label(text='Location:')
146 split.label(text=info['location'])
148 if info.get('author'):
149 split = col.row().split(factor=0.15)
150 split.label(text='Author:')
151 split.label(text=info['author'])
153 if info.get('version'):
154 split = col.row().split(factor=0.15)
155 split.label(text='Version:')
156 split.label(text='.'.join(str(x) for x in info['version']),
157 translate=False)
158 if info.get('warning'):
159 split = col.row().split(factor=0.15)
160 split.label(text='Warning:')
161 split.label(text=' ' + info['warning'], icon='ERROR')
163 tot_row = int(bool(info.get('doc_url')))
164 if tot_row:
165 split = col.row().split(factor=0.15)
166 split.label(text='Internet:')
167 if info.get('doc_url'):
168 op = split.operator('wm.url_open',
169 text='Documentation', icon='HELP')
170 op.url = info.get('doc_url')
171 for i in range(4 - tot_row):
172 split.separator()
174 # Details and settings
175 if getattr(self, 'use_' + mod_name):
176 prefs = get_addon_preferences(mod_name)
178 if prefs and hasattr(prefs, 'draw'):
179 box = box.column()
180 prefs.layout = box
181 try:
182 prefs.draw(context)
183 except:
184 import traceback
185 traceback.print_exc()
186 box.label(text='Error (see console)', icon='ERROR')
187 del prefs.layout
189 row = layout.row()
190 row.label(text="End of Pie Menu Activations", icon="FILE_PARENT")
193 for mod in sub_modules:
194 info = mod.bl_info
195 mod_name = mod.__name__.split('.')[-1]
197 def gen_update(mod):
198 def update(self, context):
199 enabled = getattr(self, 'use_' + mod.__name__.split('.')[-1])
200 if enabled:
201 register_submodule(mod)
202 else:
203 unregister_submodule(mod)
204 mod.__addon_enabled__ = enabled
205 return update
207 create_property(
208 PIEToolsPreferences,
209 'use_' + mod_name,
210 BoolProperty(
211 name=info['name'],
212 description=info.get('description', ''),
213 update=gen_update(mod),
214 default=True,
217 create_property(
218 PIEToolsPreferences,
219 'show_expanded_' + mod_name,
220 BoolProperty())
223 classes = (
224 PIEToolsPreferences,
228 def register():
229 for cls in classes:
230 bpy.utils.register_class(cls)
232 prefs = get_addon_preferences()
233 for mod in sub_modules:
234 if not hasattr(mod, '__addon_enabled__'):
235 mod.__addon_enabled__ = False
236 name = mod.__name__.split('.')[-1]
237 if getattr(prefs, 'use_' + name):
238 register_submodule(mod)
241 def unregister():
242 for mod in sub_modules:
243 if mod.__addon_enabled__:
244 unregister_submodule(mod)
246 for cls in reversed(classes):
247 bpy.utils.unregister_class(cls)
250 if __name__ == "__main__":
251 register()