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:

Hi,

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:
                bitmaps.ShowBitmap(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
        g_thread.Start()
        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())