Skip to content

Commit fcefc20

Browse files
committed
Blender: Go back to bytes, for command output
Python 3.4 (AppImages) doesn't let us set the encoding, which can cause problems. Now we forcibly decode as utf-8.
1 parent 39d7de4 commit fcefc20

File tree

1 file changed

+65
-56
lines changed

1 file changed

+65
-56
lines changed

src/windows/views/blender_listview.py

+65-56
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,6 @@ def init_slider_values(self):
298298
def btnRefresh_clicked(self, checked):
299299

300300
# Render current frame
301-
preview_frame_number = self.win.sliderPreview.value()
302301
self.preview_timer.start()
303302

304303
@pyqtSlot()
@@ -675,20 +674,21 @@ def Render(self, blend_file_path, target_script, preview_mode=False):
675674
# Init regex expression used to determine blender's render progress
676675
s = settings.get_settings()
677676

677+
_ = get_app()._tr
678+
678679
# get the blender executable path
679680
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
685681
self.preview_mode = preview_mode
686682
self.frame_detected = False
683+
self.last_frame = 0
687684
self.version = None
688685
self.command_output = ""
689686
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 (.*?) ")
692692

693693
startupinfo = None
694694
if sys.platform == 'win32':
@@ -698,90 +698,99 @@ def Render(self, blend_file_path, target_script, preview_mode=False):
698698
try:
699699
# Shell the blender command to create the image sequence
700700
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]
702702

703703
# Check the version of Blender
704704
import shlex
705705
log.info("Checking Blender version, command: {}".format(
706706
" ".join([shlex.quote(x) for x in command_get_version])))
707707

708-
self.process = subprocess.Popen(
708+
proc = subprocess.Popen(
709709
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,
712712
)
713713

714714
# 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)
716724

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")
721727

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
725735

726736
# debug info
727737
log.info("Running Blender, command: {}".format(
728738
" ".join([shlex.quote(x) for x in command_render])))
729739
log.info("Blender output:")
730740

731741
# Run real command to render Blender project
732-
self.process = subprocess.Popen(
733-
command_render,
742+
proc = subprocess.Popen(
743+
command_render, bufsize=512,
734744
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
735-
startupinfo=startupinfo, universal_newlines=True,
745+
startupinfo=startupinfo,
736746
)
747+
self.process = proc
748+
self.is_running = True
737749

738-
except Exception as ex:
750+
except subprocess.SubprocessError:
739751
# Error running command. Most likely the blender executable path in
740752
# the settings is incorrect, or is not a supported Blender version
741753
self.is_running = False
742754
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))
744758
return
745759

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()
750763

751-
# Skip blank lines
752-
if not line:
753-
continue
764+
# Skip blank output
765+
if not line:
766+
continue
754767

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))
758771

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)
760775

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
767780

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))
772783

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)
775788

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
782790

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))
785794

786795
log.info("Blender process exited.")
787796

0 commit comments

Comments
 (0)