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

    Erratic Keyboard Messages in GeDialog

    Cinema 4D SDK
    python r23 windows
    3
    7
    1.1k
    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.
    • ?
      A Former User
      last edited by A Former User

      Hello,
      I am having an issue getting a consistent result with the GeDialog.Message and BFM_INPUT_KEYBOARD. In the code below, I'm listening to BFM_INPUT_CHANNEL 69 (the 'E' key) and printing to the Console. The Message will only work once or twice and then lose functionality until I interact with the GeDialog in some way. Sometimes it takes a few interactions to get it started again. In the screencast below, every time the menu icon and window title are flashing is when I am pressing the 'E' key.

      Is there a way to make this interaction more consistent, please?

      GeUserArea Message with Keyboard

      import c4d, random
      from c4d import gui
      
      GADGET_ID_GEUSERAREA = 10000
      SCROLL_ID = 10001
      SLIDER_ID = 10002
      
      class ExampleGeUserArea(c4d.gui.GeUserArea):
          width = 400
          height = 500
          bmp_cache = None
      
          def GetBitmap(self):
              bmp = c4d.bitmaps.BaseBitmap()
              bmp.Init(self.width,self.height)
              for h in range(self.height):
                  for w in range(self.width):
                      r = random.randint(0, 70)
                      bmp.SetPixel(w, h, r, r, r)
              return bmp
      
          def DrawMsg(self, x1, y1, x2, y2, msg):
              self.OffScreenOn()
              self.SetClippingRegion(x1, y1, x2, y2)
              self.DrawSetPen(c4d.Vector(1,0,0))
              self.DrawRectangle(x1, y1, x2, y2)
              if self.bmp_cache == None:
                  self.bmp_cache = self.GetBitmap()
      
              self.DrawBitmap(self.bmp_cache, x1, y1, x2, y2, 0, 0,
                              w=self.bmp_cache.GetBw(),
                              h=self.bmp_cache.GetBh(),
                              mode=c4d.BMP_NORMAL)        
      
          def Message(self, msg, result):
              # Catch the draw message to cancel it (return True)
              # and call ourself the DrawMsg with the dimension we expect
              if msg.GetId() == c4d.BFM_DRAW:
                  self.DrawMsg(0, 0, self.width, self.height, c4d.BaseContainer())
      
                  return True
          
              return c4d.gui.GeUserArea.Message(self, msg, result)
      
          def GetMinSize(self):
              return self.width,self.height
      
      class ExampleDialog(c4d.gui.GeDialog):
          geUserArea = ExampleGeUserArea()
      
          def DrawUA(self,scale):
              self.geUserArea.width = int(400*scale)
              self.geUserArea.height = int(500*scale)
              self.LayoutChanged(SCROLL_ID)
      
          def CreateLayout(self):
              self.SetTitle("GeUserArea")
              if self.ScrollGroupBegin(SCROLL_ID, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, c4d.SCROLLGROUP_HORIZ | c4d.SCROLLGROUP_VERT):
                  self.AddUserArea(GADGET_ID_GEUSERAREA, c4d.BFH_CENTER | c4d.BFH_SCALE | c4d.BFV_CENTER | c4d.BFV_SCALE, initw=gui.SizePix(400), inith=gui.SizePix(500))
                  self.AttachUserArea(self.geUserArea, GADGET_ID_GEUSERAREA)
              self.GroupEnd()
              return True
      
          def Message(self, msg, result):
              device = msg.GetLong(c4d.BFM_INPUT_DEVICE)
              channel = msg.GetLong(c4d.BFM_INPUT_CHANNEL)
      
              if device == c4d.BFM_INPUT_KEYBOARD:
                  if channel==69:
                      #E
                      print("E pressed.")
              return c4d.gui.GeDialog.Message(self, msg, result)
      
      def main():
          global dlg
          dlg = ExampleDialog()
          dlg.Open(c4d.DLG_TYPE_ASYNC, pluginid=1234567, defaultw=300, defaulth=300)
      
      
      if __name__ == "__main__":
          main()
      

      Thank you.

      1 Reply Last reply Reply Quote 0
      • M
        mp5gosu
        last edited by mp5gosu

        This happens because tools that will be called twice in short succession gain focus in the C4D layout. Therefore your Dialog loses focus as the Move tool is bound toE.
        I don't kbnow exactly how to prevent that behavior, but there should be some message that can be processed. SDK team will be more of help here.

        edit: Easy fix: return c4d.NOTOK after your print statement. That consumes the message and does not call the base function, so Cinema simply does not get notified of the event.

        1 Reply Last reply Reply Quote 0
        • ManuelM
          Manuel
          last edited by

          Hi,

          i don't think it's the reason, it look like more the even isn't propagate to this window if you really spam like hell.
          Instead of EEEEEE if you go ERERERERERERERERERERER it works a lot better.(unless you go too fast)

          I will ask the devs to see if there's kind of "optimisation" here.

          Cheers,
          Manuel

          MAXON SDK Specialist

          MAXON Registered Developer

          ? 1 Reply Last reply Reply Quote 0
          • ?
            A Former User @Manuel
            last edited by

            @m_magalhaes Hi Manuel, thank you and @mp5gosu for the replies.

            I'm trying to create a keyboard shortcut for my plugin so unfortunately ERERERERERERERERERERER isn't a workaround that I can use. Please let me know what the devs say. Thanks!

            1 Reply Last reply Reply Quote 0
            • ManuelM
              Manuel
              last edited by

              hi,

              If it's a shortcut, it should work as expected. The input key is there, it's the spam of one key that isn't.
              Just as if you press and hold the key down. You will see it catchs one input than wait a bit, than 2 and stop receiving the event.

              But let's wait for the devs' answers

              Cheers,
              Manuel

              MAXON SDK Specialist

              MAXON Registered Developer

              1 Reply Last reply Reply Quote 0
              • M
                mp5gosu
                last edited by

                Did you try my proposed fix? 😉

                ? 1 Reply Last reply Reply Quote 0
                • ?
                  A Former User @mp5gosu
                  last edited by

                  @mp5gosu Sorry, I missed it! That works! In case other devs have a solution, I'll mark yours as the right answer. Thank you!

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