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

    [SOLVED]Start Drag from GeUserArea

    PYTHON Development
    0
    19
    3.3k
    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.
    • H
      Helper
      last edited by

      On 07/06/2017 at 03:19, xxxxxxxx wrote:

      Gonna do some test but I guess I can mark the thread as solved.

      Thanks you alot.

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 07/06/2017 at 13:57, xxxxxxxx wrote:

        I don't success to get it to work properly. The main issue is I don't know when to start drag event. Same for end it. So for exemple it didn't make the difference beetween a simple click and a drag event.

        Moreover kills event doesn't seem to work.
        Here is an exemple

        import c4d
          
        class Area(c4d.gui.GeUserArea) :
          
            xValue = 0
            yValue = 0
           
            def DrawMsg(self, x1, y1, x2, y2, msg) : 
          
                self.DrawSetPen(c4d.Vector(.2))
                self.DrawRectangle(x1, y1, x2, y2)
                
                
            def drag_message(self, msg, result) :
                bc_click = c4d.BaseContainer()
                self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, bc_click)
                mousex = bc_click.GetLong(c4d.BFM_INPUT_X)
                mousey = bc_click.GetLong(c4d.BFM_INPUT_X)
          
                self.MouseDragStart(c4d.KEY_MLEFT, mousex, mousey, c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE | c4d.MOUSEDRAGFLAGS_NOMOVE)
            
                mx = mousex
                my = mousey
                drag_result, dx, dy, channels = self.MouseDrag()
                first = True
                drag = False
                while drag_result == c4d.MOUSEDRAGRESULT_CONTINUE:
                    drag = True
                    if first:
                        print 'Start'
                        first = False
                    mx += dx
                    my += dy
                    if dx==0.0 and dy==0.0:
                        drag_result, dx, dy, channels = self.MouseDrag()
                        continue
                    self.KillEvents() #Don't work
          
                    drag_result, dx, dy, channel = self.MouseDrag()
                    print "Mouse Dragging at position [%f,%f]" % (mx, my)
          
                if self.MouseDragEnd() == c4d.MOUSEDRAGRESULT_FINISHED and drag:
                    print "Mouse Dragging Ended: ", self.MouseDragEnd()
          
                return
                
            def Message(self, msg, result) :
                self.drag_message(msg, result)
                if msg.GetId() == c4d.BFM_INPUT:
                    print 'clicked'
                return c4d.gui.GeUserArea.Message(self, msg, result)
                
          
        class MyDialog(c4d.gui.GeDialog) :
          
            def __init__(self, area) :
                self.area = area
          
            def CreateLayout(self) :
                self.SetTitle("My UserArea")
          
                self.AddUserArea(1000, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)
                self.AttachUserArea(self.area, 1000)
                self.GroupEnd()
                return True
          
        def main() :
            area = Area()
            dialog = None
          
            dialog = MyDialog(area)
            dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=500, defaulth=500)
          
        if __name__=='__main__':
            main()
        

        As you could see if you click its also print you drag. Hope you understand my problem ^^'. Who is Get the start of a drag event and get the end of a drag event. Like that in the Message function I can do if START_OF_DRAG : self.drag_message, and if END_OF_DRAG : print 'end'

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 08/06/2017 at 03:25, xxxxxxxx wrote:

          To check for a drag event the solution is to simply use MouseDragStart()/MouseDrag()/MouseDragEnd().
          Instead of Message(), move the mouse dragging into InputEvent().
          Then to check if the started drag processing was just a click add this condition at the beginning of the while dragging loop:

          if bc_click[c4d.BFM_INPUT_VALUE] == 0:
              break
          

          This condition exits the loop whenever the mouse left button is released. Then check if the mouse was really moved or if it was just a mouse click.

          Finally, I don't think KillEvents() is useful here if it's called inside the while dragging loop.

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 08/06/2017 at 04:40, xxxxxxxx wrote:

            Thanks you sadly I didnt succes to get the click evaluated properly.

            import c4d
              
            class Area(c4d.gui.GeUserArea) :
              
                def DrawMsg(self, x1, y1, x2, y2, msg) : 
                    self.DrawSetPen(c4d.Vector(.2))
                    self.DrawRectangle(x1, y1, x2, y2)
                    
                    
                def InputEvent(self, msg) :
                    mousex = msg[c4d.BFM_INPUT_X]
                    mousey = msg[c4d.BFM_INPUT_Y]
                    
                    self.MouseDragStart(c4d.KEY_MLEFT, mousex, mousey, c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE | c4d.MOUSEDRAGFLAGS_NOMOVE)
                    
                    mx = mousex
                    my = mousey
                    while True:
                        if msg[c4d.BFM_INPUT_VALUE] == 0:
                            break
                        
                        result, dx, dy, channels = self.MouseDrag()
                        if result!=c4d.MOUSEDRAGRESULT_CONTINUE: break
                        
                        #If we don't move that mean we clicked'
                        if not dx or not dy:
                            print 'clicked'
                        else:
                            mx += dx
                            my += dy
                            
                            print "Mouse Dragging at position [%f,%f]" % (mx, my)
                        
              
                    
                    end_state = self.MouseDragEnd()
                    if end_state == c4d.MOUSEDRAGRESULT_ESCAPE:
                        print "Escaped"
                    elif end_state == c4d.MOUSEDRAGRESULT_FINISHED:
                        print 'Mouse Drag End'             
                    
                        
                    return True        
              
            class MyDialog(c4d.gui.GeDialog) :
                def CreateLayout(self) :
                    self.area = Area()
                    
                    self.AddUserArea(1000, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)
                    self.AttachUserArea(self.area, 1000)
                    return True
              
            def main() :
                dialog = MyDialog()
                dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=500, defaulth=500)
              
            if __name__=='__main__':
                main()
            

            As you could see, the first tick is always drag (dx and dy are not equal to 0) even if you don't move the mouse.

            Moreover I would like to ask is there a way for changing mouse icon? For exemple I would like to change it when she is outside of my GeUserArea.

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 08/06/2017 at 08:14, xxxxxxxx wrote:

              Sorry my first post was missing information.
              MouseDrag() has to be called first in the loop for each drag event. Then the current input state for the mouse left button has to be retrieved before checking c4d.BFM_INPUT_VALUE.
              So the dragging loop would be:

              mx = mousex
              my = mousey
              state = c4d.BaseContainer()
              while True:
                
                  result, dx, dy, channels = self.MouseDrag()
                  if result == c4d.MOUSEDRAGRESULT_ESCAPE:
                    break
                
                  if not self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, state) :
                      break
                
                  if state[c4d.BFM_INPUT_VALUE] == 0:
                      print "Released Left Mouse"
                      break
                
                  if dx == 0 and dy == 0:
                      continue
                
                  mx += dx
                  my += dy
                  print "Mouse Dragging at position [%f,%f]" % (mx, my)
              

              state[c4d.BFM_INPUT_VALUE] gives the mouse left button clicked state. So this allows to check when the mouse button has been released.
              If the mouse position hasn't changed then no dragging should be processed.

              You can change the mouse icon with gui.SetMousePointer().

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 08/06/2017 at 09:38, xxxxxxxx wrote:

                Thanks you. Tested and solved ! 🙂

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 09/06/2017 at 00:54, xxxxxxxx wrote:

                  Sorry to bump this thread but is there a way for start drag from a GeUserArea and recieve drop message from TreeViewCustomGui? Or at least is it possible to send message to this TreeViewCustomGui? Or a timer? 
                  Just tell me yes or no 😉

                  Cause I think I must do the following thing but I prefer ask if there is no other way before ^^
                  Make my timer function into my GeDialog who call a custom timer function inside my TreeView 🙂

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    On 09/06/2017 at 02:29, xxxxxxxx wrote:

                    GeUserArea.HandleMouseDrag() is missing in the Python API so it would be really difficult and hacky to send drag and drop data to other gadgets.

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      On 09/06/2017 at 02:46, xxxxxxxx wrote:

                      Ok thanks for confirming ! 🙂

                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        On 09/06/2017 at 13:53, xxxxxxxx wrote:

                        Sorry again to bump this thread, but I don't udnerstand the output code while the mouse is not moving, delta y is always -22 while it should be 0

                            def InputEvent(self, msg) :
                                mousex = msg[c4d.BFM_INPUT_X]
                                mousey = msg[c4d.BFM_INPUT_Y]
                          
                                self.MouseDragStart(c4d.KEY_MLEFT, mousex, mousey, c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE | c4d.MOUSEDRAGFLAGS_NOMOVE)
                          
                                start_x = mousex
                                start_y = mousey
                          
                                mx = mousex
                                my = mousey
                                state = c4d.BaseContainer()
                                while True:
                          
                                    result, dx, dy, channels = self.MouseDrag()
                                    if result == c4d.MOUSEDRAGRESULT_ESCAPE:
                                        break
                          
                                    if not self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, state) :
                                        break
                          
                                    if state[c4d.BFM_INPUT_VALUE] == 0:
                                        print "Released Left Mouse"
                                        break
                          
                                    if dx == 0 and dy == 0: #dy != 0 while not moving
                                        continue
                          
                                    mx += dx
                                    my += dy
                          
                                   #Should not be display if not moving
                                   print 'drag'
                          
                                print start_x - mx
                                print start_y - my #-22 if not moving
                          
                                return True
                        
                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          On 12/06/2017 at 07:06, xxxxxxxx wrote:

                          Originally posted by xxxxxxxx

                          Sorry again to bump this thread, but I don't understand the output code while the mouse is not moving, delta y is always -22 while it should be 0

                          If the mouse doesn't move dx and dy are 0. The final mouse delta X and Y values depends on how you calculate the current mouse position.
                          It's better to subtract the mouse drag delta values:

                          mx -= dx
                          my -= dy
                          

                          Then the final delta value can be calculated:
                          print mx - mousex
                          print my - mousey

                          If you don't want MouseDrag() to return when the mouse doesn't move, don't pass MOUSEDRAGFLAGS_NOMOVE to MouseDragStart().

                          1 Reply Last reply Reply Quote 0
                          • H
                            Helper
                            last edited by

                            On 13/06/2017 at 04:52, xxxxxxxx wrote:

                            Ok I get why it's wrong... The corect loop initialization is:

                                    mousex = msg[c4d.BFM_INPUT_X]
                                    mousey = msg[c4d.BFM_INPUT_Y]
                                    
                                    self.MouseDragStart(c4d.KEY_MLEFT, mousex, mousey, c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE | c4d.MOUSEDRAGFLAGS_NOMOVE)
                                    
                                    while self.MouseDrag()[0] == c4d.MOUSEDRAGRESULT_CONTINUE:
                                        if msg[c4d.BFM_INPUT_VALUE] == 0:
                                            break
                                        
                                        result, dx, dy, channels = self.MouseDrag()
                                        print "dx {} - dy {}".format(dx, dy)
                            

                            While in the documention of https://developers.maxon.net/docs/py/2023_2/modules/c4d.gui/EditorWindow/index.html#EditorWindow.MouseDragStart the main drag loop is done with While true, which give you a wrong value for dx/dy for the first packet of the drag input.

                            So doing it like in the C++ exemple

                                win->MouseDragStart(button, mouseX, mouseY, MOUSEDRAGFLAGS_DONTHIDEMOUSE | MOUSEDRAGFLAGS_NOMOVE);
                                while (win->MouseDrag(&dx, &dy, &device) == MOUSEDRAGRESULT_CONTINUE)
                            

                            give us in python

                                    self.MouseDragStart(c4d.KEY_MLEFT, mousex, mousey, c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE | c4d.MOUSEDRAGFLAGS_NOMOVE)
                                    
                                    while self.MouseDrag()[0] == c4d.MOUSEDRAGRESULT_CONTINUE:
                            

                            Anyway thanks for your support ! 🙂

                            1 Reply Last reply Reply Quote 0
                            • H
                              Helper
                              last edited by

                              On 13/06/2017 at 08:18, xxxxxxxx wrote:

                              I can't confirm that because the delta values returned from the call to MouseDrag()[0] aren't processed for each while loop:

                              while self.MouseDrag()[0] == c4d.MOUSEDRAGRESULT_CONTINUE: # dx, dy and channels not retrieved and processed
                              

                              There should be only one MouseDrag() call for each while loop.

                              1 Reply Last reply Reply Quote 0
                              • H
                                Helper
                                last edited by

                                On 13/06/2017 at 08:28, xxxxxxxx wrote:

                                Juste copy paste thoses two codes and do a normal click without dragging. Just a simple click (no move, nothing just a click), So result should be 0 and 0 for dx/dy in all case (in all packet of the drag pool)
                                The first one give correct result for dx , dy

                                import c4d
                                  
                                class Area(c4d.gui.GeUserArea) :
                                  
                                    def InputEvent(self, msg) :
                                        mousex = msg[c4d.BFM_INPUT_X]
                                        mousey = msg[c4d.BFM_INPUT_Y]
                                        
                                        self.MouseDragStart(c4d.KEY_MLEFT, mousex, mousey, c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE | c4d.MOUSEDRAGFLAGS_NOMOVE)
                                        
                                        while self.MouseDrag()[0]:
                                            if msg[c4d.BFM_INPUT_VALUE] == 0:
                                                break
                                            
                                            result, dx, dy, channels = self.MouseDrag()
                                            if result!=c4d.MOUSEDRAGRESULT_CONTINUE: break
                                            
                                            print "dx {} - dy {}".format(dx, dy)
                                                        
                                        return True
                                  
                                class MyDialog(c4d.gui.GeDialog) :
                                    def CreateLayout(self) :
                                        self.area = Area()
                                        
                                        self.AddUserArea(1000, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)
                                        self.AttachUserArea(self.area, 1000)
                                        return True
                                  
                                def main() :
                                    dialog = MyDialog()
                                    dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=500, defaulth=500)
                                  
                                if __name__=='__main__':
                                    main()
                                

                                While the sdk code(using While True) give wrong result for dx, dy in the first packet (dx 4 and dy 4)

                                import c4d
                                  
                                class Area(c4d.gui.GeUserArea) :
                                  
                                    def InputEvent(self, msg) :
                                        mousex = msg[c4d.BFM_INPUT_X]
                                        mousey = msg[c4d.BFM_INPUT_Y]
                                        
                                        self.MouseDragStart(c4d.KEY_MLEFT, mousex, mousey, c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE | c4d.MOUSEDRAGFLAGS_NOMOVE)
                                        
                                        while True:
                                            if msg[c4d.BFM_INPUT_VALUE] == 0:
                                                break
                                            
                                            result, dx, dy, channels = self.MouseDrag()
                                            if result!=c4d.MOUSEDRAGRESULT_CONTINUE: break
                                            
                                            print "dx {} - dy {}".format(dx, dy)
                                                        
                                        return True
                                  
                                class MyDialog(c4d.gui.GeDialog) :
                                    def CreateLayout(self) :
                                        self.area = Area()
                                        
                                        self.AddUserArea(1000, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)
                                        self.AttachUserArea(self.area, 1000)
                                        return True
                                  
                                def main() :
                                    dialog = MyDialog()
                                    dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=500, defaulth=500)
                                  
                                if __name__=='__main__':
                                    main()
                                
                                1 Reply Last reply Reply Quote 0
                                • H
                                  Helper
                                  last edited by

                                  On 14/06/2017 at 03:17, xxxxxxxx wrote:

                                  You're not retrieving and printing the delta values dx and dy from the self.MouseDrag()[0] calls in the first script. The delta values are 4.0 for the first mouse drag there too.

                                  The limitation with MouseDrag() in Python is the language doesn't support assignments in expressions.

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