diff --git a/plugins/BlackBeltPlugin/CuraEngineBackendPatches.py b/plugins/BlackBeltPlugin/CuraEngineBackendPatches.py index 7e4e024c95..a7bba5e493 100644 --- a/plugins/BlackBeltPlugin/CuraEngineBackendPatches.py +++ b/plugins/BlackBeltPlugin/CuraEngineBackendPatches.py @@ -20,7 +20,7 @@ class CuraEngineBackendPatches(): ## Perform a slice of the scene. def slice(self): - Logger.log("d", "starting to slice!") + Logger.log("d", "Starting to slice...") self._backend._slice_start_time = time() if not self._backend._build_plates_to_be_sliced: self._backend.processingProgress.emit(1.0) @@ -28,17 +28,21 @@ class CuraEngineBackendPatches(): return if self._backend._process_layers_job: - Logger.log("d", " ## Process layers job still busy, trying later") + Logger.log("d", "Process layers job still busy, trying later.") return if not hasattr(self._backend._scene, "gcode_dict"): self._backend._scene.gcode_dict = {} # see if we really have to slice - active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate build_plate_to_be_sliced = self._backend._build_plates_to_be_sliced.pop(0) Logger.log("d", "Going to slice build plate [%s]!" % build_plate_to_be_sliced) - num_objects = self._backend._numObjects() + num_objects = self._backend._numObjectsPerBuildPlate() + + self._backend._stored_layer_data = [] + self._backend._stored_optimized_layer_data[build_plate_to_be_sliced] = [] + if build_plate_to_be_sliced not in num_objects or num_objects[build_plate_to_be_sliced] == 0: self._backend._scene.gcode_dict[build_plate_to_be_sliced] = [] Logger.log("d", "Build plate %s has no objects to be sliced, skipping", build_plate_to_be_sliced) @@ -46,9 +50,6 @@ class CuraEngineBackendPatches(): self._backend.slice() return - self._backend._stored_layer_data = [] - self._backend._stored_optimized_layer_data[build_plate_to_be_sliced] = [] - if Application.getInstance().getPrintInformation() and build_plate_to_be_sliced == active_build_plate: Application.getInstance().getPrintInformation().setToZeroPrintInformation(build_plate_to_be_sliced) @@ -78,19 +79,3 @@ class CuraEngineBackendPatches(): self._backend._process_layers_job.setBuildPlate(build_plate_number) self._backend._process_layers_job.finished.connect(self._backend._onProcessLayersFinished) self._backend._process_layers_job.start() - - ## Called when the user changes the active view mode. - def _onActiveViewChanged(self): - view = Application.getInstance().getController().getActiveView() - if view: - if view.getPluginId() == "SimulationView": # If switching to layer view, we should process the layers if that hasn't been done yet. - self._backend._layer_view_active = True - # There is data and we're not slicing at the moment - # if we are slicing, there is no need to re-calculate the data as it will be invalid in a moment. - if self._backend._layer_view_active and (self._backend._process_layers_job is None or not self._backend._process_layers_job.isRunning()): - self._backend._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._backend._stored_optimized_layer_data) - self._backend._process_layers_job.finished.connect(self._backend._onProcessLayersFinished) - self._backend._process_layers_job.start() - self._backend._stored_optimized_layer_data = [] - else: - self._backend._layer_view_active = False diff --git a/plugins/BlackBeltPlugin/ProcessSlicedLayersJob.py b/plugins/BlackBeltPlugin/ProcessSlicedLayersJob.py index 5fba8a36c6..d95b8feaa0 100644 --- a/plugins/BlackBeltPlugin/ProcessSlicedLayersJob.py +++ b/plugins/BlackBeltPlugin/ProcessSlicedLayersJob.py @@ -84,7 +84,8 @@ class ProcessSlicedLayersJob(Job): Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged) - new_node = CuraSceneNode() + # The no_setting_override is here because adding the SettingOverrideDecorator will trigger a reslice + new_node = CuraSceneNode(no_setting_override = True) new_node.addDecorator(BuildPlateDecorator(self._build_plate_number)) # Force garbage collection. diff --git a/plugins/BlackBeltPlugin/StartSliceJob.py b/plugins/BlackBeltPlugin/StartSliceJob.py index 0bcb41036e..084d61c8bf 100644 --- a/plugins/BlackBeltPlugin/StartSliceJob.py +++ b/plugins/BlackBeltPlugin/StartSliceJob.py @@ -62,19 +62,19 @@ class GcodeStartEndFormatter(Formatter): extruder_nr = int(kwargs["-1"][key_fragments[1]]) # get extruder_nr values from the global stack except (KeyError, ValueError): # either the key does not exist, or the value is not an int - Logger.log("w", "Unable to determine stack nr '%s' for key '%s' in start/end gcode, using global stack", key_fragments[1], key_fragments[0]) + Logger.log("w", "Unable to determine stack nr '%s' for key '%s' in start/end g-code, using global stack", key_fragments[1], key_fragments[0]) elif len(key_fragments) != 1: - Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end gcode", key) + Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end g-code", key) return "{" + str(key) + "}" key = key_fragments[0] try: return kwargs[str(extruder_nr)][key] except KeyError: - Logger.log("w", "Unable to replace '%s' placeholder in start/end gcode", key) + Logger.log("w", "Unable to replace '%s' placeholder in start/end g-code", key) return "{" + key + "}" else: - Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end gcode", key) + Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end g-code", key) return "{" + str(key) + "}" @@ -130,16 +130,25 @@ class StartSliceJob(Job): self.setResult(StartJobResult.BuildPlateError) return - for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()): + # Don't slice if the buildplate or the nozzle type is incompatible with the materials + if not Application.getInstance().getMachineManager().variantBuildplateCompatible and \ + not Application.getInstance().getMachineManager().variantBuildplateUsable: + self.setResult(StartJobResult.MaterialIncompatible) + return + + for position, extruder_stack in stack.extruders.items(): material = extruder_stack.findContainer({"type": "material"}) + if not extruder_stack.isEnabled: + continue if material: if material.getMetaDataEntry("compatible") == False: self.setResult(StartJobResult.MaterialIncompatible) return + # Don't slice if there is a per object setting with an error value. for node in DepthFirstIterator(self._scene.getRoot()): - if type(node) is not CuraSceneNode or not node.isSelectable(): + if not isinstance(node, CuraSceneNode) or not node.isSelectable(): continue if self._checkStackForErrors(node.callDecoration("getStack")): @@ -171,7 +180,7 @@ class StartSliceJob(Job): children = node.getAllChildren() children.append(node) for child_node in children: - if type(child_node) is CuraSceneNode and child_node.getMeshData() and child_node.getMeshData().getVertices() is not None: + if child_node.getMeshData() and child_node.getMeshData().getVertices() is not None: temp_list.append(child_node) if temp_list: @@ -183,17 +192,21 @@ class StartSliceJob(Job): temp_list = [] has_printing_mesh = False for node in DepthFirstIterator(self._scene.getRoot()): - if node.callDecoration("isSliceable") and type(node) is CuraSceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None: + if node.callDecoration("isSliceable") and node.getMeshData() and node.getMeshData().getVertices() is not None: per_object_stack = node.callDecoration("getStack") is_non_printing_mesh = False if per_object_stack: is_non_printing_mesh = any(per_object_stack.getProperty(key, "value") for key in NON_PRINTING_MESH_SETTINGS) - if (node.callDecoration("getBuildPlateNumber") == self._build_plate_number): - if not getattr(node, "_outside_buildarea", False) or is_non_printing_mesh: - temp_list.append(node) - if not is_non_printing_mesh: - has_printing_mesh = True + # Find a reason not to add the node + if node.callDecoration("getBuildPlateNumber") != self._build_plate_number: + continue + if getattr(node, "_outside_buildarea", False) and not is_non_printing_mesh: + continue + + temp_list.append(node) + if not is_non_printing_mesh: + has_printing_mesh = True Job.yieldThread() @@ -205,10 +218,22 @@ class StartSliceJob(Job): if temp_list: object_groups.append(temp_list) + extruders_enabled = {position: stack.isEnabled for position, stack in Application.getInstance().getGlobalContainerStack().extruders.items()} + filtered_object_groups = [] + for group in object_groups: + stack = Application.getInstance().getGlobalContainerStack() + skip_group = False + for node in group: + if not extruders_enabled[node.callDecoration("getActiveExtruderPosition")]: + skip_group = True + break + if not skip_group: + filtered_object_groups.append(group) + # There are cases when there is nothing to slice. This can happen due to one at a time slicing not being # able to find a possible sequence or because there are no objects on the build plate (or they are outside # the build volume) - if not object_groups: + if not filtered_object_groups: self.setResult(StartJobResult.NothingToSlice) return @@ -249,7 +274,7 @@ class StartSliceJob(Job): self._buildGlobalInheritsStackMessage(stack) # Build messages for extruder stacks - for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack_id): + for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()): if gantry_angle: # not 0 or None # Act on a copy of the stack, so these changes don't cause a reslice _extruder_stack = CuraContainerStack(extruder_stack.getId() + "_temp") @@ -271,7 +296,7 @@ class StartSliceJob(Job): belt_layer_mesh_data = {} if gantry_angle: # not 0 or None # Add a modifier mesh to all printable meshes touching the belt - for group in object_groups: + for group in filtered_object_groups: added_meshes = [] for object in group: @@ -331,9 +356,9 @@ class StartSliceJob(Job): transform_matrix = self._scene.getRoot().callDecoration("getTransformMatrix") front_offset = None - for group in object_groups: + for group in filtered_object_groups: group_message = self._slice_message.addRepeatedMessage("object_lists") - if group[0].getParent().callDecoration("isGroup"): + if group[0].getParent() is not None and group[0].getParent().callDecoration("isGroup"): self._handlePerObjectSettings(group[0].getParent(), group_message) for object in group: mesh_data = object.getMeshData() @@ -413,9 +438,15 @@ class StartSliceJob(Job): # \return A dictionary of replacement tokens to the values they should be # replaced with. def _buildReplacementTokens(self, stack) -> dict: + default_extruder_position = int(Application.getInstance().getMachineManager().defaultExtruderPosition) result = {} for key in stack.getAllKeys(): - result[key] = stack.getProperty(key, "value") + setting_type = stack.definition.getProperty(key, "type") + value = stack.getProperty(key, "value") + if setting_type == "extruder" and value == -1: + # replace with the default value + value = default_extruder_position + result[key] = value Job.yieldThread() result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings. @@ -453,7 +484,7 @@ class StartSliceJob(Job): settings["default_extruder_nr"] = default_extruder_nr return str(fmt.format(value, **settings)) except: - Logger.logException("w", "Unable to do token replacement on start/end gcode") + Logger.logException("w", "Unable to do token replacement on start/end g-code") return str(value) ## Create extruder message from stack @@ -521,11 +552,11 @@ class StartSliceJob(Job): # limit_to_extruder property. def _buildGlobalInheritsStackMessage(self, stack): for key in stack.getAllKeys(): - extruder = int(round(float(stack.getProperty(key, "limit_to_extruder")))) - if extruder >= 0: #Set to a specific extruder. + extruder_position = int(round(float(stack.getProperty(key, "limit_to_extruder")))) + if extruder_position >= 0: # Set to a specific extruder. setting_extruder = self._slice_message.addRepeatedMessage("limit_to_extruder") setting_extruder.name = key - setting_extruder.extruder = extruder + setting_extruder.extruder = extruder_position Job.yieldThread() ## Check if a node has per object settings and ensure that they are set correctly in the message