Is that posible to create a dialog like this with python ?
-
Hi Plugincafe
I'm wondering to create a window dialog like Cinema 4D About Dialog.
Rounded corner, without window frame, fade in fade out and transparency maybe ?
is that poible to do that?
Or is there any other way to highly customize the window? -
Hello @gheyret,
Thank you for reaching out to us. In short what you want to do is mostly not possible, as the About dialog of Cinema 4D is highly customized.
You can have a borderless dialog in Cinema 4D with
DLG_TYPE_ASYNC_POPUPEDIT
. Fading of gadgets is possible withBFM_FADE
, but not on a dialog level for users. Rounded corners and transparencies are not possible at all.When you want a color other than the builtin background color of dialogs, you will need to cover the whole dialog with a
GeUserArea
canvas or bitmap. And even then a small border will be left, even in borderless mode. You will also have to implement a way to close the dialog without its title bar; this is usually done via the dialog focus state. Finally, it is also not possible to reimplement moving the dialog window, as you can neither get or set the position of the window handle. Find below a quick draft of how close you can get.If you really need something like this, I recommend using a third-party UI library like QT, tkInter, imGUI, and others.
Cheers,
FerdinandResult:
Code:
"""Realizes a dialog with not border and a white background. """ import c4d class CanvasArea(c4d.gui.GeUserArea): """Realizes a white background element with text on it. """ # Default size of the gadget. DEFAULT_SIZE: tuple[int, int] = (50, 50) # The drawing colors and the offset of the drawn text in relation to the origin. COLOR_BACKGROUND: c4d.Vector = c4d.Vector(1) COLOR_TEXT: c4d.Vector = c4d.Vector(.1) OFFSET_TEXT: tuple[int, int] = (5, 5) # Indicates a f block. NEW_BLOCK: int = -1 def __init__(self) -> None: """Initializes the canvas area. """ self._size: tuple[int, int] = CanvasArea.DEFAULT_SIZE self._value: str = "" def GetMinSize(self) -> tuple[int, int]: """Returns the minimum size of the canvas area. """ return self._size def DrawMsg(self, x1: int, y1: int, x2: int, y2: int, msg: c4d.BaseContainer) -> None: """Draws the white background and text on it. """ self.DrawSetPen(CanvasArea.COLOR_BACKGROUND) self.DrawSetTextCol(CanvasArea.COLOR_TEXT, CanvasArea.COLOR_BACKGROUND) self.DrawRectangle(x1, y1, x2, y2) self.DrawSetFont(c4d.FONT_STANDARD) self.DrawText(self._value, *CanvasArea.OFFSET_TEXT) return @property def Value(self) -> str: """Returns the current value of the instance. """ return self._value @Value.setter def Value(self, value: str) -> None: """Sets the value of the instance. """ self._value = str(value) self.Redraw() class MyDialog(c4d.gui.GeDialog): """Realizes a simple dialog that uses and #InputArea. """ ID_GRP_MAIN: int = 1000 # The identifier for the main layout group in the dialog. ID_USR_CANVAS: int = 1001 # The identifier for an #CanvasArea field in the dialog. def __init__(self) -> None: """Initializes the dialog. """ self._canvas: CanvasArea = CanvasArea() self._canvas.Value = "Hello World" def CreateLayout(self) -> bool: """Adds the InputArea gadget to the dialog inside a main layout group. """ self.SetTitle("Canvas Area Example") self.GroupBegin(MyDialog.ID_GRP_MAIN, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT) self.GroupBorderSpace(5, 5, 5, 5) self.AddUserArea(MyDialog.ID_USR_CANVAS, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT) self.AttachUserArea(self._canvas, MyDialog.ID_USR_CANVAS) self.GroupEnd() return True def Message(self, msg: c4d.BaseContainer, result: c4d.BaseContainer) -> int: """Called by Cinema 4D to convey events to the dialog. """ # Close the dialog when it loses focus. if msg.GetId() == c4d.BFM_LOSTFOCUS: self.Close() return super().Message(msg, result) if __name__ == "__main__": # Run the example dialog. It is not recommended to use async dialogs in Script Manager scripts # in a production environment. dlg: MyDialog = MyDialog() dlg.Open(c4d.DLG_TYPE_ASYNC_POPUPEDIT, defaultw=300, default=200)
-
Hi @ferdinand
Thank you for your reply. In fact, I have thought of several different solutions, such as:-
Take a screenshot using third-party library like pillow or pywin32 and use it as the background in
GeUserArea
, and draw some UI element what i want. -
Just using pyside2 to draw the user interface.
-
Make a tiny software and use socket library to interact with C4D.
But the aforementioned methods, in my opinion, lack the convenience and safety offered by C4D's methods. Additionally, it is worth noting that the methods I mentioned above may have certain imperfection.
In fact, a few years ago I was concerned about whether there is a relevant way to achieve the effect I want, and tried to import Pyside2 in C4D, but there will be a "DLL import failed" error, this problem has been bothering me for a long time, and I still do not know how to deal with this problem.
I realized that some of the effects of the "About" dialog box in C4D were exactly what I was looking for, so I came back to the forum to ask for your help again.
-
-
Hey @gheyret,
Make a tiny software and use socket library to interact with C4D.
If I understand you correctly here, then yes, this is probably the best way. You have basically two ways to integrate another GUI library into Cinema 4D.
- Install the library in one of the paths where you can install external libs in Cinema 4D, c4dpy, etc. The problem with this is that the Python VM of Cinema 4D is very similar to
CPython
, i.e., the standard Python, but not identical. And GUI libraries tend to be very specific about the environments they run in. We do not support third party GUI libraries in c4d for multiple reasons (tkinter is not part of our Python for exmple). We primarily want to enforce a uniform UI but the technical difficulties that come with using them is also one. - Run the foreign GUI in a standard CPython instance of your choice or whatever the GUI lib considers to be its native environment. Then use sockets to communicate between Cinema and that external app. The subject has once been discussed here with some code examples being provided.
I would recommend using the second pattern, as it is more secure. Because the first pattern might run fine on one machine (your development machine for example) and then miserably fail on another one.
As a personal note: I would recommend not losing yourself too much in creating the most elaborate UIs. I know that you are going for a very polished look with the tools you publish in the plugin manager with Dunhou and jackadux, but sometimes UI stuff can be very time consuming for only looking a tiny bit better.
Cheers,
Ferdinand - Install the library in one of the paths where you can install external libs in Cinema 4D, c4dpy, etc. The problem with this is that the Python VM of Cinema 4D is very similar to
-
@ferdinand
Indeed, the allure of good looks can be captivating at times. In fact, my primary objective was to explore the development of a pie toolbar, which may seem unconventional but has always held a deep fascination for me. I sincerely appreciate your valuable advice and will certainly give it a try.Cheers,
Gheyret