Keyboard input



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 27/10/2012 at 15:42, xxxxxxxx wrote:

    Hey guys.
    I'm still struggling with input for my tool plugin. What am trying to get is a functionality like cloning an object: you have the move tool active, you hold the CTRL key and click with the left mouse-button and drag. The mouse part I get, thanks to Yannicks great answer to my post a couple of days ago. But it seems to be impossible to get the CTRL key working. I have no problem getting keys like ESC or F1 with this code-snippet:

      def KeyboardInput(self, doc, data, bd, win, msg) :  
      if msg.GetLong(c4d.BFM_INPUT_CHANNEL) == c4d.KEY_ESC:
                print "ESC pressed"
    

    But the qualifier-keys just won't work that way. I tried this code you can find without problem in forums:

    msg[c4d.BFM_INPUT_QUALIFIER] & c4d.QCTRL:
        print "CTRL pressed"
    

    But this doesn't seems to work as the SDK says >A bitmask with the qualifiers at the time when the event occured.

    So this seems only to work when you press the plugin button (which for any reasons doesn't work either, it only works with scripts for me). So the obvious question is how do I get the CTRL key (and SHIFT key for that matter) working.
    And there would be a subsequent question: As I stated I want to use the control key to change the mode my tool is working like the cloning as mentioned above. So this would be done using a variable which is set while the control key is hold and reset when it's released (which is checked using a while loop) like in this code:

    def KeyboardInput(self, doc, data, bd, win, msg) :  
      
    if msg.GetLong(c4d.BFM_INPUT_CHANNEL) == c4d.KEY_ESC:  
    print "Start ESC Pressed"  
      self.mode = 1  #Set Mode  
      
    while True:  
    bc = c4d.BaseContainer()  
    if gui.GetInputState(c4d.BFM_INPUT_KEYBOARD, c4d.KEY_ESC, bc) :  
    if bc.GetLong(c4d.BFM_INPUT_CHANNEL)==c4d.KEY_ESC:  
    if not bc.GetBool(c4d.BFM_INPUT_VALUE) : break  
      self.mode = 2 #Reset Mode
    

    Problem is, when I click the mouse-button the keyboard loop is ended and the mode reset before the clicking of the mouse button really comes into action.
    This more of a cosmetic thing, as is would also work with activating one mode by pressing the control key once and deactivate it by pressing it again, but it would be really nice to have it.
    Phil



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 29/10/2012 at 10:29, xxxxxxxx wrote:

    Hi,

    You have to test the qualifier key in MouseInput() if you want to use it with a mouse event (e.g. CTRL+mouse left move) and in KeyboardInput() with a key event (e.g. CTRL+C). And ESC can't be used as a qualifier key (or even trying to emulating it). It's only possible with CTRL or SHIFT.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 29/10/2012 at 11:31, xxxxxxxx wrote:

    Hi Yannick.
    Thanks for the answer but I just don't know what to do with it. There are not many examples to find how to use which input method.
    Since I don't know where to start here's what would work for me (if I could just change it from ESC to CTRL) :

    mode = True
    def KeyboardInput(self, doc, data, bd, win, msg) :  
    if msg.GetLong(c4d.BFM_INPUT_CHANNEL) == c4d.KEY_ESC:  
    self.mode = not self.mode  
    return True  
      return False
    

    This works the way I want it. If I press ESC while I have my tool-plugin active, it switches the mode from true to false (which changes some colors and drawn polygons in the Draw function). Does your answer mean you can use CTRL and SHIFT only in conjunction with a mouse-event like clicking or another key?
    I'm almost on giving up on CTRL or SHIFT and thought why not use a character key. Problem is I don't know how to check it. The SDK says >BFM_INPUT_CHANNEL

    LONG
    The channel contains the key or button ('A' means A, KEY_F1 means F1)

    F1, F2, and so on work without problem, a character not so much. I tried c4d.A, not working, I tried it as a string 'A', and I'm running out of ideas 😂
    Maybe you could help me out here one more time.
    Thanks
    Phil



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 29/10/2012 at 13:22, xxxxxxxx wrote:

    First get the mouse loop working. So when you hold a MB down your code does it's thing.
    Then add the extra if condition to that mouse loop so that it only works if the Ctrl key is being pressed.

    Something like this:

    win.MouseDragStart(button=mbutton, mx=int(mx), my=int(my), flags=c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE)  
    result, dx, dy, channel = win.MouseDrag()  
    while result==c4d.MOUSEDRAGRESULT_CONTINUE:          
      bc = c4d.BaseContainer()  
      if c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD,c4d.BFM_INPUT_CHANNEL,bc) :  #If the keyboard is being used  
          if bc[c4d.BFM_INPUT_QUALIFIER] & c4d.QCTRL:                             #If the Ctrl key is being pressed...Then do your drawing stuff...
    

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 29/10/2012 at 14:15, xxxxxxxx wrote:

    Thank you very much for your answer and the file.
    The problem in this case is I need to click before the CTRL-key kicks in. Let me explain a little bit more what I have in mind: my tool gives visual feedback how it is going to operate. So by default my tool works in world space and draws some guides according to that. Now what I wanted to do is by holding the CTRL-key is to switch to local space and correspondingly change the guides (still nothing is exectued as I haven't clicked anything). Or as holding the button down might not be an option: just pressing it once to change the mode. I know it would be an option to put a mode-changing button in the tool-dialog, but I still think there must be a way using keyboard input (and there is as it works with ESC in the KeyboardInput function ...  but seriously: who wants to use ESC to change a mode?).
    Sorry if it wasn't clear enough what I wanted before (it always makes perfect sense in my head 😉).
    Cheers,
    Phil



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 29/10/2012 at 15:16, xxxxxxxx wrote:

    Oh. I see.

    What about this?:

      
      if c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD,c4d.BFM_INPUT_CHANNEL,msg) :  
          if msg[c4d.BFM_INPUT_QUALIFIER] & c4d.QCTRL:  
              #Do your mode variable stuff here
    

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 29/10/2012 at 15:47, xxxxxxxx wrote:

    I tried this in at least a dozen of arrangements, but I can't get it to work within the keyboard input (could have something to do with the things Yannick wrote ... maybe). It works by executing a python script without a problem, but in a plugin ... at least I don't know how.
    As this works:

    def KeyboardInput(self, doc, data, bd, win, msg) :  
    if msg.GetLong(c4d.BFM_INPUT_CHANNEL) == c4d.KEY_ESC:  
    self.mode = not self.mode  
    return True  
    return False
    

    The most logical thing to me would be to replace c4d.KEY_ESC with c4d.QCTRL, but no chance. Neither does

    if msg[c4d.BFM_INPUT_QUALIFIER] == c4d.QCTRL:
    

    the trick.
    I get that CTRL, SHIFT and ALT are special keys and maybe there is no way to integrate them like I want it.
    I think the whole input stuff is very confusing, and sadly as you mentioned in the other thread the SDK isn't very helpful. As I'm not a regular programmer this is even more difficult I guess.
    Phil



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 29/10/2012 at 18:39, xxxxxxxx wrote:

    You're right.
    Something is definitely off when it comes to getting the state of the qualifier keys. But only when trying to do it inside of python plugins.
    This also looks like it might be intentional.

    This is how to get the state of the Ctrl key in C++.
    When you press the Ctrl key you get the expected print return

        GetInputState(BFM_INPUT_KEYBOARD, BFM_INPUT_CHANNEL, msg);  
      if(msg.GetLong(BFM_INPUT_QUALIFIER) & QCTRL)  
       {  
        GePrint("You pushed the ctrl key");  
       }
    

    This is the same code. Only written in python.
    However..You don't get any return until you have the Ctrl key pressed.. ** then**..some other key pressed at the same time

         c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD, c4d.BFM_INPUT_CHANNEL, msg)  
      if msg.GetLong(c4d.BFM_INPUT_QUALIFIER) & c4d.QCTRL:  
          print "You pushed the ctrl key"
    

    This looks to me like someone maybe decided that they didn't like the way C++ could get a return from just pressing the Ctrl key by itself. So they intentionally re-wrote the python version so we have to press a second key to get a return from the BFM_INPUT_QUALIFIER's.

    We'll need to hear from Yannick or Sebastian about what's going on with these qualifier keys.

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 29/10/2012 at 18:47, xxxxxxxx wrote:

    It looks as if you don't check the outcome of GetInputState().
    At least for me in an Expression Plugin it works getting only the CTRL msg.

    So try:

      
    if GetInputState() :   
        if msg ..etc:   
            print 'OK'   
    

    Cheers
    Lennart



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 01:35, xxxxxxxx wrote:

    Hi Lennart.
    This doesn't seem to work either. I thought the whole point of these keyboard and mouse functions is that you don't need to use the GetInputState() as msg is already the container with all the input data.
    Phil



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 03:16, xxxxxxxx wrote:

    If you want to replicate the CTRL+move behavior, here's how to do it:

    def MouseInput(self, doc, data, bd, win, msg) :
            if msg[c4d.BFM_INPUT_QUALIFIER]&c4d.QCTRL:
                print "CTRL Qualifier"
            
                if msg.GetLong(c4d.BFM_INPUT_CHANNEL)==c4d.BFM_INPUT_MOUSELEFT:
                    print "Begin Mouse Left Pressed"
      
                    while True:
                        bc = c4d.BaseContainer()
                        if gui.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, bc) :
                            if bc.GetLong(c4d.BFM_INPUT_CHANNEL)==c4d.BFM_INPUT_MOUSELEFT:
                                if not bc.GetBool(c4d.BFM_INPUT_VALUE) : break
      
                    print "End Mouse Left Pressed"
                    
                    return True
            
            return False
    


  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 03:29, xxxxxxxx wrote:

    Hi Yannick thank you very much for your effort.
    You're absolutely right this simulates exactly the cloning behavior and it's really good to know where to put these queries.
    But I'm guessing it is just not possible to get the qualifier key working alone like a normal key  (as I need to change the visual feedback before the mousebutton is clicked), as Scott suggested.
    Sorry for all the trouble, I guess I will put some kind of gizmo in the viewport and when clicked it will change the mode. 
    Thanks again
    Phil



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 03:57, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    I'm almost on giving up on CTRL or SHIFT and thought why not use a character key. Problem is I don't know how to check it. The SDK says >BFM_INPUT_CHANNEL

    LONG
    The channel contains the key or button ('A' means A, KEY_F1 means F1)

    F1, F2, and so on work without problem, a character not so much. I tried c4d.A, not working, I tried it as a string 'A', and I'm running out of ideas

    In the case of a key pressed, the channel returned is an integer value containing the ASCII code of the key.
    In Python we can call ord()/unichr() to convert a key code from/to its character. Here's some code:

    def KeyboardInput(self, doc, data, bd, win, msg) :
        channel = msg.GetLong(c4d.BFM_INPUT_CHANNEL)
        if channel<128: # ascii key code
            chr = str(unichr(channel))
            print chr
            if chr=='B':
                return True
        else:
            #see KEY_ enum
            print channel
        return False
    

    Also, only return True if you really used the event. So if you return False the event is passed along and not blocked.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 04:07, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    But I'm guessing it is just not possible to get the qualifier key working alone like a normal key  (as I need to change the visual feedback before the mousebutton is clicked), as Scott suggested.

    Yes, CTRL and SHIFT qualifiers are not 'normal' keys and are processed in a different way by CINEMA in plugins input events.
    Qualifiers are meant to be used in association with other keys.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 04:27, xxxxxxxx wrote:

    Alright, then I'm giving up on that thought, nevertheless the character-key-stuff will be really helpful.
    Thanks again for all the effort. 
    Phil



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 08:55, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Yes, CTRL and SHIFT qualifiers are not 'normal' keys and are processed in a different way by CINEMA in plugins input events.
    Qualifiers are meant to be used in association with other keys.

    Could you please offer an explanation why this was changed from the way C++ qualifiers work Yannick?
    In C++ we can use the qualifier keys all by themselves without needing to press a second key.
    In my own personal opinion...I really like that. And I find it rather annoying that it's not doable within python plugins.
    But maybe I'm missing the down side of having it set up this way.

    There must be a reason (benefit) why Sebastian decided to deviate from the C++ SDK implementation of the qualifiers. Could you please tell us what that reasoning(benefit?) is for changing it?

    Thanks,
    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 09:37, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Could you please offer an explanation why this was changed from the way C++ qualifiers work Yannick?
    In C++ we can use the qualifier keys all by themselves without needing to press a second key.
    In my own personal opinion...I really like that. And I find it rather annoying that it's not doable within python plugins. 
    But maybe I'm missing the down side of having it set up this way.

    I don't see any difference between qualifiers in C++ and Python plugins.
    In both C++ and Python we have to press a second key/mouse button to enter KeyboardInput()/MouseInput().
    Do you have some code showing this? I have seen the code posted by Scott above but the behavior is the same.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 10:04, xxxxxxxx wrote:

    I'm referring to just the keyboard actions by themselves.
    Not combined with mouse events. **

    C++ plugin version**
    When we press the Ctrl key all by itself. We get a return return

        GetInputState(BFM_INPUT_KEYBOARD, BFM_INPUT_CHANNEL, msg);  
      if(msg.GetLong(BFM_INPUT_QUALIFIER) & QCTRL)  
       {  
        GePrint("You pushed the ctrl key");  
       }
    

    Python plugin version.
    When we press the Ctrl key all by itself. We do not get a return.
    We only get a return if another key besides the Ctrl key is pressed

        c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD, c4d.BFM_INPUT_CHANNEL, msg)  
      if msg.GetLong(c4d.BFM_INPUT_QUALIFIER) & c4d.QCTRL:  
          print "You pushed the ctrl key"
    

    What makes this whole thing even more strange to me is that if you use this code in a python script or python tag instead of a plugin. The Ctrl key works like the C++ implementation. Meaning..You don't have to hold down a second key to get a result when the Ctrl key is pressed all by itself.

    So just in python.
    What I'm seeing is that we have two different qualifier behaviors occurring. Depending on whether it's used in a plugin situation. Or in a script or python tag situation. Using the same code.
    Is this a bug? Or is it intentional for some reason?

    -ScottA

    *Edit
    Just for sake of full clarity. Here's the python tag code I'm using.
    With the timeline running. I get a return from pressing just the Ctrl key by itself.
    While in a python plugin scenario. This does not return anything unless a second key is pressed.
    This is the same code as the python plugin code. Except of course I have to create the container by hand.

    import c4d  
    def main() :  
        
      msg = c4d.BaseContainer()      
      c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD, c4d.BFM_INPUT_CHANNEL, msg)  
      if msg.GetLong(c4d.BFM_INPUT_QUALIFIER) & c4d.QCTRL:  
          print "You pushed the ctrl key"
    


  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 11:01, xxxxxxxx wrote:

    I can't confirm this. In both C++ and Python plugins the behavior is the same: KeyboardInput() is never called when we just press CTRL or SHIFT.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/10/2012 at 11:36, xxxxxxxx wrote:

    Are using R14 to test this Yannick?
    I just tested the code in a python tag in the R14 demo. And indeed it doesn't seem to work the same way as in R12&R13.
    Maybe that's why we're getting different results?

    I still haven't used R14 that much yet. So I'm not very familiar with it. But from what I understand. Maxon changed the Ctrl key options a lot in R14 compared to earlier versions.

    -ScottA


Log in to reply