Message if (render-) frame changes
Helper last edited by
On 22/10/2017 at 11:03, xxxxxxxx wrote:
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
Helper last edited by
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:
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())