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
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.
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) :
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:
# Command sets data in thread and then starts the thread
class RenderToPVCommandData(c4d.plugins.CommandData) :
def Execute(self, doc) :
# 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
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())