Setting a hotkey for a custom runTimeCommand in Maya

1.1k views Asked by At

My goal: Set up a simple class to add some keyboard macros to Maya at startup.

My Issue: The intended key mappings are not set in the hotkey editor. Editing them manually does work, but as these are default commands, they need to be set programmatically.

-thanks

class Macros(object):
    '''
    '''
    def __init__(self):
        '''
        '''

    def setMacro(self, name=None, k=None, cat=None, ann=None):
        '''
        Sets a default runtime command with a keyboard shotcut.
        args:
            name = 'string' - The command name you provide must be unique. The name itself must begin with an alphabetic character or underscore followed by alphanumeric characters or underscores.
            cat = 'string' - catagory - Category for the command.
            ann = 'string' - annotation - Description of the command.
            k = 'string' - keyShortcut - Specify what key is being set.
                            modifiers: alt, ctl, sht - Modifier values are set by adding a '+' between chars. ie. 'sht+z'.
        '''
        command = "from macros import Macros; Macros.{0}();".format(name)

        #set runTimeCommand
        pm.runTimeCommand(
                name,
                annotation=ann,
                category=cat,
                command=command,
                default=True,
        )

        #set hotkey
        #modifiers
        ctl=False; alt=False; sht=False
        for char in k.split('+'):
            if char=='ctl':
                ctl = True
            elif char=='alt':
                alt = True
            elif char=='sht':
                sht = True
            else:
                key = char

        pm.hotkey(keyShortcut=key, name=name, ctl=ctl, alt=alt, sht=sht) #set only the key press.




    #  ------------------------------------------------------

    @staticmethod
    def hk_back_face_culling():
        '''
        hk_back_face_culling
        Toggle Back-Face Culling
        1
        '''
        print 'hk_back_face_culling()'

Call:

m = Macros()
m.setMacro(name='hk_back_face_culling', k='1', cat='Display', ann='Toggle back-face culling')

Edit: I got it halfway working by adding a nameCommand.

#set command
nameCommand = pm.nameCommand(
        '{0}Command'.format(name),
        annotation=ann,
        command='python("{0}")'.format(command),
)
1

There are 1 answers

0
m3trik On BEST ANSWER

Here is A fully working example. Perhaps it can help someone in the future.

import pymel.core as pm

class Macros(object):
    '''Macro functions with assigned hotkeys.
    
    ex. usage: in startup script call: from macros import Macros; Macros().setMacros()
    '''
    def __init__(self, *args, **kwargs):
        '''
        '''

    def setMacros(self, macros={}):
        '''Extends setMacro to accept a dictionary.

        :Parameters:
            macros (dict) = Command names as keys, with dict values containing any keyword args for 'setMacro'. ex. {'m_group':{'k':'ctl+g', 'cat':'Edit'}}
        '''
        if not macros:
            macros = {
                'm_back_face_culling':      {'k':'1', 'cat':'Display'},
            }

        for name, kwargs in macros.items():
            self.setMacro(name, **kwargs)


    def setMacro(self, name, k=None, cat=None, ann=None, default=False, deleteExisting=True):
        '''Sets a default runtime command with a keyboard shortcut.

        :Parameters:
            name (str) = The command name you provide must be unique. (alphanumeric characters, or underscores)
            cat (str) = catagory - Category for the command.
            ann (str) = annotation - Description of the command.
            k (str) = keyShortcut - Specify what key is being set.
                        key modifier values are set by adding a '+' between chars. ie. 'sht+z'.
                        modifiers:
                            alt, ctl, sht
                        additional valid keywords are:
                            Up, Down, Right, Left,
                            Home, End, Page_Up, Page_Down, Insert
                            Return, Space
                            F1 to F12
                            Tab (Will only work when modifiers are specified)
                            Delete, Backspace (Will only work when modifiers are specified)
            default (bool) = Indicate that this run time command is a default command. Default run time commands will not be saved to preferences.
            deleteExisting = Delete any existing (non-default) runtime commands of the given name.
        '''
        command = "if 'macros' not in globals(): from macros import Macros; global macros; macros = Macros();\nmacros.{}();".format(name)

        if not ann: #if no ann is given, try using the method's docstring.
            method = getattr(self, name)
            ann = method.__doc__.split('\n')[0] #use only the first line.

        if pm.runTimeCommand(name, exists=True):
            if pm.runTimeCommand(name, query=True, default=True):
                return #can not delete default runtime commands.
            elif deleteExisting:#delete any existing (non-default) runtime commands of that name.
                pm.runTimeCommand(name, edit=True, delete=True)

        try: #set runTimeCommand
            pm.runTimeCommand(
                name,
                annotation=ann,
                category=cat,
                command=command,
                default=default,
            )
        except RuntimeError as error:
            print ('# Error: {}: {} #'.format(__file__, error))
            return error

        #set command
        nameCommand = pm.nameCommand(
                '{0}Command'.format(name),
                annotation=ann,
                command=name,
        )

        #set hotkey
        #modifiers
        ctl=False; alt=False; sht=False
        for char in k.split('+'):
            if char=='ctl':
                ctl = True
            elif char=='alt':
                alt = True
            elif char=='sht':
                sht = True
            else:
                key = char

        # print(name, char, ctl, alt, sht)
        pm.hotkey(keyShortcut=key, name=nameCommand, ctl=ctl, alt=alt, sht=sht) #set only the key press.


    @staticmethod
    def m_back_face_culling():
        '''Toggle Back-Face Culling.
        '''
        print ('<call to: {}.m_back_face_culling>'.format(__name__))