Render to picture viewer from plugin crash
-
Hey guys,
This is probably a very simple question and i suspect to do with threading. I have a little workflow tool i'm working on and have this Render to Picture Viewer button.
The code behind this button is as simple as this
if id == BTN_SceneRenderPictureViewer: self.PrintStatusMessage('Rendering to Picture Viewer.') self.Close() c4d.StopAllThreads() time.sleep(0.1) # Wait a bit to ensure the dialog is closed before rendering c4d.CallCommand(12099)
However this causes Cinema to crash. I've tried recreating the Render to Picture viewer function but this was seems much simpler so would be great for it work - any help appreaciated
Thanks alot,
Will -
Hello @popandchop,
Welcome to the Maxon developers forum and its community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.
- Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
- Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
- Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.
It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions.
About your First Question
The question is impossible to answer in this form, we would need something concrete (a plugin and a scene which crashes for you) or a time stamp of a submitted crash report.
What you do there is this code snippet looks a bit unusual. I assume from the screen shot that you are inside a
GeDialog
, the code looks a bit like this could beGeDialog.Command
orMessage
. Please read the Threading Manual, invoking an event, e.g., a command, is forbidden off-main thread. But in a dialog you are usually on the main thread (but you should still check withc4d,.threading.GeIsMainThread()
). What is also rather odd, is what you call there:if id == BTN_SceneRenderPictureViewer: self.Close() # This will shut down the dialog, think of it as a return statement. c4d.StopAllThreads() # This is generally the biggest nuke you can drop on Cinema 4D and should # be avoided. But in this context (a dialog that has been closed) this # seems extra dangerous. Why are you doing this? time.sleep(0.1) # This makes things even worse, as it increases the chance that the dialog # has been destroyed before the last line of this function has been # executed. If I had to guess, this is probably crashing here. c4d.CallCommand(12099)
I assume you hve a modal dialog and that you run into issues with opening the picture viewer due to that? Either make your dialog non-modal (in GeDialog.Open) and then first send the command and then close the dialog or keep using a modal dialog and detach the code from the instance of the dialog.
import c4d class MyModalDialog (c4d.gui.GeDialog): BTN_SceneRenderPictureViewer: int = 1000 # ... def Command(self, cid: int, msg: c4d.BaseContainer) -> bool: if cid == MyModalDialog.BTN_SceneRenderPictureViewer: MyModalDialog.CloseAndAction(self, 12099) return True @staticmethod def CloseAndAction(dlg: "MyModalDialog", cid: int) -> None: """Closes the passed dialog and executes a command. Args: dlg (MyModalDialog): The dialog instance to close. cid (int): The command ID to execute after closing the dialog. """ if not dlg or not c4d.threading.GeIsMainThread(): return dlg.Close() c4d.CallCommand(cid) if __name__ == '__main__': dlg = MyModalDialog() dlg.Open(c4d.DLG_TYPE_MODAL, defaultw=400, defaulth=300, title="My Modal Dialog")
Cheers,
Ferdinand