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

    Problem with MessageData plugin

    Cinema 4D SDK
    2023 windows python
    2
    5
    903
    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

      Hi guys~

      My goal is detecting and get any keybord key pressed and released.
      So my idea is useing MessageData.CoreMessage() and gui.GetInputEvent() to get which key was pressed and released.
      But the problem is when i press some key , some time it can print the result, but mostly it can't .
      I don't know if i do some mistakes, there is the code:

      import c4d
      from c4d import plugins
      
      pid = 20231019
      pname = "msg_test"
      
      class MSG(plugins.MessageData):
      
          def GetTimer(self):
              return 100  # ms
      
          def CoreMessage(self, id, bc):
              if id == c4d.MSG_TIMER:
                  if c4d.gui.GetInputEvent(c4d.BFM_INPUT_KEYBOARD, bc):
                       key = bc[c4d.BFM_INPUT_CHANNEL]
                       print(key)
                       print (c4d.gui.Shortcut2String(bc[c4d.BFM_INPUT_QUALIFIER], bc[c4d.BFM_INPUT_CHANNEL]))
      
      
              return True
      
      if __name__ == '__main__':
          reg = plugins.RegisterMessagePlugin(id=pid, str=pname, info=0, dat=MSG())
      

      www.boghma.com

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

        Hey @gheyret,

        Thank you for reaching out to us. What you do there does not match the description of what you want to do.

        My goal is detecting and get any keybord key pressed and released.

        What you do in your code is checking the current input state of the keyboard every 100 milliseconds. When the user happens to press the key in between your polling, i.e., the user already released the key when your function runs, you will detect nothing. This is even further complicated by the fact that timer events are not the most precise thing in the world and for requesting a stride of 100 ms, you will end up with an event queue which looks for example like this 92ms, 117ms, 81ms, 123ms, ....

        Core messages are the wrong choice for this, the natural message stream for this would be GUI messages; specifically the BFM_INPUT family. But for that you need a dialog or similar entity, and it must be in focus. In C++ there is SceneHookData and its method KeyBoardInput which allows you to hook into the global keyboard input stream. But SceneHookData has never been exposed to Python.

        Maybe you can explain what you want to achieve on a functionality level, e.g., "create a new material everytime the user presses the 'm' key", so that we can see if there is some "out-of-the-box-thinking"-solution for your problem.

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

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

          @ferdinand
          oops , my bad, i forgot to delet the Timer in this test code. However, even if I delete the Timer, the above problem still exists.

          In fact, this is a pre-development feasibility test. My idea goes something like this: I have a pre-written toolset, and then users can bind these tool commands to the shortcut they want, and when the shortcut is pressed, the corresponding command will be executed.

          And you sad the CoreMessage is wrong choice and SceneHookData is not available in python.
          I want to know why the CoreMessage is wrong choice and is there have other way to get global keyboard input?

          www.boghma.com

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

            Hey @gheyret ,

            @gheyret said in Problem with MessageData plugin:

            I want to know why the CoreMessage is wrong choice and is there have other way to get global keyboard input?

            Because core messages are not the message stream for mouse and keyboard inputs. Core events covey things like the scene having been updated, or viewports or other parts of Cinema 4D being redrawn. Timer events are also conveyed as core messages. Your code cannot work and it is always hard to answer questions when users show us other code than the one they are using, but:

            1. You do what your code from above shows, hook into MSG_TIMER and register for 100 ms: I have explained above why this is error prone.
            2. You do not hook into MSG_TIMER and instead evaluate the keyboard state every time CoreMessage is called (so on each core message event). This is even worse, because there is no guarantee that a core message is broadcasted at the same time when the user is typing. In fact, there is a good chance that you get core event starved when the user is typing, and you have no timer running which is forcing core messages.

            As I said, the natural message stream for this is GUI messages, as Cinema 4D will call you there on its own when the user is making inputs (with BFM_INPUT as lined out above). But you need some form of UI implementation for that, and it only works when the user is focusing on that UI of yours. The thing which does what you want is a SceneHook as they are meant to be the spider in the web kind of thing you are here after.

            I would recommend having a look at the Message Manual, it should clarify things.

            You can get the global keyboard state, just as you do it. But what you cannot do is hook into the global input stream (get state: you pull state, stream: Cinema 4D pushes states to you). SceneHookData is sort of an exception, but as you can see in the C++ docs I linked to in my former post, you must be careful there too.

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

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

              Hi @ferdinand

              Thank you so much for your explain, i understand what's happen now.

              Cheers

              www.boghma.com

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