Message if (render-) frame changes

  • On 22/10/2017 at 11:03, xxxxxxxx wrote:

    hi there...

    does anybody know if there is a message on a new frame when rendering?
    (goal is to change things in the scene for each frame while rendering)

    i'm also doing this from a python tag... so it should work there, too :)

    tx for any hints!

    ps... while i'm at it...
    would it be possible to manipulate the render process (renderdata?)
    to maybe not render each frame but only a selection. ie frame 1,5,7,10

  • On 23/10/2017 at 09:15, xxxxxxxx wrote:


    there is no message when rendering a new frame. Actually a tag plugin gets executed (Execute() called) on every change. So maybe here the problem is not so much being executed, but the wish to be executed only on this specific event?
    Then I'd suggest to store the last frame, when one was executed, either in the BaseContainer or in a member/global variable. Then you can compare against the current frame and execute only if changed.

    On the second question (actually we'd prefer to have different threads for different questions, as it greatly increases overview and "searchability" of the forum), well, I guess you already know you can edit RenderData (render settings), but the options for the rendered frames are limited and such an arbitrary selection of frames can not be rendered by a single RenderData.

    There are a whole bunch of options to work around this limitation, I'll just suggest two from the top of my head:

    a) Clone the RenderData for every frame you need to render. Then for example have a Take per RenderData and use the "Render All Takes to PV" command.

    b) Do it manually via a CommandData plugin. A skeleton which demonstrates asynchronous rendering is shown below. You'd still need to add a loop to render only those frames you want, the example only renders a single image.

    import c4d
    from c4d.threading import C4DThread
    from c4d import bitmaps, documents
    PLUGIN_ID =  <your unique plugin ID here>  # DON'T FORGET TO GET A UNIQUE ID
    PLUGIN_ID_MSGDATA = <your unique plugin ID here>  # DON'T FORGET TO GET A UNIQUE ID
    CUSTOM_ID_RENDER_FINISH = <your unique plugin ID here>  # DON'T FORGET TO GET A UNIQUE ID
    g_bmp = None
    g_thread = None
    # provide this thread with a cloned document and sz
    class RenderThread(C4DThread) :
        _docRender = None
        def Main(self) :
            global g_bmp
            rd = self._docRender.GetActiveRenderData().GetData()
            # Set frame to render
            rd[c4d.RDATA_FRAMESEQUENCE] = 0 # render manual frame sequence (from .. to)
            frameNumber = 0
            t = c4d.BaseTime(frameNumber, self._docRender.GetFps())
            rd[c4d.RDATA_FRAMEFROM] = t
            rd[c4d.RDATA_FRAMETO] = t
            #Initialize the bitmap with the result size
            #The resolution must match with the output size of the render settings
            xres = int(rd[c4d.RDATA_XRES])
            yres = int(rd[c4d.RDATA_YRES])
            g_bmp = bitmaps.BaseBitmap()
            g_bmp.Init(x = xres, y = yres, depth = 24)
            res = c4d.documents.RenderDocument(self._docRender, rd, g_bmp, c4d.RENDERFLAGS_NODOCUMENTCLONE | c4d.RENDERFLAGS_EXTERNAL, None)
            if res == c4d.RENDERRESULT_OK:
                c4d.SpecialEventAdd(CUSTOM_ID_RENDER_FINISH) # Notify MessageData plugiin about successful render
    # As the thread renders asynchronously the command can not catch the end/success of the rendering.
    # Instead this MessageData receives a custom finish message and shows the rendered image in PV.
    class RenderFinishMessage(c4d.plugins.MessageData) :
        def CoreMessage(self, id, bc) :
            if id == CUSTOM_ID_RENDER_FINISH:
                if g_bmp:
            return True
    # Command sets data in thread and then starts the thread
    class RenderToPVCommandData(c4d.plugins.CommandData) :
        def Execute(self, doc) :
            global g_thread
            # ToDo: take care of already running thread
            g_thread = RenderThread()
            g_thread._docRender = doc.GetClone(c4d.COPYFLAGS_0) # ToDo: rather have setter function in RenderThread
            return True
    if __name__ == "__main__":
        c4d.plugins.RegisterCommandPlugin(id = PLUGIN_ID, str = "Py-Render to PV",
                                          help = "Render asynchronously.",info = 0,
                                          dat = RenderToPVCommandData(), icon = None)
        c4d.plugins.RegisterMessagePlugin(id=PLUGIN_ID_MSGDATA, str="", info=0, dat=RenderFinishMessage())

Log in to reply