diff --git a/cura/Machines/Models/IntentCategoryModel.py b/cura/Machines/Models/IntentCategoryModel.py index 20d07864bf..a968d12b7a 100644 --- a/cura/Machines/Models/IntentCategoryModel.py +++ b/cura/Machines/Models/IntentCategoryModel.py @@ -41,11 +41,11 @@ class IntentCategoryModel(ListModel): } _translations["engineering"] = { "name": catalog.i18nc("@label", "Engineering"), - "description": catalog.i18nc("@text", "Suitable for engineering work") + "description": catalog.i18nc("@text", "Optimized for higher accuracy") } - _translations["smooth"] = { - "name": catalog.i18nc("@label", "Smooth"), - "description": catalog.i18nc("@text", "Optimized for a smooth surfaces") + _translations["quick"] = { + "name": catalog.i18nc("@label", "Draft"), + "description": catalog.i18nc("@text", "Optimized for fast results") } diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 29a6d8ff30..43d54d8b12 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Ultimaker B.V. +# Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import numpy @@ -72,7 +72,7 @@ class GcodeStartEndFormatter(Formatter): value = default_value_str # "-1" is global stack, and if the setting value exists in the global stack, use it as the fallback value. if key in kwargs["-1"]: - value = kwargs["-1"] + value = kwargs["-1"][key] if str(extruder_nr) in kwargs and key in kwargs[str(extruder_nr)]: value = kwargs[str(extruder_nr)][key] diff --git a/plugins/ImageReader/ConfigUI.qml b/plugins/ImageReader/ConfigUI.qml index 47ba10778c..0429fae4e1 100644 --- a/plugins/ImageReader/ConfigUI.qml +++ b/plugins/ImageReader/ConfigUI.qml @@ -143,6 +143,52 @@ UM.Dialog } } + UM.TooltipArea { + Layout.fillWidth:true + height: childrenRect.height + text: catalog.i18nc("@info:tooltip","For lithophanes a simple logarithmic model for translucency is available. For height maps the pixel values correspond to heights linearly.") + Row { + width: parent.width + + Label { + text: "Color Model" + width: 150 * screenScaleFactor + anchors.verticalCenter: parent.verticalCenter + } + ComboBox { + id: color_model + objectName: "ColorModel" + model: [ catalog.i18nc("@item:inlistbox","Linear"), catalog.i18nc("@item:inlistbox","Translucency") ] + width: 180 * screenScaleFactor + onCurrentIndexChanged: { manager.onColorModelChanged(currentIndex) } + } + } + } + + UM.TooltipArea { + Layout.fillWidth:true + height: childrenRect.height + text: catalog.i18nc("@info:tooltip","The percentage of light penetrating a print with a thickness of 1 millimeter. Lowering this value increases the contrast in dark regions and decreases the contrast in light regions of the image.") + visible: color_model.currentText == catalog.i18nc("@item:inlistbox","Translucency") + Row { + width: parent.width + + Label { + text: catalog.i18nc("@action:label", "1mm Transmittance (%)") + width: 150 * screenScaleFactor + anchors.verticalCenter: parent.verticalCenter + } + TextField { + id: transmittance + objectName: "Transmittance" + focus: true + validator: RegExpValidator {regExp: /^[1-9]\d{0,2}([\,|\.]\d*)?$/} + width: 180 * screenScaleFactor + onTextChanged: { manager.onTransmittanceChanged(text) } + } + } + } + UM.TooltipArea { Layout.fillWidth:true height: childrenRect.height diff --git a/plugins/ImageReader/ImageReader.py b/plugins/ImageReader/ImageReader.py index e720ce4854..d6c2827d16 100644 --- a/plugins/ImageReader/ImageReader.py +++ b/plugins/ImageReader/ImageReader.py @@ -3,6 +3,8 @@ import numpy +import math + from PyQt5.QtGui import QImage, qRed, qGreen, qBlue from PyQt5.QtCore import Qt @@ -46,9 +48,9 @@ class ImageReader(MeshReader): def _read(self, file_name): size = max(self._ui.getWidth(), self._ui.getDepth()) - return self._generateSceneNode(file_name, size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512, self._ui.lighter_is_higher) + return self._generateSceneNode(file_name, size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512, self._ui.lighter_is_higher, self._ui.use_transparency_model, self._ui.transmittance_1mm) - def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size, lighter_is_higher): + def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size, lighter_is_higher, use_transparency_model, transmittance_1mm): scene_node = SceneNode() mesh = MeshBuilder() @@ -99,12 +101,14 @@ class ImageReader(MeshReader): for x in range(0, width): for y in range(0, height): qrgb = img.pixel(x, y) - avg = float(qRed(qrgb) + qGreen(qrgb) + qBlue(qrgb)) / (3 * 255) - height_data[y, x] = avg + if use_transparency_model: + height_data[y, x] = (0.299 * math.pow(qRed(qrgb) / 255.0, 2.2) + 0.587 * math.pow(qGreen(qrgb) / 255.0, 2.2) + 0.114 * math.pow(qBlue(qrgb) / 255.0, 2.2)) + else: + height_data[y, x] = (0.212655 * qRed(qrgb) + 0.715158 * qGreen(qrgb) + 0.072187 * qBlue(qrgb)) / 255 # fast computation ignoring gamma and degamma Job.yieldThread() - if not lighter_is_higher: + if lighter_is_higher == use_transparency_model: height_data = 1 - height_data for _ in range(0, blur_iterations): @@ -124,8 +128,15 @@ class ImageReader(MeshReader): Job.yieldThread() - height_data *= scale_vector.y - height_data += base_height + if use_transparency_model: + divisor = 1.0 / math.log(transmittance_1mm / 100.0) # log-base doesn't matter here. Precompute this value for faster computation of each pixel. + min_luminance = (transmittance_1mm / 100.0) ** (peak_height - base_height) + for (y, x) in numpy.ndindex(height_data.shape): + mapped_luminance = min_luminance + (1.0 - min_luminance) * height_data[y, x] + height_data[y, x] = base_height + divisor * math.log(mapped_luminance) # use same base as a couple lines above this + else: + height_data *= scale_vector.y + height_data += base_height heightmap_face_count = 2 * height_minus_one * width_minus_one total_face_count = heightmap_face_count + (width_minus_one * 2) * (height_minus_one * 2) + 2 diff --git a/plugins/ImageReader/ImageReaderUI.py b/plugins/ImageReader/ImageReaderUI.py index 213468a2ab..a61fabb742 100644 --- a/plugins/ImageReader/ImageReaderUI.py +++ b/plugins/ImageReader/ImageReaderUI.py @@ -34,6 +34,8 @@ class ImageReaderUI(QObject): self.peak_height = 2.5 self.smoothing = 1 self.lighter_is_higher = False; + self.use_transparency_model = True; + self.transmittance_1mm = 50.0; # based on pearl PLA self._ui_lock = threading.Lock() self._cancelled = False @@ -75,6 +77,7 @@ class ImageReaderUI(QObject): self._ui_view.findChild(QObject, "Base_Height").setProperty("text", str(self.base_height)) self._ui_view.findChild(QObject, "Peak_Height").setProperty("text", str(self.peak_height)) + self._ui_view.findChild(QObject, "Transmittance").setProperty("text", str(self.transmittance_1mm)) self._ui_view.findChild(QObject, "Smoothing").setProperty("value", self.smoothing) def _createConfigUI(self): @@ -144,3 +147,11 @@ class ImageReaderUI(QObject): @pyqtSlot(int) def onImageColorInvertChanged(self, value): self.lighter_is_higher = (value == 1) + + @pyqtSlot(int) + def onColorModelChanged(self, value): + self.use_transparency_model = (value == 0) + + @pyqtSlot(int) + def onTransmittanceChanged(self, value): + self.transmittance_1mm = value diff --git a/plugins/VersionUpgrade/VersionUpgrade43to44/VersionUpgrade43to44.py b/plugins/VersionUpgrade/VersionUpgrade43to44/VersionUpgrade43to44.py index e8eefb1bb0..40927fe3a0 100644 --- a/plugins/VersionUpgrade/VersionUpgrade43to44/VersionUpgrade43to44.py +++ b/plugins/VersionUpgrade/VersionUpgrade43to44/VersionUpgrade43to44.py @@ -66,6 +66,13 @@ class VersionUpgrade43to44(VersionUpgrade): # Alternate skin rotation should be translated to top/bottom line directions. if "skin_alternate_rotation" in parser["values"] and parseBool(parser["values"]["skin_alternate_rotation"]): parser["values"]["skin_angles"] = "[45, 135, 0, 90]" + # Unit of adaptive layers topography size changed. + if "adaptive_layer_height_threshold" in parser["values"]: + val = parser["values"]["adaptive_layer_height_threshold"] + if val.startswith("="): + val = val[1:] + val = "=({val}) / 1000".format(val = val) # Convert microns to millimetres. Works even if the profile contained a formula. + parser["values"]["adaptive_layer_height_threshold"] = val result = io.StringIO() parser.write(result) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8511d9e969..90d6c8e2d8 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -7074,11 +7074,12 @@ }, "adaptive_layer_height_threshold": { - "label": "Adaptive Layers Threshold", - "description": "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer.", + "label": "Adaptive Layers Topography Size", + "description": "Target horizontal distance between two adjacent layers. Reducing this setting causes thinner layers to be used to bring the edges of the layers closer together.", "type": "float", "enabled": "adaptive_layer_height_enabled", - "default_value": 200.0, + "default_value": 0.2, + "unit": "mm", "settable_per_mesh": false, "settable_per_extruder": false, "settable_per_meshgroup": false diff --git a/resources/definitions/kupido.def.json b/resources/definitions/kupido.def.json index a81a40542b..ad0182a5f6 100644 --- a/resources/definitions/kupido.def.json +++ b/resources/definitions/kupido.def.json @@ -18,12 +18,12 @@ "supports_usb_connection": false, "machine_extruder_trains": { - "0": "alya3dp_extruder_0" + "0": "kupido_extruder_0" } }, "overrides": { - "machine_name": { "default_value": "ALYA 3DP" }, + "machine_name": { "default_value": "KUPIDO" }, "machine_heated_bed": { "default_value": true }, "machine_width": { "default_value": 195 }, "machine_height": { "default_value": 190 }, diff --git a/resources/definitions/ultimaker_s3.def.json b/resources/definitions/ultimaker_s3.def.json index 7348c14a2a..efdc7cca0a 100644 --- a/resources/definitions/ultimaker_s3.def.json +++ b/resources/definitions/ultimaker_s3.def.json @@ -67,8 +67,6 @@ "extruder_prime_pos_abs": { "default_value": true }, "machine_start_gcode": { "default_value": "" }, "machine_end_gcode": { "default_value": "" }, - "prime_tower_position_x": { "value": "345" }, - "prime_tower_position_y": { "value": "222.5" }, "prime_blob_enable": { "enabled": true, "default_value": false }, "speed_travel": diff --git a/resources/extruders/bibo2_dual_extruder_0.def.json b/resources/extruders/bibo2_dual_extruder_0.def.json index b918d070be..91508ecc6d 100644 --- a/resources/extruders/bibo2_dual_extruder_0.def.json +++ b/resources/extruders/bibo2_dual_extruder_0.def.json @@ -1,45 +1,45 @@ { - "version": 2, - "name": "Extruder 1", - "inherits": "fdmextruder", - "metadata": { - "machine": "BIBO2 dual", - "position": "0" - }, - "overrides": { - "extruder_nr": { - "default_value": 0, - "maximum_value": "1" - }, - "material_diameter": { - "default_value": 1.75 - }, - "machine_nozzle_size": { - "default_value": 0.4 - }, - "machine_nozzle_offset_x": { - "default_value": 0.0 - }, - "machine_nozzle_offset_y": { - "default_value": 0.0 - }, - "machine_extruder_start_pos_abs": { - "default_value": true - }, - "machine_extruder_start_pos_x": { - "value": "prime_tower_position_x" - }, - "machine_extruder_start_pos_y": { - "value": "prime_tower_position_y" - }, - "machine_extruder_end_pos_abs": { - "default_value": true - }, - "machine_extruder_end_pos_x": { - "value": "prime_tower_position_x" - }, - "machine_extruder_end_pos_y": { - "value": "prime_tower_position_y" - } - } + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "bibo2_dual", + "position": "0" + }, + "overrides": { + "extruder_nr": { + "default_value": 0, + "maximum_value": "1" + }, + "material_diameter": { + "default_value": 1.75 + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "machine_nozzle_offset_x": { + "default_value": 0.0 + }, + "machine_nozzle_offset_y": { + "default_value": 0.0 + }, + "machine_extruder_start_pos_abs": { + "default_value": true + }, + "machine_extruder_start_pos_x": { + "value": "prime_tower_position_x" + }, + "machine_extruder_start_pos_y": { + "value": "prime_tower_position_y" + }, + "machine_extruder_end_pos_abs": { + "default_value": true + }, + "machine_extruder_end_pos_x": { + "value": "prime_tower_position_x" + }, + "machine_extruder_end_pos_y": { + "value": "prime_tower_position_y" + } + } } diff --git a/resources/extruders/bibo2_dual_extruder_1.def.json b/resources/extruders/bibo2_dual_extruder_1.def.json index e0386188bb..129ad27273 100644 --- a/resources/extruders/bibo2_dual_extruder_1.def.json +++ b/resources/extruders/bibo2_dual_extruder_1.def.json @@ -1,45 +1,45 @@ { - "version": 2, - "name": "Extruder 2", - "inherits": "fdmextruder", - "metadata": { - "machine": "BIBO2 dual", - "position": "1" - }, - "overrides": { - "extruder_nr": { - "default_value": 1, - "maximum_value": "1" - }, - "material_diameter": { - "default_value": 1.75 - }, - "machine_nozzle_size": { - "default_value": 0.4 - }, - "machine_nozzle_offset_x": { - "default_value": 0.0 - }, - "machine_nozzle_offset_y": { - "default_value": 0.0 - }, - "machine_extruder_start_pos_abs": { - "default_value": true - }, - "machine_extruder_start_pos_x": { - "value": "prime_tower_position_x" - }, - "machine_extruder_start_pos_y": { - "value": "prime_tower_position_y" - }, - "machine_extruder_end_pos_abs": { - "default_value": true - }, - "machine_extruder_end_pos_x": { - "value": "prime_tower_position_x" - }, - "machine_extruder_end_pos_y": { - "value": "prime_tower_position_y" - } - } + "version": 2, + "name": "Extruder 2", + "inherits": "fdmextruder", + "metadata": { + "machine": "bibo2_dual", + "position": "1" + }, + "overrides": { + "extruder_nr": { + "default_value": 1, + "maximum_value": "1" + }, + "material_diameter": { + "default_value": 1.75 + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "machine_nozzle_offset_x": { + "default_value": 0.0 + }, + "machine_nozzle_offset_y": { + "default_value": 0.0 + }, + "machine_extruder_start_pos_abs": { + "default_value": true + }, + "machine_extruder_start_pos_x": { + "value": "prime_tower_position_x" + }, + "machine_extruder_start_pos_y": { + "value": "prime_tower_position_y" + }, + "machine_extruder_end_pos_abs": { + "default_value": true + }, + "machine_extruder_end_pos_x": { + "value": "prime_tower_position_x" + }, + "machine_extruder_end_pos_y": { + "value": "prime_tower_position_y" + } + } } diff --git a/resources/extruders/cr-x_extruder_0.def.json b/resources/extruders/cr-x_extruder_0.def.json index 4e73fd0e8e..d9b7b03021 100644 --- a/resources/extruders/cr-x_extruder_0.def.json +++ b/resources/extruders/cr-x_extruder_0.def.json @@ -3,7 +3,7 @@ "name": "Left Extruder", "inherits": "fdmextruder", "metadata": { - "machine": "Creality CR-X", + "machine": "creality_cr-x", "position": "0" }, diff --git a/resources/extruders/cr-x_extruder_1.def.json b/resources/extruders/cr-x_extruder_1.def.json index ed6056dab9..8e763df64f 100644 --- a/resources/extruders/cr-x_extruder_1.def.json +++ b/resources/extruders/cr-x_extruder_1.def.json @@ -3,7 +3,7 @@ "name": "Right Extruder", "inherits": "fdmextruder", "metadata": { - "machine": "Creality CR-X", + "machine": "creality_cr-x", "position": "1" }, diff --git a/resources/extruders/creatable_d3_extruder_0.def.json b/resources/extruders/creatable_d3_extruder_0.def.json index 6a805febd5..95883d0f69 100644 --- a/resources/extruders/creatable_d3_extruder_0.def.json +++ b/resources/extruders/creatable_d3_extruder_0.def.json @@ -3,7 +3,7 @@ "name": "Extruder 1", "inherits": "fdmextruder", "metadata": { - "machine": "Creatable_D3", + "machine": "creatable_d3", "position": "0" }, diff --git a/resources/extruders/hellbot_magna_i_extruder.def.json b/resources/extruders/hellbot_magna_i_extruder.def.json index dc63081bd2..70117c2aed 100644 --- a/resources/extruders/hellbot_magna_i_extruder.def.json +++ b/resources/extruders/hellbot_magna_i_extruder.def.json @@ -3,7 +3,7 @@ "name": "Extruder 1", "inherits": "fdmextruder", "metadata": { - "machine": "hellbot_magna_i", + "machine": "hellbot_magna_I", "position": "0" }, diff --git a/resources/extruders/key3d_tyro_extruder_0.def.json b/resources/extruders/key3d_tyro_extruder_0.def.json index 11619da332..f08ae351ab 100644 --- a/resources/extruders/key3d_tyro_extruder_0.def.json +++ b/resources/extruders/key3d_tyro_extruder_0.def.json @@ -3,7 +3,7 @@ "name": "0.4mm Nozzle", "inherits": "fdmextruder", "metadata": { - "machine": "Tyro", + "machine": "key3d_tyro", "position": "0" }, diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Draft_Print_Quick.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Draft_Print_Quick.inst.cfg index b41f636e63..92d91840b5 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Draft_Print_Quick.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Draft_Print_Quick.inst.cfg @@ -6,7 +6,7 @@ definition = ultimaker_s3 [metadata] setting_version = 10 type = intent -intent_category = smooth +intent_category = quick quality_type = draft material = generic_abs variant = AA 0.4 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Draft_Visual.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Draft_Visual.inst.cfg deleted file mode 100644 index 49672fcb72..0000000000 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Draft_Visual.inst.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[general] -version = 4 -name = Visual -definition = ultimaker_s3 - -[metadata] -setting_version = 10 -type = intent -intent_category = visual -quality_type = draft -material = generic_abs -variant = AA 0.4 - -[values] -speed_infill = 50 -wall_thickness = =wall_line_width * 3 -top_bottom_thickness = =wall_thickness diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Draft_Print_Quick.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Draft_Print_Quick.inst.cfg index 8095a53141..1d990b83c0 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Draft_Print_Quick.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Draft_Print_Quick.inst.cfg @@ -6,7 +6,7 @@ definition = ultimaker_s3 [metadata] setting_version = 10 type = intent -intent_category = smooth +intent_category = quick quality_type = draft material = generic_pla variant = AA 0.4 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Draft_Visual.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Draft_Visual.inst.cfg deleted file mode 100644 index 0c39d43c6a..0000000000 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Draft_Visual.inst.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[general] -version = 4 -name = Visual -definition = ultimaker_s3 - -[metadata] -setting_version = 10 -type = intent -quality_type = draft -intent_category = visual -material = generic_pla -variant = AA 0.4 - -[values] -speed_infill = 50 -wall_thickness = =wall_line_width * 3 -top_bottom_thickness = =wall_thickness diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Draft_Print_Quick.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Draft_Print_Quick.inst.cfg index edae808491..020a4bbc99 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Draft_Print_Quick.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Draft_Print_Quick.inst.cfg @@ -6,7 +6,7 @@ definition = ultimaker_s3 [metadata] setting_version = 10 type = intent -intent_category = smooth +intent_category = quick quality_type = draft material = generic_tough_pla variant = AA 0.4 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Draft_Visual.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Draft_Visual.inst.cfg deleted file mode 100644 index f52eb22ec2..0000000000 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Draft_Visual.inst.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[general] -version = 4 -name = Visual -definition = ultimaker_s3 - -[metadata] -setting_version = 10 -type = intent -quality_type = draft -intent_category = visual -material = generic_tough_pla -variant = AA 0.4 - -[values] -speed_infill = 50 -wall_thickness = =wall_line_width * 3 -top_bottom_thickness = =wall_thickness diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Print_Quick.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Print_Quick.inst.cfg index f627fbf74b..14bb0e0f54 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Print_Quick.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Print_Quick.inst.cfg @@ -6,7 +6,7 @@ definition = ultimaker_s5 [metadata] setting_version = 10 type = intent -intent_category = smooth +intent_category = quick quality_type = draft material = generic_abs variant = AA 0.4 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Visual.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Visual.inst.cfg deleted file mode 100644 index 4f7ee148f9..0000000000 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Visual.inst.cfg +++ /dev/null @@ -1,16 +0,0 @@ -[general] -version = 4 -name = Visual -definition = ultimaker_s5 - -[metadata] -setting_version = 10 -type = intent -intent_category = visualquality_type = draft -material = generic_abs -variant = AA 0.4 - -[values] -speed_infill = 50 -wall_thickness = =wall_line_width * 3 -top_bottom_thickness = =wall_thickness diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Draft_Print_Quick.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Draft_Print_Quick.inst.cfg index 553a68201d..86062ecf19 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Draft_Print_Quick.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Draft_Print_Quick.inst.cfg @@ -6,7 +6,7 @@ definition = ultimaker_s5 [metadata] setting_version = 10 type = intent -intent_category = smooth +intent_category = quick quality_type = draft material = generic_pla variant = AA 0.4 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Draft_Visual.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Draft_Visual.inst.cfg deleted file mode 100644 index a71bb898d3..0000000000 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Draft_Visual.inst.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[general] -version = 4 -name = Visual -definition = ultimaker_s5 - -[metadata] -setting_version = 10 -type = intent -quality_type = draft -intent_category = visual -material = generic_pla -variant = AA 0.4 - -[values] -speed_infill = 50 -wall_thickness = =wall_line_width * 3 -top_bottom_thickness = =wall_thickness diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Draft_Print_Quick.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Draft_Print_Quick.inst.cfg index 458b283dd8..3a6e19c64c 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Draft_Print_Quick.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Draft_Print_Quick.inst.cfg @@ -6,7 +6,7 @@ definition = ultimaker_s5 [metadata] setting_version = 10 type = intent -intent_category = smooth +intent_category = quick quality_type = draft material = generic_tough_pla variant = AA 0.4 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Draft_Visual.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Draft_Visual.inst.cfg deleted file mode 100644 index b522d262af..0000000000 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Draft_Visual.inst.cfg +++ /dev/null @@ -1,16 +0,0 @@ -[general] -version = 4 -name = Visual -definition = ultimaker_s5 - -[metadata] -setting_version = 10 -type = intent -intent_category = visual -material = generic_tough_pla -variant = AA 0.4 - -[values] -speed_infill = 50 -wall_thickness = =wall_line_width * 3 -top_bottom_thickness = =wall_thickness diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml index 3c7caad470..5e58faec78 100644 --- a/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml +++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml @@ -124,18 +124,6 @@ Item elide: Text.ElideRight } - NoIntentIcon - { - affected_extruders: Cura.MachineManager.extruderPositionsWithNonActiveIntent - intent_type: model.name - anchors.right: intentCategoryLabel.right - anchors.rightMargin: UM.Theme.getSize("narrow_margin").width - width: intentCategoryLabel.height * 0.75 - anchors.verticalCenter: parent.verticalCenter - height: width - visible: Cura.MachineManager.activeIntentCategory == model.intent_category && affected_extruders.length - } - Cura.RadioCheckbar { anchors @@ -164,8 +152,9 @@ Item isCheckedFunction: checkedFunction } - MouseArea // tooltip hover area + MouseArea // Intent description tooltip hover area { + id: intentDescriptionHoverArea anchors.fill: parent hoverEnabled: true enabled: model.description !== undefined @@ -181,6 +170,20 @@ Item } onExited: base.hideTooltip() } + + NoIntentIcon // This icon has hover priority over intentDescriptionHoverArea, so draw it above it. + { + affected_extruders: Cura.MachineManager.extruderPositionsWithNonActiveIntent + intent_type: model.name + anchors.right: intentCategoryLabel.right + anchors.rightMargin: UM.Theme.getSize("narrow_margin").width + width: intentCategoryLabel.height * 0.75 + anchors.verticalCenter: parent.verticalCenter + height: width + visible: Cura.MachineManager.activeIntentCategory == model.intent_category && affected_extruders.length + } + + } } diff --git a/tests/Machines/TestVariantNode.py b/tests/Machines/TestVariantNode.py index bc860058a1..8ccde9bc74 100644 --- a/tests/Machines/TestVariantNode.py +++ b/tests/Machines/TestVariantNode.py @@ -137,38 +137,17 @@ def test_materialAdded_update(container_registry, machine_node, metadata, change def test_preferredMaterialExactMatch(empty_variant_node): empty_variant_node.materials = { "some_different_material": MagicMock(getMetaDataEntry = lambda x: 3), - "preferred_material_base_file": MagicMock(getMetaDataEntry = lambda x: 3) # Exact match. + "preferred_material": MagicMock(getMetaDataEntry = lambda x: 3) # Exact match. } - assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material_base_file"], "It should match exactly on this one since it's the preferred material." - -## Tests the preferred material when a submaterial is available in the -# materials list for this node. -def test_preferredMaterialSubmaterial(empty_variant_node): - empty_variant_node.materials = { - "some_different_material": MagicMock(getMetaDataEntry = lambda x: 3), - "preferred_material_base_file_aa04": MagicMock(getMetaDataEntry = lambda x: 3) # This is a submaterial of the preferred material. - } - - assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material_base_file_aa04"], "It should match on the submaterial just as well." - -## Tests the preferred material matching on the approximate diameter of the -# filament. -def test_preferredMaterialDiameter(empty_variant_node): - empty_variant_node.materials = { - "some_different_material": MagicMock(getMetaDataEntry = lambda x: 3), - "preferred_material_wrong_diameter": MagicMock(getMetaDataEntry = lambda x: 2), # Approximate diameter is 2 instead of 3. - "preferred_material_correct_diameter": MagicMock(getMetaDataEntry = lambda x: 3) # Correct approximate diameter. - } - - assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material_correct_diameter"], "It should match only on the material with correct diameter." + assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material"], "It should match exactly on this one since it's the preferred material." ## Tests the preferred material matching on a different material if the # diameter is wrong. def test_preferredMaterialDiameterNoMatch(empty_variant_node): empty_variant_node.materials = collections.OrderedDict() empty_variant_node.materials["some_different_material"] = MagicMock(getMetaDataEntry = lambda x: 3) # This one first so that it gets iterated over first. - empty_variant_node.materials["preferred_material_wrong_diameter"] = MagicMock(getMetaDataEntry = lambda x: 2) + empty_variant_node.materials["preferred_material"] = MagicMock(getMetaDataEntry = lambda x: 2) # Wrong diameter. assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["some_different_material"], "It should match on another material with the correct diameter if the preferred one is unavailable." @@ -177,7 +156,7 @@ def test_preferredMaterialDiameterNoMatch(empty_variant_node): def test_preferredMaterialDiameterPreference(empty_variant_node): empty_variant_node.materials = collections.OrderedDict() empty_variant_node.materials["some_different_material"] = MagicMock(getMetaDataEntry = lambda x: 2) # This one first so that it gets iterated over first. - empty_variant_node.materials["preferred_material_wrong_diameter"] = MagicMock(getMetaDataEntry = lambda x: 2) # Matches on ID but not diameter. + empty_variant_node.materials["preferred_material"] = MagicMock(getMetaDataEntry = lambda x: 2) # Matches on ID but not diameter. empty_variant_node.materials["not_preferred_but_correct_diameter"] = MagicMock(getMetaDataEntry = lambda x: 3) # Matches diameter but not ID. assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["not_preferred_but_correct_diameter"], "It should match on the correct diameter even if it's not the preferred one." \ No newline at end of file diff --git a/tests/Settings/TestDefinitionContainer.py b/tests/Settings/TestDefinitionContainer.py index 6e502280cd..4487388b86 100644 --- a/tests/Settings/TestDefinitionContainer.py +++ b/tests/Settings/TestDefinitionContainer.py @@ -17,6 +17,10 @@ Resources.addSearchPath(os.path.abspath(os.path.join(os.path.dirname(__file__), machine_filepaths = sorted(os.listdir(os.path.join(os.path.dirname(__file__), "..", "..", "resources", "definitions"))) +machine_filepaths = [os.path.join(os.path.dirname(__file__), "..", "..", "resources", "definitions", filename) for filename in machine_filepaths] +extruder_filepaths = sorted(os.listdir(os.path.join(os.path.dirname(__file__), "..", "..", "resources", "extruders"))) +extruder_filepaths = [os.path.join(os.path.dirname(__file__), "..", "..", "resources", "extruders", filename) for filename in extruder_filepaths] +definition_filepaths = machine_filepaths + extruder_filepaths all_meshes = os.listdir(os.path.join(os.path.dirname(__file__), "..", "..", "resources", "meshes")) all_images = os.listdir(os.path.join(os.path.dirname(__file__), "..", "..", "resources", "images")) @@ -29,17 +33,16 @@ def definition_container(): ## Tests all definition containers -@pytest.mark.parametrize("file_name", machine_filepaths) -def test_validateMachineDefinitionContainer(file_name, definition_container): +@pytest.mark.parametrize("file_path", machine_filepaths) +def test_validateMachineDefinitionContainer(file_path, definition_container): + file_name = os.path.basename(file_path) if file_name == "fdmprinter.def.json" or file_name == "fdmextruder.def.json": return # Stop checking, these are root files. - definition_path = os.path.join(os.path.dirname(__file__), "..", "..", "resources", "definitions") - assertIsDefinitionValid(definition_container, definition_path, file_name) + assertIsDefinitionValid(definition_container, file_path) - -def assertIsDefinitionValid(definition_container, path, file_name): - with open(os.path.join(path, file_name), encoding = "utf-8") as data: +def assertIsDefinitionValid(definition_container, file_path): + with open(file_path, encoding = "utf-8") as data: json = data.read() parser, is_valid = definition_container.readAndValidateSerialized(json) assert is_valid #The definition has invalid JSON structure. @@ -57,10 +60,9 @@ def assertIsDefinitionValid(definition_container, path, file_name): # When a definition container defines a "default_value" but inherits from a # definition that defines a "value", the "default_value" is ineffective. This # test fails on those things. -@pytest.mark.parametrize("file_name", machine_filepaths) -def test_validateOverridingDefaultValue(file_name: str): - definition_path = os.path.join(os.path.dirname(__file__), "..", "..", "resources", "definitions", file_name) - with open(definition_path, encoding = "utf-8") as f: +@pytest.mark.parametrize("file_path", definition_filepaths) +def test_validateOverridingDefaultValue(file_path: str): + with open(file_path, encoding = "utf-8") as f: doc = json.load(f) if "inherits" not in doc: @@ -69,8 +71,8 @@ def test_validateOverridingDefaultValue(file_name: str): return # No settings are being overridden. No need to check anything. parent_settings = getInheritedSettings(doc["inherits"]) for key, val in doc["overrides"].items(): - if "value" in parent_settings[key]: - assert "default_value" not in val, "Unnecessary default_value for {key} in {file_name}".format(key = key, file_name = file_name) # If there is a value in the parent settings, then the default_value is not effective. + if key in parent_settings and "value" in parent_settings[key]: + assert "default_value" not in val, "Unnecessary default_value for {key} in {file_name}".format(key = key, file_name = file_path) # If there is a value in the parent settings, then the default_value is not effective. ## Get all settings and their properties from a definition we're inheriting # from. @@ -130,10 +132,46 @@ def merge_dicts(base: Dict[str, Any], overrides: Dict[str, Any]) -> Dict[str, An # # ID fields are legacy. They should not be used any more. This is legacy that # people don't seem to be able to get used to. -@pytest.mark.parametrize("file_name", machine_filepaths) -def test_noId(file_name): - definition_path = os.path.join(os.path.dirname(__file__), "..", "..", "resources", "definitions", file_name) - with open(definition_path, encoding = "utf-8") as f: +@pytest.mark.parametrize("file_path", definition_filepaths) +def test_noId(file_path: str): + with open(file_path, encoding = "utf-8") as f: doc = json.load(f) - assert "id" not in doc, "Definitions should not have an ID field." \ No newline at end of file + assert "id" not in doc, "Definitions should not have an ID field." + +## Verifies that extruders say that they work on the same extruder_nr as what +# is listed in their machine definition. +@pytest.mark.parametrize("file_path", extruder_filepaths) +def test_extruderMatch(file_path: str): + extruder_id = os.path.basename(file_path).split(".")[0] + with open(file_path, encoding = "utf-8") as f: + doc = json.load(f) + + if "metadata" not in doc: + return # May not be desirable either, but it's probably unfinished then. + if "machine" not in doc["metadata"] or "position" not in doc["metadata"]: + return # FDMextruder doesn't have this since it's not linked to a particular printer. + machine = doc["metadata"]["machine"] + position = doc["metadata"]["position"] + + # Find the machine definition. + for machine_filepath in machine_filepaths: + machine_id = os.path.basename(machine_filepath).split(".")[0] + if machine_id == machine: + break + else: + assert False, "The machine ID {machine} is not found.".format(machine = machine) + with open(machine_filepath, encoding = "utf-8") as f: + machine_doc = json.load(f) + + # Make sure that the two match up. + assert "metadata" in machine_doc, "Machine definition missing metadata entry." + assert "machine_extruder_trains" in machine_doc["metadata"], "Machine must define extruder trains." + extruder_trains = machine_doc["metadata"]["machine_extruder_trains"] + assert position in extruder_trains, "There must be a reference to the extruder in the machine definition." + assert extruder_trains[position] == extruder_id, "The extruder referenced in the machine definition must match up." + + # Also test if the extruder_nr setting is properly overridden. + if "overrides" not in doc or "extruder_nr" not in doc["overrides"] or "default_value" not in doc["overrides"]["extruder_nr"]: + assert position == "0" # Default to 0 is allowed. + assert doc["overrides"]["extruder_nr"]["default_value"] == int(position) \ No newline at end of file