@@ -298,7 +298,6 @@ def init_slider_values(self):
298
298
def btnRefresh_clicked (self , checked ):
299
299
300
300
# Render current frame
301
- preview_frame_number = self .win .sliderPreview .value ()
302
301
self .preview_timer .start ()
303
302
304
303
@pyqtSlot ()
@@ -675,20 +674,21 @@ def Render(self, blend_file_path, target_script, preview_mode=False):
675
674
# Init regex expression used to determine blender's render progress
676
675
s = settings .get_settings ()
677
676
677
+ _ = get_app ()._tr
678
+
678
679
# get the blender executable path
679
680
self .blender_exec_path = s .get ("blender_command" )
680
- self .blender_frame_expression = re .compile (r"Fra:([0-9,]*).*Mem:(.*?) .*Sce:" )
681
- self .blender_saved_expression = re .compile (r"Saved: '(.*.png)(.*)'" )
682
- self .blender_version = re .compile (r"Blender (.*?) " )
683
- self .blend_file_path = blend_file_path
684
- self .target_script = target_script
685
681
self .preview_mode = preview_mode
686
682
self .frame_detected = False
683
+ self .last_frame = 0
687
684
self .version = None
688
685
self .command_output = ""
689
686
self .process = None
690
- self .is_running = True
691
- _ = get_app ()._tr
687
+ self .is_running = False
688
+
689
+ blender_frame_re = re .compile (r"Fra:([0-9,]*)" )
690
+ blender_saved_re = re .compile (r"Saved: '(.*\.png)" )
691
+ blender_version_re = re .compile (r"Blender (.*?) " )
692
692
693
693
startupinfo = None
694
694
if sys .platform == 'win32' :
@@ -698,90 +698,99 @@ def Render(self, blend_file_path, target_script, preview_mode=False):
698
698
try :
699
699
# Shell the blender command to create the image sequence
700
700
command_get_version = [self .blender_exec_path , '-v' ]
701
- command_render = [self .blender_exec_path , '-b' , self . blend_file_path , '-P' , self . target_script ]
701
+ command_render = [self .blender_exec_path , '-b' , blend_file_path , '-P' , target_script ]
702
702
703
703
# Check the version of Blender
704
704
import shlex
705
705
log .info ("Checking Blender version, command: {}" .format (
706
706
" " .join ([shlex .quote (x ) for x in command_get_version ])))
707
707
708
- self . process = subprocess .Popen (
708
+ proc = subprocess .Popen (
709
709
command_get_version ,
710
- stdout = subprocess .PIPE , stderr = subprocess .PIPE ,
711
- startupinfo = startupinfo , universal_newlines = True ,
710
+ stdout = subprocess .PIPE , stderr = subprocess .STDOUT ,
711
+ startupinfo = startupinfo ,
712
712
)
713
713
714
714
# Check the version of Blender
715
- self .version = self .blender_version .findall (self .process .stdout .readline ())
715
+ try :
716
+ # Give Blender up to 10 seconds to respond
717
+ (out , err ) = proc .communicate (timeout = 10 )
718
+ except subprocess .TimeoutExpired :
719
+ self .blender_error_nodata .emit ()
720
+ return
721
+
722
+ ver_string = out .decode ('utf-8' )
723
+ ver_match = blender_version_re .search (ver_string )
716
724
717
- if self .version :
718
- if self .version [0 ] < info .BLENDER_MIN_VERSION :
719
- # change cursor to "default" and stop running blender command
720
- self .is_running = False
725
+ if not ver_match :
726
+ raise Exception ("No Blender version detected in output" )
721
727
722
- # Wrong version of Blender.
723
- self .blender_version_error .emit (self .version [0 ])
724
- return
728
+ self .version = ver_match .group (1 )
729
+ log .info ("Found Blender version {}" .format (self .version ))
730
+
731
+ if self .version < info .BLENDER_MIN_VERSION :
732
+ # Wrong version of Blender.
733
+ self .blender_version_error .emit (self .version )
734
+ return
725
735
726
736
# debug info
727
737
log .info ("Running Blender, command: {}" .format (
728
738
" " .join ([shlex .quote (x ) for x in command_render ])))
729
739
log .info ("Blender output:" )
730
740
731
741
# Run real command to render Blender project
732
- self . process = subprocess .Popen (
733
- command_render ,
742
+ proc = subprocess .Popen (
743
+ command_render , bufsize = 512 ,
734
744
stdout = subprocess .PIPE , stderr = subprocess .STDOUT ,
735
- startupinfo = startupinfo , universal_newlines = True ,
745
+ startupinfo = startupinfo ,
736
746
)
747
+ self .process = proc
748
+ self .is_running = True
737
749
738
- except Exception as ex :
750
+ except subprocess . SubprocessError :
739
751
# Error running command. Most likely the blender executable path in
740
752
# the settings is incorrect, or is not a supported Blender version
741
753
self .is_running = False
742
754
self .blender_error_nodata .emit ()
743
- log .error ("Could not execute Blender: {}" .format (ex ))
755
+ raise
756
+ except Exception as ex :
757
+ log .error ("{}" .format (ex ))
744
758
return
745
759
746
- while self .is_running and self .process .poll () is None :
747
-
748
- # Look for progress info in the Blender Output
749
- line = self .process .stdout .readline ().strip ()
760
+ while self .is_running and proc .poll () is None :
761
+ for outline in iter (proc .stdout .readline , b'' ):
762
+ line = outline .decode ('utf-8' ).strip ()
750
763
751
- # Skip blank lines
752
- if not line :
753
- continue
764
+ # Skip blank output
765
+ if not line :
766
+ continue
754
767
755
- # append all output into a variable, and log
756
- self .command_output = self .command_output + line + "\n "
757
- log .info (" {}" .format (line ))
768
+ # append all output into a variable, and log
769
+ self .command_output = self .command_output + line + "\n "
770
+ log .info (" {}" .format (line ))
758
771
759
- output_frame = self .blender_frame_expression .findall (line )
772
+ # Look for progress info in the Blender Output
773
+ output_frame = blender_frame_re .search (line )
774
+ output_saved = blender_saved_re .search (line )
760
775
761
- # Does it have a match?
762
- if output_frame :
763
- # Yes, we have a match
764
- self .frame_detected = True
765
- current_frame = output_frame [0 ][0 ]
766
- memory = output_frame [0 ][1 ]
776
+ # Does it have a match?
777
+ if output_frame or output_saved :
778
+ # Yes, we have a match
779
+ self .frame_detected = True
767
780
768
- # Update progress bar
769
- if not self .preview_mode :
770
- # only update progress if in 'render' mode
771
- self .progress .emit (int (current_frame ))
781
+ if output_frame :
782
+ current_frame = int (output_frame .group (1 ))
772
783
773
- # Look for progress info in the Blender Output
774
- output_saved = self .blender_saved_expression .findall (line )
784
+ # Update progress bar
785
+ if current_frame != self .last_frame and not self .preview_mode :
786
+ # update progress on frame change, if in 'render' mode
787
+ self .progress .emit (current_frame )
775
788
776
- # Does it have a match?
777
- if output_saved :
778
- # Yes, we have a match
779
- self .frame_detected = True
780
- image_path = output_saved [0 ][0 ]
781
- time_saved = output_saved [0 ][1 ]
789
+ self .last_frame = current_frame
782
790
783
- # Update preview image
784
- self .image_updated .emit (image_path )
791
+ if output_saved :
792
+ # Update preview image
793
+ self .image_updated .emit (output_saved .group (1 ))
785
794
786
795
log .info ("Blender process exited." )
787
796
0 commit comments