Import images: add file handler
[blender-addons.git] / space_view3d_pie_menus / __init__.py
blob03fa95674bb3dfc80129d36c3af3383db7f4ddeb
1 # SPDX-FileCopyrightText: 2016-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # Contributed to by meta-androcto, pitiwazou, chromoly, italic, kc98
7 import bpy
8 from bpy.props import (
9 BoolProperty,
10 PointerProperty,
12 from bpy.types import (
13 PropertyGroup,
14 AddonPreferences,
18 bl_info = {
19 "name": "3D Viewport Pie Menus",
20 "author": "meta-androcto",
21 "version": (1, 3, 0),
22 "blender": (2, 80, 0),
23 "description": "Pie Menu Activation",
24 "location": "Addons Preferences",
25 "warning": "",
26 "doc_url": "{BLENDER_MANUAL_URL}/addons/interface/viewport_pies.html",
27 "category": "Interface"
30 sub_modules_names = (
31 "pie_modes_menu",
32 "pie_views_numpad_menu",
33 "pie_sculpt_menu",
34 "pie_origin",
35 "pie_manipulator_menu",
36 "pie_shading_menu",
37 "pie_align_menu",
38 "pie_delete_menu",
39 "pie_apply_transform_menu",
40 "pie_select_menu",
41 "pie_animation_menu",
42 "pie_save_open_menu",
43 "pie_editor_switch_menu",
44 "pie_defaults_menu",
45 "pie_proportional_menu",
49 sub_modules = [__import__(__package__ + "." + submod, {}, {}, submod) for submod in sub_modules_names]
50 sub_modules.sort(key=lambda mod: (mod.bl_info['category'], mod.bl_info['name']))
53 def _get_pref_class(mod):
54 import inspect
56 for obj in vars(mod).values():
57 if inspect.isclass(obj) and issubclass(obj, PropertyGroup):
58 if hasattr(obj, 'bl_idname') and obj.bl_idname == mod.__name__:
59 return obj
62 def get_addon_preferences(name=''):
63 """Acquisition and registration"""
64 addons = bpy.context.preferences.addons
65 if __name__ not in addons: # wm.read_factory_settings()
66 return None
67 addon_prefs = addons[__name__].preferences
68 if name:
69 if not hasattr(addon_prefs, name):
70 for mod in sub_modules:
71 if mod.__name__.split('.')[-1] == name:
72 cls = _get_pref_class(mod)
73 if cls:
74 prop = PointerProperty(type=cls)
75 create_property(PIEToolsPreferences, name, prop)
76 bpy.utils.unregister_class(PIEToolsPreferences)
77 bpy.utils.register_class(PIEToolsPreferences)
78 return getattr(addon_prefs, name, None)
79 else:
80 return addon_prefs
83 def create_property(cls, name, prop):
84 if not hasattr(cls, '__annotations__'):
85 cls.__annotations__ = dict()
86 cls.__annotations__[name] = prop
89 def register_submodule(mod):
90 mod.register()
91 mod.__addon_enabled__ = True
94 def unregister_submodule(mod):
95 if mod.__addon_enabled__:
96 mod.unregister()
97 mod.__addon_enabled__ = False
99 prefs = get_addon_preferences()
100 name = mod.__name__.split('.')[-1]
101 if hasattr(PIEToolsPreferences, name):
102 delattr(PIEToolsPreferences, name)
103 if prefs:
104 bpy.utils.unregister_class(PIEToolsPreferences)
105 bpy.utils.register_class(PIEToolsPreferences)
106 if name in prefs:
107 del prefs[name]
110 class PIEToolsPreferences(AddonPreferences):
111 bl_idname = __name__
113 def draw(self, context):
114 layout = self.layout
116 for mod in sub_modules:
117 mod_name = mod.__name__.split('.')[-1]
118 info = mod.bl_info
119 column = layout.column()
120 box = column.box()
122 # first stage
123 expand = getattr(self, 'show_expanded_' + mod_name)
124 icon = 'TRIA_DOWN' if expand else 'TRIA_RIGHT'
125 col = box.column()
126 row = col.row()
127 sub = row.row()
128 sub.context_pointer_set('addon_prefs', self)
129 op = sub.operator('wm.context_toggle', text='', icon=icon,
130 emboss=False)
131 op.data_path = 'addon_prefs.show_expanded_' + mod_name
132 sub.label(text='{}: {}'.format(info['category'], info['name']))
133 sub = row.row()
134 sub.alignment = 'RIGHT'
135 if info.get('warning'):
136 sub.label(text='', icon='ERROR')
137 sub.prop(self, 'use_' + mod_name, text='')
139 # The second stage
140 if expand:
141 if info.get('description'):
142 split = col.row().split(factor=0.15)
143 split.label(text='Description:')
144 split.label(text=info['description'])
145 if info.get('location'):
146 split = col.row().split(factor=0.15)
147 split.label(text='Location:')
148 split.label(text=info['location'])
150 if info.get('author'):
151 split = col.row().split(factor=0.15)
152 split.label(text='Author:')
153 split.label(text=info['author'])
155 if info.get('version'):
156 split = col.row().split(factor=0.15)
157 split.label(text='Version:')
158 split.label(text='.'.join(str(x) for x in info['version']),
159 translate=False)
160 if info.get('warning'):
161 split = col.row().split(factor=0.15)
162 split.label(text='Warning:')
163 split.label(text=' ' + info['warning'], icon='ERROR')
165 tot_row = int(bool(info.get('doc_url')))
166 if tot_row:
167 split = col.row().split(factor=0.15)
168 split.label(text='Internet:')
169 if info.get('doc_url'):
170 op = split.operator('wm.url_open',
171 text='Documentation', icon='HELP')
172 op.url = info.get('doc_url')
173 for i in range(4 - tot_row):
174 split.separator()
176 # Details and settings
177 if getattr(self, 'use_' + mod_name):
178 prefs = get_addon_preferences(mod_name)
180 if prefs and hasattr(prefs, 'draw'):
181 box = box.column()
182 prefs.layout = box
183 try:
184 prefs.draw(context)
185 except:
186 import traceback
187 traceback.print_exc()
188 box.label(text='Error (see console)', icon='ERROR')
189 del prefs.layout
191 row = layout.row()
192 row.label(text="End of Pie Menu Activations", icon="FILE_PARENT")
195 for mod in sub_modules:
196 info = mod.bl_info
197 mod_name = mod.__name__.split('.')[-1]
199 def gen_update(mod):
200 def update(self, context):
201 enabled = getattr(self, 'use_' + mod.__name__.split('.')[-1])
202 if enabled:
203 register_submodule(mod)
204 else:
205 unregister_submodule(mod)
206 mod.__addon_enabled__ = enabled
207 return update
209 create_property(
210 PIEToolsPreferences,
211 'use_' + mod_name,
212 BoolProperty(
213 name=info['name'],
214 description=info.get('description', ''),
215 update=gen_update(mod),
216 default=True,
219 create_property(
220 PIEToolsPreferences,
221 'show_expanded_' + mod_name,
222 BoolProperty())
225 classes = (
226 PIEToolsPreferences,
230 def register():
231 for cls in classes:
232 bpy.utils.register_class(cls)
234 prefs = get_addon_preferences()
235 for mod in sub_modules:
236 if not hasattr(mod, '__addon_enabled__'):
237 mod.__addon_enabled__ = False
238 name = mod.__name__.split('.')[-1]
239 if getattr(prefs, 'use_' + name):
240 register_submodule(mod)
243 def unregister():
244 for mod in sub_modules:
245 if mod.__addon_enabled__:
246 unregister_submodule(mod)
248 for cls in reversed(classes):
249 bpy.utils.unregister_class(cls)
252 if __name__ == "__main__":
253 register()