CURA-4525 refined the condition when to reslice build plates; however from the layer view it (still) doesn't always show the layers

This commit is contained in:
Jack Ha 2017-11-13 13:01:58 +01:00
parent e21acd1a07
commit c732470169
2 changed files with 74 additions and 41 deletions

View file

@ -26,5 +26,8 @@ class BuildPlateDecorator(SceneNodeDecorator):
def getPreviousBuildPlateNumber(self): def getPreviousBuildPlateNumber(self):
return self._previous_build_plate_number return self._previous_build_plate_number
def removePreviousBuildPlateNumber(self):
self._previous_build_plate_number = None
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
return BuildPlateDecorator() return BuildPlateDecorator()

View file

@ -16,6 +16,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Qt.Duration import DurationFormat from UM.Qt.Duration import DurationFormat
from PyQt5.QtCore import QObject, pyqtSlot from PyQt5.QtCore import QObject, pyqtSlot
from collections import defaultdict
from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderManager import ExtruderManager
from . import ProcessSlicedLayersJob from . import ProcessSlicedLayersJob
from . import StartSliceJob from . import StartSliceJob
@ -117,7 +118,7 @@ class CuraEngineBackend(QObject, Backend):
self._backend_log_max_lines = 20000 # Maximum number of lines to buffer self._backend_log_max_lines = 20000 # Maximum number of lines to buffer
self._error_message = None # Pop-up message that shows errors. self._error_message = None # Pop-up message that shows errors.
self._last_num_objects = 0 # Count number of objects to see if there is something changed self._last_num_objects = defaultdict(int) # Count number of objects to see if there is something changed
self._postponed_scene_change_sources = [] # scene change is postponed (by a tool) self._postponed_scene_change_sources = [] # scene change is postponed (by a tool)
self.backendQuit.connect(self._onBackendQuit) self.backendQuit.connect(self._onBackendQuit)
@ -192,17 +193,26 @@ class CuraEngineBackend(QObject, Backend):
## Perform a slice of the scene. ## Perform a slice of the scene.
def slice(self): def slice(self):
Logger.log("d", "starting to slice again!") Logger.log("d", "starting to slice!")
self._slice_start_time = time() self._slice_start_time = time()
if not self._build_plates_to_be_sliced: if not self._build_plates_to_be_sliced:
self.processingProgress.emit(1.0) self.processingProgress.emit(1.0)
self.backendStateChange.emit(BackendState.Done) self.backendStateChange.emit(BackendState.Done)
Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.") Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.")
return return
if Application.getInstance().getPrintInformation():
Application.getInstance().getPrintInformation().setToZeroPrintInformation() # see if we really have to slice
build_plate_to_be_sliced = self._build_plates_to_be_sliced.pop(0)
num_objects = self._numObjects()
if build_plate_to_be_sliced not in num_objects or num_objects[build_plate_to_be_sliced] == 0:
Logger.log("d", " ## Build plate %s has 0 objects to be sliced, skipping", build_plate_to_be_sliced)
self._invokeSlice()
self._stored_layer_data = [] self._stored_layer_data = []
self._stored_optimized_layer_data[build_plate_to_be_sliced] = []
if Application.getInstance().getPrintInformation():
Application.getInstance().getPrintInformation().setToZeroPrintInformation()
if self._process is None: if self._process is None:
self._createSocket() self._createSocket()
@ -218,8 +228,7 @@ class CuraEngineBackend(QObject, Backend):
slice_message = self._socket.createMessage("cura.proto.Slice") slice_message = self._socket.createMessage("cura.proto.Slice")
self._start_slice_job = StartSliceJob.StartSliceJob(slice_message) self._start_slice_job = StartSliceJob.StartSliceJob(slice_message)
self._start_slice_job_build_plate = self._build_plates_to_be_sliced.pop(0) self._start_slice_job_build_plate = build_plate_to_be_sliced
self._stored_optimized_layer_data[self._start_slice_job_build_plate] = []
self._start_slice_job.setBuildPlate(self._start_slice_job_build_plate) self._start_slice_job.setBuildPlate(self._start_slice_job_build_plate)
self._start_slice_job.start() self._start_slice_job.start()
self._start_slice_job.finished.connect(self._onStartSliceCompleted) self._start_slice_job.finished.connect(self._onStartSliceCompleted)
@ -364,40 +373,62 @@ class CuraEngineBackend(QObject, Backend):
self.disableTimer() self.disableTimer()
return False return False
## Return a dict with number of objects per build plate
def _numObjects(self):
num_objects = defaultdict(int)
for node in DepthFirstIterator(self._scene.getRoot()):
# Only count sliceable objects
if node.callDecoration("isSliceable"):
build_plate_number = node.callDecoration("getBuildPlateNumber")
num_objects[build_plate_number] += 1
return num_objects
## Listener for when the scene has changed. ## Listener for when the scene has changed.
# #
# This should start a slice if the scene is now ready to slice. # This should start a slice if the scene is now ready to slice.
# #
# \param source The scene node that was changed. # \param source The scene node that was changed.
def _onSceneChanged(self, source): def _onSceneChanged(self, source):
Logger.log("d", " ##### scene changed: %s", source)
if not issubclass(type(source), SceneNode): if not issubclass(type(source), SceneNode):
return return
root_scene_nodes_changed = False build_plate_changed = set()
build_plates_changed = set() source_build_plate_number = source.callDecoration("getBuildPlateNumber")
if source == self._scene.getRoot(): if source == self._scene.getRoot():
num_objects = 0 # we got the root node
num_objects = self._numObjects()
# num_objects = defaultdict(int)
for node in DepthFirstIterator(self._scene.getRoot()): for node in DepthFirstIterator(self._scene.getRoot()):
# Only count sliceable objects # # Only count sliceable objects
if node.callDecoration("isSliceable"): # if node.callDecoration("isSliceable"):
num_objects += 1 # build_plate_number = node.callDecoration("getBuildPlateNumber")
build_plates_changed.add(node.callDecoration("getBuildPlateNumber")) # num_objects[build_plate_number] += 1
build_plates_changed.add(node.callDecoration("getPreviousBuildPlateNumber")) node.callDecoration("removePreviousBuildPlateNumber") # use the previous build plate number one time
if num_objects != self._last_num_objects: for build_plate_number in list(self._last_num_objects.keys()) + list(num_objects.keys()):
self._last_num_objects = num_objects if build_plate_number not in self._last_num_objects or num_objects[build_plate_number] != self._last_num_objects[build_plate_number]:
root_scene_nodes_changed = True self._last_num_objects[build_plate_number] = num_objects[build_plate_number]
# else: build_plate_changed.add(build_plate_number)
# return # ?? else:
build_plates_changed.discard(None) # we got a single scenenode, how do we know if it's changed?
build_plates_changed.discard(-1) # object not on build plate # build_plate_changed.add(source_build_plate_number)
Logger.log("d", " #### build plates changed: %s", build_plates_changed) # build_plate_changed.add(source.callDecoration("getPreviousBuildPlateNumber"))
# source.callDecoration("removePreviousBuildPlateNumber") # use the previous build plate number one time
if not source.callDecoration("isGroup"):
if source.getMeshData() is None:
return
if source.getMeshData().getVertices() is None:
return
# if not source.callDecoration("isGroup") and not root_scene_nodes_changed: # we got a single object and it passed all the tests of being changed
# if source.getMeshData() is None: build_plate_changed.add(source_build_plate_number)
# return build_plate_changed.add(source.callDecoration("getPreviousBuildPlateNumber"))
# if source.getMeshData().getVertices() is None: source.callDecoration("removePreviousBuildPlateNumber") # use the previous build plate number one time
# return
build_plate_changed.discard(None)
build_plate_changed.discard(-1) # object not on build plate
if not build_plate_changed:
return
# Logger.log("d", " #### build plates changed: %s", build_plate_changed)
if self._tool_active: if self._tool_active:
# do it later, each source only has to be done once # do it later, each source only has to be done once
@ -405,19 +436,18 @@ class CuraEngineBackend(QObject, Backend):
self._postponed_scene_change_sources.append(source) self._postponed_scene_change_sources.append(source)
return return
if build_plates_changed: Logger.log("d", " going to reslice: %s", build_plate_changed)
Logger.log("d", " going to reslice") self.stopSlicing()
self.stopSlicing() for build_plate_number in build_plate_changed:
for build_plate_number in build_plates_changed: if build_plate_number not in self._build_plates_to_be_sliced:
if build_plate_number not in self._build_plates_to_be_sliced: self._build_plates_to_be_sliced.append(build_plate_number)
self._build_plates_to_be_sliced.append(build_plate_number) self.processingProgress.emit(0.0)
self.processingProgress.emit(0.0) self.backendStateChange.emit(BackendState.NotStarted)
self.backendStateChange.emit(BackendState.NotStarted) if not self._use_timer:
if not self._use_timer: # With manually having to slice, we want to clear the old invalid layer data.
# With manually having to slice, we want to clear the old invalid layer data. self._clearLayerData(build_plate_changed)
self._clearLayerData(build_plates_changed)
self._invokeSlice() self._invokeSlice()
# #self.needsSlicing() # #self.needsSlicing()
# self.stopSlicing() # self.stopSlicing()
@ -445,7 +475,7 @@ class CuraEngineBackend(QObject, Backend):
def _clearLayerData(self, build_plate_numbers = set()): def _clearLayerData(self, build_plate_numbers = set()):
for node in DepthFirstIterator(self._scene.getRoot()): for node in DepthFirstIterator(self._scene.getRoot()):
if node.callDecoration("getLayerData"): if node.callDecoration("getLayerData"):
if node.callDecoration("getBuildPlateNumber") in build_plate_numbers or not build_plate_numbers: if not build_plate_numbers or node.callDecoration("getBuildPlateNumber") in build_plate_numbers:
node.getParent().removeChild(node) node.getParent().removeChild(node)
def markSliceAll(self): def markSliceAll(self):