Skip to content
Snippets Groups Projects
render.py 251 KiB
Newer Older
  • Learn to ignore specific revisions
  •             # Maybe change the above to a funtion copyInternalRenderer settings when
                # user pushes a button, then:
                #scene.pov.radio_enable = world.light_settings.use_indirect_light
                # and other such translations but maybe this would not be allowed either?
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
            ###############################################################
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Campbell Barton's avatar
    Campbell Barton committed
            mist = world.mist_settings
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
            if mist.use_mist:
    
                tabWrite("fog {\n")
                tabWrite("distance %.6f\n" % mist.depth)
    
                tabWrite("color rgbt<%.3g, %.3g, %.3g, %.3g>\n" % \
    
                         (*world.horizon_color, 1.0 - mist.intensity))
    
                #tabWrite("fog_offset %.6f\n" % mist.start)
                #tabWrite("fog_alt 5\n")
                #tabWrite("turbulence 0.2\n")
                #tabWrite("turb_depth 0.3\n")
                tabWrite("fog_type 1\n")
                tabWrite("}\n")
    
                tabWrite("scattering { 1, rgb <%.4g, %.4g, %.4g>}\n" % scene.pov.media_color[:])
                tabWrite("samples %.d\n" % scene.pov.media_samples)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
        def exportGlobalSettings(scene):
    
    
            tabWrite("global_settings {\n")
            tabWrite("assumed_gamma 1.0\n")
    
            tabWrite("max_trace_level %d\n" % scene.pov.max_trace_level)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                tabWrite("adc_bailout %.4g\n" % scene.pov.radio_adc_bailout)
                tabWrite("always_sample %d\n" % scene.pov.radio_always_sample)
                tabWrite("brightness %.4g\n" % scene.pov.radio_brightness)
                tabWrite("count %d\n" % scene.pov.radio_count)
                tabWrite("error_bound %.4g\n" % scene.pov.radio_error_bound)
                tabWrite("gray_threshold %.4g\n" % scene.pov.radio_gray_threshold)
                tabWrite("low_error_factor %.4g\n" % scene.pov.radio_low_error_factor)
                tabWrite("media %d\n" % scene.pov.radio_media)
                tabWrite("minimum_reuse %.4g\n" % scene.pov.radio_minimum_reuse)
                tabWrite("nearest_count %d\n" % scene.pov.radio_nearest_count)
                tabWrite("normal %d\n" % scene.pov.radio_normal)
                tabWrite("pretrace_start %.3g\n" % scene.pov.radio_pretrace_start)
                tabWrite("pretrace_end %.3g\n" % scene.pov.radio_pretrace_end)
                tabWrite("recursion_limit %d\n" % scene.pov.radio_recursion_limit)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            for material in bpy.data.materials:
    
                if material.subsurface_scattering.use and onceSss:
    
                    # In pov, the scale has reversed influence compared to blender. these number
                    # should correct that
                    tabWrite("mm_per_unit %.6f\n" % \
    
                             (material.subsurface_scattering.scale * 1000.0))
                             # 1000 rather than scale * (-100.0) + 15.0))
    
    
                    # In POV-Ray, the scale factor for all subsurface shaders needs to be the same
    
                    
                    # formerly sslt_samples were multiplied by 100 instead of 10
                    sslt_samples = (11 - material.subsurface_scattering.error_threshold) * 10 
    
    
    Campbell Barton's avatar
    Campbell Barton committed
                    tabWrite("subsurface { samples %d, %d }\n" % (sslt_samples, sslt_samples / 10))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                    tabWrite("ambient_light rgbt<%.3g, %.3g, %.3g,1>\n" % world.ambient_color[:])
    
                if (oncePhotons and
                        (material.pov.refraction_type == "2" or
                        material.pov.photons_reflection == True)):
    
                    tabWrite("photons {\n")
                    tabWrite("spacing %.6f\n" % scene.pov.photon_spacing)
                    tabWrite("max_trace_level %d\n" % scene.pov.photon_max_trace_level)
                    tabWrite("adc_bailout %.3g\n" % scene.pov.photon_adc_bailout)
    
                    tabWrite("gather %d, %d\n" % (scene.pov.photon_gather_min,
                        scene.pov.photon_gather_max))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            # Write CurrentAnimation Frame for use in Custom POV Code
            file.write("#declare CURFRAMENUM = %d;\n" % bpy.context.scene.frame_current)
            #Change path and uncomment to add an animated include file by hand:
            file.write("//#include \"/home/user/directory/animation_include_file.inc\"\n")
    
                    # Why are the newlines needed?
                    file.write("\n")
                    file.write(txt.as_string())
                    file.write("\n")
    
        sel = renderable_objects()
    
            file.write("//----------------------------------------------\n" \
                       "//--Exported with POV-Ray exporter for Blender--\n" \
                       "//----------------------------------------------\n\n")
    
            file.write("\n//--Global settings--\n\n")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        exportGlobalSettings(scene)
    
            file.write("\n//--Custom Code--\n\n")
        exportCustomCode()
    
    
        if comments:
            file.write("\n//--Patterns Definitions--\n\n")
        LocalPatternNames = []
        for texture in bpy.data.textures: #ok?
            if texture.users > 0:
    
                currentPatName = string_strip_hyphen(bpy.path.clean_name(texture.name)) 
                #string_strip_hyphen(patternNames[texture.name]) #maybe instead of the above
                LocalPatternNames.append(currentPatName) 
                #use above list to prevent writing texture instances several times and assign in mats?
    
                file.write("\n #declare PAT_%s = \n" % currentPatName)
                file.write(exportPattern(texture))
                file.write("\n")                
    
            file.write("\n//--Background--\n\n")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        exportWorld(scene.world)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        exportCamera()
    
        exportLamps([L for L in sel if (L.type == 'LAMP' and L.pov.object_as != 'RAINBOW')])
        
        if comments:
            file.write("\n//--Rainbows--\n\n")
        exportRainbows([L for L in sel if (L.type == 'LAMP' and L.pov.object_as == 'RAINBOW')])
    
    
        if comments:
            file.write("\n//--Special Curves--\n\n")
        for c in sel:
            if c.type == 'CURVE' and (c.pov.curveshape in {'lathe','sphere_sweep','loft','birail'}):
                exportCurves(scene,c)    
    
                
    
            file.write("\n//--Material Definitions--\n\n")
    
        # write a default pigment for objects with no material (comment out to show black)
        file.write("#default{ pigment{ color rgb 0.8 }}\n")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        # Convert all materials to strings we can access directly per vertex.
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #exportMaterials()
    
        shading.writeMaterial(DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, None)  # default material
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        for material in bpy.data.materials:
    
            if material.users > 0:
    
                shading.writeMaterial(DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, material)
    
        exportMeta([m for m in sel if m.type == 'META'])
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #What follow used to happen here:
        #exportCamera()
        #exportWorld(scene.world)
        #exportGlobalSettings(scene)
    
        # MR:..and the order was important for implementing pov 3.7 baking
    
        # CR: Baking should be a special case than. If "baking", than we could change the order.
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
        #print("pov file closed %s" % file.closed)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        file.close()
    
        #print("pov file closed %s" % file.closed)
    
    def write_pov_ini(scene, filename_ini, filename_pov, filename_image):
    
        feature_set = bpy.context.user_preferences.addons[__package__].preferences.branch_feature_set_povray
        using_uberpov = (feature_set=='uberpov')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        render = scene.render
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        x = int(render.resolution_x * render.resolution_percentage * 0.01)
        y = int(render.resolution_y * render.resolution_percentage * 0.01)
    
    
        file = open(filename_ini, "w")
    
        file.write("Input_File_Name='%s'\n" % filename_pov)
        file.write("Output_File_Name='%s'\n" % filename_image)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
        file.write("Width=%d\n" % x)
        file.write("Height=%d\n" % y)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
        # Border render.
        if render.use_border:
            file.write("Start_Column=%4g\n" % render.border_min_x)
            file.write("End_Column=%4g\n" % (render.border_max_x))
    
    
    Campbell Barton's avatar
    Campbell Barton committed
            file.write("Start_Row=%4g\n" % (1.0 - render.border_max_y))
            file.write("End_Row=%4g\n" % (1.0 - render.border_min_y))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
        file.write("Bounding_Method=2\n")  # The new automatic BSP is faster in most scenes
    
        # Activated (turn this back off when better live exchange is done between the two programs
        # (see next comment)
        file.write("Display=1\n")
    
        # PNG, with POV-Ray 3.7, can show background color with alpha. In the long run using the
        # POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
        file.write("Output_File_Type=N\n")
    
        #file.write("Output_File_Type=T\n") # TGA, best progressive loading
        file.write("Output_Alpha=1\n")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
        if scene.pov.antialias_enable:
            # method 2 (recursive) with higher max subdiv forced because no mipmapping in POV-Ray
            # needs higher sampling.
            # aa_mapping = {"5": 2, "8": 3, "11": 4, "16": 5}
    
            if using_uberpov:
                method = {"0": 1, "1": 2, "2": 3}
            else:
                method = {"0": 1, "1": 2, "2": 2}
    
            file.write("Antialias_Depth=%d\n" % scene.pov.antialias_depth)
            file.write("Antialias_Threshold=%.3g\n" % scene.pov.antialias_threshold)
    
            if using_uberpov and scene.pov.antialias_method == '2':
                file.write("Sampling_Method=%s\n" % method[scene.pov.antialias_method])
                file.write("Antialias_Confidence=%.3g\n" % scene.pov.antialias_confidence)
            else:
                file.write("Sampling_Method=%s\n" % method[scene.pov.antialias_method])
    
            file.write("Antialias_Gamma=%.3g\n" % scene.pov.antialias_gamma)
            if scene.pov.jitter_enable:
    
                file.write("Jitter_Amount=%3g\n" % scene.pov.jitter_amount)
    
                file.write("Jitter=off\n")  # prevent animation flicker
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        else:
    
            file.write("Antialias=off\n")
        #print("ini file closed %s" % file.closed)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        file.close()
    
        #print("ini file closed %s" % file.closed)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    class PovrayRender(bpy.types.RenderEngine):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        bl_idname = 'POVRAY_RENDER'
    
        @staticmethod
        def _locate_binary():
            addon_prefs = bpy.context.user_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
                else:
    
                    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 sys.platform[:3] == "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
    
    
                # Then try 32bits UberPOV
                pov_binary = os.path.join(win_home, "bin", "uberpov32.exe")
                if os.path.exists(pov_binary):
                    return pov_binary 
                    
                # Then try 32bits POV
    
                pov_binary = os.path.join(win_home, "bin", "pvengine.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, scene, povPath, renderImagePath):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            import tempfile
    
                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
            else:
                self._temp_file_in = povPath + ".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 = renderImagePath + ".png"
    
                #self._temp_file_out = renderImagePath + ".tga"
                self._temp_file_ini = povPath + ".ini"
                '''
                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"
                '''
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
            def info_callback(txt):
    
                self.update_stats("", "POV-Ray 3.7: " + txt)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            # os.makedirs(user_dir, exist_ok=True)  # handled with previews
            os.makedirs(preview_dir, exist_ok=True)
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            write_pov(self._temp_file_in, scene, info_callback)
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            try:
    
                os.remove(self._temp_file_out)  # so as not to load the old file
    
    Campbell Barton's avatar
    Campbell Barton committed
            except OSError:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                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(scene, self._temp_file_ini, self._temp_file_in, self._temp_file_out)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            if scene.pov.command_line_switches != "":
                for newArg in scene.pov.command_line_switches.split(" "):
    
            if sys.platform[:3] == "win":
    
                if"/EXIT" not in extra_args and not scene.pov.pov_editor:
                    extra_args.append("/EXIT")
    
                # added -d option to prevent render window popup which leads to segfault on linux
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            # 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
    
                print("Command line arguments passed: " + str(extra_args))
                return True
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def _cleanup(self):
            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 c 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)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def render(self, scene):
    
            import tempfile
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            print("***INITIALIZING***")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    ##WIP output format
    
    ##        if r.image_settings.file_format == 'OPENEXR':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    ##            fformat = 'EXR'
    
    ##            render.image_settings.color_mode = 'RGBA'
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    ##        else:
    ##            fformat = 'TGA'
    
    ##            r.image_settings.file_format = 'TARGA'
    
    ##            r.image_settings.color_mode = 'RGBA'
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            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)
    
                povPath = bpy.path.abspath(scene.pov.scene_path).replace('\\', '/')
    
                if povPath == "":
    
                        povPath = bpy.path.abspath("//")
                    else:
                        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)
    
                '''
                # Bug in POV-Ray RC3
    
                renderImagePath = bpy.path.abspath(scene.pov.renderimage_path).replace('\\','/')
    
                if renderImagePath == "":
    
                        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 blendSceneName != "":
                        povSceneName = blendSceneName
                    else:
                        povSceneName = "untitled"
                else:
    
                    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(scene, povPath, renderImagePath)
            self.update_stats("", "POV-Ray 3.7: Parsing File")
    
            if not self._render(scene):
                self.update_stats("", "POV-Ray 3.7: Not found")
                return
    
            r = scene.render
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            # compute resolution
            x = int(r.resolution_x * r.resolution_percentage * 0.01)
            y = int(r.resolution_y * r.resolution_percentage * 0.01)
    
    
            # 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
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                if self.test_break():
                    try:
    
    Campbell Barton's avatar
    Campbell Barton committed
                        self._process.terminate()
    
    Campbell Barton's avatar
    Campbell Barton committed
                    except OSError:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                        pass
    
                # POV process is finisehd, one way or the other
    
    Campbell Barton's avatar
    Campbell Barton committed
                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
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            # 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 does not output its stdout/stderr, it displays them in its GUI
                if self._is_windows:
                    self.update_stats("", "POV-Ray 3.7: Rendering File")
                else:
    
    Campbell Barton's avatar
    Campbell Barton committed
                    if not t_data:
                        continue
    
                    # 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")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                    elif parsing.search(data):
                        self.update_stats("", "POV-Ray 3.7: Parsing File")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            if os.path.exists(self._temp_file_out):
                # print("***POV FILE OK***")
                #self.update_stats("", "POV-Ray 3.7: Rendering")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita 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)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                # 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)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                # 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)
                '''
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            if scene.pov.tempfiles_enable or scene.pov.deletefiles_enable:
    
                self._cleanup()
    
    ##################################################################################
    #################################Operators########################################
    ##################################################################################
    
    class RenderPovTexturePreview(Operator):
        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"
    
            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(exportPattern(tex))
    
            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)
            im = tree.nodes.new("TextureNodeImage")  
            pathPrev="%s.png"%outputPrevFile
            im.image = bpy.data.images.load(pathPrev)
            name=pathPrev
            name=name.split("/")
            name=name[len(name)-1]
            im.name = name  
            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"