Newer
Older
# it was finished one way or the other.
# It also pauses the script (time.sleep())
def _test_wait():
time.sleep(self.DELAY)
# User interrupts the rendering
print("***POV INTERRUPTED***")
return False
Doug Hammond
committed
poll_result = self._process.poll()
# POV process is finisehd, one way or the other
if poll_result < 0:
print("***POV PROCESS FAILED : %s ***" % poll_result)
self.update_stats("", "POV-Ray 3.7: Failed")
return False
return True
if bpy.context.scene.pov.text_block !="":
Maurice Raybaud
committed
if scene.pov.tempfiles_enable:
self._temp_file_in = tempfile.NamedTemporaryFile(suffix=".pov", delete=False).name
self._temp_file_out = tempfile.NamedTemporaryFile(suffix=".png", delete=False).name
#self._temp_file_out = tempfile.NamedTemporaryFile(suffix=".tga", delete=False).name
self._temp_file_ini = tempfile.NamedTemporaryFile(suffix=".ini", delete=False).name
self._temp_file_log = os.path.join(tempfile.gettempdir(), "alltext.out")
else:
povPath = scene.pov.text_block
renderImagePath = os.path.splitext(povPath)[0]
self._temp_file_out =os.path.join(preview_dir, renderImagePath )
self._temp_file_in = os.path.join(preview_dir, povPath)
self._temp_file_ini = os.path.join(preview_dir, (os.path.splitext(self._temp_file_in)[0]+".INI"))
self._temp_file_log = os.path.join(preview_dir, "alltext.out")
Maurice Raybaud
committed
Maurice Raybaud
committed
'''
try:
os.remove(self._temp_file_in) # so as not to load the old file
except OSError:
pass
Maurice Raybaud
committed
print(scene.pov.text_block)
text = bpy.data.texts[scene.pov.text_block]
file=open("%s"%self._temp_file_in,"w")
# Why are the newlines needed?
file.write("\n")
file.write(text.as_string())
Maurice Raybaud
committed
file.close()
# has to be called to update the frame on exporting animations
scene.frame_set(scene.frame_current)
Maurice Raybaud
committed
pov_binary = PovrayRender._locate_binary()
if not pov_binary:
print("POV-Ray 3.7: could not execute povray, possibly POV-Ray isn't installed")
return False
Maurice Raybaud
committed
# start ini UI options export
self.update_stats("", "POV-Ray 3.7: Exporting ini options from Blender")
Maurice Raybaud
committed
write_pov_ini(scene, self._temp_file_ini, self._temp_file_log, self._temp_file_in, self._temp_file_out)
print ("***-STARTING-***")
extra_args = []
Maurice Raybaud
committed
if scene.pov.command_line_switches != "":
for newArg in scene.pov.command_line_switches.split(" "):
extra_args.append(newArg)
if sys.platform[:3] == "win":
if"/EXIT" not in extra_args and not scene.pov.pov_editor:
extra_args.append("/EXIT")
else:
Maurice Raybaud
committed
# added -d option to prevent render window popup which leads to segfault on linux
extra_args.append("-d")
# Start Rendering!
try:
if sys.platform[:3] != "win" and scene.pov.sdl_window_enable: #segfault on linux == False !!!
env = {'POV_DISPLAY_SCALED': 'off'}
env.update(os.environ)
self._process = subprocess.Popen([pov_binary, self._temp_file_ini],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
env=env)
else:
self._process = subprocess.Popen([pov_binary, self._temp_file_ini] + extra_args,
Maurice Raybaud
committed
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
# TODO, report api
print("POV-Ray 3.7: could not execute '%s'" % pov_binary)
import traceback
traceback.print_exc()
print ("***-DONE-***")
return False
else:
print("Engine ready!...")
print("Command line arguments passed: " + str(extra_args))
#return True
self.update_stats("", "POV-Ray 3.7: Parsing File")
Maurice Raybaud
committed
Maurice Raybaud
committed
# Indented in main function now so repeated here but still not working
Maurice Raybaud
committed
# to bring back render result to its buffer
Maurice Raybaud
committed
if os.path.exists(self._temp_file_out):
xmin = int(r.border_min_x * x)
ymin = int(r.border_min_y * y)
xmax = int(r.border_max_x * x)
ymax = int(r.border_max_y * y)
Maurice Raybaud
committed
lay = result.layers[0]
Maurice Raybaud
committed
time.sleep(self.DELAY)
try:
lay.load_from_file(self._temp_file_out)
except RuntimeError:
print("***POV ERROR WHILE READING OUTPUT FILE***")
self.end_result(result)
#print(self._temp_file_log) #bring the pov log to blender console with proper path?
with open(self._temp_file_log) as f: # The with keyword automatically closes the file when you are done
Maurice Raybaud
committed
self.update_stats("", "")
Maurice Raybaud
committed
Maurice Raybaud
committed
if scene.pov.tempfiles_enable or scene.pov.deletefiles_enable:
Maurice Raybaud
committed
else:
Maurice Raybaud
committed
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
##WIP output format
## if r.image_settings.file_format == 'OPENEXR':
## fformat = 'EXR'
## render.image_settings.color_mode = 'RGBA'
## else:
## fformat = 'TGA'
## r.image_settings.file_format = 'TARGA'
## r.image_settings.color_mode = 'RGBA'
blendSceneName = bpy.data.filepath.split(os.path.sep)[-1].split(".")[0]
povSceneName = ""
povPath = ""
renderImagePath = ""
# has to be called to update the frame on exporting animations
scene.frame_set(scene.frame_current)
if not scene.pov.tempfiles_enable:
# check paths
povPath = bpy.path.abspath(scene.pov.scene_path).replace('\\', '/')
if povPath == "":
if bpy.data.is_saved:
povPath = bpy.path.abspath("//")
else:
Maurice Raybaud
committed
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
povPath = tempfile.gettempdir()
elif povPath.endswith("/"):
if povPath == "/":
povPath = bpy.path.abspath("//")
else:
povPath = bpy.path.abspath(scene.pov.scene_path)
if not os.path.exists(povPath):
try:
os.makedirs(povPath)
except:
import traceback
traceback.print_exc()
print("POV-Ray 3.7: Cannot create scenes directory: %r" % povPath)
self.update_stats("", "POV-Ray 3.7: Cannot create scenes directory %r" % \
povPath)
time.sleep(2.0)
#return
'''
# Bug in POV-Ray RC3
renderImagePath = bpy.path.abspath(scene.pov.renderimage_path).replace('\\','/')
if renderImagePath == "":
if bpy.data.is_saved:
renderImagePath = bpy.path.abspath("//")
else:
renderImagePath = tempfile.gettempdir()
#print("Path: " + renderImagePath)
elif path.endswith("/"):
if renderImagePath == "/":
renderImagePath = bpy.path.abspath("//")
else:
renderImagePath = bpy.path.abspath(scene.pov.renderimage_path)
if not os.path.exists(path):
print("POV-Ray 3.7: Cannot find render image directory")
self.update_stats("", "POV-Ray 3.7: Cannot find render image directory")
time.sleep(2.0)
return
'''
# check name
if scene.pov.scene_name == "":
if blendSceneName != "":
povSceneName = blendSceneName
else:
povSceneName = "untitled"
else:
povSceneName = scene.pov.scene_name
if os.path.isfile(povSceneName):
povSceneName = os.path.basename(povSceneName)
povSceneName = povSceneName.split('/')[-1].split('\\')[-1]
if not povSceneName:
print("POV-Ray 3.7: Invalid scene name")
self.update_stats("", "POV-Ray 3.7: Invalid scene name")
time.sleep(2.0)
#return
povSceneName = os.path.splitext(povSceneName)[0]
print("Scene name: " + povSceneName)
print("Export path: " + povPath)
povPath = os.path.join(povPath, povSceneName)
povPath = os.path.realpath(povPath)
# for now this has to be the same like the pov output. Bug in POV-Ray RC3.
# renderImagePath = renderImagePath + "\\" + povSceneName
renderImagePath = povPath # Bugfix for POV-Ray RC3 bug
# renderImagePath = os.path.realpath(renderImagePath) # Bugfix for POV-Ray RC3 bug
#print("Export path: %s" % povPath)
#print("Render Image path: %s" % renderImagePath)
# start export
self.update_stats("", "POV-Ray 3.7: Exporting data from Blender")
self._export(depsgraph, povPath, renderImagePath)
Maurice Raybaud
committed
self.update_stats("", "POV-Ray 3.7: Parsing File")
if not self._render(depsgraph):
Maurice Raybaud
committed
self.update_stats("", "POV-Ray 3.7: Not found")
#return
#r = scene.render
# compute resolution
#x = int(r.resolution_x * r.resolution_percentage * 0.01)
#y = int(r.resolution_y * r.resolution_percentage * 0.01)
# Wait for the file to be created
# XXX This is no more valid, as 3.7 always creates output file once render is finished!
parsing = re.compile(br"= \[Parsing\.\.\.\] =")
rendering = re.compile(br"= \[Rendering\.\.\.\] =")
percent = re.compile(r"\(([0-9]{1,3})%\)")
# print("***POV WAITING FOR FILE***")
data = b""
last_line = ""
while _test_wait():
Maurice Raybaud
committed
# POV in Windows did not output its stdout/stderr, it displayed them in its GUI
# But now writes file
Maurice Raybaud
committed
if self._is_windows:
self.update_stats("", "POV-Ray 3.7: Rendering File")
else:
t_data = self._process.stdout.read(10000)
if not t_data:
continue
Maurice Raybaud
committed
data += t_data
# XXX This is working for UNIX, not sure whether it might need adjustments for
# other OSs
# First replace is for windows
t_data = str(t_data).replace('\\r\\n', '\\n').replace('\\r', '\r')
lines = t_data.split('\\n')
last_line += lines[0]
lines[0] = last_line
print('\n'.join(lines), end="")
last_line = lines[-1]
if rendering.search(data):
_pov_rendering = True
match = percent.findall(str(data))
if match:
self.update_stats("", "POV-Ray 3.7: Rendering File (%s%%)" % match[-1])
else:
self.update_stats("", "POV-Ray 3.7: Rendering File")
Maurice Raybaud
committed
elif parsing.search(data):
self.update_stats("", "POV-Ray 3.7: Parsing File")
Maurice Raybaud
committed
if os.path.exists(self._temp_file_out):
# print("***POV FILE OK***")
#self.update_stats("", "POV-Ray 3.7: Rendering")
Maurice Raybaud
committed
# prev_size = -1
Maurice Raybaud
committed
xmin = int(r.border_min_x * x)
ymin = int(r.border_min_y * y)
xmax = int(r.border_max_x * x)
ymax = int(r.border_max_y * y)
Maurice Raybaud
committed
# print("***POV UPDATING IMAGE***")
result = self.begin_result(0, 0, x, y)
Bastien Montagne
committed
# XXX, tests for border render.
Maurice Raybaud
committed
#result = self.begin_result(xmin, ymin, xmax - xmin, ymax - ymin)
#result = self.begin_result(0, 0, xmax - xmin, ymax - ymin)
lay = result.layers[0]
Maurice Raybaud
committed
# This assumes the file has been fully written We wait a bit, just in case!
time.sleep(self.DELAY)
Campbell Barton
committed
try:
lay.load_from_file(self._temp_file_out)
# XXX, tests for border render.
#lay.load_from_file(self._temp_file_out, xmin, ymin)
except RuntimeError:
Maurice Raybaud
committed
print("***POV ERROR WHILE READING OUTPUT FILE***")
Campbell Barton
committed
Maurice Raybaud
committed
# Not needed right now, might only be useful if we find a way to use temp raw output of
# pov 3.7 (in which case it might go under _test_wait()).
'''
def update_image():
# possible the image wont load early on.
Campbell Barton
committed
try:
Maurice Raybaud
committed
lay.load_from_file(self._temp_file_out)
# XXX, tests for border render.
#lay.load_from_file(self._temp_file_out, xmin, ymin)
#lay.load_from_file(self._temp_file_out, xmin, ymin)
except RuntimeError:
Campbell Barton
committed
pass
Maurice Raybaud
committed
# Update while POV-Ray renders
while True:
# print("***POV RENDER LOOP***")
Campbell Barton
committed
Maurice Raybaud
committed
# test if POV-Ray exists
if self._process.poll() is not None:
print("***POV PROCESS FINISHED***")
update_image()
break
Campbell Barton
committed
Maurice Raybaud
committed
# user exit
if self.test_break():
try:
self._process.terminate()
print("***POV PROCESS INTERRUPTED***")
except OSError:
pass
Campbell Barton
committed
Maurice Raybaud
committed
break
Campbell Barton
committed
Maurice Raybaud
committed
# Would be nice to redirect the output
# stdout_value, stderr_value = self._process.communicate() # locks
Maurice Raybaud
committed
# check if the file updated
new_size = os.path.getsize(self._temp_file_out)
Maurice Raybaud
committed
if new_size != prev_size:
update_image()
prev_size = new_size
Maurice Raybaud
committed
time.sleep(self.DELAY)
'''
Maurice Raybaud
committed
self.end_result(result)
Maurice Raybaud
committed
else:
print("***POV FILE NOT FOUND***")
print("***POV FILE FINISHED***")
#print(filename_log) #bring the pov log to blender console with proper path?
with open(self._temp_file_log) as f: # The with keyword automatically closes the file when you are done
print(f.read())
Maurice Raybaud
committed
self.update_stats("", "")
if scene.pov.tempfiles_enable or scene.pov.deletefiles_enable:
self._cleanup()
##################################################################################
#################################Operators########################################
##################################################################################
class RenderPovTexturePreview(Operator):
"""Export only files necessary to texture preview and render image."""
bl_idname = "tex.preview_update"
bl_label = "Update preview"
def execute(self, context):
tex=bpy.context.object.active_material.active_texture #context.texture
texPrevName=string_strip_hyphen(bpy.path.clean_name(tex.name))+"_prev"
Maurice Raybaud
committed
## Make sure Preview directory exists and is empty
if not os.path.isdir(preview_dir):
os.mkdir(preview_dir)
iniPrevFile=os.path.join(preview_dir, "Preview.ini")
inputPrevFile=os.path.join(preview_dir, "Preview.pov")
outputPrevFile=os.path.join(preview_dir, texPrevName)
##################### ini ##########################################
fileIni=open("%s"%iniPrevFile,"w")
fileIni.write('Version=3.7\n')
fileIni.write('Input_File_Name="%s"\n'%inputPrevFile)
fileIni.write('Output_File_Name="%s.png"\n'%outputPrevFile)
fileIni.write('Library_Path="%s"\n' % preview_dir)
fileIni.write('Width=256\n')
fileIni.write('Height=256\n')
fileIni.write('Pause_When_Done=0\n')
fileIni.write('Output_File_Type=N\n')
fileIni.write('Output_Alpha=1\n')
fileIni.write('Antialias=on\n')
fileIni.write('Sampling_Method=2\n')
fileIni.write('Antialias_Depth=3\n')
fileIni.write('-d\n')
fileIni.close()
##################### pov ##########################################
filePov=open("%s"%inputPrevFile,"w")
PATname = "PAT_"+string_strip_hyphen(bpy.path.clean_name(tex.name))
filePov.write("#declare %s = \n"%PATname)
filePov.write(shading.exportPattern(tex, string_strip_hyphen))
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
filePov.write("#declare Plane =\n")
filePov.write("mesh {\n")
filePov.write(" triangle {<-2.021,-1.744,2.021>,<-2.021,-1.744,-2.021>,<2.021,-1.744,2.021>}\n")
filePov.write(" triangle {<-2.021,-1.744,-2.021>,<2.021,-1.744,-2.021>,<2.021,-1.744,2.021>}\n")
filePov.write(" texture{%s}\n"%PATname)
filePov.write("}\n")
filePov.write("object {Plane}\n")
filePov.write("light_source {\n")
filePov.write(" <0,4.38,-1.92e-07>\n")
filePov.write(" color rgb<4, 4, 4>\n")
filePov.write(" parallel\n")
filePov.write(" point_at <0, 0, -1>\n")
filePov.write("}\n")
filePov.write("camera {\n")
filePov.write(" location <0, 0, 0>\n")
filePov.write(" look_at <0, 0, -1>\n")
filePov.write(" right <-1.0, 0, 0>\n")
filePov.write(" up <0, 1, 0>\n")
filePov.write(" angle 96.805211\n")
filePov.write(" rotate <-90.000003, -0.000000, 0.000000>\n")
filePov.write(" translate <0.000000, 0.000000, 0.000000>\n")
filePov.write("}\n")
filePov.close()
##################### end write ##########################################
pov_binary = PovrayRender._locate_binary()
if sys.platform[:3] == "win":
p1=subprocess.Popen(["%s"%pov_binary,"/EXIT","%s"%iniPrevFile],
stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
p1=subprocess.Popen(["%s"%pov_binary,"-d","%s"%iniPrevFile],
stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
p1.wait()
tex.use_nodes = True
tree = tex.node_tree
links = tree.links
for n in tree.nodes:
tree.nodes.remove(n)
pathPrev="%s.png"%outputPrevFile
im.image = bpy.data.images.load(pathPrev)
name=pathPrev
name=name.split("/")
name=name[len(name)-1]
im.location = 200,200
previewer = tree.nodes.new('TextureNodeOutput')
previewer.label = "Preview"
previewer.location = 400,400
links.new(im.outputs[0],previewer.inputs[0])
#tex.type="IMAGE" # makes clip extend possible
#tex.extension="CLIP"
Maurice Raybaud
committed
class RunPovTextRender(Operator):
"""Export files depending on text editor options and render image."""
Maurice Raybaud
committed
bl_idname = "text.run"
bl_label = "Run"
bl_context = "text"
bl_description = "Run a render with this text only"
Maurice Raybaud
committed
def execute(self, context):
scene = context.scene
scene.pov.text_block = context.space_data.text.name
Maurice Raybaud
committed
bpy.ops.render.render()
Maurice Raybaud
committed
Maurice Raybaud
committed
#empty text name property engain
scene.pov.text_block = ""
return {'FINISHED'}
classes = (
PovrayRender,
RenderPovTexturePreview,
RunPovTextRender,
)
def register():
#from bpy.utils import register_class
for cls in classes:
register_class(cls)
def unregister():
from bpy.utils import unregister_class
for cls in reversed(classes):