diff --git a/cura/QualityManager.py b/cura/QualityManager.py index 813d23ea13..c0b5afb71e 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -61,8 +61,6 @@ class QualityManager: machine_definition = global_stack.definition result = self.findAllQualityChangesForMachine(machine_definition) - for extruder in self.findAllExtruderDefinitionsForMachine(machine_definition): - result.extend(self.findAllQualityChangesForExtruder(extruder)) result = [quality_change for quality_change in result if quality_change.getName() == quality_changes_name] return result @@ -151,7 +149,7 @@ class QualityManager: else: definition_id = "fdmprinter" - filter_dict = { "type": "quality_changes", "extruder": None, "definition": definition_id } + filter_dict = { "type": "quality_changes", "definition": definition_id } quality_changes_list = ContainerRegistry.getInstance().findInstanceContainers(**filter_dict) return quality_changes_list diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 4fb700e5ea..e807e49200 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -965,7 +965,7 @@ class MachineManager(QObject): if container_type == "quality": stack.quality.nameChanged.disconnect(self._onQualityNameChanged) stack.setQuality(container, postpone_emit = postpone_emit) - stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged) + stack.quality.nameChanged.connect(self._onQualityNameChanged) elif container_type == "quality_changes" or container_type is None: # If the container is an empty container, we need to change the quality_changes. # Quality can never be set to empty. diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index 4df362cdef..e39ed949b0 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -75,6 +75,7 @@ class ProfilesModel(InstanceContainersModel): # The actual list of quality profiles come from the first extruder in the extruder list. result = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition, materials) + for quality in QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders( global_container_stack, extruder_stacks): if quality not in result: diff --git a/cura/Settings/QualityAndUserProfilesModel.py b/cura/Settings/QualityAndUserProfilesModel.py index b6ac3fb6d0..1fa45a5902 100644 --- a/cura/Settings/QualityAndUserProfilesModel.py +++ b/cura/Settings/QualityAndUserProfilesModel.py @@ -25,21 +25,30 @@ class QualityAndUserProfilesModel(ProfilesModel): machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom()) quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition) + # Detecting if the machine has multiple extrusion + multiple_extrusion = False # Get the list of extruders and place the selected extruder at the front of the list. extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = extruder_manager.getActiveExtruderStacks() if active_extruder in extruder_stacks: + multiple_extrusion = True extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks # Fetch the list of useable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. - quality_list = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, + quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) # Filter the quality_change by the list of available quality_types quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list]) - filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and qc.getMetaDataEntry("extruder") is None] + + if multiple_extrusion: + # If the printer has multiple extruders then quality changes related to the current extruder are kept + filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and qc.getMetaDataEntry("extruder") == active_extruder.definition.getId()] + else: + # If not, the quality changes of the global stack are selected + filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set] return quality_list + filtered_quality_changes diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index a19005057c..57b3b9e0fd 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -12,12 +12,12 @@ from UM.Mesh.MeshBuilder import MeshBuilder from UM.Mesh.MeshReader import MeshReader from UM.Scene.GroupDecorator import GroupDecorator from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator -from cura.ZOffsetDecorator import ZOffsetDecorator from UM.Application import Application from cura.Settings.ExtruderManager import ExtruderManager from cura.QualityManager import QualityManager from UM.Scene.SceneNode import SceneNode from cura.SliceableObjectDecorator import SliceableObjectDecorator +from cura.ZOffsetDecorator import ZOffsetDecorator MYPY = False @@ -47,7 +47,7 @@ class ThreeMFReader(MeshReader): def _createMatrixFromTransformationString(self, transformation): if transformation == "": return Matrix() - + splitted_transformation = transformation.split() ## Transformation is saved as: ## M00 M01 M02 0.0 @@ -105,8 +105,8 @@ class ThreeMFReader(MeshReader): # Add the setting override decorator, so we can add settings to this node. if settings: um_node.addDecorator(SettingOverrideDecorator()) - global_container_stack = Application.getInstance().getGlobalContainerStack() + global_container_stack = Application.getInstance().getGlobalContainerStack() # Ensure the correct next container for the SettingOverride decorator is set. if global_container_stack: multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 @@ -144,15 +144,12 @@ class ThreeMFReader(MeshReader): if len(um_node.getChildren()) > 0: group_decorator = GroupDecorator() um_node.addDecorator(group_decorator) - um_node.setSelectable(True) - if um_node.getMeshData(): # Assuming that all nodes with mesh data are printable objects # affects (auto) slicing sliceable_decorator = SliceableObjectDecorator() um_node.addDecorator(sliceable_decorator) - return um_node def read(self, file_name): @@ -172,18 +169,10 @@ class ThreeMFReader(MeshReader): transform_matrix = Matrix() mesh_data = um_node.getMeshData() - if mesh_data is not None: extents = mesh_data.getExtents() center_vector = Vector(extents.center.x, extents.center.y, extents.center.z) - - # If the object in a saved project is below the bed, keep it that way - if extents.minimum.z < 0.0: - um_node.addDecorator(ZOffsetDecorator()) - um_node.callDecoration("setZOffset", extents.minimum.z) - transform_matrix.setByTranslation(center_vector) - transform_matrix.multiply(um_node.getLocalTransformation()) um_node.setTransformation(transform_matrix) @@ -215,6 +204,13 @@ class ThreeMFReader(MeshReader): # Pre multiply the transformation with the loaded transformation, so the data is handled correctly. um_node.setTransformation(um_node.getLocalTransformation().preMultiply(transformation_matrix)) + # Check if the model is positioned below the build plate and honor that when loading project files. + if um_node.getMeshData() is not None: + minimum_z_value = um_node.getMeshData().getExtents(um_node.getWorldTransformation()).minimum.y # y is z in transformation coordinates + if minimum_z_value < 0: + um_node.addDecorator(ZOffsetDecorator()) + um_node.callDecoration("setZOffset", minimum_z_value) + result.append(um_node) except Exception: diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index dd5b182607..cb7d333cde 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -195,8 +195,8 @@ class CuraEngineBackend(QObject, Backend): self.backendStateChange.emit(BackendState.Done) Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.") return - - Application.getInstance().getPrintInformation().setToZeroPrintInformation() + if Application.getInstance().getPrintInformation(): + Application.getInstance().getPrintInformation().setToZeroPrintInformation() self._stored_layer_data = [] self._stored_optimized_layer_data = [] diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index 274b5c695c..21032be6ea 100755 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -342,7 +342,7 @@ Item { id: slider width: handleSize - height: parent.height - 2*UM.Theme.getSize("slider_layerview_margin").height + height: UM.Theme.getSize("layerview_menu_size").height anchors.top: parent.bottom anchors.topMargin: UM.Theme.getSize("slider_layerview_margin").height anchors.right: layerViewMenu.right diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 072b6d2ee7..c91c1fcb93 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -53,7 +53,7 @@ Item Component.onCompleted: { - qualityRow.updateAvailableTotalTicks() + qualityRow.updateQualitySliderProperties() } Connections @@ -61,17 +61,10 @@ Item target: Cura.MachineManager onActiveQualityChanged: { - qualityRow.updateAvailableTotalTicks() + qualityRow.updateQualitySliderProperties() } } - /* - Component.onCompleted: - { - updateCurrentQualityIndex(); - updateBar(); - } - */ id: qualityRow @@ -84,7 +77,7 @@ Item property var sliderAvailableMax : 0 property var sliderMarginRight : 0 - function updateAvailableTotalTicks() + function updateQualitySliderProperties() { qualityRow.totalTicks = Cura.ProfilesModel.rowCount() - 1 // minus one, because slider starts from 0 @@ -142,12 +135,6 @@ Item qualityRow.sliderAvailableMin = availableMin qualityRow.sliderAvailableMax = availableMax - - //console.log("==>>FIND.availableMin: " + availableMin) - //console.log("==>>FIND.availableMax: " + availableMax) - //console.log("==>>FIND.qualitySliderSelectedValue: " + qualitySliderSelectedValue) - //console.log("==>>FIND.sliderMarginRightVALUE: "+ sliderMarginRight) - } height: UM.Theme.getSize("sidebar_margin").height @@ -179,10 +166,8 @@ Item anchors.top: parent.top anchors.topMargin: UM.Theme.getSize("sidebar_margin").height / 2 color: UM.Theme.getColor("text") - text: - { - return Cura.ProfilesModel.getItem(index).layer_height_without_unit - } + text: Cura.ProfilesModel.getItem(index).layer_height_without_unit + width: 1 x: { @@ -213,7 +198,7 @@ Item height: 2 color: UM.Theme.getColor("quality_slider_unavailable") //radius: parent.radius - y: 9 + anchors.verticalCenter: qualityRowSlider.verticalCenter x: 0 } @@ -248,26 +233,24 @@ Item value: qualityRow.qualitySliderSelectedValue - width:{ - return qualityRow.qualitySliderStep * (qualityRow.availableTotalTicks) - } + width: qualityRow.qualitySliderStep * (qualityRow.availableTotalTicks) anchors.right: parent.right - anchors.rightMargin:{ - return qualityRow.sliderMarginRight - } + anchors.rightMargin: qualityRow.sliderMarginRight style: SliderStyle { //Draw Available line groove: Rectangle { implicitHeight: 2 + anchors.verticalCenter: qualityRowSlider.verticalCenter color: UM.Theme.getColor("quality_slider_available") radius: 1 } handle: Item { Rectangle { id: qualityhandleButton + anchors.verticalCenter: qualityRowSlider.verticalCenter anchors.centerIn: parent color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") implicitWidth: 10 @@ -334,7 +317,7 @@ Item id: infillCellLeft anchors.top: qualityRow.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 2 anchors.left: parent.left width: UM.Theme.getSize("sidebar").width * .45 - UM.Theme.getSize("sidebar_margin").width @@ -386,6 +369,8 @@ Item anchors.top: selectedInfillRateText.bottom anchors.left: parent.left + anchors.right: infillIcon.left + anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width height: UM.Theme.getSize("sidebar_margin").height width: infillCellRight.width - UM.Theme.getSize("sidebar_margin").width - style.handleWidth @@ -442,19 +427,23 @@ Item } } - Item + Rectangle { - width: (infillCellRight.width / 5) - (UM.Theme.getSize("sidebar_margin").width) + id: infillIcon + + width: (parent.width / 5) - (UM.Theme.getSize("sidebar_margin").width) height: width - anchors.right: infillCellRight.right - anchors.top: infillSlider.top + anchors.right: parent.right + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("sidebar_margin").height / 2 // we loop over all density icons and only show the one that has the current density and steps Repeater { id: infillIconList model: infillModel + anchors.fill: parent property int activeIndex: { for (var i = 0; i < infillModel.count; i++) { @@ -472,21 +461,21 @@ Item return -1 } - Item { + Rectangle + { anchors.fill: parent + visible: infillIconList.activeIndex == index - Rectangle { + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("quality_slider_available") + + UM.RecolorImage { anchors.fill: parent - visible: infillIconList.activeIndex == index - - UM.RecolorImage { - id: infillIcon - anchors.fill: parent - sourceSize.width: width - sourceSize.height: width - source: UM.Theme.getIcon(model.icon) - color: UM.Theme.getColor("quality_slider_available") - } + anchors.margins: 2 + sourceSize.width: width + sourceSize.height: width + source: UM.Theme.getIcon(model.icon) + color: UM.Theme.getColor("quality_slider_unavailable") } } } diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index 0903c0555b..bc7905c527 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -34,7 +34,15 @@ Item Button { text: model.name - iconSource: UM.Theme.getIcon(model.icon); + iconSource: + { + var result = UM.Theme.getIcon(model.icon) + if(result == "") + { + return model.location + "/" + model.icon + } + return result + } checkable: true; checked: model.active;