diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index b6739740f5..5d0ad612cf 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -111,7 +111,7 @@ class ExtruderManager(QObject): ## Creates a container stack for an extruder train. # # The container stack has an extruder definition at the bottom, which is - # linked to a machine definition. Then it has a nozzle profile, a material + # linked to a machine definition. Then it has a variant profile, a material # profile, a quality profile and a user profile, in that order. # # The resulting container stack is added to the registry. @@ -136,31 +136,31 @@ class ExtruderManager(QObject): container_stack.addMetaDataEntry("position", position) container_stack.addContainer(extruder_definition) - #Find the nozzle to use for this extruder. - nozzle = container_registry.getEmptyInstanceContainer() - if machine_definition.getMetaDataEntry("has_nozzles", default = "False") == "True": - #First add any nozzle. Later, overwrite with preference if the preference is valid. - nozzles = container_registry.findInstanceContainers(machine = machine_id, type = "nozzle") - if len(nozzles) >= 1: - nozzle = nozzles[0] - preferred_nozzle_id = machine_definition.getMetaDataEntry("preferred_nozzle") - if preferred_nozzle_id: - preferred_nozzles = container_registry.findInstanceContainers(id = preferred_nozzle_id, type = "nozzle") - if len(preferred_nozzles) >= 1: - nozzle = preferred_nozzles[0] + #Find the variant to use for this extruder. + variant = container_registry.getEmptyInstanceContainer() + if machine_definition.getMetaDataEntry("has_variants"): + #First add any variant. Later, overwrite with preference if the preference is valid. + variants = container_registry.findInstanceContainers(definition = machine_id, type = "variant") + if len(variants) >= 1: + variant = variants[0] + preferred_variant_id = machine_definition.getMetaDataEntry("preferred_variant") + if preferred_variant_id: + preferred_variants = container_registry.findInstanceContainers(id = preferred_variant_id, type = "variant") + if len(preferred_variants) >= 1: + variant = preferred_variants[0] else: - UM.Logger.log("w", "The preferred nozzle \"%s\" of machine %s doesn't exist or is not a nozzle profile.", preferred_nozzle_id, machine_id) - #And leave it at the default nozzle. - container_stack.addContainer(nozzle) + UM.Logger.log("w", "The preferred variant \"%s\" of machine %s doesn't exist or is not a variant profile.", preferred_variant_id, machine_id) + #And leave it at the default variant. + container_stack.addContainer(variant) - #Find a material to use for this nozzle. + #Find a material to use for this variant. material = container_registry.getEmptyInstanceContainer() - if machine_definition.getMetaDataEntry("has_materials", default = "False") == "True": + if machine_definition.getMetaDataEntry("has_materials"): #First add any material. Later, overwrite with preference if the preference is valid. - if machine_definition.getMetaDataEntry("has_nozzle_materials", default = "False") == "True": - materials = container_registry.findInstanceContainers(type = "material", machine = machine_id, nozzle = nozzle.getId()) + if machine_definition.getMetaDataEntry("has_variant_materials", default = "False") == "True": + materials = container_registry.findInstanceContainers(type = "material", definition = machine_id, variant = variant.getId()) else: - materials = container_registry.findInstanceContainers(type = "material", machine = machine_id) + materials = container_registry.findInstanceContainers(type = "material", definition = machine_id) if len(materials) >= 1: material = materials[0] preferred_material_id = machine_definition.getMetaDataEntry("preferred_material") @@ -175,7 +175,7 @@ class ExtruderManager(QObject): #Find a quality to use for this extruder. quality = container_registry.getEmptyInstanceContainer() - + #First add any quality. Later, overwrite with preference if the preference is valid. qualities = container_registry.findInstanceContainers(type = "quality") if len(qualities) >= 1: diff --git a/cura/ExtrudersModel.py b/cura/ExtrudersModel.py index 3ba6c5a99a..7edbb8b7c5 100644 --- a/cura/ExtrudersModel.py +++ b/cura/ExtrudersModel.py @@ -46,12 +46,17 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): self._add_global = False + self._active_extruder_stack = None + #Listen to changes. manager = cura.ExtruderManager.ExtruderManager.getInstance() manager.extrudersChanged.connect(self._updateExtruders) #When the list of extruders changes in general. - UM.Application.globalContainerStackChanged.connect(self._updateExtruders) #When the current machine changes. + UM.Application.getInstance().globalContainerStackChanged.connect(self._updateExtruders) #When the current machine changes. self._updateExtruders() + manager.activeExtruderChanged.connect(self._onActiveExtruderChanged) + self._onActiveExtruderChanged() + def setAddGlobal(self, add): if add != self._add_global: self._add_global = add @@ -63,6 +68,25 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): def addGlobal(self): return self._add_global + def _onActiveExtruderChanged(self): + manager = cura.ExtruderManager.ExtruderManager.getInstance() + active_extruder_stack = manager.getActiveExtruderStack() + if self._active_extruder_stack != active_extruder_stack: + if self._active_extruder_stack: + self._active_extruder_stack.containersChanged.disconnect(self._onExtruderStackContainersChanged) + + if active_extruder_stack: + # Update the model when the material container is changed + active_extruder_stack.containersChanged.connect(self._onExtruderStackContainersChanged) + self._active_extruder_stack = active_extruder_stack + + + def _onExtruderStackContainersChanged(self, container): + if container.getMetaDataEntry("type") == "material": + self._updateExtruders() + + modelChanged = pyqtSignal() + ## Update the list of extruders. # # This should be called whenever the list of extruders changes. @@ -85,7 +109,10 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): self.appendItem(item) for extruder in manager.getMachineExtruders(global_container_stack.getBottom().getId()): + extruder_name = extruder.getName() material = extruder.findContainer({ "type": "material" }) + if material: + extruder_name = "%s (%s)" % (material.getName(), extruder_name) position = extruder.getBottom().getMetaDataEntry("position", default = "0") #Position in the definition. try: position = int(position) @@ -95,10 +122,11 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): colour = material.getMetaDataEntry("color_code", default = default_colour) if material else default_colour item = { #Construct an item with only the relevant information. "id": extruder.getId(), - "name": extruder.getName(), + "name": extruder_name, "colour": colour, "index": position } self.appendItem(item) self.sort(lambda item: item["index"]) + self.modelChanged.emit() diff --git a/cura/MachineManagerModel.py b/cura/MachineManagerModel.py index 2960d48ed1..70953ee712 100644 --- a/cura/MachineManagerModel.py +++ b/cura/MachineManagerModel.py @@ -376,11 +376,16 @@ class MachineManagerModel(QObject): return old_material = self._active_container_stack.findContainer({"type":"material"}) + old_quality = self._active_container_stack.findContainer({"type": "quality"}) if old_material: material_index = self._active_container_stack.getContainerIndex(old_material) self._active_container_stack.replaceContainer(material_index, containers[0]) - self.setActiveQuality(self._updateQualityContainer(self._active_container_stack.getBottom(), containers[0]).id) + preferred_quality_name = None + if old_quality: + preferred_quality_name = old_quality.getName() + + self.setActiveQuality(self._updateQualityContainer(self._global_container_stack.getBottom(), containers[0], preferred_quality_name).id) @pyqtSlot(str) def setActiveVariant(self, variant_id): @@ -389,11 +394,16 @@ class MachineManagerModel(QObject): return old_variant = self._active_container_stack.findContainer({"type": "variant"}) + old_material = self._active_container_stack.findContainer({"type": "material"}) if old_variant: variant_index = self._active_container_stack.getContainerIndex(old_variant) self._active_container_stack.replaceContainer(variant_index, containers[0]) - self.setActiveMaterial(self._updateMaterialContainer(self._active_container_stack.getBottom(), containers[0]).id) + preferred_material = None + if old_material: + preferred_material = old_material.getId() + + self.setActiveMaterial(self._updateMaterialContainer(self._global_container_stack.getBottom(), containers[0], preferred_material).id) @pyqtSlot(str) def setActiveQuality(self, quality_id): @@ -503,7 +513,7 @@ class MachineManagerModel(QObject): return self._empty_variant_container - def _updateMaterialContainer(self, definition, variant_container = None): + def _updateMaterialContainer(self, definition, variant_container = None, preferred_material = None): if not definition.getMetaDataEntry("has_materials"): return self._empty_material_container @@ -517,7 +527,8 @@ class MachineManagerModel(QObject): else: search_criteria["definition"] = "fdmprinter" - preferred_material = definition.getMetaDataEntry("preferred_material") + if not preferred_material: + preferred_material = definition.getMetaDataEntry("preferred_material") if preferred_material: search_criteria["id"] = preferred_material @@ -527,7 +538,7 @@ class MachineManagerModel(QObject): return self._empty_material_container - def _updateQualityContainer(self, definition, material_container = None): + def _updateQualityContainer(self, definition, material_container = None, preferred_quality_name = None): search_criteria = { "type": "quality" } if definition.getMetaDataEntry("has_machine_quality"): @@ -538,9 +549,12 @@ class MachineManagerModel(QObject): else: search_criteria["definition"] = "fdmprinter" - preferred_quality = definition.getMetaDataEntry("preferred_quality") - if preferred_quality: - search_criteria["id"] = preferred_quality + if preferred_quality_name: + search_criteria["name"] = preferred_quality_name + else: + preferred_quality = definition.getMetaDataEntry("preferred_quality") + if preferred_quality: + search_criteria["id"] = preferred_quality containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) if containers: diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 71b29c8186..30b2105522 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -10,9 +10,11 @@ from UM.View.Renderer import Renderer from UM.View.GL.OpenGL import OpenGL +from cura.ExtrudersModel import ExtrudersModel + import math -## Standard view for mesh models. +## Standard view for mesh models. class SolidView(View): def __init__(self): super().__init__() @@ -22,6 +24,8 @@ class SolidView(View): self._enabled_shader = None self._disabled_shader = None + self._extruders_model = ExtrudersModel() + def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() @@ -50,15 +54,37 @@ class SolidView(View): # TODO: Find a better way to handle this #if node.getBoundingBoxMesh(): # renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(),mode = Renderer.RenderLines) + + uniforms = {} + if self._extruders_model.rowCount() > 0: + # Get color to render this mesh in from ExtrudersModel + extruder_index = 0 + extruder_id = node.callDecoration("getActiveExtruder") + if extruder_id: + extruder_index = max(0, self._extruders_model.find("id", extruder_id)) + + extruder_color = self._extruders_model.getItem(extruder_index)["colour"] + try: + # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs + # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0]) + uniforms["diffuse_color"] = [ + int(extruder_color[1:3], 16) / 255, + int(extruder_color[3:5], 16) / 255, + int(extruder_color[5:7], 16) / 255, + 1.0 + ] + except: + pass + if hasattr(node, "_outside_buildarea"): if node._outside_buildarea: renderer.queueNode(node, shader = self._disabled_shader) else: - renderer.queueNode(node, shader = self._enabled_shader) + renderer.queueNode(node, shader = self._enabled_shader, uniforms = uniforms) else: - renderer.queueNode(node, material = self._enabled_shader) + renderer.queueNode(node, material = self._enabled_shader, uniforms = uniforms) if node.callDecoration("isGroup"): - renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(),mode = Renderer.RenderLines) + renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(), mode = Renderer.RenderLines) def endRendering(self): pass diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index 55a104a21f..a2304d1d3e 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -13,7 +13,7 @@ Column id: base; property int totalHeightHeader: childrenRect.height - property int currentExtruderIndex; + property int currentExtruderIndex: -1; spacing: UM.Theme.getSize("default_margin").height @@ -50,7 +50,7 @@ Column text: Cura.MachineManager.activeMachineName; height: UM.Theme.getSize("setting_control").height - tooltip: Cura.MachineManager.activeMachineName; + tooltip: Cura.MachineManager.activeMachineName anchors.verticalCenter: parent.verticalCenter style: UM.Theme.styles.sidebar_header_button @@ -111,14 +111,25 @@ Column model: Cura.ExtrudersModel { id: extrudersModel; addGlobal: true } + Connections + { + target: Cura.MachineManager + onGlobalContainerChanged: + { + base.currentExtruderIndex = -1; + ExtruderManager.setActiveExtruderIndex(index); + } + } + delegate: Button { height: ListView.view.height width: ListView.view.width / extrudersModel.rowCount() text: model.name - exclusiveGroup: extruderMenuGroup; - checkable: true; + tooltip: model.name + exclusiveGroup: extruderMenuGroup + checkable: true checked: base.currentExtruderIndex == index onClicked: @@ -144,6 +155,7 @@ Column Rectangle { id: swatch + visible: index > -1 height: UM.Theme.getSize("setting_control").height / 2 width: height anchors.left: parent.left @@ -158,8 +170,8 @@ Column Label { anchors.verticalCenter: parent.verticalCenter - anchors.left: swatch.right - anchors.leftMargin: UM.Theme.getSize("default_margin").width / 2 + anchors.left: swatch.visible ? swatch.right : parent.left + anchors.leftMargin: swatch.visible ? UM.Theme.getSize("default_margin").width / 2 : UM.Theme.getSize("default_margin").width anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_margin").width / 2 @@ -216,6 +228,7 @@ Column text: Cura.MachineManager.activeVariantName tooltip: Cura.MachineManager.activeVariantName; visible: Cura.MachineManager.hasVariants + enabled: !extrudersList.visible || base.currentExtruderIndex > -1 height: UM.Theme.getSize("setting_control").height width: materialSelection.visible ? (parent.width - UM.Theme.getSize("default_margin").width) / 2 : parent.width @@ -260,6 +273,7 @@ Column text: Cura.MachineManager.activeMaterialName tooltip: Cura.MachineManager.activeMaterialName visible: Cura.MachineManager.hasMaterials + enabled: !extrudersList.visible || base.currentExtruderIndex > -1 height: UM.Theme.getSize("setting_control").height width: variantSelection.visible ? (parent.width - UM.Theme.getSize("default_margin").width) / 2 : parent.width diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 80870ac29f..6e6e28be3b 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -319,11 +319,13 @@ Item id: extruderModel Component.onCompleted: populateExtruderModel() } - Connections + + //: Invisible list used to populate the extrudelModel + ListView { - id: machineChange - target: Cura.MachineManager - onGlobalContainerChanged: populateExtruderModel() + id: extruders + model: Cura.ExtrudersModel { onModelChanged: populateExtruderModel() } + visible: false } } @@ -331,11 +333,13 @@ Item { extruderModel.clear(); extruderModel.append({ - text: catalog.i18nc("@label", "Don't print support") + text: catalog.i18nc("@label", "Don't print support"), + color: "" }) - for(var extruder = 0; extruder < machineExtruderCount.properties.value ; extruder++) { + for(var extruderNr = 0; extruderNr < extruders.model.rowCount() ; extruderNr++) { extruderModel.append({ - text: catalog.i18nc("@label", "Print using Extruder %1").arg(extruder + 1) + text: catalog.i18nc("@label", "Print using %1").arg(extruders.model.getItem(extruderNr).name), + color: extruders.model.getItem(extruderNr).colour }) } } diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml index 1428c3d40a..3fdc7c896e 100644 --- a/resources/themes/cura/styles.qml +++ b/resources/themes/cura/styles.qml @@ -11,9 +11,10 @@ QtObject { property Component sidebar_header_button: Component { ButtonStyle { background: Rectangle { - color: Theme.getColor("setting_control") + color: control.enabled ? Theme.getColor("setting_control") : Theme.getColor("setting_control_disabled") border.width: Theme.getSize("default_lining").width - border.color: control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border") + border.color: !control.enabled ? Theme.getColor("setting_control_disabled_border") : + control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border") UM.RecolorImage { id: downArrow anchors.verticalCenter: parent.verticalCenter @@ -23,12 +24,12 @@ QtObject { height: Theme.getSize("standard_arrow").height sourceSize.width: width sourceSize.height: width - color: Theme.getColor("setting_category_text") + color: control.enabled ? Theme.getColor("setting_category_text") : Theme.getColor("setting_control_disabled_text") source: Theme.getIcon("arrow_bottom") } Label { id: sidebarComboBoxLabel - color: Theme.getColor("setting_control_text") + color: control.enabled ? Theme.getColor("setting_control_text") : Theme.getColor("setting_control_disabled_text") text: control.text; elide: Text.ElideRight; anchors.left: parent.left;