diff --git a/cura/Scene/CuraSceneNode.py b/cura/Scene/CuraSceneNode.py index df346baaad..88f89522f6 100644 --- a/cura/Scene/CuraSceneNode.py +++ b/cura/Scene/CuraSceneNode.py @@ -1,9 +1,12 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. +from copy import deepcopy from typing import List from UM.Application import Application from UM.Scene.SceneNode import SceneNode -from copy import deepcopy -from cura.Settings.ExtrudersModel import ExtrudersModel + +from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator ## Scene nodes that are models are only seen when selecting the corresponding build plate @@ -11,6 +14,8 @@ from cura.Settings.ExtrudersModel import ExtrudersModel class CuraSceneNode(SceneNode): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + if "no_setting_override" not in kwargs: + self.addDecorator(SettingOverrideDecorator()) # now we always have a getActiveExtruderPosition, unless explicitly disabled self._outside_buildarea = False def setOutsideBuildArea(self, new_value): diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index b3a2a7ed9e..817317bf0a 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -52,6 +52,8 @@ class MachineManager(QObject): self._current_quality_group = None self._current_quality_changes_group = None + self._default_extruder_position = "0" # to be updated when extruders are switched on and off + self.machine_extruder_material_update_dict = collections.defaultdict(list) self._error_check_timer = QTimer() @@ -696,6 +698,39 @@ class MachineManager(QObject): if containers: return containers[0].definition.getId() + ## Update extruder number to a valid value when the number of extruders are changed, or when an extruder is changed + def correctExtruderSettings(self): + definition_changes_container = self._global_container_stack.definitionChanges + extruder_count = definition_changes_container.getProperty("machine_extruder_count", "value") + + # reset all extruder number settings whose value is no longer valid + for setting_instance in self._global_container_stack.userChanges.findInstances(): + setting_key = setting_instance.definition.key + if not self._global_container_stack.getProperty(setting_key, "type") in ("extruder", "optional_extruder"): + continue + + old_value = self._global_container_stack.userChanges.getProperty(setting_key, "value") + if int(old_value) >= extruder_count: + self._global_container_stack.userChanges.removeInstance(setting_key) + Logger.log("d", "Reset [%s] because its old value [%s] is no longer valid", setting_key, old_value) + if not self._global_container_stack.extruders[str(old_value)].isEnabled: + self._global_container_stack.userChanges.removeInstance(setting_key) + Logger.log("d", "Reset [%s] because its old value [%s] is no longer valid (2)", setting_key, old_value) + + for setting_key in self._global_container_stack.definition.getAllKeys(): + if not self._global_container_stack.getProperty(setting_key, "type") in ("extruder", "optional_extruder"): + continue + if setting_key == "support_infill_extruder_nr": + print("asdf") + current_value = self._global_container_stack.getProperty(setting_key, "value") + if current_value is None: + continue + if current_value == "-1": + continue + if not self._global_container_stack.extruders[str(current_value)].isEnabled: + self._global_container_stack.userChanges.setProperty(setting_key, "value", str(self._default_extruder_position)) + Logger.log("d", "Change [%s] to [%s] because its value [%s] is not valid", setting_key, self._default_extruder_position, current_value) + ## Set the amount of extruders on the active machine (global stack) # \param extruder_count int the number of extruders to set def setActiveMachineExtruderCount(self, extruder_count): @@ -709,16 +744,10 @@ class MachineManager(QObject): if extruder_count == previous_extruder_count: return - # reset all extruder number settings whose value is no longer valid - for setting_instance in self._global_container_stack.userChanges.findInstances(): - setting_key = setting_instance.definition.key - if not self._global_container_stack.getProperty(setting_key, "type") in ("extruder", "optional_extruder"): - continue + definition_changes_container.setProperty("machine_extruder_count", "value", extruder_count) - old_value = int(self._global_container_stack.userChanges.getProperty(setting_key, "value")) - if old_value >= extruder_count: - self._global_container_stack.userChanges.removeInstance(setting_key) - Logger.log("d", "Reset [%s] because its old value [%s] is no longer valid ", setting_key, old_value) + self.updateDefaultExtruder() + self.correctExtruderSettings() # Check to see if any objects are set to print with an extruder that will no longer exist root_node = Application.getInstance().getController().getScene().getRoot() @@ -729,8 +758,6 @@ class MachineManager(QObject): if extruder_nr is not None and int(extruder_nr) > extruder_count - 1: node.callDecoration("setActiveExtruder", extruder_manager.getExtruderStack(extruder_count - 1).getId()) - definition_changes_container.setProperty("machine_extruder_count", "value", extruder_count) - # Make sure one of the extruder stacks is active extruder_manager.setActiveExtruderIndex(0) @@ -765,11 +792,26 @@ class MachineManager(QObject): extruder = self._global_container_stack.extruders.get(str(position)) return extruder + def updateDefaultExtruder(self): + extruder_items = sorted(self._global_container_stack.extruders.items()) + new_default_position = "0" + for position, extruder in extruder_items: + if extruder.isEnabled: + new_default_position = position + break + self._default_extruder_position = new_default_position + + @pyqtProperty(str, notify = extruderChanged) + def defaultExtruderPosition(self): + return self._default_extruder_position + @pyqtSlot(int, bool) def setExtruderEnabled(self, position: int, enabled) -> None: extruder = self.getExtruder(position) extruder.setEnabled(enabled) - + if enabled == False: + self.updateDefaultExtruder() + self.correctExtruderSettings() self.extruderChanged.emit() def _onMachineNameChanged(self): diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index c1fc597d80..cbc097bb33 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -81,7 +81,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/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 11d98c0e43..cdf33eac26 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -110,7 +110,6 @@ class StartSliceJob(Job): return stack = Application.getInstance().getGlobalContainerStack() - extruder_stack_id_to_position = {} # a lookup table because we need the position, not the id. if not stack: self.setResult(StartJobResult.Error) return @@ -131,7 +130,6 @@ class StartSliceJob(Job): return for position, extruder_stack in stack.extruders.items(): - extruder_stack_id_to_position[extruder_stack.getId()] = position material = extruder_stack.findContainer({"type": "material"}) if material: if material.getMetaDataEntry("compatible") == False: @@ -200,8 +198,7 @@ class StartSliceJob(Job): continue if getattr(node, "_outside_buildarea", False) and is_non_printing_mesh: continue - node_extruder_id = node.callDecoration("getActiveExtruder") - node_position = extruder_stack_id_to_position.get(node_extruder_id, "0") + node_position = node.callDecoration("getActiveExtruderPosition") if not stack.extruders[str(node_position)].isEnabled: continue @@ -391,11 +388,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 and stack.extruders[str(extruder)].isEnabled: #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