diff options
Diffstat (limited to 'render_povray/render.py')
-rwxr-xr-x | render_povray/render.py | 1349 |
1 files changed, 175 insertions, 1174 deletions
diff --git a/render_povray/render.py b/render_povray/render.py index 0f7da3c6..150d892d 100755 --- a/render_povray/render.py +++ b/render_povray/render.py @@ -8,12 +8,11 @@ import bpy import subprocess import os from sys import platform -import time +#import time from math import ( pi, ) # maybe move to scenography.py and topology_*****_data.py respectively with smoke and matrix - -import re +import mathutils #import less than full import tempfile # generate temporary files with random names from bpy.types import Operator from bpy.utils import register_class, unregister_class @@ -21,19 +20,34 @@ from bpy.utils import register_class, unregister_class from . import ( scripting, ) # for writing, importing and rendering directly POV Scene Description Language items +from . import render_core from . import scenography # for atmosphere, environment, effects, lighting, camera from . import shading # for BI POV shaders emulation -from . import object_mesh_topology # for mesh based geometry -from . import object_curve_topology # for curves based geometry +from . import nodes_fn +from . import texturing_procedural # for Blender procedurals to POV patterns emulation +from . import model_all # for mesh based geometry +from . import model_meta_topology # for mesh based geometry +from . import model_curve_topology # for curves based geometry -# from . import object_primitives # for import and export of POV specific primitives +# from . import model_primitives # for import and export of POV specific primitives from .scenography import image_format, img_map, img_map_transforms, path_image from .shading import write_object_material_interior -from .object_primitives import write_object_modifiers +from .model_primitives import write_object_modifiers + +tab_level = 0 +tab="" +comments = False +using_uberpov = False +unpacked_images = [] + +from .render_core import ( + preview_dir, + PovRender, +) def string_strip_hyphen(name): @@ -95,19 +109,31 @@ def renderable_objects(): return [ob for ob in bpy.data.objects if is_renderable(ob)] -def no_renderable_objects(): +def non_renderable_objects(): """Boolean operands only. Not to render""" return list(csg_list) -tab_level = 0 -unpacked_images = [] +def set_tab(tabtype, spaces): + """Apply the configured indentation all along the exported POV file + + Arguments: + tabtype -- Specifies user preference between tabs or spaces indentation + spaces -- If using spaces, sets the number of space characters to use + Returns: + The beginning blank space for each line of the generated pov file + """ + tab_str = "" + match tabtype: + case 'SPACE': + tab_str = spaces * " " + case 'NONE': + tab_str = "" + case 'TAB': + tab_str = "\t" + return tab_str -user_dir = bpy.utils.resource_path('USER') -preview_dir = os.path.join(user_dir, "preview") -# Make sure Preview directory exists and is empty -smoke_path = os.path.join(preview_dir, "smoke.df3") ''' @@ -132,7 +158,7 @@ smoke_path = os.path.join(preview_dir, "smoke.df3") # # Maybe return that string to be added instead of directly written. # '''XXX WIP -# import .object_mesh_topology.write_object_csg_inside_vector +# import .model_all.write_object_csg_inside_vector # write_object_csg_inside_vector(ob, file) # ''' @@ -178,12 +204,55 @@ smoke_path = os.path.join(preview_dir, "smoke.df3") # File.write("caustics %.4g\n"%ob.pov.fake_caustics_power) # ''' +def tab_write(file, str_o, scene=None): + """write directly to exported file if user checked autonamed temp files (faster). + Otherwise, indent POV syntax from brackets levels and write to exported file""" + + if not scene: + scene = bpy.data.scenes[0] + global tab + tab = set_tab(scene.pov.indentation_character, scene.pov.indentation_spaces) + if scene.pov.tempfiles_enable: + file.write(str_o) + else: + global tab_level + brackets = str_o.count("{") - str_o.count("}") + str_o.count("[") - str_o.count("]") + if brackets < 0: + tab_level = tab_level + brackets + if tab_level < 0: + print("Indentation Warning: tab_level = %s" % tab_level) + tab_level = 0 + if tab_level >= 1: + file.write("%s" % tab * tab_level) + file.write(str_o) + if brackets > 0: + tab_level = tab_level + brackets + +def write_matrix(file, matrix): + """Translate some transform matrix from Blender UI + to POV syntax and write to exported file """ + tab_write(file, + "matrix <%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f>\n" + % ( + matrix[0][0], + matrix[1][0], + matrix[2][0], + matrix[0][1], + matrix[1][1], + matrix[2][1], + matrix[0][2], + matrix[1][2], + matrix[2][2], + matrix[0][3], + matrix[1][3], + matrix[2][3], + ) + ) +global_matrix = mathutils.Matrix.Rotation(-pi / 2.0, 4, 'X') def write_pov(filename, scene=None, info_callback=None): """Main export process from Blender UI to POV syntax and write to exported file """ - import mathutils - with open(filename, "w") as file: # Only for testing if not scene: @@ -191,12 +260,13 @@ def write_pov(filename, scene=None, info_callback=None): render = scene.render world = scene.world - global_matrix = mathutils.Matrix.Rotation(-pi / 2.0, 4, 'X') + global comments comments = scene.pov.comments_enable and not scene.pov.tempfiles_enable - linebreaksinlists = scene.pov.list_lf_enable and not scene.pov.tempfiles_enable + feature_set = bpy.context.preferences.addons[__package__].preferences.branch_feature_set_povray + global using_uberpov using_uberpov = feature_set == 'uberpov' - pov_binary = PovrayRender._locate_binary() + pov_binary = PovRender._locate_binary() if using_uberpov: print("Unofficial UberPOV feature set chosen in preferences") @@ -207,40 +277,6 @@ def write_pov(filename, scene=None, info_callback=None): else: print("The name of the binary suggests you are probably rendering with standard POV engine") - def set_tab(tabtype, spaces): - tab_str = "" - if tabtype == 'NONE': - tab_str = "" - elif tabtype == 'TAB': - tab_str = "\t" - elif tabtype == 'SPACE': - tab_str = spaces * " " - return tab_str - - tab = set_tab(scene.pov.indentation_character, scene.pov.indentation_spaces) - if not scene.pov.tempfiles_enable: - - def tab_write(str_o): - """Indent POV syntax from brackets levels and write to exported file """ - global tab_level - brackets = str_o.count("{") - str_o.count("}") + str_o.count("[") - str_o.count("]") - if brackets < 0: - tab_level = tab_level + brackets - if tab_level < 0: - print("Indentation Warning: tab_level = %s" % tab_level) - tab_level = 0 - if tab_level >= 1: - file.write("%s" % tab * tab_level) - file.write(str_o) - if brackets > 0: - tab_level = tab_level + brackets - - else: - - def tab_write(str_o): - """write directly to exported file if user checked autonamed temp files (faster).""" - - file.write(str_o) def unique_name(name, name_seq): """Increment any generated POV name that could get identical to avoid collisions""" @@ -257,329 +293,20 @@ def write_pov(filename, scene=None, info_callback=None): name = string_strip_hyphen(name) return name - def write_matrix(matrix): - """Translate some transform matrix from Blender UI - to POV syntax and write to exported file """ - tab_write( - "matrix <%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f>\n" - % ( - matrix[0][0], - matrix[1][0], - matrix[2][0], - matrix[0][1], - matrix[1][1], - matrix[2][1], - matrix[0][2], - matrix[1][2], - matrix[2][2], - matrix[0][3], - matrix[1][3], - matrix[2][3], - ) - ) - material_names_dictionary = {} DEF_MAT_NAME = "" # or "Default"? # ----------------------------------------------------------------------------- - def export_meta(metas): - """write all POV blob primitives and Blender Metas to exported file """ - # TODO - blenders 'motherball' naming is not supported. - - if comments and len(metas) >= 1: - file.write("//--Blob objects--\n\n") - # Get groups of metaballs by blender name prefix. - meta_group = {} - meta_elems = {} - for meta_ob in metas: - prefix = meta_ob.name.split(".")[0] - if prefix not in meta_group: - meta_group[prefix] = meta_ob # .data.threshold - elems = [ - (elem, meta_ob) - for elem in meta_ob.data.elements - if elem.type in {'BALL', 'ELLIPSOID', 'CAPSULE', 'CUBE', 'PLANE'} - ] - if prefix in meta_elems: - meta_elems[prefix].extend(elems) - else: - meta_elems[prefix] = elems - - # empty metaball - if len(elems) == 0: - tab_write("\n//dummy sphere to represent empty meta location\n") - tab_write( - "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} " - "no_image no_reflection no_radiosity " - "photons{pass_through collect off} hollow}\n\n" - % (meta_ob.location.x, meta_ob.location.y, meta_ob.location.z) - ) # meta_ob.name > povdataname) - # other metaballs - else: - for mg, mob in meta_group.items(): - if len(meta_elems[mg]) != 0: - tab_write("blob{threshold %.4g // %s \n" % (mob.data.threshold, mg)) - for elems in meta_elems[mg]: - elem = elems[0] - loc = elem.co - stiffness = elem.stiffness - if elem.use_negative: - stiffness = -stiffness - if elem.type == 'BALL': - tab_write( - "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g " - % (loc.x, loc.y, loc.z, elem.radius, stiffness) - ) - write_matrix(global_matrix @ elems[1].matrix_world) - tab_write("}\n") - elif elem.type == 'ELLIPSOID': - tab_write( - "sphere{ <%.6g, %.6g, %.6g>,%.4g,%.4g " - % ( - loc.x / elem.size_x, - loc.y / elem.size_y, - loc.z / elem.size_z, - elem.radius, - stiffness, - ) - ) - tab_write( - "scale <%.6g, %.6g, %.6g>" - % (elem.size_x, elem.size_y, elem.size_z) - ) - write_matrix(global_matrix @ elems[1].matrix_world) - tab_write("}\n") - elif elem.type == 'CAPSULE': - tab_write( - "cylinder{ <%.6g, %.6g, %.6g>,<%.6g, %.6g, %.6g>,%.4g,%.4g " - % ( - (loc.x - elem.size_x), - loc.y, - loc.z, - (loc.x + elem.size_x), - loc.y, - loc.z, - elem.radius, - stiffness, - ) - ) - # tab_write("scale <%.6g, %.6g, %.6g>" % (elem.size_x, elem.size_y, elem.size_z)) - write_matrix(global_matrix @ elems[1].matrix_world) - tab_write("}\n") - - elif elem.type == 'CUBE': - tab_write( - "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n" - % ( - elem.radius * 2.0, - stiffness / 4.0, - loc.x, - loc.y, - loc.z, - elem.size_x, - elem.size_y, - elem.size_z, - ) - ) - write_matrix(global_matrix @ elems[1].matrix_world) - tab_write("}\n") - tab_write( - "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n" - % ( - elem.radius * 2.0, - stiffness / 4.0, - loc.x, - loc.y, - loc.z, - elem.size_x, - elem.size_y, - elem.size_z, - ) - ) - write_matrix(global_matrix @ elems[1].matrix_world) - tab_write("}\n") - tab_write( - "cylinder { -z*8, +z*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1,1/4> scale <%.6g, %.6g, %.6g>\n" - % ( - elem.radius * 2.0, - stiffness / 4.0, - loc.x, - loc.y, - loc.z, - elem.size_x, - elem.size_y, - elem.size_z, - ) - ) - write_matrix(global_matrix @ elems[1].matrix_world) - tab_write("}\n") - - elif elem.type == 'PLANE': - tab_write( - "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n" - % ( - elem.radius * 2.0, - stiffness / 4.0, - loc.x, - loc.y, - loc.z, - elem.size_x, - elem.size_y, - elem.size_z, - ) - ) - write_matrix(global_matrix @ elems[1].matrix_world) - tab_write("}\n") - tab_write( - "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n" - % ( - elem.radius * 2.0, - stiffness / 4.0, - loc.x, - loc.y, - loc.z, - elem.size_x, - elem.size_y, - elem.size_z, - ) - ) - write_matrix(global_matrix @ elems[1].matrix_world) - tab_write("}\n") - - try: - one_material = elems[1].data.materials[ - 0 - ] # lame! - blender cant do enything else. - except BaseException as e: - print(e.__doc__) - print('An exception occurred: {}'.format(e)) - one_material = None - if one_material: - diffuse_color = one_material.diffuse_color - trans = 1.0 - one_material.pov.alpha - if ( - one_material.use_transparency - and one_material.transparency_method == 'RAYTRACE' - ): - pov_filter = one_material.pov_raytrace_transparency.filter * ( - 1.0 - one_material.alpha - ) - trans = (1.0 - one_material.pov.alpha) - pov_filter - else: - pov_filter = 0.0 - material_finish = material_names_dictionary[one_material.name] - tab_write( - "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" - % ( - diffuse_color[0], - diffuse_color[1], - diffuse_color[2], - pov_filter, - trans, - ) - ) - tab_write("finish{%s} " % safety(material_finish, ref_level_bound=2)) - else: - material_finish = DEF_MAT_NAME - trans = 0.0 - tab_write( - "pigment{srgbt<1,1,1,%.3g>} finish{%s} " - % (trans, safety(material_finish, ref_level_bound=2)) - ) - - write_object_material_interior(one_material, mob, tab_write) - # write_object_material_interior(one_material, elems[1]) - tab_write("radiosity{importance %3g}\n" % mob.pov.importance_value) - tab_write("}\n\n") # End of Metaball block - - ''' - meta = ob.data - - # important because no elements will break parsing. - elements = [elem for elem in meta.elements if elem.type in {'BALL', 'ELLIPSOID'}] - - if elements: - tab_write("blob {\n") - tab_write("threshold %.4g\n" % meta.threshold) - importance = ob.pov.importance_value - - try: - material = meta.materials[0] # lame! - blender cant do enything else. - except: - material = None - - for elem in elements: - loc = elem.co - - stiffness = elem.stiffness - if elem.use_negative: - stiffness = - stiffness - - if elem.type == 'BALL': - - tab_write("sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" % - (loc.x, loc.y, loc.z, elem.radius, stiffness)) - - # After this wecould do something simple like... - # "pigment {Blue} }" - # except we'll write the color - - elif elem.type == 'ELLIPSOID': - # location is modified by scale - tab_write("sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" % - (loc.x / elem.size_x, - loc.y / elem.size_y, - loc.z / elem.size_z, - elem.radius, stiffness)) - tab_write("scale <%.6g, %.6g, %.6g> \n" % - (elem.size_x, elem.size_y, elem.size_z)) - - if material: - diffuse_color = material.diffuse_color - trans = 1.0 - material.pov.alpha - if material.use_transparency and material.transparency_method == 'RAYTRACE': - pov_filter = material.pov_raytrace_transparency.filter * (1.0 - material.alpha) - trans = (1.0 - material.pov.alpha) - pov_filter - else: - pov_filter = 0.0 - - material_finish = material_names_dictionary[material.name] - - tab_write("pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" % - (diffuse_color[0], diffuse_color[1], diffuse_color[2], - pov_filter, trans)) - tab_write("finish {%s}\n" % safety(material_finish, ref_level_bound=2)) - - else: - tab_write("pigment {srgb 1} \n") - # Write the finish last. - tab_write("finish {%s}\n" % (safety(DEF_MAT_NAME, ref_level_bound=2))) - - write_object_material_interior(material, elems[1]) - - write_matrix(global_matrix @ ob.matrix_world) - # Importance for radiosity sampling added here - tab_write("radiosity { \n") - # importance > ob.pov.importance_value - tab_write("importance %3g \n" % importance) - tab_write("}\n") - - tab_write("}\n") # End of Metaball block - - if comments and len(metas) >= 1: - file.write("\n") - ''' - def export_global_settings(scene): """write all POV global settings to exported file """ # Imperial units warning if scene.unit_settings.system == "IMPERIAL": print("Warning: Imperial units not supported") - tab_write("global_settings {\n") - tab_write("assumed_gamma 1.0\n") - tab_write("max_trace_level %d\n" % scene.pov.max_trace_level) + tab_write(file, "global_settings {\n") + tab_write(file, "assumed_gamma 1.0\n") + tab_write(file, "max_trace_level %d\n" % scene.pov.max_trace_level) if scene.pov.global_settings_advanced: if not scene.pov.radio_enable: @@ -589,24 +316,24 @@ def write_pov(filename, scene=None, info_callback=None): file.write(" number_of_waves %s\n" % scene.pov.number_of_waves) file.write(" noise_generator %s\n" % scene.pov.noise_generator) if scene.pov.radio_enable: - tab_write("radiosity {\n") - tab_write("adc_bailout %.4g\n" % scene.pov.radio_adc_bailout) - tab_write("brightness %.4g\n" % scene.pov.radio_brightness) - tab_write("count %d\n" % scene.pov.radio_count) - tab_write("error_bound %.4g\n" % scene.pov.radio_error_bound) - tab_write("gray_threshold %.4g\n" % scene.pov.radio_gray_threshold) - tab_write("low_error_factor %.4g\n" % scene.pov.radio_low_error_factor) - tab_write("maximum_reuse %.4g\n" % scene.pov.radio_maximum_reuse) - tab_write("minimum_reuse %.4g\n" % scene.pov.radio_minimum_reuse) - tab_write("nearest_count %d\n" % scene.pov.radio_nearest_count) - tab_write("pretrace_start %.3g\n" % scene.pov.radio_pretrace_start) - tab_write("pretrace_end %.3g\n" % scene.pov.radio_pretrace_end) - tab_write("recursion_limit %d\n" % scene.pov.radio_recursion_limit) - tab_write("always_sample %d\n" % scene.pov.radio_always_sample) - tab_write("normal %d\n" % scene.pov.radio_normal) - tab_write("media %d\n" % scene.pov.radio_media) - tab_write("subsurface %d\n" % scene.pov.radio_subsurface) - tab_write("}\n") + tab_write(file, "radiosity {\n") + tab_write(file, "adc_bailout %.4g\n" % scene.pov.radio_adc_bailout) + tab_write(file, "brightness %.4g\n" % scene.pov.radio_brightness) + tab_write(file, "count %d\n" % scene.pov.radio_count) + tab_write(file, "error_bound %.4g\n" % scene.pov.radio_error_bound) + tab_write(file, "gray_threshold %.4g\n" % scene.pov.radio_gray_threshold) + tab_write(file, "low_error_factor %.4g\n" % scene.pov.radio_low_error_factor) + tab_write(file, "maximum_reuse %.4g\n" % scene.pov.radio_maximum_reuse) + tab_write(file, "minimum_reuse %.4g\n" % scene.pov.radio_minimum_reuse) + tab_write(file, "nearest_count %d\n" % scene.pov.radio_nearest_count) + tab_write(file, "pretrace_start %.3g\n" % scene.pov.radio_pretrace_start) + tab_write(file, "pretrace_end %.3g\n" % scene.pov.radio_pretrace_end) + tab_write(file, "recursion_limit %d\n" % scene.pov.radio_recursion_limit) + tab_write(file, "always_sample %d\n" % scene.pov.radio_always_sample) + tab_write(file, "normal %d\n" % scene.pov.radio_normal) + tab_write(file, "media %d\n" % scene.pov.radio_media) + tab_write(file, "subsurface %d\n" % scene.pov.radio_subsurface) + tab_write(file, "}\n") once_sss = 1 once_ambient = 1 once_photons = 1 @@ -614,7 +341,7 @@ def write_pov(filename, scene=None, info_callback=None): if material.pov_subsurface_scattering.use and once_sss: # In pov, the scale has reversed influence compared to blender. these number # should correct that - tab_write( + tab_write(file, "mm_per_unit %.6f\n" % (material.pov_subsurface_scattering.scale * 1000.0) ) # 1000 rather than scale * (-100.0) + 15.0)) @@ -624,44 +351,48 @@ def write_pov(filename, scene=None, info_callback=None): # formerly sslt_samples were multiplied by 100 instead of 10 sslt_samples = (11 - material.pov_subsurface_scattering.error_threshold) * 10 - tab_write("subsurface { samples %d, %d }\n" % (sslt_samples, sslt_samples / 10)) + tab_write(file, "subsurface { samples %d, %d }\n" % (sslt_samples, sslt_samples / 10)) once_sss = 0 if world and once_ambient: - tab_write("ambient_light rgb<%.3g, %.3g, %.3g>\n" % world.pov.ambient_color[:]) + tab_write(file, "ambient_light rgb<%.3g, %.3g, %.3g>\n" % world.pov.ambient_color[:]) once_ambient = 0 - if scene.pov.photon_enable: - if once_photons and ( - material.pov.refraction_type == "2" or material.pov.photons_reflection - ): - tab_write("photons {\n") - tab_write("spacing %.6f\n" % scene.pov.photon_spacing) - tab_write("max_trace_level %d\n" % scene.pov.photon_max_trace_level) - tab_write("adc_bailout %.3g\n" % scene.pov.photon_adc_bailout) - tab_write( - "gather %d, %d\n" - % (scene.pov.photon_gather_min, scene.pov.photon_gather_max) - ) - if scene.pov.photon_map_file_save_load in {'save'}: - ph_file_name = 'Photon_map_file.ph' - if scene.pov.photon_map_file != '': - ph_file_name = scene.pov.photon_map_file + '.ph' - ph_file_dir = tempfile.gettempdir() - path = bpy.path.abspath(scene.pov.photon_map_dir) - if os.path.exists(path): - ph_file_dir = path - full_file_name = os.path.join(ph_file_dir, ph_file_name) - tab_write('save_file "%s"\n' % full_file_name) - scene.pov.photon_map_file = full_file_name - if scene.pov.photon_map_file_save_load in {'load'}: - full_file_name = bpy.path.abspath(scene.pov.photon_map_file) - if os.path.exists(full_file_name): - tab_write('load_file "%s"\n' % full_file_name) - tab_write("}\n") - once_photons = 0 - - tab_write("}\n") + if ( + scene.pov.photon_enable + and once_photons + and ( + material.pov.refraction_type == "2" + or material.pov.photons_reflection + ) + ): + tab_write(file, "photons {\n") + tab_write(file, "spacing %.6f\n" % scene.pov.photon_spacing) + tab_write(file, "max_trace_level %d\n" % scene.pov.photon_max_trace_level) + tab_write(file, "adc_bailout %.3g\n" % scene.pov.photon_adc_bailout) + tab_write(file, + "gather %d, %d\n" + % (scene.pov.photon_gather_min, scene.pov.photon_gather_max) + ) + if scene.pov.photon_map_file_save_load in {'save'}: + ph_file_name = 'Photon_map_file.ph' + if scene.pov.photon_map_file != '': + ph_file_name = scene.pov.photon_map_file + '.ph' + ph_file_dir = tempfile.gettempdir() + path = bpy.path.abspath(scene.pov.photon_map_dir) + if os.path.exists(path): + ph_file_dir = path + full_file_name = os.path.join(ph_file_dir, ph_file_name) + tab_write(file, 'save_file "%s"\n' % full_file_name) + scene.pov.photon_map_file = full_file_name + if scene.pov.photon_map_file_save_load in {'load'}: + full_file_name = bpy.path.abspath(scene.pov.photon_map_file) + if os.path.exists(full_file_name): + tab_write(file, 'load_file "%s"\n' % full_file_name) + tab_write(file, "}\n") + once_photons = 0 + + tab_write(file, "}\n") # sel = renderable_objects() #removed for booleans if comments: @@ -697,17 +428,17 @@ def write_pov(filename, scene=None, info_callback=None): texture.type not in {'NONE', 'IMAGE'} and texture.pov.tex_pattern_type == 'emulator' ) or (texture.type in {'NONE', 'IMAGE'} and texture.pov.tex_pattern_type != 'emulator'): file.write("\n#declare PAT_%s = \n" % current_pat_name) - file.write(shading.export_pattern(texture)) + file.write(texturing_procedural.export_pattern(texture)) file.write("\n") if comments: file.write("\n//--Background--\n\n") - scenography.export_world(scene.world, scene, global_matrix, tab_write) + scenography.export_world(file, scene.world, scene, global_matrix, tab_write) if comments: file.write("\n//--Cameras--\n\n") - scenography.export_camera(scene, global_matrix, render, tab_write) + scenography.export_camera(file, scene, global_matrix, render, tab_write) if comments: file.write("\n//--Lamps--\n\n") @@ -719,32 +450,15 @@ def write_pov(filename, scene=None, info_callback=None): csg_list.append(mod.object) if csg_list: csg = False - sel = no_renderable_objects() + sel = non_renderable_objects() # export non rendered boolean objects operands - object_mesh_topology.export_meshes( - preview_dir, + model_all.objects_loop( file, scene, sel, csg, - string_strip_hyphen, - safety, - write_object_modifiers, material_names_dictionary, - write_object_material_interior, - scenography.exported_lights_count, unpacked_images, - image_format, - img_map, - img_map_transforms, - path_image, - smoke_path, - global_matrix, - write_matrix, - using_uberpov, - comments, - linebreaksinlists, - tab, tab_level, tab_write, info_callback, @@ -758,7 +472,6 @@ def write_pov(filename, scene=None, info_callback=None): file, scene, global_matrix, - write_matrix, tab_write, ) @@ -769,7 +482,6 @@ def write_pov(filename, scene=None, info_callback=None): file, scene, global_matrix, - write_matrix, tab_write, ) @@ -780,7 +492,7 @@ def write_pov(filename, scene=None, info_callback=None): continue # don't export as pov curves objects with modifiers, but as mesh # Implicit else-if (as not skipped by previous "continue") if c.type == 'CURVE' and (c.pov.curveshape in {'lathe', 'sphere_sweep', 'loft', 'birail'}): - object_curve_topology.export_curves(file, c, string_strip_hyphen, tab_write) + model_curve_topology.export_curves(file, c, tab_write) if comments: file.write("\n//--Material Definitions--\n\n") @@ -789,10 +501,10 @@ def write_pov(filename, scene=None, info_callback=None): # Convert all materials to strings we can access directly per vertex. # exportMaterials() shading.write_material( + file, using_uberpov, DEF_MAT_NAME, tab_write, - safety, comments, unique_name, material_names_dictionary, @@ -809,7 +521,7 @@ def write_pov(filename, scene=None, info_callback=None): if len(ntree.nodes) == 0: file.write('#declare %s = texture {%s}\n' % (pov_mat_name, pigment_color)) else: - shading.write_nodes(pov_mat_name, ntree, file) + nodes_fn.write_nodes(pov_mat_name, ntree, file) for node in ntree.nodes: if node: @@ -829,10 +541,10 @@ def write_pov(filename, scene=None, info_callback=None): ) else: shading.write_material( + file, using_uberpov, DEF_MAT_NAME, tab_write, - safety, comments, unique_name, material_names_dictionary, @@ -842,46 +554,32 @@ def write_pov(filename, scene=None, info_callback=None): if comments: file.write("\n") - export_meta([m for m in sel if m.type == 'META']) + model_meta_topology.export_meta(file, + [m for m in sel if m.type == 'META'], + tab_write, + DEF_MAT_NAME,) if comments: file.write("//--Mesh objects--\n") # tbefore = time.time() - object_mesh_topology.export_meshes( - preview_dir, + model_all.objects_loop( file, scene, sel, csg, - string_strip_hyphen, - safety, - write_object_modifiers, material_names_dictionary, - write_object_material_interior, - scenography.exported_lights_count, unpacked_images, - image_format, - img_map, - img_map_transforms, - path_image, - smoke_path, - global_matrix, - write_matrix, - using_uberpov, - comments, - linebreaksinlists, - tab, tab_level, tab_write, info_callback, ) # totime = time.time() - tbefore - # print("export_meshes took" + str(totime)) + # print("objects_loop took" + str(totime)) # What follow used to happen here: # export_camera() - # scenography.export_world(scene.world, scene, global_matrix, tab_write) + # scenography.export_world(file, scene.world, scene, global_matrix, tab_write) # export_global_settings(scene) # MR:..and the order was important for implementing pov 3.7 baking # (mesh camera) comment for the record @@ -893,6 +591,7 @@ def write_pov(filename, scene=None, info_callback=None): def write_pov_ini(filename_ini, filename_log, filename_pov, filename_image): """Write ini file.""" feature_set = bpy.context.preferences.addons[__package__].preferences.branch_feature_set_povray + global using_uberpov using_uberpov = feature_set == 'uberpov' # scene = bpy.data.scenes[0] scene = bpy.context.scene @@ -963,705 +662,6 @@ def write_pov_ini(filename_ini, filename_log, filename_pov, filename_image): file.close() -class PovrayRender(bpy.types.RenderEngine): - """Define the external renderer""" - - bl_idname = 'POVRAY_RENDER' - bl_label = "Persitence Of Vision" - bl_use_shading_nodes_custom = False - DELAY = 0.5 - - @staticmethod - def _locate_binary(): - """Identify POV engine""" - addon_prefs = bpy.context.preferences.addons[__package__].preferences - - # Use the system preference if its set. - pov_binary = addon_prefs.filepath_povray - if pov_binary: - if os.path.exists(pov_binary): - return pov_binary - # Implicit else, as here return was still not triggered: - print("User Preferences path to povray %r NOT FOUND, checking $PATH" % pov_binary) - - # Windows Only - # assume if there is a 64bit binary that the user has a 64bit capable OS - if platform.startswith('win'): - import winreg - - win_reg_key = winreg.OpenKey( - winreg.HKEY_CURRENT_USER, "Software\\POV-Ray\\v3.7\\Windows" - ) - win_home = winreg.QueryValueEx(win_reg_key, "Home")[0] - - # First try 64bits UberPOV - pov_binary = os.path.join(win_home, "bin", "uberpov64.exe") - if os.path.exists(pov_binary): - return pov_binary - - # Then try 64bits POV - pov_binary = os.path.join(win_home, "bin", "pvengine64.exe") - if os.path.exists(pov_binary): - return pov_binary - - # search the path all os's - pov_binary_default = "povray" - - os_path_ls = os.getenv("PATH").split(':') + [""] - - for dir_name in os_path_ls: - pov_binary = os.path.join(dir_name, pov_binary_default) - if os.path.exists(pov_binary): - return pov_binary - return "" - - def _export(self, depsgraph, pov_path, image_render_path): - """gather all necessary output files paths user defined and auto generated and export there""" - - scene = bpy.context.scene - if scene.pov.tempfiles_enable: - self._temp_file_in = tempfile.NamedTemporaryFile(suffix=".pov", delete=False).name - # PNG with POV 3.7, can show the background color with alpha. In the long run using the - # POV-Ray interactive preview like bishop 3D could solve the preview for all formats. - 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: - self._temp_file_in = pov_path + ".pov" - # PNG with POV 3.7, can show the background color with alpha. In the long run using the - # POV-Ray interactive preview like bishop 3D could solve the preview for all formats. - self._temp_file_out = image_render_path + ".png" - # self._temp_file_out = image_render_path + ".tga" - self._temp_file_ini = pov_path + ".ini" - log_path = bpy.path.abspath(scene.pov.scene_path).replace('\\', '/') - self._temp_file_log = os.path.join(log_path, "alltext.out") - ''' - self._temp_file_in = "/test.pov" - # PNG with POV 3.7, can show the background color with alpha. In the long run using the - # POV-Ray interactive preview like bishop 3D could solve the preview for all formats. - self._temp_file_out = "/test.png" - #self._temp_file_out = "/test.tga" - self._temp_file_ini = "/test.ini" - ''' - if scene.pov.text_block == "": - - def info_callback(txt): - self.update_stats("", "POV-Ray 3.7: " + txt) - - # os.makedirs(user_dir, exist_ok=True) # handled with previews - os.makedirs(preview_dir, exist_ok=True) - - write_pov(self._temp_file_in, scene, info_callback) - else: - pass - - def _render(self, depsgraph): - """Export necessary files and render image.""" - scene = bpy.context.scene - try: - os.remove(self._temp_file_out) # so as not to load the old file - except OSError: - pass - - 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 - - write_pov_ini( - self._temp_file_ini, self._temp_file_log, self._temp_file_in, self._temp_file_out - ) - - print("***-STARTING-***") - - extra_args = [] - - if scene.pov.command_line_switches != "": - for new_arg in scene.pov.command_line_switches.split(" "): - extra_args.append(new_arg) - - self._is_windows = False - if platform.startswith('win'): - self._is_windows = True - if "/EXIT" not in extra_args and not scene.pov.pov_editor: - extra_args.append("/EXIT") - else: - # added -d option to prevent render window popup which leads to segfault on linux - extra_args.append("-d") - - # Start Rendering! - try: - self._process = subprocess.Popen( - [pov_binary, self._temp_file_ini] + extra_args, - 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 - - # Now that we have a valid process - - def _cleanup(self): - """Delete temp files and unpacked ones""" - for f in (self._temp_file_in, self._temp_file_ini, self._temp_file_out): - for i in range(5): - try: - os.unlink(f) - break - except OSError: - # Wait a bit before retrying file might be still in use by Blender, - # and Windows does not know how to delete a file in use! - time.sleep(self.DELAY) - for i in unpacked_images: - for j in range(5): - try: - os.unlink(i) - break - except OSError: - # Wait a bit before retrying file might be still in use by Blender, - # and Windows does not know how to delete a file in use! - time.sleep(self.DELAY) - - def render(self, depsgraph): - """Export necessary files from text editor and render image.""" - - scene = bpy.context.scene - r = scene.render - x = int(r.resolution_x * r.resolution_percentage * 0.01) - y = int(r.resolution_y * r.resolution_percentage * 0.01) - print("***INITIALIZING***") - - # This makes some tests on the render, returning True if all goes good, and False if - # 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 - if self.test_break(): - try: - self._process.terminate() - print("***POV INTERRUPTED***") - except OSError: - pass - return False - try: - poll_result = self._process.poll() - except AttributeError: - print("***CHECK POV PATH IN PREFERENCES***") - return False - # POV process is finisehd, one way or the other - if poll_result is not None: - 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 != "": - 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: - pov_path = scene.pov.text_block - image_render_path = os.path.splitext(pov_path)[0] - self._temp_file_out = os.path.join(preview_dir, image_render_path) - self._temp_file_in = os.path.join(preview_dir, pov_path) - 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") - - ''' - try: - os.remove(self._temp_file_in) # so as not to load the old file - except OSError: - pass - ''' - print(scene.pov.text_block) - text = bpy.data.texts[scene.pov.text_block] - with open(self._temp_file_in, "w") as file: - # Why are the newlines needed? - file.write("\n") - file.write(text.as_string()) - file.write("\n") - if not file.closed: - file.close() - - # has to be called to update the frame on exporting animations - scene.frame_set(scene.frame_current) - - 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 - - # start ini UI options export - self.update_stats("", "POV-Ray 3.7: Exporting ini options from Blender") - - write_pov_ini( - self._temp_file_ini, - self._temp_file_log, - self._temp_file_in, - self._temp_file_out, - ) - - print("***-STARTING-***") - - extra_args = [] - - if scene.pov.command_line_switches != "": - for new_arg in scene.pov.command_line_switches.split(" "): - extra_args.append(new_arg) - - if platform.startswith('win'): - if "/EXIT" not in extra_args and not scene.pov.pov_editor: - extra_args.append("/EXIT") - else: - # added -d option to prevent render window popup which leads to segfault on linux - extra_args.append("-d") - - # Start Rendering! - try: - if scene.pov.sdl_window_enable and not platform.startswith( - 'win' - ): # 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, - 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") - - # Indented in main function now so repeated here but still not working - # to bring back render result to its buffer - - 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) - result = self.begin_result(0, 0, x, y) - lay = result.layers[0] - - 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 - print(f.read()) - - self.update_stats("", "") - - if scene.pov.tempfiles_enable or scene.pov.deletefiles_enable: - self._cleanup() - else: - - # 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' - - blend_scene_name = bpy.data.filepath.split(os.path.sep)[-1].split(".")[0] - pov_scene_name = "" - pov_path = "" - image_render_path = "" - - # 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 - pov_path = bpy.path.abspath(scene.pov.scene_path).replace('\\', '/') - if pov_path == "": - if bpy.data.is_saved: - pov_path = bpy.path.abspath("//") - else: - pov_path = tempfile.gettempdir() - elif pov_path.endswith("/"): - if pov_path == "/": - pov_path = bpy.path.abspath("//") - else: - pov_path = bpy.path.abspath(scene.pov.scene_path) - - if not os.path.exists(pov_path): - try: - os.makedirs(pov_path) - except BaseException as e: - print(e.__doc__) - print('An exception occurred: {}'.format(e)) - import traceback - - traceback.print_exc() - - print("POV-Ray 3.7: Cannot create scenes directory: %r" % pov_path) - self.update_stats( - "", "POV-Ray 3.7: Cannot create scenes directory %r" % pov_path - ) - time.sleep(2.0) - # return - - ''' - # Bug in POV-Ray RC3 - image_render_path = bpy.path.abspath(scene.pov.renderimage_path).replace('\\','/') - if image_render_path == "": - if bpy.data.is_saved: - image_render_path = bpy.path.abspath("//") - else: - image_render_path = tempfile.gettempdir() - #print("Path: " + image_render_path) - elif path.endswith("/"): - if image_render_path == "/": - image_render_path = bpy.path.abspath("//") - else: - image_render_path = bpy.path.abspath(scene.pov.) - 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 blend_scene_name != "": - pov_scene_name = blend_scene_name - else: - pov_scene_name = "untitled" - else: - pov_scene_name = scene.pov.scene_name - if os.path.isfile(pov_scene_name): - pov_scene_name = os.path.basename(pov_scene_name) - pov_scene_name = pov_scene_name.split('/')[-1].split('\\')[-1] - if not pov_scene_name: - print("POV-Ray 3.7: Invalid scene name") - self.update_stats("", "POV-Ray 3.7: Invalid scene name") - time.sleep(2.0) - # return - pov_scene_name = os.path.splitext(pov_scene_name)[0] - - print("Scene name: " + pov_scene_name) - print("Export path: " + pov_path) - pov_path = os.path.join(pov_path, pov_scene_name) - pov_path = os.path.realpath(pov_path) - - image_render_path = pov_path - # print("Render Image path: " + image_render_path) - - # start export - self.update_stats("", "POV-Ray 3.7: Exporting data from Blender") - self._export(depsgraph, pov_path, image_render_path) - self.update_stats("", "POV-Ray 3.7: Parsing File") - - if not self._render(depsgraph): - 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(): - # POV in Windows did not output its stdout/stderr, it displayed them in its GUI - # But now writes file - 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 - - 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") - - elif parsing.search(data): - self.update_stats("", "POV-Ray 3.7: Parsing File") - - if os.path.exists(self._temp_file_out): - # print("***POV FILE OK***") - # self.update_stats("", "POV-Ray 3.7: Rendering") - - # prev_size = -1 - - 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) - - # print("***POV UPDATING IMAGE***") - result = self.begin_result(0, 0, x, y) - # XXX, tests for border render. - # result = self.begin_result(xmin, ymin, xmax - xmin, ymax - ymin) - # result = self.begin_result(0, 0, xmax - xmin, ymax - ymin) - lay = result.layers[0] - - # This assumes the file has been fully written We wait a bit, just in case! - time.sleep(self.DELAY) - 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: - print("***POV ERROR WHILE READING OUTPUT FILE***") - - # 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. - try: - 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: - pass - - # Update while POV-Ray renders - while True: - # print("***POV RENDER LOOP***") - - # test if POV-Ray exists - if self._process.poll() is not None: - print("***POV PROCESS FINISHED***") - update_image() - break - - # user exit - if self.test_break(): - try: - self._process.terminate() - print("***POV PROCESS INTERRUPTED***") - except OSError: - pass - - break - - # Would be nice to redirect the output - # stdout_value, stderr_value = self._process.communicate() # locks - - # check if the file updated - new_size = os.path.getsize(self._temp_file_out) - - if new_size != prev_size: - update_image() - prev_size = new_size - - time.sleep(self.DELAY) - ''' - - self.end_result(result) - - 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, encoding='utf-8' - ) as f: # The with keyword automatically closes the file when you are done - msg = f.read() - # if isinstance(msg, str): - # stdmsg = msg - # decoded = False - # else: - # if type(msg) == bytes: - # stdmsg = msg.split('\n') - # stdmsg = msg.encode('utf-8', "replace") - # stdmsg = msg.encode("utf-8", "replace") - - # stdmsg = msg.decode(encoding) - # decoded = True - # msg.encode('utf-8').decode('utf-8') - msg.replace("\t", " ") - print(msg) - # Also print to the interactive console used in POV centric workspace - # To do: get a grip on new line encoding - # and make this a function to be used elsewhere - for win in bpy.context.window_manager.windows: - if win.screen is not None: - scr = win.screen - for area in scr.areas: - if area.type == 'CONSOLE': - try: - # context override - ctx = { - 'area': area, - 'screen': scr, - 'window': win - } - - # bpy.ops.console.banner(ctx, text = "Hello world") - bpy.ops.console.clear_line(ctx) - for i in msg.split('\n'): - bpy.ops.console.scrollback_append( - ctx, - text=i, - type='INFO' - ) - # bpy.ops.console.insert(ctx, text=(i + "\n")) - except BaseException as e: - print(e.__doc__) - print('An exception occurred: {}'.format(e)) - pass - - self.update_stats("", "") - - if scene.pov.tempfiles_enable or scene.pov.deletefiles_enable: - self._cleanup() - - sound_on = bpy.context.preferences.addons[__package__].preferences.use_sounds - finished_render_message = "\'Et Voilà!\'" - - if platform.startswith('win') and sound_on: - # Could not find tts Windows command so playing beeps instead :-) - # "Korobeiniki"(Коробе́йники) - # aka "A-Type" Tetris theme - import winsound - - winsound.Beep(494, 250) # B - winsound.Beep(370, 125) # F - winsound.Beep(392, 125) # G - winsound.Beep(440, 250) # A - winsound.Beep(392, 125) # G - winsound.Beep(370, 125) # F# - winsound.Beep(330, 275) # E - winsound.Beep(330, 125) # E - winsound.Beep(392, 125) # G - winsound.Beep(494, 275) # B - winsound.Beep(440, 125) # A - winsound.Beep(392, 125) # G - winsound.Beep(370, 275) # F - winsound.Beep(370, 125) # F - winsound.Beep(392, 125) # G - winsound.Beep(440, 250) # A - winsound.Beep(494, 250) # B - winsound.Beep(392, 250) # G - winsound.Beep(330, 350) # E - time.sleep(0.5) - winsound.Beep(440, 250) # A - winsound.Beep(440, 150) # A - winsound.Beep(523, 125) # D8 - winsound.Beep(659, 250) # E8 - winsound.Beep(587, 125) # D8 - winsound.Beep(523, 125) # C8 - winsound.Beep(494, 250) # B - winsound.Beep(494, 125) # B - winsound.Beep(392, 125) # G - winsound.Beep(494, 250) # B - winsound.Beep(440, 150) # A - winsound.Beep(392, 125) # G - winsound.Beep(370, 250) # F# - winsound.Beep(370, 125) # F# - winsound.Beep(392, 125) # G - winsound.Beep(440, 250) # A - winsound.Beep(494, 250) # B - winsound.Beep(392, 250) # G - winsound.Beep(330, 300) # E - - # Mac supports natively say command - elif platform == "darwin": - # We don't want the say command to block Python, - # so we add an ampersand after the message - # but if the os TTS package isn't up to date it - # still does thus, the try except clause - try: - os.system("say %s &" % finished_render_message) - except BaseException as e: - print(e.__doc__) - print("your Mac may need an update, try to restart computer") - pass - # While Linux frequently has espeak installed or at least can suggest - # Maybe windows could as well ? - elif platform == "linux": - # We don't want the espeak command to block Python, - # so we add an ampersand after the message - # but if the espeak TTS package isn't installed it - # still does thus, the try except clause - try: - os.system("echo %s | espeak &" % finished_render_message) - except BaseException as e: - print(e.__doc__) - pass - - - # --------------------------------------------------------------------------------- # # ----------------------------------- Operators ----------------------------------- # # --------------------------------------------------------------------------------- # @@ -1703,7 +703,7 @@ class RenderPovTexturePreview(Operator): with open(input_prev_file, "w") as file_pov: pat_name = "PAT_" + string_strip_hyphen(bpy.path.clean_name(tex.name)) file_pov.write("#declare %s = \n" % pat_name) - file_pov.write(shading.export_pattern(tex)) + file_pov.write(texturing_procedural.export_pattern(tex)) file_pov.write("#declare Plane =\n") file_pov.write("mesh {\n") @@ -1735,21 +735,22 @@ class RenderPovTexturePreview(Operator): file_pov.close() # ------------------------------- end write ------------------------------- # - pov_binary = PovrayRender._locate_binary() + pov_binary = PovRender._locate_binary() if platform.startswith('win'): - p1 = subprocess.Popen( + with subprocess.Popen( ["%s" % pov_binary, "/EXIT", "%s" % ini_prev_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - ) + ) as p1: + p1.wait() else: - p1 = subprocess.Popen( + with subprocess.Popen( ["%s" % pov_binary, "-d", "%s" % ini_prev_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - ) - p1.wait() + ) as p1: + p1.wait() tex.use_nodes = True tree = tex.node_tree @@ -1793,7 +794,7 @@ class RunPovTextRender(Operator): classes = ( - PovrayRender, + #PovRender, RenderPovTexturePreview, RunPovTextRender, ) |