Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    How to Register "Hot key" plugin in python?

    Cinema 4D SDK
    python r23
    2
    5
    986
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • gheyretG
      gheyret
      last edited by gheyret

      Hello !
      I see the "hotkey" plugin in cinema 4d like "Move Parent", and the shortcut is "7", and i need to press and hold down the shortcut key to execute the plugin.
      (You can see the Type is Hotkey)
      Snipaste_2021-09-16_15-32-35.jpg
      So how do i register the "hotkey" plugin in python?
      Actually i find some hotkey stuf like Command plugin flag in SDK;
      Snipaste_2021-09-16_15-41-49.jpg
      But i am not sure it's what i want, if it's what i want, how do i use it ? and how do i bind the shortcut key for the plugin ?
      Thanks

      www.boghma.com

      gheyretG 1 Reply Last reply Reply Quote 0
      • gheyretG
        gheyret @gheyret
        last edited by gheyret

        I try to register a CommandDataPlugin with PLUGINFLAG_COMMAND_HOTKE flags,
        and i assign a shortcut key like this ; .
        But when i press the shortcut key anything doesn't happen.

        I don't know is i did something is wrong?
        How can i do it's work correctly?

        And the examle code like this:

        class Hotket(plugins.CommandData):
            def Execute(self, doc):
                print("Hotkey pressed")
        
                return True
        
        if __name__ == '__main__':
            plugins.RegisterCommandPlugin(1208170,"Hotkey Test",c4d.PLUGINFLAG_COMMAND_HOTKEY,None,"",Hotket())
        

        www.boghma.com

        1 Reply Last reply Reply Quote 0
        • gheyretG
          gheyret
          last edited by

          Hello !~~
          I'm waiting...

          www.boghma.com

          1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand
            last edited by ferdinand

            Hello @gheyret,

            thank you for reaching out to us and please excuse the slight delay. You are misunderstanding the purpose of PLUGINFLAG_COMMAND_HOTKEY, which admittedly is badly explained, and I also had to do some digging myself to understand how this is meant to be used. In bullet points:

            1. First of all, you do not need any special flags to assign a shortcut to your CommandData plugin. A simple PLUGINFLAG_SMALLNODE will be enough.
            2. Then there are these two flags PLUGINFLAG_COMMAND_HOTKEY and PLUGINFLAG_COMMAND_STICKY which are often used in conjunction internally. When you only pass PLUGINFLAG_COMMAND_HOTKEY, a command with your plugin id will be emitted continuously while the user is pressing the shortcut assigned to your plugin which did register with that flag. If also PLUGINFLAG_COMMAND_STICKY is being passed, there will only an opening and closing event for the key down and key up events.
            3. The Move Parent plugin you want to imitate is internally not a CommandData plugin, it simply registers its ID as an hotkey in a way not available to the public. But there are some CommandData plugins of ours which register as 'PLUGINFLAG_COMMAND_HOTKEY' or 'PLUGINFLAG_COMMAND_HOTKEY| PLUGINFLAG_COMMAND_STICKY'. And all these CommandData plugins then have one thing in common: They do nothing, or nothing related to the hotkey, as their Execute method will never be called or at least never be called in the context of the hotkey.
            4. So, hotkey means here that when you assign a shortcut to your plugin and press that shortcut key, a global hotkey message will be emitted. Which then can then be polled in other places. E.g., with EditorWindow.IsHotkeyDown or GeUserArea.IsHotkeyDown. Which is also why CommandData.Execute() will not be called when you pass the PLUGINFLAG_COMMAND_HOTKEY flag, since Cinema does assume you handle the associated logic in another place.
            5. So, to use PLUGINFLAG_COMMAND_HOTKEY, you will usually need at least two plugins. One that registers the hotkey and one that makes use of it. You could technically imagine a CommandData plugin which registers as a hotkey and the also makes use of the hotkey in its dialog window in some shape or form. But that will have the side effect that you cannot open the dialog with that hotkey, because CommandData.Execute() will never be called for that plugin when pressing the shortcut/hotkey. But you could still open the dialog by clicking with the mouse.
            6. If you want just some continuous execution, e.g., do XYZ while Shift + A are being pressed, you should just implement a normal CommandData and then poll in your CommandData.Execute() for these keys being pressed and do stuff while they are and stop doing when not. You can poll for the input state with c4d.gui.GetInputState and you can figure out the shortcuts assigned to your plugin with c4d.gui.GetShortcut, as shown in the code at the end of the posting.

            The description for PLUGINFLAG_COMMAND_STICKY was either always wrong or is outdated, as it does indicate that 'PLUGINFLAG_COMMAND_HOTKEY | PLUGINFLAG_COMMAND_STICKY' will cause CommandData.Execute() to be called - which is not true.

            I hope this helps,
            Ferdinand

            """Example for retrieving the shortcuts for a plugin id.
            """
            
            import c4d
            
            def GetPluginShortcuts(pid: int) -> list[list[tuple[int]]]:
                """Retrieves the shortcuts for a plugin-id.
                
                Args:
                    pid (int): The plugin id.
                
                Returns:
                    list[list[tuple[int]]]: The shortcut sequences for the plugin.
                """
                # Get all shortcut containers for the plugin id.
                count = c4d.gui.GetShortcutCount()
                matches = [c4d.gui.GetShortcut(i) for i in range(count)
                           if c4d.gui.GetShortcut(i)[c4d.SHORTCUT_PLUGINID] == pid]
            
                # build the shortcut data.
                result = []
                for item in matches:
                    sequence = []
                    for i in range(0, c4d.SHORTCUT_PLUGINID, 10):
                        a, b = item[i], item[i+1]
                        if isinstance(a, (int, float)):
                            sequence.append((a, b))
            
                    if sequence != []:
                        result.append(sequence)
                return result
            
            
            if __name__ == "__main__":
                # The shortcuts for your plugin id.
                for item in GetPluginShortcuts(1208170):
                    for a, b in item:
                        print (a, b, c4d.gui.Shortcut2String(a, b))
                # The shortcuts for the dissolve tool (multiple shortcuts)
                for item in GetPluginShortcuts(440000043):
                    for a, b in item:
                        print (a, b, c4d.gui.Shortcut2String(a, b))
            

            MAXON SDK Specialist
            developers.maxon.net

            gheyretG 1 Reply Last reply Reply Quote 1
            • gheyretG
              gheyret @ferdinand
              last edited by

              Hi @ferdinand , Thank you very much for your detailed reply. I think it is very helpful to me.
              Cheers!

              www.boghma.com

              1 Reply Last reply Reply Quote 0
              • First post
                Last post