diff options
Diffstat (limited to 'pie_menus_official')
-rw-r--r-- | pie_menus_official/__init__.py | 246 | ||||
-rw-r--r-- | pie_menus_official/pie_clip_marker_of/__init__.py | 306 | ||||
-rw-r--r-- | pie_menus_official/pie_manipulator_of/__init__.py | 90 | ||||
-rw-r--r-- | pie_menus_official/pie_object_modes_of/__init__.py | 79 | ||||
-rw-r--r-- | pie_menus_official/pie_pivot_of/__init__.py | 65 | ||||
-rw-r--r-- | pie_menus_official/pie_shade_of/__init__.py | 71 | ||||
-rw-r--r-- | pie_menus_official/pie_snap_of/__init__.py | 65 | ||||
-rw-r--r-- | pie_menus_official/pie_view_of/__init__.py | 81 | ||||
-rw-r--r-- | pie_menus_official/utils.py | 320 |
9 files changed, 1323 insertions, 0 deletions
diff --git a/pie_menus_official/__init__.py b/pie_menus_official/__init__.py new file mode 100644 index 00000000..44e7e531 --- /dev/null +++ b/pie_menus_official/__init__.py @@ -0,0 +1,246 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +import bpy +from bpy.props import ( + BoolProperty, + PointerProperty, + ) +from bpy.types import ( + PropertyGroup, + AddonPreferences, + ) + + +bl_info = { + 'name': 'UI Pie Menu Official', + 'author': 'Antony Riakiotakis, Sebastian Koenig', + 'version': (1, 1, 2), + 'blender': (2, 7, 7), + 'location': 'See preferences for Activation list', + 'description': 'Pie Menu Activate', + 'warning': '', + 'wiki_url': '', + 'category': 'Pie Menu' + } + + +sub_modules_names = ( + "pie_object_modes_of", + "pie_view_of", + "pie_shade_of", + "pie_manipulator_of", + "pie_pivot_of", + "pie_snap_of", + "pie_clip_marker_of", + ) + + +sub_modules = [__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, PropertyGroup): + if hasattr(obj, 'bl_idname') and obj.bl_idname == mod.__name__: + return obj + + +def get_addon_preferences(name=''): + """Acquisition and registration""" + addons = bpy.context.user_preferences.addons + if __name__ not in addons: # wm.read_factory_settings() + return None + addon_prefs = addons[__name__].preferences + if name: + if not hasattr(addon_prefs, name): + for mod in sub_modules: + if mod.__name__.split('.')[-1] == name: + cls = _get_pref_class(mod) + if cls: + prop = PointerProperty(type=cls) + setattr(UIToolsPreferences, name, prop) + bpy.utils.unregister_class(UIToolsPreferences) + bpy.utils.register_class(UIToolsPreferences) + return getattr(addon_prefs, name, None) + else: + return addon_prefs + + +def register_submodule(mod): + if not hasattr(mod, '__addon_enabled__'): + mod.__addon_enabled__ = False + if not mod.__addon_enabled__: + mod.register() + mod.__addon_enabled__ = True + + +def unregister_submodule(mod): + if mod.__addon_enabled__: + mod.unregister() + mod.__addon_enabled__ = False + + prefs = get_addon_preferences() + name = mod.__name__.split('.')[-1] + if hasattr(UIToolsPreferences, name): + delattr(UIToolsPreferences, name) + if prefs: + bpy.utils.unregister_class(UIToolsPreferences) + bpy.utils.register_class(UIToolsPreferences) + if name in prefs: + del prefs[name] + +class UIToolsPreferences(AddonPreferences): + bl_idname = __name__ + + def draw(self, context): + layout = self.layout + + for mod in sub_modules: + mod_name = mod.__name__.split('.')[-1] + info = mod.bl_info + column = layout.column() + box = column.box() + + # first stage + expand = getattr(self, 'show_expanded_' + mod_name) + icon = 'TRIA_DOWN' if expand else 'TRIA_RIGHT' + col = box.column() + row = col.row() + sub = row.row() + sub.context_pointer_set('addon_prefs', self) + sub.alignment = 'LEFT' + op = sub.operator('wm.context_toggle', text='', icon=icon, + emboss=False) + op.data_path = 'addon_prefs.show_expanded_' + mod_name + sub.label('{}: {}'.format(info['category'], info['name'])) + sub = row.row() + sub.alignment = 'RIGHT' + if info.get('warning'): + sub.label('', icon='ERROR') + sub.prop(self, 'use_' + mod_name, text='') + + # The second stage + if expand: + if info.get('description'): + split = col.row().split(percentage=0.15) + split.label('Description:') + split.label(info['description']) + if info.get('location'): + split = col.row().split(percentage=0.15) + split.label('Location:') + split.label(info['location']) + if info.get('author') and info.get('author') != 'chromoly': + split = col.row().split(percentage=0.15) + split.label('Author:') + split.label(info['author']) + if info.get('version'): + split = col.row().split(percentage=0.15) + split.label('Version:') + split.label('.'.join(str(x) for x in info['version']), + translate=False) + if info.get('warning'): + split = col.row().split(percentage=0.15) + split.label('Warning:') + split.label(' ' + info['warning'], icon='ERROR') + + tot_row = int(bool(info.get('wiki_url'))) + if tot_row: + split = col.row().split(percentage=0.15) + split.label(text='Internet:') + if info.get('wiki_url'): + op = split.operator('wm.url_open', + text='Documentation', icon='HELP') + op.url = info.get('wiki_url') + for i in range(4 - tot_row): + split.separator() + + # Details and settings + if getattr(self, 'use_' + mod_name): + prefs = get_addon_preferences(mod_name) + + if prefs and hasattr(prefs, 'draw'): + box = box.column() + prefs.layout = box + try: + prefs.draw(context) + except: + traceback.print_exc() + box.label(text='Error (see console)', icon='ERROR') + del prefs.layout + + row = layout.row() + row.label("End of Pie Menu Activations") + + +for mod in sub_modules: + info = mod.bl_info + mod_name = mod.__name__.split('.')[-1] + + def gen_update(mod): + def update(self, context): + if getattr(self, 'use_' + mod.__name__.split('.')[-1]): + if not mod.__addon_enabled__: + register_submodule(mod) + else: + if mod.__addon_enabled__: + unregister_submodule(mod) + return update + + prop = BoolProperty( + name=info['name'], + description=info.get('description', ''), + update=gen_update(mod), + ) + setattr(UIToolsPreferences, 'use_' + mod_name, prop) + prop = BoolProperty() + setattr(UIToolsPreferences, 'show_expanded_' + mod_name, prop) + +classes = ( + UIToolsPreferences, + ) + + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + + prefs = get_addon_preferences() + for mod in sub_modules: + if not hasattr(mod, '__addon_enabled__'): + mod.__addon_enabled__ = False + name = mod.__name__.split('.')[-1] + if getattr(prefs, 'use_' + name): + register_submodule(mod) + + +def unregister(): + for mod in sub_modules: + if mod.__addon_enabled__: + unregister_submodule(mod) + + for cls in reversed(classes): + bpy.utils.unregister_class(cls) + +if __name__ == "__main__": + register() + + diff --git a/pie_menus_official/pie_clip_marker_of/__init__.py b/pie_menus_official/pie_clip_marker_of/__init__.py new file mode 100644 index 00000000..1c303f29 --- /dev/null +++ b/pie_menus_official/pie_clip_marker_of/__init__.py @@ -0,0 +1,306 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> + +bl_info = { + "name": "Clip Editor Pies: Key: 'hotkey list Below'", + "description": "Clip Editor Pies", +# "author": "Antony Riakiotakis, Sebastian Koenig", + "version": (0, 1, 0), + "blender": (2, 77, 0), + "location": "Q, W, Shift W, E. Shift S, Shift A", + "warning": "", + "wiki_url": "", + "category": "Pie Menu" + } + +import bpy +from bpy.types import ( + Menu, + Operator, + ) + +class CLIP_PIE_refine_pie(Menu): + # Refinement Options + bl_label = "Refine Intrinsics" + + def draw(self, context): + clip = context.space_data.clip + settings = clip.tracking.settings + + layout = self.layout + pie = layout.menu_pie() + + pie.prop(settings, "refine_intrinsics", expand=True) + + +class CLIP_PIE_geometry_reconstruction(Menu): + # Geometry Reconstruction + bl_label = "Reconstruction" + + def draw(self, context): + layout = self.layout + pie = layout.menu_pie() + + pie.operator("clip.bundles_to_mesh", icon='MESH_DATA') + pie.operator("clip.track_to_empty", icon='EMPTY_DATA') + + +class CLIP_PIE_proxy_pie(Menu): + # Proxy Controls + bl_label = "Proxy Size" + + def draw(self, context): + space = context.space_data + + layout = self.layout + pie = layout.menu_pie() + + pie.prop(space.clip, "use_proxy", text="Use Proxy") + pie.prop(space.clip_user, "proxy_render_size", expand=True) + + +class CLIP_PIE_display_pie(Menu): + # Display Options + bl_label = "Marker Display" + + def draw(self, context): + space = context.space_data + + layout = self.layout + pie = layout.menu_pie() + + pie.prop(space, "show_names", text="Show Track Info", icon='WORDWRAP_ON') + pie.prop(space, "show_disabled", text="Show Disabled Tracks", icon='VISIBLE_IPO_ON') + pie.prop(space, "show_marker_search", text="Display Search Area", icon='VIEWZOOM') + pie.prop(space, "show_marker_pattern", text="Display Pattern Area", icon='BORDERMOVE') + + +class CLIP_PIE_marker_pie(Menu): + # Settings for the individual markers + bl_label = "Marker Settings" + + def draw(self, context): + clip = context.space_data.clip + track_active = clip.tracking.tracks.active + + layout = self.layout + pie = layout.menu_pie() + + prop = pie.operator("wm.context_set_enum", text="Loc", icon='OUTLINER_DATA_EMPTY') + prop.data_path = "space_data.clip.tracking.tracks.active.motion_model" + prop.value = "Loc" + prop = pie.operator("wm.context_set_enum", text="Affine", icon='OUTLINER_DATA_LATTICE') + prop.data_path = "space_data.clip.tracking.tracks.active.motion_model" + prop.value = "Affine" + + pie.operator("clip.track_settings_to_track", icon='COPYDOWN') + pie.operator("clip.track_settings_as_default", icon='SETTINGS') + + if track_active: + pie.prop(track_active, "use_normalization", text="Normalization") + pie.prop(track_active, "use_brute", text="Use Brute Force") + pie.prop(track_active, "use_blue_channel", text="Blue Channel") + + if track_active.pattern_match == "PREV_FRAME": + prop = pie.operator("wm.context_set_enum", text="Match Previous", icon='KEYINGSET') + prop.data_path = "space_data.clip.tracking.tracks.active.pattern_match" + prop.value = 'KEYFRAME' + else: + prop = pie.operator("wm.context_set_enum", text="Match Keyframe", icon='KEY_HLT') + prop.data_path = "space_data.clip.tracking.tracks.active.pattern_match" + prop.value = 'PREV_FRAME' + + +class CLIP_PIE_tracking_pie(Menu): + # Tracking Operators + bl_label = "Tracking" + + def draw(self, context): + layout = self.layout + pie = layout.menu_pie() + + prop = pie.operator("clip.track_markers", icon='PLAY_REVERSE') + prop.backwards = True + prop.sequence = True + prop = pie.operator("clip.track_markers", icon='PLAY') + prop.backwards = False + prop.sequence = True + + pie.operator("clip.disable_markers", icon='RESTRICT_VIEW_ON') + pie.operator("clip.detect_features", icon='ZOOM_SELECTED') + + pie.operator("clip.clear_track_path", icon='BACK').action = 'UPTO' + pie.operator("clip.clear_track_path", icon='FORWARD').action = 'REMAINED' + + pie.operator("clip.refine_markers", icon='LOOP_BACK').backwards = True + pie.operator("clip.refine_markers", icon='LOOP_FORWARDS').backwards = False + + +class CLIP_PIE_clipsetup_pie(Menu): + # Setup the clip display options + bl_label = "Clip and Display Setup" + + def draw(self, context): + space = context.space_data + + layout = self.layout + pie = layout.menu_pie() + + pie.operator("clip.reload", text="Reload Footage", icon='FILE_REFRESH') + pie.operator("clip.prefetch", text="Prefetch Footage", icon='LOOP_FORWARDS') + + pie.prop(space, "use_mute_footage", text="Mute Footage", icon='MUTE_IPO_ON') + pie.prop(space.clip_user, "use_render_undistorted", text="Render Undistorted") + pie.operator("clip.set_scene_frames", text="Set Scene Frames", icon='SCENE_DATA') + pie.operator("wm.call_menu_pie", text="Marker Display", icon='PLUS').name = "CLIP_PIE_display_pie" + pie.operator("clip.set_active_clip", icon='CLIP') + pie.operator("wm.call_menu_pie", text="Proxy", icon='PLUS').name = "CLIP_PIE_proxy_pie" + + +class CLIP_PIE_solver_pie(Menu): + # Operators to solve the scene + bl_label = "Solving" + + def draw(self, context): + clip = context.space_data.clip + settings = clip.tracking.settings + + layout = self.layout + pie = layout.menu_pie() + + pie.operator("clip.create_plane_track", icon='MESH_PLANE') + pie.operator("clip.solve_camera", text="Solve Camera", icon='OUTLINER_OB_CAMERA') + + pie.operator("wm.call_menu_pie", text="Refinement", icon='CAMERA_DATA').name = "CLIP_PIE_refine_pie" + pie.prop(settings, "use_tripod_solver", text="Tripod Solver") + + pie.operator("clip.set_solver_keyframe", text="Set Keyframe A", icon='KEY_HLT').keyframe = 'KEYFRAME_A' + pie.operator("clip.set_solver_keyframe", text="Set Keyframe B", icon='KEY_HLT').keyframe = 'KEYFRAME_B' + + prop = pie.operator("clip.clean_tracks", icon='STICKY_UVS_DISABLE') + pie.operator("clip.filter_tracks", icon='FILTER') + prop.frames = 15 + prop.error = 2 + + +class CLIP_PIE_reconstruction_pie(Menu): + # Scene Reconstruction + bl_label = "Reconstruction" + + def draw(self, context): + layout = self.layout + pie = layout.menu_pie() + + pie.operator("clip.set_viewport_background", text="Set Viewport Background", icon='SCENE_DATA') + pie.operator("clip.setup_tracking_scene", text="Setup Tracking Scene", icon='SCENE_DATA') + + pie.operator("clip.set_plane", text="Setup Floor", icon='MESH_PLANE') + pie.operator("clip.set_origin", text="Set Origin", icon='MANIPUL') + + pie.operator("clip.set_axis", text="Set X Axis", icon='AXIS_FRONT').axis = 'X' + pie.operator("clip.set_axis", text="Set Y Axis", icon='AXIS_SIDE').axis = 'Y' + + pie.operator("clip.set_scale", text="Set Scale", icon='ARROW_LEFTRIGHT') + pie.operator("wm.call_menu_pie", text="Reconstruction", icon='MESH_DATA').name = "CLIP_PIE_geometry_reconstruction" + + +class CLIP_PIE_timecontrol_pie(Menu): + # Time Controls + bl_label = "Time Control" + + def draw(self, context): + layout = self.layout + pie = layout.menu_pie() + + pie.operator("screen.frame_jump", text="Jump to Startframe", icon='TRIA_LEFT').end = False + pie.operator("screen.frame_jump", text="Jump to Endframe", icon='TRIA_RIGHT').end = True + + pie.operator("clip.frame_jump", text="Start of Track", icon='REW').position = 'PATHSTART' + pie.operator("clip.frame_jump", text="End of Track", icon='FF').position = 'PATHEND' + + pie.operator("screen.animation_play", text="Playback Backwards", icon='PLAY_REVERSE').reverse = True + pie.operator("screen.animation_play", text="Playback Forwards", icon='PLAY').reverse = False + + pie.operator("screen.frame_offset", text="Previous Frame", icon='TRIA_LEFT').delta = -1 + pie.operator("screen.frame_offset", text="Next Frame", icon='TRIA_RIGHT').delta = 1 + + +addon_keymaps = [] + +classes = ( + CLIP_PIE_geometry_reconstruction, + CLIP_PIE_tracking_pie, + CLIP_PIE_display_pie, + CLIP_PIE_proxy_pie, + CLIP_PIE_marker_pie, + CLIP_PIE_solver_pie, + CLIP_PIE_refine_pie, + CLIP_PIE_reconstruction_pie, + CLIP_PIE_clipsetup_pie, + CLIP_PIE_timecontrol_pie, + ) + + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + + wm = bpy.context.window_manager + + if wm.keyconfigs.addon: + km = wm.keyconfigs.addon.keymaps.new(name='Object Non-modal') + + km = wm.keyconfigs.addon.keymaps.new(name="Clip", space_type='CLIP_EDITOR') + kmi = km.keymap_items.new("wm.call_menu_pie", 'Q', 'PRESS') + kmi.properties.name = "CLIP_PIE_marker_pie" + kmi = km.keymap_items.new("wm.call_menu_pie", 'W', 'PRESS') + kmi.properties.name = "CLIP_PIE_clipsetup_pie" + kmi = km.keymap_items.new("wm.call_menu_pie", 'E', 'PRESS') + kmi.properties.name = "CLIP_PIE_tracking_pie" + kmi = km.keymap_items.new("wm.call_menu_pie", 'S', 'PRESS', shift=True) + kmi.properties.name = "CLIP_PIE_solver_pie" + kmi = km.keymap_items.new("wm.call_menu_pie", 'W', 'PRESS', shift=True) + kmi.properties.name = "CLIP_PIE_reconstruction_pie" + addon_keymaps.append(km) + + km = wm.keyconfigs.addon.keymaps.new(name="Frames") + kmi = km.keymap_items.new("wm.call_menu_pie", 'A', 'PRESS', shift=True) + kmi.properties.name = "CLIP_PIE_timecontrol_pie" + + addon_keymaps.append(km) + + +def unregister(): + for cls in classes: + bpy.utils.unregister_class(cls) + + wm = bpy.context.window_manager + + if wm.keyconfigs.addon: + for km in addon_keymaps: + for kmi in km.keymap_items: + km.keymap_items.remove(kmi) + + wm.keyconfigs.addon.keymaps.remove(km) + + addon_keymaps.clear() + +if __name__ == "__main__": + register() diff --git a/pie_menus_official/pie_manipulator_of/__init__.py b/pie_menus_official/pie_manipulator_of/__init__.py new file mode 100644 index 00000000..43f65d65 --- /dev/null +++ b/pie_menus_official/pie_manipulator_of/__init__.py @@ -0,0 +1,90 @@ + +bl_info = { + "name": "Manipulator Menu: Key: 'Ctrl Space'", + "description": "Manipulator Modes", + "author": "Antony Riakiotakis, Sebastian Koenig", + "version": (0, 1, 0), + "blender": (2, 77, 0), + "location": "Ctrl Space", + "warning": "", + "wiki_url": "", + "category": "3d View" +} + +import bpy +from bpy.types import ( + Menu, + Operator, + ) +from bpy.props import ( + EnumProperty, + ) + +# Pie Manipulator Mode - Ctrl Space +class VIEW3D_manipulator_set_of(Operator): + bl_label = "Set Manipulator" + bl_idname = "view3d.manipulator_set" + + type = EnumProperty( + name="Type", + items=(('TRANSLATE', "Translate", "Use the manipulator for movement transformations"), + ('ROTATE', "Rotate", "Use the manipulator for rotation transformations"), + ('SCALE', "Scale", "Use the manipulator for scale transformations"), + ), + ) + + def execute(self, context): + # show manipulator if user selects an option + context.space_data.show_manipulator = True + + context.space_data.transform_manipulators = {self.type} + + return {'FINISHED'} + + +class VIEW3D_PIE_manipulator_of(Menu): + bl_label = "Manipulator" + bl_idname = "view3d.manipulator_of" + def draw(self, context): + layout = self.layout + + pie = layout.menu_pie() + pie.operator("view3d.manipulator_set", icon='MAN_TRANS', text="Translate").type = 'TRANSLATE' + pie.operator("view3d.manipulator_set", icon='MAN_ROT', text="Rotate").type = 'ROTATE' + pie.operator("view3d.manipulator_set", icon='MAN_SCALE', text="Scale").type = 'SCALE' + pie.prop(context.space_data, "show_manipulator") + +classes = [ + VIEW3D_manipulator_set_of, + VIEW3D_PIE_manipulator_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', 'SPACE', 'PRESS', ctrl=True) + kmi.properties.name = "view3d.manipulator_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 == "view3d.manipulator_of": + km.keymap_items.remove(kmi) + +if __name__ == "__main__": + register() diff --git a/pie_menus_official/pie_object_modes_of/__init__.py b/pie_menus_official/pie_object_modes_of/__init__.py new file mode 100644 index 00000000..536bb7d0 --- /dev/null +++ b/pie_menus_official/pie_object_modes_of/__init__.py @@ -0,0 +1,79 @@ + +bl_info = { + "name": "Mode Set: Key: 'Tab'", + "description": "Object Modes", + "author": "Antony Riakiotakis, Sebastian Koenig", + "version": (0, 1, 0), + "blender": (2, 77, 0), + "location": "Tab key", + "warning": "", + "wiki_url": "", + "category": "3d View" + } + +import bpy +from bpy.types import ( + Menu, + Operator, + ) + +# Pie Object Mode - Tab +class VIEW3D_PIE_object_mode_of(Menu): + bl_idname = "pie.object_mode_of" + bl_label = "Mode" + + def draw(self, context): + layout = self.layout + + pie = layout.menu_pie() + pie.operator_enum("OBJECT_OT_mode_set", "mode") + +classes = [ + VIEW3D_PIE_object_mode_of, + ] + +addon_keymaps = [] + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + wm = bpy.context.window_manager + + if wm.keyconfigs.addon: + # Object Modes + km = wm.keyconfigs.addon.keymaps.new(name='Object Non-modal') + kmi = km.keymap_items.new('wm.call_menu_pie', 'TAB', 'PRESS') + kmi.properties.name = "pie.object_mode_of" + addon_keymaps.append((km, kmi)) + + if wm.keyconfigs.addon: + # Grease Pencil Edit Modes + km = wm.keyconfigs.addon.keymaps.new(name='Grease Pencil Stroke Edit Mode') + kmi = km.keymap_items.new('wm.call_menu_pie', 'TAB', 'PRESS') + kmi.properties.name = "pie.object_mode_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.object_mode_of": + km.keymap_items.remove(kmi) + + kc = wm.keyconfigs.addon + if kc: + km = kc.keymaps['Grease Pencil Stroke Edit Mode'] + for kmi in km.keymap_items: + if kmi.idname == 'wm.call_menu_pie': + if kmi.properties.name == "pie.object_mode_of": + km.keymap_items.remove(kmi) + +if __name__ == "__main__": + register() diff --git a/pie_menus_official/pie_pivot_of/__init__.py b/pie_menus_official/pie_pivot_of/__init__.py new file mode 100644 index 00000000..d1cb2acc --- /dev/null +++ b/pie_menus_official/pie_pivot_of/__init__.py @@ -0,0 +1,65 @@ + +bl_info = { + "name": "Pivot Menu: Key: '. key'", + "description": "Manipulator Modes", + "author": "Antony Riakiotakis, Sebastian Koenig", + "version": (0, 1, 0), + "blender": (2, 77, 0), + "location": ". key", + "warning": "", + "wiki_url": "", + "category": "3d View" + } + +import bpy +from bpy.types import ( + Menu, + Operator, + ) + +# Pie Pivot Mode - . key +class VIEW3D_PIE_pivot_of(Menu): + bl_label = "Pivot" + bl_idname = "view3d.pivot_of" + + def draw(self, context): + layout = self.layout + + pie = layout.menu_pie() + pie.prop(context.space_data, "pivot_point", expand=True) + if context.active_object.mode == 'OBJECT': + pie.prop(context.space_data, "use_pivot_point_align", text="Center Points") + +classes = [ + VIEW3D_PIE_pivot_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', 'PERIOD', 'PRESS') + kmi.properties.name = "view3d.pivot_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 == "view3d.pivot_of": + km.keymap_items.remove(kmi) + +if __name__ == "__main__": + register() diff --git a/pie_menus_official/pie_shade_of/__init__.py b/pie_menus_official/pie_shade_of/__init__.py new file mode 100644 index 00000000..5ef189e6 --- /dev/null +++ b/pie_menus_official/pie_shade_of/__init__.py @@ -0,0 +1,71 @@ + +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, + ) + +# 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() diff --git a/pie_menus_official/pie_snap_of/__init__.py b/pie_menus_official/pie_snap_of/__init__.py new file mode 100644 index 00000000..ed427456 --- /dev/null +++ b/pie_menus_official/pie_snap_of/__init__.py @@ -0,0 +1,65 @@ + +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, + ) + +# 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: + 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() diff --git a/pie_menus_official/pie_view_of/__init__.py b/pie_menus_official/pie_view_of/__init__.py new file mode 100644 index 00000000..1dad87b2 --- /dev/null +++ b/pie_menus_official/pie_view_of/__init__.py @@ -0,0 +1,81 @@ + +bl_info = { + "name": "View Menu: Key: 'Q key'", + "description": "View Modes", + "author": "Antony Riakiotakis, Sebastian Koenig", + "version": (0, 1, 0), + "blender": (2, 77, 0), + "location": "Q key", + "warning": "", + "wiki_url": "", + "category": "3d View" + } + +import bpy +from bpy.types import ( + Menu, + Operator, + ) + +# Pie View Mode - Q +class VIEW3D_PIE_view_more_of(Menu): + bl_label = "More" + + + def draw(self, context): + layout = self.layout + + pie = layout.menu_pie() + pie.operator("VIEW3D_OT_view_persportho", text="Persp/Ortho", icon='RESTRICT_VIEW_OFF') + pie.operator("VIEW3D_OT_camera_to_view") + pie.operator("VIEW3D_OT_view_selected") + pie.operator("VIEW3D_OT_view_all") + pie.operator("VIEW3D_OT_localview") + pie.operator("SCREEN_OT_region_quadview") + + +class VIEW3D_PIE_view_of(Menu): + bl_label = "View" + bl_idname = "pie.view_of" + + def draw(self, context): + layout = self.layout + + pie = layout.menu_pie() + pie.operator_enum("VIEW3D_OT_viewnumpad", "type") + pie.operator("wm.call_menu_pie", text="More", icon='PLUS').name = "VIEW3D_PIE_view_more_of" + +classes = [ + VIEW3D_PIE_view_more_of, + VIEW3D_PIE_view_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', 'Q', 'PRESS') + kmi.properties.name = "pie.view_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.view_of": + km.keymap_items.remove(kmi) + +if __name__ == "__main__": + register() diff --git a/pie_menus_official/utils.py b/pie_menus_official/utils.py new file mode 100644 index 00000000..540e81d8 --- /dev/null +++ b/pie_menus_official/utils.py @@ -0,0 +1,320 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + + +import bpy + + +class AddonPreferences: + _module = {} + + @classmethod + def get_prefs(cls, package=''): + if not package: + package = __package__ + if '.' in package: + pkg, name = package.split('.') + # key = cls.__qualname__ + if package in cls._module: + mod = cls._module[package] + else: + import importlib + mod = cls._module[package] = importlib.import_module(pkg) + return mod.get_addon_preferences(name) + else: + context = bpy.context + return context.user_preferences.addons[package].preferences + + @classmethod + def register(cls): + if '.' in __package__: + cls.get_prefs() + + @classmethod + def unregister(cls): + cls._module.clear() + + +class SpaceProperty: + """ + bpy.types.Space #Add the virtual property in + + # Instantiation + space_prop = SpaceProperty( + [[bpy.types.SpaceView3D, 'lock_cursor_location', + bpy.props.BoolProperty()]]) + + # When drawing + def draw(self, context): + layout = self.layout + view = context.space_data + prop = space_prop.get_prop(view, 'lock_cursor_location') + layout.prop(prop, 'lock_cursor_location') + + # register / unregister + def register(): + space_prop.register() + + def unregister(): + space_prop.unregister() + """ + + space_types = { + 'EMPTY': bpy.types.Space, + 'NONE': bpy.types.Space, + 'CLIP_EDITOR': bpy.types.SpaceClipEditor, + 'CONSOLE': bpy.types.SpaceConsole, + 'DOPESHEET_EDITOR': bpy.types.SpaceDopeSheetEditor, + 'FILE_BROWSER': bpy.types.SpaceFileBrowser, + 'GRAPH_EDITOR': bpy.types.SpaceGraphEditor, + 'IMAGE_EDITOR': bpy.types.SpaceImageEditor, + 'INFO': bpy.types.SpaceInfo, + 'LOGIC_EDITOR': bpy.types.SpaceLogicEditor, + 'NLA_EDITOR': bpy.types.SpaceNLA, + 'NODE_EDITOR': bpy.types.SpaceNodeEditor, + 'OUTLINER': bpy.types.SpaceOutliner, + 'PROPERTIES': bpy.types.SpaceProperties, + 'SEQUENCE_EDITOR': bpy.types.SpaceSequenceEditor, + 'TEXT_EDITOR': bpy.types.SpaceTextEditor, + 'TIMELINE': bpy.types.SpaceTimeline, + 'USER_PREFERENCES': bpy.types.SpaceUserPreferences, + 'VIEW_3D': bpy.types.SpaceView3D, + } + # space_types_r = {v: k for k, v in space_types.items()} + + def __init__(self, *props): + """ + :param props: [[space_type, attr, prop], ...] + [[Or string bpy.types.Space, String, + bpy.props.***()ćPropertyGroup], ...] + bpy.types.PropertyGroup In advance if you use register_class()so + It is registered + :type props: list[list] + """ + self.props = [list(elem) for elem in props] + for elem in self.props: + space_type = elem[0] + if isinstance(space_type, str): + elem[0] = self.space_types[space_type] + self.registered = [] + self.save_pre = self.save_post = self.load_post = None + + def gen_save_pre(self): + @bpy.app.handlers.persistent + def save_pre(dummy): + wm = bpy.context.window_manager + for (space_type, attr, prop), (cls, wm_prop_name) in zip( + self.props, self.registered): + if wm_prop_name not in wm: + continue + d = {p['name']: p for p in wm[wm_prop_name]} # not p.name + for screen in bpy.data.screens: + ls = [] + for area in screen.areas: + for space in area.spaces: + if isinstance(space, space_type): + key = str(space.as_pointer()) + if key in d: + ls.append(d[key]) + else: + ls.append({}) + screen[wm_prop_name] = ls + self.save_pre = save_pre + return save_pre + + def gen_save_post(self): + @bpy.app.handlers.persistent + def save_post(dummy): + # clean up + for cls, wm_prop_name in self.registered: + for screen in bpy.data.screens: + if wm_prop_name in screen: + del screen[wm_prop_name] + self.save_post = save_post + return save_post + + def gen_load_post(self): + @bpy.app.handlers.persistent + def load_post(dummy): + from collections import OrderedDict + for (space_type, attr, prop), (cls, wm_prop_name) in zip( + self.props, self.registered): + d = OrderedDict() + for screen in bpy.data.screens: + if wm_prop_name not in screen: + continue + + spaces = [] + for area in screen.areas: + for space in area.spaces: + if isinstance(space, space_type): + spaces.append(space) + + for space, p in zip(spaces, screen[wm_prop_name]): + key = p['name'] = str(space.as_pointer()) + d[key] = p + if d: + bpy.context.window_manager[wm_prop_name] = list(d.values()) + + # clean up + for cls, wm_prop_name in self.registered: + for screen in bpy.data.screens: + if wm_prop_name in screen: + del screen[wm_prop_name] + + self.load_post = load_post + return load_post + + def get_all(self, space_type=None, attr=''): + """ + :param space_type: If the property is only only one optional + :type space_type: bpy.types.Space + :param attr: If the property is only only one optional + :type attr: str + :return: + :rtype: + """ + if space_type and isinstance(space_type, str): + space_type = self.space_types.get(space_type) + context = bpy.context + for (st, attri, prop), (cls, wm_prop_name) in zip( + self.props, self.registered): + if (st == space_type or issubclass(space_type, st) or + not space_type and len(self.props) == 1): + if attri == attr or not attr and len(self.props) == 1: + seq = getattr(context.window_manager, wm_prop_name) + return seq + + def get(self, space, attr=''): + """ + :type space: bpy.types.Space + :param attr: If the property is only only one optional + :type attr: str + :return: + :rtype: + """ + seq = self.get_all(type(space), attr) + if seq is not None: + key = str(space.as_pointer()) + if key not in seq: + item = seq.add() + item.name = key + return seq[key] + + def _property_name(self, space_type, attr): + return space_type.__name__.lower() + '_' + attr + + def register(self): + import inspect + for space_type, attr, prop in self.props: + if inspect.isclass(prop) and \ + issubclass(prop, bpy.types.PropertyGroup): + cls = prop + else: + name = 'WM_PG_' + space_type.__name__ + '_' + attr + cls = type(name, (bpy.types.PropertyGroup,), {attr: prop}) + bpy.utils.register_class(cls) + + collection_prop = bpy.props.CollectionProperty(type=cls) + wm_prop_name = self._property_name(space_type, attr) + setattr(bpy.types.WindowManager, wm_prop_name, collection_prop) + + self.registered.append((cls, wm_prop_name)) + + def gen(): + def get(self): + seq = getattr(bpy.context.window_manager, wm_prop_name) + key = str(self.as_pointer()) + if key not in seq: + item = seq.add() + item.name = key + if prop == cls: + return seq[key] + else: + return getattr(seq[key], attr) + + def set(self, value): + seq = getattr(bpy.context.window_manager, wm_prop_name) + key = str(self.as_pointer()) + if key not in seq: + item = seq.add() + item.name = key + if prop != cls: # PropertyGroup It is not writable + return setattr(seq[key], attr, value) + + return property(get, set) + + setattr(space_type, attr, gen()) + + bpy.app.handlers.save_pre.append(self.gen_save_pre()) + bpy.app.handlers.save_post.append(self.gen_save_post()) + bpy.app.handlers.load_post.append(self.gen_load_post()) + + def unregister(self): + bpy.app.handlers.save_pre.remove(self.save_pre) + bpy.app.handlers.save_post.remove(self.save_post) + bpy.app.handlers.load_post.remove(self.load_post) + + for (space_type, attr, prop), (cls, wm_prop_name) in zip( + self.props, self.registered): + delattr(bpy.types.WindowManager, wm_prop_name) + if wm_prop_name in bpy.context.window_manager: + del bpy.context.window_manager[wm_prop_name] + delattr(space_type, attr) + + if prop != cls: + # originally bpy.types.PropertyGroup Skip Nara + bpy.utils.unregister_class(cls) + + for screen in bpy.data.screens: + if wm_prop_name in screen: + del screen[wm_prop_name] + + self.registered.clear() + + +def operator_call(op, *args, _scene_update=True, **kw): + """vawm Than + operator_call(bpy.ops.view3d.draw_nearest_element, + 'INVOKE_DEFAULT', type='ENABLE', _scene_update=False) + """ + import bpy + from _bpy import ops as ops_module + + BPyOpsSubModOp = op.__class__ + op_call = ops_module.call + context = bpy.context + + # Get the operator from blender + wm = context.window_manager + + # run to account for any rna values the user changes. + if _scene_update: + BPyOpsSubModOp._scene_update(context) + + if args: + C_dict, C_exec, C_undo = BPyOpsSubModOp._parse_args(args) + ret = op_call(op.idname_py(), C_dict, kw, C_exec, C_undo) + else: + ret = op_call(op.idname_py(), None, kw) + + if 'FINISHED' in ret and context.window_manager == wm: + if _scene_update: + BPyOpsSubModOp._scene_update(context) + + return ret |