Drag&Drop an image in a gui field



  • I have User Area with some images.
    Now I want to drag&drop one of those images in the UA to a Gui field, so I can get the filename of the chosen image.
    Something like this.
    1b55733c-40c7-4271-b104-41e558e7220f-image.png.

    Questions:

    • what kind of field should the Gui field be.
      A link field (top right field) or a simple text field (2e top right field)?
    • how to initiate a drag&drop in the UA?
    • how to know the image is dropped on the gui field?
    • should the field, where the image should be dropped (the gui field), also be an UA?

    Hope you can help me with a example.

    -Pim



  • Hi @pim you have to use GeUserArea.HandleMouseDrag.

    • what kind of field should the Gui field be?
      • Any that accept the DRAGRTYPE you passed, so if you pass DRAGTYPE_FILENAME_IMAGE, all Gadget that accepts a DRAGTYPE_FILENAME_IMAGE will accept the drag operation.
    • how to initiate a drag&drop in the UA?
      • Use HandleMouseDrag in your InputEvent method.
    • how to know the image is dropped on the GUI field?
      • By calling HandleMouseDrag, your code is paused until the drag operation ended. You have no way to know if the operation changed anything in the scene (you could for sure listen for EVMSG_CHANGE) the return value of HandleMouseDrag only indicate you if a drag/Drop operation happened.
    • should the field, where the image should be dropped (the gui field), also be an UA?
      • No as long as the Gadget(IcustomGUi / GeUserArea) accepts the dragtype.

    Here an example for file.

    import c4d
    
    
    class DraggingArea(c4d.gui.GeUserArea):
    
        def InputEvent(self, msg):
            filePath = "MySuperPath"
            self.HandleMouseDrag(msg, c4d.DRAGTYPE_FILENAME_IMAGE, filePath, 0)
    
            return True
    
    
    class MyDialog(c4d.gui.GeDialog):
        """
        Creates a Dialog with only a GeUserArea within.
        """
    
        def __init__(self):
            # It's important to stores our Python implementation instance of the GeUserArea in class variable,
            # This way we are sure the GeUserArea instance live as long as teh GeDialog.
            self.area = DraggingArea()
            print "droped"
    
        def CreateLayout(self):
            """
            This method is called automatically when Cinema 4D Create the Layout (display) of the Dialog.
            """
            self.AddUserArea(1000, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT)
            self.AttachUserArea(self.area, 1000)
            return True
    
    
    def main():
        # Creates a new dialog
        dialog = MyDialog()
    
        # Opens it
        dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=500, defaulth=500)
    
    
    if __name__ == '__main__':
        main()
    

    In any case, I will extend the python documentation to have all information about each type but here a summary:

    • DRAGTYPE_FILES

    • DRAGTYPE_FILENAME_SCENE

    • DRAGTYPE_FILENAME_OTHER

    • DRAGTYPE_FILENAME_IMAGE
      You should pass a string.

    • DRAGTYPE_ATOMARRAY
      A list of c4d.C4DAtom object

    • DRAGTYPE_DESCID
      A dict {"did": the c4d.DescID, "arr": a list of c4d.C4DAtom object}

    • DRAGTYPE_RGB
      A c4d.Vector

    • DRAGTYPE_RGB_ARRAY
      A list of c4d.Vector

    • DRAGTYPE_RGBA_ARRAY
      A maxon.BaseArray(maxon.ColorA)

    Other types are not supported.

    Cheers,
    Maxime.



  • Yes, it works great.
    0f447115-4f05-484b-9297-3e136daf10af-image.png

    Some questions:

    • does HandleMouseDrag() now replace MouseDrag(), MouseDragStart() and others.

    • how to get the mouse coordinates where the drag started.
      Or better, I will have some pictures in the UA, how to know which picture is being dragged&dropped?

    • where and when to call self.SetDragDestination(c4d.MOUSE_CROSS).
      Just before HandleMouseDrag in InputEvent()?

    • HandleMouseDrag() is in the UA InputEvent().
      For which message ID should I look before starting HandleMouseDrag().
      In my InputEvent() function also other messages are handled.



    1. Correct, You can then process this as a standard Cinema 4D drag operation and react to BFM_DRAGRECEIVE in your GeUserArea Message method.

    2. You can retrieve it from BFM_INPUT_X and BFM_INPUT_Y

        def InputEvent(self, msg):
            mouseX = msg[c4d.BFM_INPUT_X]
            mouseY = msg[c4d.BFM_INPUT_Y]
    
    1. As you will do in a normal drag process so in your Message method override.

    2. InputEvent is only called with BFM_INPUT, so if you want to do something before handling the drag, then do it previously and avoid HandleMouseDrag.

    Hope it helps,
    Cheers,
    Maxime.


Log in to reply