diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 800f2a3b95..08d46af4df 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -585,18 +585,16 @@ class CuraApplication(QtApplication): node = Selection.getSelectedObject(0) if node: + current_node = node + # Find the topmost group + while current_node.getParent() and current_node.getParent().callDecoration("isGroup"): + current_node = current_node.getParent() + + new_node = copy.deepcopy(current_node) + op = GroupedOperation() for _ in range(count): - if node.getParent() and node.getParent().callDecoration("isGroup"): - new_node = copy.deepcopy(node.getParent()) #Copy the group node. - new_node.callDecoration("recomputeConvexHull") - - op.addOperation(AddSceneNodeOperation(new_node,node.getParent().getParent())) - else: - new_node = copy.deepcopy(node) - new_node.callDecoration("recomputeConvexHull") - op.addOperation(AddSceneNodeOperation(new_node, node.getParent())) - + op.addOperation(AddSceneNodeOperation(new_node, current_node.getParent())) op.push() ## Center object on platform. diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 5432da5dcc..6ba1274a49 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -7,6 +7,8 @@ from UM.Application import Application from UM.Qt.Duration import Duration from UM.Preferences import Preferences +import cura.Settings.ExtruderManager + import math import os.path import unicodedata @@ -44,7 +46,8 @@ class PrintInformation(QObject): self._current_print_time = Duration(None, self) - self._material_amounts = [] + self._material_lengths = [] + self._material_weights = [] self._backend = Application.getInstance().getBackend() if self._backend: @@ -62,11 +65,17 @@ class PrintInformation(QObject): def currentPrintTime(self): return self._current_print_time - materialAmountsChanged = pyqtSignal() + materialLengthsChanged = pyqtSignal() - @pyqtProperty("QVariantList", notify = materialAmountsChanged) - def materialAmounts(self): - return self._material_amounts + @pyqtProperty("QVariantList", notify = materialLengthsChanged) + def materialLengths(self): + return self._material_lengths + + materialWeightsChanged = pyqtSignal() + + @pyqtProperty("QVariantList", notify = materialWeightsChanged) + def materialWeights(self): + return self._material_weights def _onPrintDurationMessage(self, total_time, material_amounts): self._current_print_time.setDuration(total_time) @@ -74,13 +83,24 @@ class PrintInformation(QObject): # Material amount is sent as an amount of mm^3, so calculate length from that r = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value") / 2 - self._material_amounts = [] - for amount in material_amounts: - self._material_amounts.append(round((amount / (math.pi * r ** 2)) / 1000, 2)) - self.materialAmountsChanged.emit() + self._material_lengths = [] + self._material_weights = [] + extruder_stacks = list(cura.Settings.ExtruderManager.getInstance().getMachineExtruders(Application.getInstance().getGlobalContainerStack().getId())) + for index, amount in enumerate(material_amounts): + ## Find the right extruder stack. As the list isn't sorted because it's a annoying generator, we do some + # list comprehension filtering to solve this for us. + extruder_stack = [extruder for extruder in extruder_stacks if extruder.getMetaDataEntry("position") == str(index)][0] + density = extruder_stack.getMetaDataEntry("properties", {}).get("density", 0) + self._material_weights.append(float(amount) * float(density)) + self._material_lengths.append(round((amount / (math.pi * r ** 2)) / 1000, 2)) + self.materialLengthsChanged.emit() + self.materialWeightsChanged.emit() @pyqtSlot(str) def setJobName(self, name): + # Ensure that we don't use entire path but only filename + name = os.path.basename(name) + # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its # extension. This cuts the extension off if necessary. name = os.path.splitext(name)[0] diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 23335e3e63..4b3141f900 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -126,6 +126,9 @@ class MachineManager(QObject): self._auto_change_material_hotend_flood_time = time.time() self._auto_change_material_hotend_flood_last_choice = button + if button == QMessageBox.No: + return + Logger.log("d", "Setting hotend variant of hotend %d to %s" % (index, hotend_id)) extruder_manager = ExtruderManager.getInstance() @@ -174,6 +177,9 @@ class MachineManager(QObject): self._auto_change_material_hotend_flood_time = time.time() self._auto_change_material_hotend_flood_last_choice = button + if button == QMessageBox.No: + return + Logger.log("d", "Setting material of hotend %d to %s" % (index, material_id)) extruder_manager = ExtruderManager.getInstance() @@ -493,6 +499,7 @@ class MachineManager(QObject): self.activeQualityChanged.emit() @pyqtSlot(str) + @pyqtSlot() def updateQualityContainerFromUserContainer(self, quality_id = None): if not self._active_container_stack: return diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 6aa9c4660b..5b715230e2 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -180,6 +180,12 @@ class StartSliceJob(Job): setting.value = str(stack.getProperty(key, "value")).encode("utf-8") Job.yieldThread() + # ALso send the material GUID as a setting. + material_instance_container = stack.findContainer({"type": "material"}) + if material_instance_container: + setting = message.getMessage("settings").addRepeatedMessage("settings") + setting.name = "material_GUID" + setting.value = str(material_instance_container.getMetaDataEntry("GUID", "")).encode("utf-8") ## Sends all global settings to the engine. # # The settings are taken from the global stack. This does not include any diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 39a55702ab..913ad467c5 100644 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -59,7 +59,7 @@ class SliceInfo(Extension): material_radius = 0.5 * global_container_stack.getProperty("material_diameter", "value") # TODO: Send material per extruder instead of mashing it on a pile - material_used = math.pi * material_radius * material_radius * sum(print_information.materialAmounts) #Volume of all materials used + material_used = math.pi * material_radius * material_radius * sum(print_information.materialLengths) #Volume of all materials used # Get model information (bounding boxes, hashes and transformation matrix) models_info = [] diff --git a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml index 86429ed119..34544dca75 100644 --- a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml +++ b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml @@ -196,8 +196,8 @@ Cura.MachineAction visible: checkupMachineAction.usbConnected Button { + height: 20 text: checkupMachineAction.heatupHotendStarted ? catalog.i18nc("@action:button","Stop Heating") : catalog.i18nc("@action:button","Start Heating") - // onClicked: { if (checkupMachineAction.heatupHotendStarted) @@ -259,6 +259,7 @@ Cura.MachineAction Button { text: checkupMachineAction.heatupBedStarted ?catalog.i18nc("@action:button","Stop Heating") : catalog.i18nc("@action:button","Start Heating") + height: 20 onClicked: { if (checkupMachineAction.heatupBedStarted) diff --git a/resources/definitions/fdmextruder.def.json b/resources/definitions/fdmextruder.def.json index 4e3ee0a84f..7ce44b77b0 100644 --- a/resources/definitions/fdmextruder.def.json +++ b/resources/definitions/fdmextruder.def.json @@ -145,30 +145,6 @@ "settable_per_meshgroup": false, "settable_globally": false }, - "extruder_prime_pos_x": - { - "label": "Extruder Prime X Position", - "description": "The X coordinate of the position where the nozzle primes at the start of printing.", - "type": "float", - "unit": "mm", - "default_value": 0, - "minimum_value_warning": "machine_nozzle_offset_x", - "maximum_value_warning": "machine_width", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "extruder_prime_pos_y": - { - "label": "Extruder Prime Y Position", - "description": "The Y coordinate of the position where the nozzle primes at the start of printing.", - "type": "float", - "unit": "mm", - "default_value": 0, - "minimum_value_warning": "machine_nozzle_offset_y", - "maximum_value_warning": "machine_depth", - "settable_per_mesh": false, - "settable_per_extruder": true - }, "extruder_prime_pos_z": { "label": "Extruder Prime Z Position", @@ -182,6 +158,42 @@ "settable_per_extruder": true } } + }, + "platform_adhesion": + { + "label": "Platform Adhesion", + "type": "category", + "icon": "category_adhesion", + "description": "Adhesion", + "children": + { + "extruder_prime_pos_x": + { + "label": "Extruder Prime X Position", + "description": "The X coordinate of the position where the nozzle primes at the start of printing.", + "type": "float", + "unit": "mm", + "default_value": 0, + "minimum_value_warning": "machine_nozzle_offset_x", + "maximum_value_warning": "machine_width", + "settable_per_mesh": false, + "settable_per_extruder": true, + "enabled": false + }, + "extruder_prime_pos_y": + { + "label": "Extruder Prime Y Position", + "description": "The Y coordinate of the position where the nozzle primes at the start of printing.", + "type": "float", + "unit": "mm", + "default_value": 0, + "minimum_value_warning": "machine_nozzle_offset_y", + "maximum_value_warning": "machine_depth", + "settable_per_mesh": false, + "settable_per_extruder": true, + "enabled": false + } + } } } } diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 6c39aaa330..8833c175f3 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -326,30 +326,6 @@ "settable_per_extruder": false, "settable_per_meshgroup": false }, - "extruder_prime_pos_x": - { - "label": "Extruder Prime X Position", - "description": "The X coordinate of the position where the nozzle primes at the start of printing.", - "type": "float", - "unit": "mm", - "default_value": 0, - "minimum_value_warning": "0", - "maximum_value_warning": "machine_width", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "extruder_prime_pos_y": - { - "label": "Extruder Prime Y Position", - "description": "The Y coordinate of the position where the nozzle primes at the start of printing.", - "type": "float", - "unit": "mm", - "default_value": 0, - "minimum_value_warning": "0", - "maximum_value_warning": "machine_depth", - "settable_per_mesh": false, - "settable_per_extruder": true - }, "extruder_prime_pos_z": { "label": "Extruder Prime Z Position", @@ -904,7 +880,7 @@ "type": "float", "default_value": 2, "minimum_value": "0", - "value": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density * (2 if infill_pattern == \"grid\" else (3 if infill_pattern == \"triangles\" else 1))", + "value": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density * (2 if infill_pattern == \"grid\" else (3 if infill_pattern == \"triangles\" or infill_pattern == \"cubic\" else (4 if infill_pattern == \"tetrahedral\" else 1)))", "settable_per_mesh": true } } @@ -912,13 +888,15 @@ "infill_pattern": { "label": "Infill Pattern", - "description": "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle and concentric patterns are fully printed every layer.", + "description": "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, cubic, tetrahedral and concentric patterns are fully printed every layer. Cubic and tetrahedral infill change with every layer to provide a more equal distribution of strength over each direction.", "type": "enum", "options": { "grid": "Grid", "lines": "Lines", "triangles": "Triangles", + "cubic": "Cubic", + "tetrahedral": "Tetrahedral", "concentric": "Concentric", "zigzag": "Zig Zag" }, @@ -2446,6 +2424,32 @@ "description": "Adhesion", "children": { + "extruder_prime_pos_x": + { + "label": "Extruder Prime X Position", + "description": "The X coordinate of the position where the nozzle primes at the start of printing.", + "type": "float", + "unit": "mm", + "default_value": 0, + "minimum_value_warning": "0", + "maximum_value_warning": "machine_width", + "settable_per_mesh": false, + "settable_per_extruder": true, + "enabled": false + }, + "extruder_prime_pos_y": + { + "label": "Extruder Prime Y Position", + "description": "The Y coordinate of the position where the nozzle primes at the start of printing.", + "type": "float", + "unit": "mm", + "default_value": 0, + "minimum_value_warning": "0", + "maximum_value_warning": "machine_depth", + "settable_per_mesh": false, + "settable_per_extruder": true, + "enabled": false + }, "adhesion_type": { "label": "Platform Adhesion Type", @@ -2998,7 +3002,7 @@ "type": "extruder", "default_value": "0", "value": "support_extruder_nr", - "enabled": "support_enable", + "enabled": "support_enable and support_roof_enable", "settable_per_mesh": false, "settable_per_extruder": false } diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index db58b5ee4e..8e14241741 100644 --- a/resources/qml/JobSpecs.qml +++ b/resources/qml/JobSpecs.qml @@ -24,7 +24,8 @@ Rectangle { UM.I18nCatalog { id: catalog; name:"cura"} property variant printDuration: PrintInformation.currentPrintTime - property variant printMaterialAmounts: PrintInformation.materialAmounts + property variant printMaterialLengths: PrintInformation.materialLengths + property variant printMaterialWeights: PrintInformation.materialWeights height: childrenRect.height color: "transparent" @@ -195,9 +196,9 @@ Rectangle { text: { var amounts = []; - if(base.printMaterialAmounts) { - for(var index = 0; index < base.printMaterialAmounts.length; index++) { - amounts.push(base.printMaterialAmounts[index].toFixed(2)); + if(base.printMaterialLengths) { + for(var index = 0; index < base.printMaterialLengths.length; index++) { + amounts.push(base.printMaterialLengths[index].toFixed(2)); } } else { amounts = ["0.00"];