Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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

    Grabbing a GeUserArea when using InputEvent

    Cinema 4D SDK
    r23 python windows
    2
    4
    499
    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

      Hello,
      Please excuse my multiple posts about the GeUserArea in a Scrollgroup, but I was unable to find any information about the following in the documentation or the forum.

      By default, the GeUserArea in a ScrollGroup in this script can be grabbed by middle-mouse button clicking and dragging.
      GeUserArea_Grab.jpg

      In my plugin however, I need to override the GeUserArea:InputEvent method. This seems to be where the grabbing functionality exists. How can I add the middle-mouse grab to my InputEvent override? Thank you!

      import c4d
      import 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 InputEvent(self, msg):
              #This stops the grab functionality
              device = msg.GetLong(c4d.BFM_INPUT_DEVICE)
              channel = msg.GetLong(c4d.BFM_INPUT_CHANNEL)
              if device == c4d.BFM_INPUT_MOUSE and channel == c4d.BFM_INPUT_MOUSEMIDDLE:
                  print (device,channel)
              return True
          """
      
          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 _centerAlignScrollGroup(self):
              _, _, sgw, sgh = self.GetItemDim(SCROLL_ID).values()
              _, _, uaw, uah = self.GetItemDim(GADGET_ID_GEUSERAREA).values()
      
              sax1, say1, sax2, say2 = self.GetVisibleArea(SCROLL_ID).values()
              dx, dy = sgw - (sax2 - sax1), sgh - (say2 - say1) # 16, 15
              sgw -= dx
              sgh -= dy
      
              x, y = int((uaw - sgw) * .5), int((uah - sgh) * .5)
              self.SetVisibleArea(SCROLL_ID, x, y, x + sgw, y + sgh)
      
          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()
              self.AddEditSlider(SLIDER_ID, c4d.BFH_SCALEFIT | c4d.BFV_CENTER)
              return True
      
          def InitValues(self):
              self.SetFloat(SLIDER_ID, 1.0, min=0.01, max=2, step=0.01)
              self._centerAlignScrollGroup()
              return True
      
          def Command(self, id, msg):
              if id == SLIDER_ID:
                  self.DrawUA(msg[c4d.BFM_ACTION_VALUE])
              self._centerAlignScrollGroup()
              return True
      
      
      def main():
          global dlg
          dlg = ExampleDialog()
          dlg.Open(c4d.DLG_TYPE_ASYNC, pluginid=1234567, defaultw=300, defaulth=300)
      
      
      if __name__ == "__main__":
          main()
      
      1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand
        last edited by

        Hi @blastframe,

        thank you for reaching out to us. You are returning True in your commented InputEvent which consumes that event. So you have to return False and it will work like you want it to work. Although not being stated in the documents, I would also say a call to the base/super implementation would not hurt here for retrieving the return value.

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

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

          @ferdinand That was so simple, thank you!

          How would I call the Base/Super Implementation in this case? Do you mean something like this?

          def InputEvent(self, msg):
              # override code goes here
              return super().InputEvent(msg)
          
          1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand
            last edited by ferdinand

            Hi @blastframe,

            yes, that would be one, and probably the more modern way to do it. I personally like also an explicit call to the base implementation. I think it is more readable for someone else reading your code. But that is probably a rather subjective choice. So for clarity, I am speaking about something like this:

            foo = bar * baz
            return c4d.gui.GeUserArea.InputEvent(self, msg)
            

            There is of course the advantage of super taking care of calling the proper implementation(s) for you which is not taken care of by this approach, but you cannot have everything and in this case things are rather unambiguous for us here 😉

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

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