Drag and Drop onto Range Slider



  • Hm,

    you want to drag and drop a data type that is not accepted by a RangeCustomGui onto it and reroute that dragged data into a BaseLink gui somewhere else? I do not think that this is possible in Python. Why cannot you use a BaseLink in your user data and reroute these inputs?

    Cheers
    zipit



  • Dragging into a BaseLink is just an example, I want to add the drag and drop freature simply for improved user experience.
    How do you know this isn't an acceptable operation? I get the drop box icon as I hover over the slider data. If this isn't possible I'll abandon this topic.



  • Hm,

    I am slightly confused, either I or you do not really understand something here ;) A RangeCustomGui obviously only accepts RangeData as drag and drop event data, since it is a GUI that has been purposely build for that type. You can set the DESC_ACCEPT description field for your description elements with which you can specify the type of BaseList2Ds you can drag and drop onto that element. But this only works for the two GUIs that are meant to display arbitrary BaseList2Ds (the BaseLink gui and the InExcludeCustomGui).

    I am still confused on what you are trying to do. At least for me it would be better to know what exactly you are trying to do rather than having "just an example".

    Cheers
    zipit



  • I just want to get the object data from the object that is dropped on the slider. Thats about as simple as I can say it.

    It looks as though you can't pass any DRAG AND DROP message from the Range Slider.

    check = op[c4d.ID_USERDATA, 1].Message(c4d.MSG_DRAGANDDROP)
    

    Console: AttributeError: 'c4d.RangeData' object has no attribute 'Message'
    but works for a link object like you said earlier.

    Is there maybe a way to draw a GeUserArea with a drop area over the Range Slider?



  • Hi,

    @gsmetzer said in Drag and Drop onto Range Slider:

    I just want to get the object data from the object that is dropped on the slider. Thats about as simple as I can say it.

    It looks as though you can't pass any DRAG AND DROP message from the Range Slider.

    check = op[c4d.ID_USERDATA, 1].Message(c4d.MSG_DRAGANDDROP)
    

    Console: AttributeError: 'c4d.RangeData' object has no attribute 'Message'
    but works for a link object like you said earlier.

    Is there maybe a way to draw a GeUserArea with a drop area over the Range Slider?

    c4d.C4DAtom.Message() is a method of the atomic type of c4d -c4d.C4DAtom. So you can only invoke it on types that are deriving from that type. Most types that are presented in GUI elements are not derived from C4dAtom (e.g. float, int, bool, str, c4d.Vector, c4d.SplineData, c4d.RangeData, etc.). This is the reason why you get the exception: RangeData is not derived from c4d.C4DAtom, while a BaseList2D (the type objects are collected under in the object link GUIs) is derived from it.

    But there is also another misunderstanding. You do not have to invoke Message() yourself , but Cinema does it for you. And Message() is also invoked on the C4DAtom that is hosting the description that drag and drop event has occurred on, not on its data elements (for the reasons described above). You can then listen to that message in the implementation of your atoms Message() method - or message() function in case of a scripting object - as shown above. Here is a more complete example, for your case of a Python generator object:

    import c4d
    # Put this in a Python generator and drag and drop stuff onto that generator's description elements, 
    # i.e. stuff in the attribute manager.
    
    def main():
        return c4d.BaseObject(c4d.Ocube)
    
    def message(mid, data):
        if mid == c4d.MSG_DRAGANDDROP:
            print mid, data
    

    The drag and drop event also sends its drag and drop data, but it is a PyCObject, which is of no use to us, since it is only a pointer to the C(++) data structure of that drag and drop data. So to properly react to drag and drop events in Python, we only can deal with drag and drop events of data that matches the data type of the gadget/element it is dropped onto. Since we then can either just compare the (cached) previous value and the new current value or just deal with the current value.

    I hope this helps.

    edit: While GeUserArea also offers a Message() method, you cannot use it. Because GeUserAreas are for dialog resources and not description resources. Everything displayed in the attribute manager has a description resource (with ToolData being an exception). You also cannot place / draw stuff on top of each other in general in c4d.

    Cheers
    zipit



  • Hello,

    as @zipit said, it's not possible in python as the object is a PyCObject.

    What kind of workflow do you want to achieve with this ?

    Cheers,
    Manuel



  • Ok, I see, @zipit example finally got a message to work for me. (I'm still wrapping my head around the message system) Thank You Zipit.

    I'm not ready to dive into C++ yet. I would love to be able to use a PyCObject but it looks as though that may be a ways off for me.

    @m_magalhaes I am building an object list by dropping objects on the range slider and using the range slider's knot data to animate the object. The drag and drop would be a much cleaner way of building that list without using an InExclude or bunch of Link's.

    Looks like I will just use Link for now. If you know of any sample PyCObject code I would love to have a look. Thank you for the help.



  • Hi,

    Looks like I will just use Link for now. If you know of any sample PyCObject code I would love to have a look. Thank you for the help.

    There are no such examples. PyCObject is a type of Python itself, it is meant to pass C(++) data through Python as a glue language. You can finde here more information on that class. But don't expect much from it, it is just an extension of the atomic Python type - PyObject and meant to pass the data opaquely, i.e. access form Python is not intended. You will have to use C++ to get access to all message data.

    Cheers
    zipit



  • hello,

    As @zipit said there's nothing you can do with this object.
    But I'm not even sure you can do what you want to achieve in C++

    Just to understand, how do you want to link the animation with the rangedata ?

    Cheers,
    Manuel



  • @m_magalhaes My aim is to create a drag and drop interface so the user can drop an object between the knots of the range slider. The range slider would represent the timeline and each knot in the range slider an in-out edit point. Drag and drop is just a cleaner way to assign edit points to an object than iterating through a link list or inExclude list.

    SetEditorMode(c4d.MODE_ON)
    SetEditorMode(c4d.MODE_OFF)
    


  • @gsmetzer

    Hi,

    drag and drop messages do contain the position of the mouse at the time of the event. However, to make use of that position in your intended use case, you would need to know the screen space bounding box of the description element on which that event did occur. This is not possible in Python, no matter if the drag event has been accepted by the element or not (I think this is not even possible in C++).

    There are countless ways how you could approach this. But the most important thing is IMHO to ask yourself, if diluting the concepts of timeline and attribute manger is a good idea in the first place. What are the trade-offs and are you willing to pay a probably rather hefty price of development effort for such an unusual feature? The answer might be very well yes, but at least considering alternative concepts seems to be a good idea.

    Cheers
    zipit



  • hello,

    I'll mark this thread as solved tomorrow if you have nothing to add.

    Cheers,
    Manuel