pie menus official, add individual activation system. re: T48709

This commit is contained in:
meta-androcto
2016-08-03 11:31:25 +10:00
parent cf4ac00ea0
commit 1b9a94b5f9
9 changed files with 1034 additions and 176 deletions

View File

@ -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()

View File

@ -19,132 +19,22 @@
# <pep8 compliant>
bl_info = {
"name": "Pie Menus Official",
"author": "Antony Riakiotakis, Sebastian Koenig",
"version": (1, 0, 3),
"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),
"description": "Enable official Pie Menus in Blender",
"wiki_url": "http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.72/UI/Pie_Menus",
"tracker_url": "https://developer.blender.org/maniphest/task/create/?project=3&type=Bug",
"category": "User Interface",
}
"location": "Q, W, Shift W, E. Shift S, Shift A",
"warning": "",
"wiki_url": "",
"category": "Pie Menu"
}
import bpy
from bpy.types import Menu, Operator
from bpy.props import EnumProperty
class VIEW3D_PIE_object_mode(Menu):
bl_label = "Mode"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator_enum("OBJECT_OT_mode_set", "mode")
class VIEW3D_PIE_view_more(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(Menu):
bl_label = "View"
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"
class VIEW3D_PIE_shade(Menu):
bl_label = "Shade"
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")
class VIEW3D_manipulator_set(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(Menu):
bl_label = "Manipulator"
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")
class VIEW3D_PIE_pivot(Menu):
bl_label = "Pivot"
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")
class VIEW3D_PIE_snap(Menu):
bl_label = "Snapping"
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")
from bpy.types import (
Menu,
Operator,
)
class CLIP_PIE_refine_pie(Menu):
# Refinement Options
@ -352,43 +242,9 @@ class CLIP_PIE_timecontrol_pie(Menu):
pie.operator("screen.frame_offset", text="Next Frame", icon='TRIA_RIGHT').delta = 1
class PieMenuPrefs(bpy.types.AddonPreferences):
bl_idname = __name__
bpy.types.Scene.Enable_Tab_01 = bpy.props.BoolProperty(default=False)
def draw(self, context):
layout = self.layout
layout.prop(context.scene, "Enable_Tab_01", text="Hotkey List", icon="INFO")
if context.scene.Enable_Tab_01:
row = layout.row()
layout.label(text="Object Mode: 'TAB', 'PRESS'")
layout.label(text="Shade: 'Z', 'PRESS'")
layout.label(text="View: 'Q', 'PRESS'")
layout.label(text="Manipulator: 'SPACE', 'PRESS', ctrl=True")
layout.label(text="Pivot: 'PERIOD', 'PRESS'")
layout.label(text="Snap: 'TAB', 'PRESS', ctrl=True, shift=True")
layout.label(text="Grease Pencil Stroke Edit Mode: 'TAB', 'PRESS'")
layout.label(text="Marker: 'Q', 'PRESS'")
layout.label(text="Clipsetup: 'W', 'PRESS'")
layout.label(text="Tracking: 'E', 'PRESS'")
layout.label(text="Solver: 'S', 'PRESS', shift=True")
layout.label(text="Reconstruction: 'W', 'PRESS', shift=True")
layout.label(text="Timecontrol: 'A', 'PRESS', oskey=True")
addon_keymaps = []
classes = (
VIEW3D_manipulator_set,
VIEW3D_PIE_object_mode,
VIEW3D_PIE_view,
VIEW3D_PIE_view_more,
VIEW3D_PIE_shade,
VIEW3D_PIE_manipulator,
VIEW3D_PIE_pivot,
VIEW3D_PIE_snap,
PieMenuPrefs,
CLIP_PIE_geometry_reconstruction,
CLIP_PIE_tracking_pie,
CLIP_PIE_display_pie,
@ -410,24 +266,6 @@ def register():
if wm.keyconfigs.addon:
km = wm.keyconfigs.addon.keymaps.new(name='Object Non-modal')
kmi = km.keymap_items.new('wm.call_menu_pie', 'TAB', 'PRESS')
kmi.properties.name = 'VIEW3D_PIE_object_mode'
kmi = km.keymap_items.new('wm.call_menu_pie', 'Z', 'PRESS')
kmi.properties.name = 'VIEW3D_PIE_shade'
kmi = km.keymap_items.new('wm.call_menu_pie', 'Q', 'PRESS')
kmi.properties.name = 'VIEW3D_PIE_view'
kmi = km.keymap_items.new('wm.call_menu_pie', 'SPACE', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_PIE_manipulator'
kmi = km.keymap_items.new('wm.call_menu_pie', 'PERIOD', 'PRESS')
kmi.properties.name = 'VIEW3D_PIE_pivot'
kmi = km.keymap_items.new('wm.call_menu_pie', 'TAB', 'PRESS', ctrl=True, shift=True)
kmi.properties.name = 'VIEW3D_PIE_snap'
addon_keymaps.append(km)
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 = 'VIEW3D_PIE_object_mode'
addon_keymaps.append(km)
km = wm.keyconfigs.addon.keymaps.new(name="Clip", space_type='CLIP_EDITOR')
kmi = km.keymap_items.new("wm.call_menu_pie", 'Q', 'PRESS')
@ -443,7 +281,7 @@ def register():
addon_keymaps.append(km)
km = wm.keyconfigs.addon.keymaps.new(name="Frames")
kmi = km.keymap_items.new("wm.call_menu_pie", 'A', 'PRESS', oskey=True)
kmi = km.keymap_items.new("wm.call_menu_pie", 'A', 'PRESS', shift=True)
kmi.properties.name = "CLIP_PIE_timecontrol_pie"
addon_keymaps.append(km)
@ -463,3 +301,6 @@ def unregister():
wm.keyconfigs.addon.keymaps.remove(km)
addon_keymaps.clear()
if __name__ == "__main__":
register()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

320
pie_menus_official/utils.py Normal file
View File

@ -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