Hi
I want to pull all the commands associated with the numpad keys in the user prefs.
This I can then eval to execute the associated function.
Has anyone got a clean way to do this.
Thanks Greg
How about this:
import bpy
wm = bpy.context.window_manager
for km in wm.keyconfigs.user.keymaps:
print(km.name)
print("="*80)
for kmi in km.keymap_items:
if kmi.type.startswith("NUMPAD_"):
hotkey = []
if kmi.ctrl: hotkey.append("Ctrl")
if kmi.shift: hotkey.append("Shift")
if kmi.alt: hotkey.append("Alt")
hotkey.append("%s (%s)" % (kmi.type, kmi.value))
print(" %s" % kmi.name)
print(" %s" % " + ".join(hotkey))
if hasattr(kmi, "properties"):
props = []
for prop in dir(kmi.properties):
if not prop.startswith("_") and prop not in {"bl_rna", "rna_type"}:
attr = getattr(kmi.properties, prop)
prop_str = "%s=%r" % (prop, attr)
props.append(prop_str)
print(" %s" % prop_str)
cmd = "bpy.ops.%s(%s)" % (kmi.idname, ", ".join(props))
print(" >>> %s" % cmd)
print("-"*80)
More advanced with panel:
import bpy
def get_numpad_ops(wm):
ops = []
for km in wm.keyconfigs.user.keymaps:
if km.space_type == 'VIEW_3D':
print(km.name)
print("="*80)
for kmi in km.keymap_items:
if kmi.type.startswith("NUMPAD_"):
if kmi.ctrl or kmi.shift or kmi.alt:
continue
hotkey = []
if kmi.ctrl: hotkey.append("Ctrl")
if kmi.shift: hotkey.append("Shift")
if kmi.alt: hotkey.append("Alt")
hotkey.append("%s (%s)" % (kmi.type, kmi.value))
print(" %s" % kmi.name)
print(" %s" % " + ".join(hotkey))
if hasattr(kmi, "properties"):
props = {}
for prop in dir(kmi.properties):
if not prop.startswith("_") and prop not in {"bl_rna", "rna_type"}:
attr = getattr(kmi.properties, prop)
props[prop] = attr
print(" %s=%r" % (prop, attr))
cmd = "bpy.ops.%s(%s)" % (kmi.idname, ", ".join(map(lambda x: "%s=%r" % (x[0], x[1]), props)))
ops.append((kmi.idname, props))
print(" >>> %s" % cmd)
print("-"*80)
return ops
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
bl_category = "Tools"
#bl_context = "objectmode"
def draw(self, context):
layout = self.layout
wm = context.window_manager
flow = layout.column_flow(columns=2)
for op, props in get_numpad_ops(wm):
t = props.get("type")
if t is not None:
p = flow.operator(op, text=props['type'].capitalize())
else:
p = flow.operator(op)
for prop, attr in props.items():
setattr(p, prop, attr)
def register():
bpy.utils.register_class(HelloWorldPanel)
def unregister():
bpy.utils.unregister_class(HelloWorldPanel)
if __name__ == "__main__":
register()
But I don’t see a real benefit, you can perform the most common operations with your mouse (+ modifier key for certain things)
Thanks heaps
Ill play with it tonight after work.
I guess the point is I know more about coding than blender and all the ref material talks about how you really need a numpad and I work mostly on a laptop and didn’t want to buy one.
Also I can learn the numpad workflow without one.
Thanks for your help tho.
Below is the basic code without the hooks to user prefs
Id like to hear what you think
Thanks again.
Greg
import bpy
# Each Button
class OBJECT_OT_NumpadButton(bpy.types.Operator):
bl_idname = "numpad.button"
bl_label = "Button"
type = bpy.props.StringProperty()
mod_key = bpy.props.StringProperty("Off")
def execute(self, context):
# context.area.header_text_set("ModKey %s Me %s" % (self.mod_key, self.type))
if self.type == '7':
if self.mod_key == 'Ctrl':
bpy.ops.view3d.viewnumpad(type='BOTTOM')
else:
bpy.ops.view3d.viewnumpad(type='TOP')
if self.type == '5':
bpy.ops.view3d.view_persportho()
if self.type == '4':
bpy.ops.view3d.view_orbit(type='ORBITLEFT')
if self.type == '6':
bpy.ops.view3d.view_orbit(type='ORBITRIGHT')
if self.type == '8':
bpy.ops.view3d.view_orbit(type='ORBITUP')
if self.type == '2':
bpy.ops.view3d.view_orbit(type='ORBITDOWN')
if self.type == '3':
if self.mod_key == 'Ctrl':
bpy.ops.view3d.viewnumpad(type='LEFT')
else:
bpy.ops.view3d.viewnumpad(type='RIGHT')
if self.type == '1':
if self.mod_key == 'Ctrl':
bpy.ops.view3d.viewnumpad(type='BACK')
else:
bpy.ops.view3d.viewnumpad(type='FRONT')
if self.type == '0':
bpy.ops.view3d.viewnumpad(type='CAMERA')
if self.type == '.':
if self.mod_key == 'Ctrl':
bpy.ops.view3d.view_lock_to_active()
else:
bpy.ops.view3d.snap_cursor_to_selected()
# Alt + . bpy.ops.view3d.view_lock_clear
return{'FINISHED'}
def invoke(self, context, event):
#import code
#if context.area.type == 'VIEW_3D':
if event.shift:
self.mod_key = "Shift"
elif event.alt:
self.mod_key = "Alt"
elif event.ctrl:
self.mod_key = "Ctrl"
elif event.oskey:
self.mod_key = "OSKey"
else:
self.mod_key = "Off"
self.execute(context)
return {'FINISHED'}
# Class for panel definition
class VIEW3D_PT_NumpadPanel(bpy.types.Panel):
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_label = "Numpad"
bl_options = {"DEFAULT_CLOSED"}
# bl_options = {"HIDE_HEADER"}
def draw(self, context):
layout = self.layout
view = context.space_data
window_manager = context.window_manager
# my numpad version
# [<] [^] [v] [>]
# [7] [8] [9] [/]
# [4] [5] [6] [-]
# [1] [2] [3] [+]
# [0] [.]
# [home] [enter]
# Layout
col = layout.column(align=True)
col.label(text="Numpad Emulator")
# Arrows
# row = col.row()
# row.operator("numpad.button", text="", icon='TRIA_LEFT').type='ARROWLEFT'
# row.operator("numpad.button", text="", icon='TRIA_UP').type='ARROWUP'
# row.operator("numpad.button", text="", icon='TRIA_DOWN').type='ARROWDOWN'
# row.operator("numpad.button", text="", icon='TRIA_RIGHT').type='ARROWRIGHT'
# Top Row
row = col.row()
row.operator("numpad.button", text="7").type='7'
row.operator("numpad.button", text="8").type='8'
row.operator("numpad.button", text="9").type='9'
# row.operator("numpad.button", text="/").type='/'
# 2nd Row
row = col.row()
row.operator("numpad.button", text="4").type='4'
row.operator("numpad.button", text="5").type='5'
row.operator("numpad.button", text="6").type='6'
# row.operator("numpad.button", text="-").type='-'
# 3rd Row
row = col.row()
row.operator("numpad.button", text="3").type='3'
row.operator("numpad.button", text="2").type='2'
row.operator("numpad.button", text="1").type='1'
# row.operator("numpad.button", text="+").type='+'
# 4th Row
row = col.row()
row.operator("numpad.button", text="0").type='0'
row.operator("numpad.button", text=".").type='.'
# row = col.row()
# row.operator("numpad.button", text="home").type='home'
# row.operator("numpad.button", text="enter").type='enter'
# register the classes
def register():
bpy.utils.register_module(__name__)
pass
def unregister():
bpy.utils.unregister_module(__name__)
pass
if __name__ == "__main__":
register()
I have just had a quick look at your code.
Thanks very much.
This is brilliant.
It is a very elegant piece of work that shows a deep understanding of coding, python and blender.
For someone who can’t see the point of the exercise, you have produced an amazing piece of work.
For me this is a great insight into the way python and blender work. Thank you.
Also thanks for both lines 11 and 12
and leaving in 14 15 and 16 this has answered many questions I would have spent a long time tracking down the answers to.
I have added
if kmi.oskey: hotkey.append(“OSKey”)
to catch all the key states
Also I have noticed also that the “Any” setting simply returns all modifiers so I’m guessing that the logic is
when all are set then it becomes
OR OR OR
with the other combinations being a simple AND
Is this correct.
Thanks heaps you are a great asset to the blender community.
Greg
Yeah, that sounds right, any modifier key will work, thus it’s … OR … OR … OR …, not sure if no modifier key works as well?
Otherwise it’s AND, to allow for combinations, e.g. Ctrl + C vs. Ctrl + Shift + C vs. Ctrl + Shift + Alt + C
Thanks for all your help.