On 24/01/2016 at 15:00, xxxxxxxx wrote:
Hey Rui,
I'm just sitting here watching football and writing some code. And I might have written something that might help you.
This is a GeDialog plugin with a UserArea.
The custom thread renders the scene and the UA displays it.
The trick to getting the UA to Redraw is the use of the Timer() method in the GeDialog class while the renderer is running.
I think you just wanted to kill a single frame render?
I'm rending a sequence of frames. So you can see the image update in the UA easier.
So that part you'll need to change.
Put some object in the scene and key frame it from 0-20 so it rotates. Just so you can see the result in the UA.
import c4d, os, time, threading
from c4d import plugins, utils, gui, bitmaps, documents
PLUGIN_ID=1000010 #<-------------- Testing id ONLY!!!!!!!
rImage = bitmaps.BaseBitmap()
class UserArea(c4d.gui.GeUserArea) :
def __init__(self, bmp) :
super(UserArea, self).__init__()
self.bmp = rImage
def GetMinSize(self) :
x = 100
y = 100
return x,y
def DrawMsg(self, x1, y1, x2, y2, msg) :
self.SetClippingRegion(x1, y1, x2, y2)
self.DrawSetPen(c4d.COLOR_BG)
self.DrawRectangle(x1, y1, x2, y2)
#Draw the bitmap rendered in the custom thread below
if self.bmp:
w, h = self.bmp.GetSize()
self.DrawBitmap(self.bmp, x1, y1, w, h, x1, y1, w, h,c4d.BMP_NORMAL | c4d.BMP_ALLOWALPHA)
#This custom thread will render the scene to a bitmap variable
#The UserArea will display this bitmap
#NOTE: I set it to render 20 frames just as a test..change as desired
class MyThread(c4d.threading.C4DThread) :
ua = UserArea(None)
def Main(self) :
doc = c4d.documents.GetActiveDocument()
rd = doc.GetActiveRenderData().GetData()
rd[c4d.RDATA_ALPHACHANNEL]= True
rd[c4d.RDATA_XRES]=100
rd[c4d.RDATA_YRES]=100
xres = int(round(rd[c4d.RDATA_XRES]))
yres = int(round(rd[c4d.RDATA_YRES]))
fps = doc.GetFps()
rd[c4d.RDATA_FRAMESEQUENCE] = 3
startFrame = rd[c4d.RDATA_FRAMEFROM]= c4d.BaseTime(0, fps)
stopFrame = rd[c4d.RDATA_FRAMETO]= c4d.BaseTime(20, fps)
rImage.Init(xres, yres, depth=24)
res = documents.RenderDocument(doc, rd, rImage, c4d.RENDERFLAGS_EXTERNAL)
#enums
USER_AREA = 1000
BTN_START = 1001
BTN_STOP = 1002
class MyDialog_Gui(gui.GeDialog) :
ua = UserArea(None)
thread = MyThread()
def CreateLayout(self) :
self.SetTitle("Start/Stop Rendering Example")
self.AddUserArea(USER_AREA, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, c4d.BFV_SCALEFIT)
self.AttachUserArea(self.ua, USER_AREA)
self.GroupBegin(0, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT, 3, 1, "Master Group",0) #The master group
self.GroupBorder(c4d.BORDER_BLACK)
self.GroupBorderSpace(10, 20, 10, 10) #left, top, right, bottom
############# Start Rendering Button ##################################
bc1 = c4d.BaseContainer()
self.GroupBegin(0, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT, 0, 0, "Start Button",0)
self.GroupBorder(c4d.BORDER_BLACK)
self.AddButton(BTN_START, c4d.BFH_SCALE|c4d.BFV_SCALE, 130, 30, "Start")
self.GroupEnd()
############## Stop Rendering Button ############################
bc2 = c4d.BaseContainer()
self.GroupBegin(0, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT, 0, 0, "Stop Button",0)
self.GroupBorder(c4d.BORDER_BLACK)
self.AddButton(BTN_STOP, c4d.BFH_SCALE|c4d.BFV_SCALE, 130, 30, "Stop")
self.GroupEnd() #The end of the button's group
self.GroupEnd() #The end of the master group holding the two button groups
return True
def InitValues(self) :
self.SetTimer(300);
return True
def Timer(self, msg) :
#Since we can't update the USER_AREA manually while rendering
#We must ReDraw it constantly before we start rendering
#Only do this ReDrawing when we are actually rendering!!!
if self.thread.IsRunning() : self.ua.Redraw()
def Command(self, id, msg) :
if id == BTN_START:
print "Start Pressed"
self.thread.Start() #Start the custom rendering thread
if id == BTN_STOP:
self.thread.End() #Stop the thread
c4d.CallCommand(430000731) #Stop Rendering
print "Stop Button Pressed"
c4d.EventAdd()
return True
class myDialog_Main(plugins.CommandData) :
dialog = None
def Execute(self, doc) :
if self.dialog is None:
self.dialog = MyDialog_Gui()
return self.dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1)
def RestoreLayout(self, sec_ref) :
if self.dialog is None:
self.dialog = MyDialog_Gui()
return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
if __name__ == "__main__":
path, fn = os.path.split(__file__)
bmp = bitmaps.BaseBitmap()
bmp.InitWith(os.path.join(path, "res/icons/", "None"))
plugins.RegisterCommandPlugin(PLUGIN_ID, "Render To UA",0,None,"", myDialog_Main())
This is still fairly crude. It doesn't quite stop & restart the thread properly when using it on multiple frames like I'm doing.
But it does stop the rendering while the dialog is open. And it does Redraw the UA.
If I was only rendering one frame rather than several frames. I think this would be close to good enough.
Maybe Yannick will have some pointers on how to stop and start the thread better.
-ScottA