Hello @pyxelrigger,
Thank you for reaching out to us. Please share your code in the future, especially when you have a demo. In the days of AI it is not that time consuming anymore to pump out a basic setup, but it still costs me time to write the query to ask the AI to write me a GeDialog with an edit field in it and then fix the little mistakes the AI makes.
What you want to do is not directly possible. The edit field of a dialog does not support drag and drop events for scene elements. You are comparing it with the multiline edit of the console and with a string parameter in a description, which are both entirely different things.
What you can do, is implement the drag handling yourself. At least to some degree. You cannot mimic the drag-and-drop mouse cursor because the edit field over-rules you there. You can only set the drag cursor when you implement the gadget yourself. You could implement for example a text field with a GeUserArea
which lets you both type and drag, and then also displays the correct drag cursor.
Here is a quick and dirty version, which simply handles the drag event on a dialog level.
Cheers,
Ferdinand
Result
Code
"""Demonstrates how to handle drag events in a GeDialog.
"""
import c4d
from c4d import gui
class MyDialog(gui.GeDialog):
"""A simple dialog that displays a text edit field.
"""
ID_TEXTEDIT: int = 1000
def CreateLayout(self) -> bool:
"""Called by Cinema 4D to let the dialog populate its controls.
"""
self.SetTitle('My Dialog')
self.AddEditText(MyDialog.ID_TEXTEDIT, c4d.BFH_SCALEFIT, 200, 26)
return True
def InitValues(self) -> bool:
"""Called by Cinema 4D to let the dialog initialize its controls.
"""
self.SetString(MyDialog.ID_TEXTEDIT, "Initial text")
return True
def Message(self, msg: c4d.BaseContainer, result: c4d.BaseContainer) -> bool:
"""Called by Cinema 4D to convey events to the dialog.
We use it here to handle drag events.
"""
# This is an on-going drag event, i.e., the user is actively dragging something over the
# dialog and the user is hitting the edit text field.
if (msg.GetId() == c4d.BFM_DRAGRECEIVE and
self.CheckDropArea(MyDialog.ID_TEXTEDIT, msg, True, True)):
# Set the cursor: Does not work because we do not own the gadget implementation, the
# edit text field overwrites our cursor.
# self.SetDragDestination(c4d.MOUSE_POINT_HAND)
# We unpack the drag data from the drag message. The drag data is a dictionary with two
# keys: 'type' and 'object'. The 'type' key holds the type of the drag data (e.g.,
# files). The 'object' key holds the actual drag data (e.g., a list of files).
dragData: dict = self.GetDragObject(msg)
dragType: int = dragData.get('type', c4d.NOTOK)
dragObject: any = dragData.get('object', None)
if dragType == c4d.NOTOK or dragObject is None:
return c4d.gui.GeDialog.Message(self, msg, result)
text: str | None = None
# An atom array (a C++ thing which does not exist in Python) is a list of scene elements.
# Objects, tags, layers, shaders, materials, etc. are currently dragged over the dialog.
if dragType == c4d.DRAGTYPE_ATOMARRAY:
text = (", ".join([obj.GetName() for obj in dragObject])
if len(dragObject) > 1 else dragObject[0].GetName())
# Unknown file types, images, or scenes are currently dragged over the dialog.
if dragType in (c4d.DRAGTYPE_FILES, c4d.DRAGTYPE_FILENAME_IMAGE,
c4d.DRAGTYPE_FILENAME_OTHER, c4d.DRAGTYPE_FILENAME_SCENE):
dragObject = list(dragObject) if not isinstance(dragObject, list) else dragObject
text = (", ".join(dragObject) if len(dragObject) > 1 else dragObject[0])
# We set the text in the edit text field when we had a valid drag event.
if text is not None:
self.SetString(MyDialog.ID_TEXTEDIT, text)
return c4d.gui.GeDialog.Message(self, msg, result)
dialog: MyDialog = MyDialog()
if __name__=='__main__':
dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, xpos=-2, ypos=-2, defaultw=400, default=400)