From 2caddee2fa9e7e696f77426e4cd1e0842f8bc0e5 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Wed, 28 Dec 2016 08:38:33 +0000 Subject: [PATCH 01/37] Add infill_angles setting to control direction of lines and zig zag infill. This setting provides 4 options: Default - the original directions, 45 and 135. Uniform - one each of 45, 90, 135 and 180. Stronger X - 45, 90, 135 and 90 again - provides more strength in X direction. Stronger Y - 45, 0, 135 and 0 again - provides more strength in Y direction. --- resources/definitions/fdmprinter.def.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 842a2a5bfd..3938ecaaad 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1071,6 +1071,22 @@ "value": "'lines' if infill_sparse_density > 25 else 'grid'", "settable_per_mesh": true }, + "infill_angles": + { + "label": "Infill Line Directions", + "description": "The line directions to use when the infill pattern is lines or zig zag. Default directions are 45 and 135 degrees, Uniform directions are 45, 90, 135 and 180, Stronger X directions are 45, 90, 135 and 90 again and Stronger Y directions are 45, 0, 135 and 0 again.", + "type": "enum", + "options": + { + "45,135": "Default", + "45,90,135,180": "Uniform", + "45,90,135,90": "Stronger X", + "45,0,135,0": "Stronger Y" + }, + "default_value": "45,135", + "enabled": "infill_pattern == 'lines' or infill_pattern == 'zigzag'", + "settable_per_mesh": true + }, "sub_div_rad_mult": { "label": "Cubic Subdivision Radius", From 8d3984a7b48e90eb0d58ea87b500d649322a9bd8 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Thu, 29 Dec 2016 11:32:02 +0000 Subject: [PATCH 02/37] Change Default label to Orthogonal. --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 3938ecaaad..f53720d863 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1074,11 +1074,11 @@ "infill_angles": { "label": "Infill Line Directions", - "description": "The line directions to use when the infill pattern is lines or zig zag. Default directions are 45 and 135 degrees, Uniform directions are 45, 90, 135 and 180, Stronger X directions are 45, 90, 135 and 90 again and Stronger Y directions are 45, 0, 135 and 0 again.", + "description": "The line directions to use when the infill pattern is lines or zig zag. Orthogonal directions are 45 and 135 degrees, Uniform directions are 45, 90, 135 and 180, Stronger X directions are 45, 90, 135 and 90 again and Stronger Y directions are 45, 0, 135 and 0 again.", "type": "enum", "options": { - "45,135": "Default", + "45,135": "Orthogonal", "45,90,135,180": "Uniform", "45,90,135,90": "Stronger X", "45,0,135,0": "Stronger Y" From 03fe03ed65eb39ed82448376f3984be3c847dc46 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Mon, 16 Jan 2017 16:05:21 +0000 Subject: [PATCH 03/37] Modify the constraints of the SettingTextField when the setting type is "str". When the setting type is "str" it now allows the setting contents to be up to 20 characters long with no constraint on what those characters are. --- resources/qml/Settings/SettingTextField.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index da24f0f521..af899bec12 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -98,9 +98,9 @@ SettingItem selectByMouse: true; - maximumLength: 10; + maximumLength: (definition.type == "str") ? 20 : 10; - validator: RegExpValidator { regExp: (definition.type == "int") ? /^-?[0-9]{0,10}$/ : /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ } // definition.type property from parent loader used to disallow fractional number entry + validator: RegExpValidator { regExp: (definition.type == "str") ? /^.{0,20}$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ } // definition.type property from parent loader used to disallow fractional number entry Binding { From efc3869efe4d8cf10488cb385739ca51dc9583ce Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Mon, 16 Jan 2017 16:09:48 +0000 Subject: [PATCH 04/37] Infill Line Directions setting can now contain an arbitrary string. The SettingTextField can now cope with strings of arbitrary characters (not just digits) so revert to plan A and let the user input a comma separated list of angles rather than having fixed combinations. CuraEngine will parse the list and ignore bad input. --- resources/definitions/fdmprinter.def.json | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index dd863719f0..6dd30800be 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1089,15 +1089,8 @@ "infill_angles": { "label": "Infill Line Directions", - "description": "The line directions to use when the infill pattern is lines or zig zag. Orthogonal directions are 45 and 135 degrees, Uniform directions are 45, 90, 135 and 180, Stronger X directions are 45, 90, 135 and 90 again and Stronger Y directions are 45, 0, 135 and 0 again.", - "type": "enum", - "options": - { - "45,135": "Orthogonal", - "45,90,135,180": "Uniform", - "45,90,135,90": "Stronger X", - "45,0,135,0": "Stronger Y" - }, + "description": "A comma separated list of line directions to use when the infill pattern is lines or zig zag. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. Default directions are 45 and 135 degrees.", + "type": "str", "default_value": "45,135", "enabled": "infill_pattern == 'lines' or infill_pattern == 'zigzag'", "settable_per_mesh": true From 3e7b9e99f31d3f96d4b123ca52992814c9fc230e Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Tue, 24 Jan 2017 18:09:11 +0000 Subject: [PATCH 05/37] Now the Infill Line Directions setting is enabled for all infill patterns. The default value is now the empty string which tells the engine to use the traditional angles (45 & 135 for lines and zig zag patterns, just 45 for everything else. --- resources/definitions/fdmprinter.def.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index a85a50b37c..ffabf9a7d5 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1089,10 +1089,9 @@ "infill_angles": { "label": "Infill Line Directions", - "description": "A comma separated list of line directions to use when the infill pattern is lines or zig zag. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. Default directions are 45 and 135 degrees.", + "description": "A comma separated list of line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. Default is empty which means use the traditional default angles (45 and 135 degrees for the lines and zig zag patterns and 45 degrees for all other patterns).", "type": "str", - "default_value": "45,135", - "enabled": "infill_pattern == 'lines' or infill_pattern == 'zigzag'", + "default_value": "", "settable_per_mesh": true }, "sub_div_rad_mult": From db3cf0c0fb271461143049285cd7f099d043253f Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Fri, 27 Jan 2017 15:54:19 +0000 Subject: [PATCH 06/37] Add the [int] setting type for settings that are a list of integers. The RegExpValidator (more of a restrictor than a validator) requires the text to start with a '[' and then have a sequence of integers separated by commas. A trailing ']' is accepted. --- cura/CuraApplication.py | 2 ++ plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml | 2 ++ resources/qml/Settings/SettingTextField.qml | 4 ++-- resources/qml/Settings/SettingView.qml | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 6288c2d211..d1f6504431 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -107,6 +107,8 @@ class CuraApplication(QtApplication): SettingDefinition.addSettingType("extruder", None, str, Validator) + SettingDefinition.addSettingType("[int]", None, str, None) + SettingFunction.registerOperator("extruderValues", cura.Settings.ExtruderManager.getExtruderValues) SettingFunction.registerOperator("extruderValue", cura.Settings.ExtruderManager.getExtruderValue) SettingFunction.registerOperator("resolveOrValue", cura.Settings.ExtruderManager.getResolveOrValue) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 9811316948..cb65da635b 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -209,6 +209,8 @@ Item { { case "int": return settingTextField + case "[int]": + return settingTextField case "float": return settingTextField case "enum": diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index af899bec12..05c99d7e25 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -98,9 +98,9 @@ SettingItem selectByMouse: true; - maximumLength: (definition.type == "str") ? 20 : 10; + maximumLength: (definition.type == "[int]") ? 20 : 10; - validator: RegExpValidator { regExp: (definition.type == "str") ? /^.{0,20}$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ } // definition.type property from parent loader used to disallow fractional number entry + validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[(\s*-?[0-9]+\s*,)*(\s*-?[0-9]+)\s*\]$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ } // definition.type property from parent loader used to disallow fractional number entry Binding { diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 24022891c3..7138d4acd3 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -217,6 +217,8 @@ Item { case "int": return "SettingTextField.qml" + case "[int]": + return "SettingTextField.qml" case "float": return "SettingTextField.qml" case "enum": From afc75b6c3e5af11636ea9fe64d845f73af713457 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Fri, 27 Jan 2017 15:54:58 +0000 Subject: [PATCH 07/37] Now uses the [int] setting type. The default value is [ ] (an empty list). --- resources/definitions/fdmprinter.def.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index ffabf9a7d5..4f39be7462 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1089,9 +1089,9 @@ "infill_angles": { "label": "Infill Line Directions", - "description": "A comma separated list of line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. Default is empty which means use the traditional default angles (45 and 135 degrees for the lines and zig zag patterns and 45 degrees for all other patterns).", - "type": "str", - "default_value": "", + "description": "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees for the lines and zig zag patterns and 45 degrees for all other patterns).", + "type": "[int]", + "default_value": "[ ]", "settable_per_mesh": true }, "sub_div_rad_mult": From 27a52092d301121e439097777614529ba28a4dcd Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Fri, 27 Jan 2017 15:55:22 +0000 Subject: [PATCH 08/37] Add the skin_angles setting which is analogous to the infill_angles setting. --- resources/definitions/fdmprinter.def.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 4f39be7462..adf909a644 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -905,6 +905,14 @@ "value": "top_bottom_pattern", "settable_per_mesh": true }, + "skin_angles": + { + "label": "Top/Bottom Line Directions", + "description": "A list of integer line directions to use when the top/bottom layers use the lines or zig zag pattern. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees).", + "type": "[int]", + "default_value": "[ ]", + "settable_per_mesh": true + }, "wall_0_inset": { "label": "Outer Wall Inset", From 5817905459d7b7f12e4161a3db0fdd876b34de3a Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Tue, 31 Jan 2017 18:47:27 +0000 Subject: [PATCH 09/37] Added anchor_skin_in_infill setting. When enabled, skin areas are increased in size so that they project into the infill by at least the distance between infill lines. --- resources/definitions/fdmprinter.def.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index f6cb2060c6..825686640e 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1240,6 +1240,14 @@ "minimum_value": "0", "default_value": 0, "settable_per_mesh": true + }, + "anchor_skin_in_infill": + { + "label": "Anchor Skin In Infill", + "description": "Expand skin areas so that they are anchored by the infill layers above and below. The skin areas are expanded sufficiently so that they bridge the gap between the infill lines.", + "type": "bool", + "default_value": false, + "settable_per_mesh": true } } }, From 45dc52de1639702f52b87659177941cf275847f9 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Wed, 1 Feb 2017 08:37:20 +0000 Subject: [PATCH 10/37] Provide separate settings for anchoring upper and lower skins in infill. Just expanding the upper skins into the infill is probably sufficient for most situations but if users want a symmetrical structure then expanding lower skins too could be useful. Users will need to experiment to get the desired results for a given model. --- resources/definitions/fdmprinter.def.json | 27 ++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 825686640e..ab00f55ef6 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1241,13 +1241,34 @@ "default_value": 0, "settable_per_mesh": true }, - "anchor_skin_in_infill": + "anchor_skins_in_infill": { - "label": "Anchor Skin In Infill", + "label": "Anchor Skins In Infill", "description": "Expand skin areas so that they are anchored by the infill layers above and below. The skin areas are expanded sufficiently so that they bridge the gap between the infill lines.", "type": "bool", "default_value": false, - "settable_per_mesh": true + "settable_per_mesh": true, + "children": + { + "anchor_upper_skin_in_infill": + { + "label": "Anchor Upper Skin In Infill", + "description": "Expand upper skin areas (areas with air above) so that they are anchored by the infill layers above and below. The skin areas are expanded sufficiently so that they bridge the gap between the infill lines.", + "type": "bool", + "default_value": false, + "value": "anchor_skins_in_infill", + "settable_per_mesh": true + }, + "anchor_lower_skin_in_infill": + { + "label": "Anchor Lower Skin In Infill", + "description": "Expand lower skin areas (areas with air below) so that they are anchored by the infill layers above and below. The skin areas are expanded sufficiently so that they bridge the gap between the infill lines.", + "type": "bool", + "default_value": false, + "value": "anchor_skins_in_infill", + "settable_per_mesh": true + } + } } } }, From eabfb797d68b117e77a87daa6f79e580b3ecfa25 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Wed, 1 Feb 2017 12:54:35 +0000 Subject: [PATCH 11/37] Add anchor_skin_distance setting and tweak descriptions of related settings. Now, the user can control how far the skins are expanded into the infill. --- resources/definitions/fdmprinter.def.json | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index ab00f55ef6..fe2809b872 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1244,7 +1244,7 @@ "anchor_skins_in_infill": { "label": "Anchor Skins In Infill", - "description": "Expand skin areas so that they are anchored by the infill layers above and below. The skin areas are expanded sufficiently so that they bridge the gap between the infill lines.", + "description": "Expand skin areas into the infill behind walls. By default, skins stop when they reach the wall lines that surround infill. This setting extends the skins beyond the wall lines so that the skins become anchored in the infill.", "type": "bool", "default_value": false, "settable_per_mesh": true, @@ -1253,7 +1253,7 @@ "anchor_upper_skin_in_infill": { "label": "Anchor Upper Skin In Infill", - "description": "Expand upper skin areas (areas with air above) so that they are anchored by the infill layers above and below. The skin areas are expanded sufficiently so that they bridge the gap between the infill lines.", + "description": "Expand upper skin areas (areas with air above) so that they are anchored by the infill layers above and below.", "type": "bool", "default_value": false, "value": "anchor_skins_in_infill", @@ -1262,11 +1262,22 @@ "anchor_lower_skin_in_infill": { "label": "Anchor Lower Skin In Infill", - "description": "Expand lower skin areas (areas with air below) so that they are anchored by the infill layers above and below. The skin areas are expanded sufficiently so that they bridge the gap between the infill lines.", + "description": "Expand lower skin areas (areas with air below) so that they are anchored by the infill layers above and below.", "type": "bool", "default_value": false, "value": "anchor_skins_in_infill", "settable_per_mesh": true + }, + "anchor_skin_distance": + { + "label": "Anchor Skin Distance", + "description": "The distance the skins are expanded into the infill. The default value is sufficient to bridge the gap between the infill lines.", + "unit": "mm", + "type": "float", + "default_value": 1.0, + "value": "infill_line_distance * 1.4", + "minimum_value": "0", + "settable_per_mesh": true } } } From a3326a83137bd33db107103e476208103f57750c Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 2 Feb 2017 15:54:44 +0100 Subject: [PATCH 12/37] 3mf reader now uses libSavitar for loading This greatly decreases (~factor 10) the time required to load 3mf files CURA-3215 --- plugins/3MFReader/ThreeMFReader.py | 132 ++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 42 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 0f4ab532fa..2595f8affa 100644 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -18,6 +18,9 @@ from cura.Settings.ExtruderManager import ExtruderManager from cura.QualityManager import QualityManager from UM.Scene.SceneNode import SceneNode +import Savitar +import numpy + try: import xml.etree.cElementTree as ET except ImportError: @@ -129,6 +132,9 @@ class ThreeMFReader(MeshReader): return node def _createMatrixFromTransformationString(self, transformation): + if transformation == "": + return Matrix() + splitted_transformation = transformation.split() ## Transformation is saved as: ## M00 M01 M02 0.0 @@ -155,51 +161,92 @@ class ThreeMFReader(MeshReader): return temp_mat + def _convertSavitarNodeToUMNode(self, savitar_node): + um_node = SceneNode() + transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation()) + um_node.setTransformation(transformation) + mesh_builder = MeshBuilder() + + data = numpy.fromstring(savitar_node.getMeshData().getFlatVerticesAsBytes(), dtype=numpy.float32) + + vertices = numpy.resize(data, (int(data.size / 3), 3)) + mesh_builder.setVertices(vertices) + mesh_builder.calculateNormals(fast=True) + mesh_data = mesh_builder.build() + + if len(mesh_data.getVertices()): + um_node.setMeshData(mesh_data) + + for child in savitar_node.getChildren(): + um_node.addChild(self._convertSavitarNodeToUMNode(child)) + settings = savitar_node.getSettings() + + # 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() + # 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 + + # Ensure that all extruder data is reset + if not multi_extrusion: + default_stack_id = global_container_stack.getId() + else: + default_stack = ExtruderManager.getInstance().getExtruderStack(0) + if default_stack: + default_stack_id = default_stack.getId() + else: + default_stack_id = global_container_stack.getId() + um_node.callDecoration("setActiveExtruder", default_stack_id) + + # Get the definition & set it + definition = QualityManager.getInstance().getParentMachineDefinition(global_container_stack.getBottom()) + um_node.callDecoration("getStack").getTop().setDefinition(definition) + + setting_container = um_node.callDecoration("getStack").getTop() + + for key in settings: + setting_value = settings[key] + + # Extruder_nr is a special case. + if key == "extruder_nr": + extruder_stack = ExtruderManager.getInstance().getExtruderStack(int(setting_value)) + if extruder_stack: + um_node.callDecoration("setActiveExtruder", extruder_stack.getId()) + else: + Logger.log("w", "Unable to find extruder in position %s", setting_value) + continue + setting_container.setProperty(key,"value", setting_value) + + if len(um_node.getChildren()) > 0: + group_decorator = GroupDecorator() + um_node.addDecorator(group_decorator) + um_node.setSelectable(True) + return um_node + def read(self, file_name): result = [] # The base object of 3mf is a zipped archive. - archive = zipfile.ZipFile(file_name, "r") - self._base_name = os.path.basename(file_name) try: - self._root = ET.parse(archive.open("3D/3dmodel.model")) - self._unit = self._root.getroot().get("unit") - - build_items = self._root.findall("./3mf:build/3mf:item", self._namespaces) - - for build_item in build_items: - id = build_item.get("objectid") - object = self._root.find("./3mf:resources/3mf:object[@id='{0}']".format(id), self._namespaces) - if "type" in object.attrib: - if object.attrib["type"] == "support" or object.attrib["type"] == "other": - # Ignore support objects, as cura does not support these. - # We can't guarantee that they wont be made solid. - # We also ignore "other", as I have no idea what to do with them. - Logger.log("w", "3MF file contained an object of type %s which is not supported by Cura", object.attrib["type"]) - continue - elif object.attrib["type"] == "solidsupport" or object.attrib["type"] == "model": - pass # Load these as normal - else: - # We should technically fail at this point because it's an invalid 3MF, but try to continue anyway. - Logger.log("e", "3MF file contained an object of type %s which is not supported by the 3mf spec", - object.attrib["type"]) - continue - - build_item_node = self._createNodeFromObject(object, self._base_name + "_" + str(id)) - + archive = zipfile.ZipFile(file_name, "r") + self._base_name = os.path.basename(file_name) + parser = Savitar.ThreeMFParser() + scene_3mf = parser.parse(archive.open("3D/3dmodel.model").read()) + self._unit = scene_3mf.getUnit() + for node in scene_3mf.getSceneNodes(): + um_node = self._convertSavitarNodeToUMNode(node) # compensate for original center position, if object(s) is/are not around its zero position + transform_matrix = Matrix() - mesh_data = build_item_node.getMeshData() + 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) transform_matrix.setByTranslation(center_vector) - - # offset with transform from 3mf - transform = build_item.get("transform") - if transform is not None: - transform_matrix.multiply(self._createMatrixFromTransformationString(transform)) - - build_item_node.setTransformation(transform_matrix) + transform_matrix.multiply(um_node.getLocalTransformation()) + um_node.setTransformation(transform_matrix) global_container_stack = UM.Application.getInstance().getGlobalContainerStack() @@ -214,9 +261,9 @@ class ThreeMFReader(MeshReader): # Second step: 3MF defines the left corner of the machine as center, whereas cura uses the center of the # build volume. if global_container_stack: - translation_vector = Vector(x = -global_container_stack.getProperty("machine_width", "value") / 2, - y = -global_container_stack.getProperty("machine_depth", "value") / 2, - z = 0) + translation_vector = Vector(x=-global_container_stack.getProperty("machine_width", "value") / 2, + y=-global_container_stack.getProperty("machine_depth", "value") / 2, + z=0) translation_matrix = Matrix() translation_matrix.setByTranslation(translation_vector) transformation_matrix.multiply(translation_matrix) @@ -227,12 +274,13 @@ class ThreeMFReader(MeshReader): transformation_matrix.multiply(scale_matrix) # Pre multiply the transformation with the loaded transformation, so the data is handled correctly. - build_item_node.setTransformation(build_item_node.getLocalTransformation().preMultiply(transformation_matrix)) + um_node.setTransformation(um_node.getLocalTransformation().preMultiply(transformation_matrix)) - result.append(build_item_node) + result.append(um_node) - except Exception as e: - Logger.log("e", "An exception occurred in 3mf reader: %s", e) + except Exception: + Logger.logException("e", "An exception occurred in 3mf reader.") + return [] return result From b83537f27d828ff7e74b67763f6696ff758ece09 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Sun, 5 Feb 2017 15:58:42 +0000 Subject: [PATCH 13/37] Hide children of anchor_skins_in_infill when it isn't enabled. --- resources/definitions/fdmprinter.def.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index fe2809b872..c90f17edb6 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1257,6 +1257,7 @@ "type": "bool", "default_value": false, "value": "anchor_skins_in_infill", + "enabled": "anchor_skins_in_infill", "settable_per_mesh": true }, "anchor_lower_skin_in_infill": @@ -1266,6 +1267,7 @@ "type": "bool", "default_value": false, "value": "anchor_skins_in_infill", + "enabled": "anchor_skins_in_infill", "settable_per_mesh": true }, "anchor_skin_distance": @@ -1277,6 +1279,7 @@ "default_value": 1.0, "value": "infill_line_distance * 1.4", "minimum_value": "0", + "enabled": "anchor_skins_in_infill", "settable_per_mesh": true } } From 495a73e9762f568072b4ff6c053b30014e076e2e Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Mon, 6 Feb 2017 08:44:25 +0000 Subject: [PATCH 14/37] Tweaked descriptions of anchor_skin_in_infill and anchor_skin_distance. --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index c90f17edb6..bbb9d14e8d 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1244,7 +1244,7 @@ "anchor_skins_in_infill": { "label": "Anchor Skins In Infill", - "description": "Expand skin areas into the infill behind walls. By default, skins stop when they reach the wall lines that surround infill. This setting extends the skins beyond the wall lines so that the skins become anchored in the infill.", + "description": "Expand skin areas into the infill behind walls. By default, skins stop under the wall lines that surround infill but this can lead to holes appearing when the infill density is low. This setting extends the skins beyond the wall lines so that the skins become anchored in the infill.", "type": "bool", "default_value": false, "settable_per_mesh": true, @@ -1273,7 +1273,7 @@ "anchor_skin_distance": { "label": "Anchor Skin Distance", - "description": "The distance the skins are expanded into the infill. The default value is sufficient to bridge the gap between the infill lines.", + "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", "unit": "mm", "type": "float", "default_value": 1.0, From b6118a764e28326aaf9ebc97acd4847dcd60ad77 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 6 Feb 2017 14:13:20 +0100 Subject: [PATCH 15/37] Updated documentation CURA-3215 --- plugins/3MFReader/ThreeMFReader.py | 95 ++---------------------------- 1 file changed, 4 insertions(+), 91 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 2595f8affa..bfa9d2764b 100644 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -40,97 +40,6 @@ class ThreeMFReader(MeshReader): self._base_name = "" self._unit = None - def _createNodeFromObject(self, object, name = ""): - node = SceneNode() - node.setName(name) - mesh_builder = MeshBuilder() - vertex_list = [] - - components = object.find(".//3mf:components", self._namespaces) - if components: - for component in components: - id = component.get("objectid") - new_object = self._root.find("./3mf:resources/3mf:object[@id='{0}']".format(id), self._namespaces) - new_node = self._createNodeFromObject(new_object, self._base_name + "_" + str(id)) - node.addChild(new_node) - transform = component.get("transform") - if transform is not None: - new_node.setTransformation(self._createMatrixFromTransformationString(transform)) - - # for vertex in entry.mesh.vertices.vertex: - for vertex in object.findall(".//3mf:vertex", self._namespaces): - vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")]) - Job.yieldThread() - - xml_settings = list(object.findall(".//cura:setting", self._namespaces)) - - # Add the setting override decorator, so we can add settings to this node. - if xml_settings: - node.addDecorator(SettingOverrideDecorator()) - - 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 - # Ensure that all extruder data is reset - if not multi_extrusion: - default_stack_id = global_container_stack.getId() - else: - default_stack = ExtruderManager.getInstance().getExtruderStack(0) - if default_stack: - default_stack_id = default_stack.getId() - else: - default_stack_id = global_container_stack.getId() - node.callDecoration("setActiveExtruder", default_stack_id) - - # Get the definition & set it - definition = QualityManager.getInstance().getParentMachineDefinition(global_container_stack.getBottom()) - node.callDecoration("getStack").getTop().setDefinition(definition) - - setting_container = node.callDecoration("getStack").getTop() - for setting in xml_settings: - setting_key = setting.get("key") - setting_value = setting.text - - # Extruder_nr is a special case. - if setting_key == "extruder_nr": - extruder_stack = ExtruderManager.getInstance().getExtruderStack(int(setting_value)) - if extruder_stack: - node.callDecoration("setActiveExtruder", extruder_stack.getId()) - else: - Logger.log("w", "Unable to find extruder in position %s", setting_value) - continue - setting_container.setProperty(setting_key,"value", setting_value) - - if len(node.getChildren()) > 0: - group_decorator = GroupDecorator() - node.addDecorator(group_decorator) - - triangles = object.findall(".//3mf:triangle", self._namespaces) - mesh_builder.reserveFaceCount(len(triangles)) - - for triangle in triangles: - v1 = int(triangle.get("v1")) - v2 = int(triangle.get("v2")) - v3 = int(triangle.get("v3")) - - mesh_builder.addFaceByPoints(vertex_list[v1][0], vertex_list[v1][1], vertex_list[v1][2], - vertex_list[v2][0], vertex_list[v2][1], vertex_list[v2][2], - vertex_list[v3][0], vertex_list[v3][1], vertex_list[v3][2]) - - Job.yieldThread() - - # TODO: We currently do not check for normals and simply recalculate them. - mesh_builder.calculateNormals(fast=True) - mesh_builder.setFileName(name) - mesh_data = mesh_builder.build() - - if len(mesh_data.getVertices()): - node.setMeshData(mesh_data) - - node.setSelectable(True) - return node - def _createMatrixFromTransformationString(self, transformation): if transformation == "": return Matrix() @@ -161,6 +70,9 @@ class ThreeMFReader(MeshReader): return temp_mat + + ## Convenience function that converts a SceneNode object (as obtained from libSavitar) to a Uranium scenenode. + # \returns Uranium Scenen node. def _convertSavitarNodeToUMNode(self, savitar_node): um_node = SceneNode() transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation()) @@ -179,6 +91,7 @@ class ThreeMFReader(MeshReader): for child in savitar_node.getChildren(): um_node.addChild(self._convertSavitarNodeToUMNode(child)) + settings = savitar_node.getSettings() # Add the setting override decorator, so we can add settings to this node. From 4dc70cc2b129dcf4ff6a0254fcbb86e41dcc31cd Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 6 Feb 2017 14:14:03 +0100 Subject: [PATCH 16/37] 3MF writer now also uses libSavitar CURA-3215 --- plugins/3MFWriter/ThreeMFWriter.py | 185 ++++++++++++----------------- 1 file changed, 75 insertions(+), 110 deletions(-) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 764c73b1f0..f7ea04ed0d 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -6,6 +6,11 @@ from UM.Math.Vector import Vector from UM.Logger import Logger from UM.Math.Matrix import Matrix from UM.Application import Application +import UM.Scene.SceneNode + +import Savitar + +import numpy try: import xml.etree.cElementTree as ET @@ -33,18 +38,18 @@ class ThreeMFWriter(MeshWriter): def _convertMatrixToString(self, matrix): result = "" - result += str(matrix._data[0,0]) + " " - result += str(matrix._data[1,0]) + " " - result += str(matrix._data[2,0]) + " " - result += str(matrix._data[0,1]) + " " - result += str(matrix._data[1,1]) + " " - result += str(matrix._data[2,1]) + " " - result += str(matrix._data[0,2]) + " " - result += str(matrix._data[1,2]) + " " - result += str(matrix._data[2,2]) + " " - result += str(matrix._data[0,3]) + " " - result += str(matrix._data[1,3]) + " " - result += str(matrix._data[2,3]) + result += str(matrix._data[0, 0]) + " " + result += str(matrix._data[1, 0]) + " " + result += str(matrix._data[2, 0]) + " " + result += str(matrix._data[0, 1]) + " " + result += str(matrix._data[1, 1]) + " " + result += str(matrix._data[2, 1]) + " " + result += str(matrix._data[0, 2]) + " " + result += str(matrix._data[1, 2]) + " " + result += str(matrix._data[2, 2]) + " " + result += str(matrix._data[0, 3]) + " " + result += str(matrix._data[1, 3]) + " " + result += str(matrix._data[2, 3]) return result ## Should we store the archive @@ -53,6 +58,48 @@ class ThreeMFWriter(MeshWriter): def setStoreArchive(self, store_archive): self._store_archive = store_archive + ## Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode + # \returns Uranium Scenen node. + def _convertUMNodeToSavitarNode(self, um_node, transformation = Matrix()): + if type(um_node) is not UM.Scene.SceneNode.SceneNode: + return None + + savitar_node = Savitar.SceneNode() + + node_matrix = um_node.getLocalTransformation() + + matrix_string = self._convertMatrixToString(node_matrix.preMultiply(transformation)) + + savitar_node.setTransformation(matrix_string) + mesh_data = um_node.getMeshData() + if mesh_data is not None: + savitar_node.getMeshData().setVerticesFromBytes(mesh_data.getVerticesAsByteArray()) + indices_array = mesh_data.getIndicesAsByteArray() + if indices_array is not None: + savitar_node.getMeshData().setFacesFromBytes(indices_array) + else: + savitar_node.getMeshData().setFacesFromBytes(numpy.arange(mesh_data.getVertices().size / 3, dtype=numpy.int32).tostring()) + + # Handle per object settings (if any) + stack = um_node.callDecoration("getStack") + if stack is not None: + changed_setting_keys = set(stack.getTop().getAllKeys()) + + # Ensure that we save the extruder used for this object. + if stack.getProperty("machine_extruder_count", "value") > 1: + changed_setting_keys.add("extruder_nr") + + # Get values for all changed settings & save them. + for key in changed_setting_keys: + savitar_node.setSetting(key, str(stack.getProperty(key, "value"))) + + for child_node in um_node.getChildren(): + savitar_child_node = self._convertUMNodeToSavitarNode(child_node) + if savitar_child_node is not None: + savitar_node.addChild(savitar_child_node) + + return savitar_node + def getArchive(self): return self._archive @@ -77,98 +124,7 @@ class ThreeMFWriter(MeshWriter): relations_element = ET.Element("Relationships", xmlns = self._namespaces["relationships"]) model_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/3D/3dmodel.model", Id = "rel0", Type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel") - model = ET.Element("model", unit = "millimeter", xmlns = self._namespaces["3mf"]) - model.set("xmlns:cura", self._namespaces["cura"]) - - # Add the version of Cura this was created with. Since there is no "version" or similar metadata name we need - # to prefix it with the cura namespace, as specified by the 3MF specification. - version_metadata = ET.SubElement(model, "metadata", name = "cura:version") - version_metadata.text = Application.getInstance().getVersion() - - resources = ET.SubElement(model, "resources") - build = ET.SubElement(model, "build") - - added_nodes = [] - index = 0 # Ensure index always exists (even if there are no nodes to write) - # Write all nodes with meshData to the file as objects inside the resource tag - for index, n in enumerate(MeshWriter._meshNodes(nodes)): - added_nodes.append(n) # Save the nodes that have mesh data - object = ET.SubElement(resources, "object", id = str(index+1), type = "model") - mesh = ET.SubElement(object, "mesh") - - mesh_data = n.getMeshData() - vertices = ET.SubElement(mesh, "vertices") - verts = mesh_data.getVertices() - - if verts is None: - Logger.log("d", "3mf writer can't write nodes without mesh data. Skipping this node.") - continue # No mesh data, nothing to do. - if mesh_data.hasIndices(): - for face in mesh_data.getIndices(): - v1 = verts[face[0]] - v2 = verts[face[1]] - v3 = verts[face[2]] - xml_vertex1 = ET.SubElement(vertices, "vertex", x = str(v1[0]), y = str(v1[1]), z = str(v1[2])) - xml_vertex2 = ET.SubElement(vertices, "vertex", x = str(v2[0]), y = str(v2[1]), z = str(v2[2])) - xml_vertex3 = ET.SubElement(vertices, "vertex", x = str(v3[0]), y = str(v3[1]), z = str(v3[2])) - - triangles = ET.SubElement(mesh, "triangles") - for face in mesh_data.getIndices(): - triangle = ET.SubElement(triangles, "triangle", v1 = str(face[0]) , v2 = str(face[1]), v3 = str(face[2])) - else: - triangles = ET.SubElement(mesh, "triangles") - for idx, vert in enumerate(verts): - xml_vertex = ET.SubElement(vertices, "vertex", x = str(vert[0]), y = str(vert[1]), z = str(vert[2])) - - # If we have no faces defined, assume that every three subsequent vertices form a face. - if idx % 3 == 0: - triangle = ET.SubElement(triangles, "triangle", v1 = str(idx), v2 = str(idx + 1), v3 = str(idx + 2)) - - # Handle per object settings - stack = n.callDecoration("getStack") - if stack is not None: - changed_setting_keys = set(stack.getTop().getAllKeys()) - - # Ensure that we save the extruder used for this object. - if stack.getProperty("machine_extruder_count", "value") > 1: - changed_setting_keys.add("extruder_nr") - - settings_xml = ET.SubElement(object, "settings", xmlns=self._namespaces["cura"]) - - # Get values for all changed settings & save them. - for key in changed_setting_keys: - setting_xml = ET.SubElement(settings_xml, "setting", key = key) - setting_xml.text = str(stack.getProperty(key, "value")) - - # Add one to the index as we haven't incremented the last iteration. - index += 1 - nodes_to_add = set() - - for node in added_nodes: - # Check the parents of the nodes with mesh_data and ensure that they are also added. - parent_node = node.getParent() - while parent_node is not None: - if parent_node.callDecoration("isGroup"): - nodes_to_add.add(parent_node) - parent_node = parent_node.getParent() - else: - parent_node = None - - # Sort all the nodes by depth (so nodes with the highest depth are done first) - sorted_nodes_to_add = sorted(nodes_to_add, key=lambda node: node.getDepth(), reverse = True) - - # We have already saved the nodes with mesh data, but now we also want to save nodes required for the scene - for node in sorted_nodes_to_add: - object = ET.SubElement(resources, "object", id=str(index + 1), type="model") - components = ET.SubElement(object, "components") - for child in node.getChildren(): - if child in added_nodes: - component = ET.SubElement(components, "component", objectid = str(added_nodes.index(child) + 1), transform = self._convertMatrixToString(child.getLocalTransformation())) - index += 1 - added_nodes.append(node) - - # Create a transformation Matrix to convert from our worldspace into 3MF. - # First step: flip the y and z axis. + savitar_scene = Savitar.Scene() transformation_matrix = Matrix() transformation_matrix._data[1, 1] = 0 transformation_matrix._data[1, 2] = -1 @@ -186,14 +142,23 @@ class ThreeMFWriter(MeshWriter): translation_matrix.setByTranslation(translation_vector) transformation_matrix.preMultiply(translation_matrix) - # Find out what the final build items are and add them. - for node in added_nodes: - if node.getParent().callDecoration("isGroup") is None: - node_matrix = node.getLocalTransformation() - ET.SubElement(build, "item", objectid = str(added_nodes.index(node) + 1), transform = self._convertMatrixToString(node_matrix.preMultiply(transformation_matrix))) + root_node = UM.Application.getInstance().getController().getScene().getRoot() + for node in nodes: + if node == root_node: + for root_child in node.getChildren(): + savitar_node = self._convertUMNodeToSavitarNode(root_child, transformation_matrix) + if savitar_node: + savitar_scene.addSceneNode(savitar_node) + else: + savitar_node = self._convertUMNodeToSavitarNode(node, transformation_matrix) + if savitar_node: + savitar_scene.addSceneNode(savitar_node) - archive.writestr(model_file, b' \n' + ET.tostring(model)) + parser = Savitar.ThreeMFParser() + scene_string = parser.sceneToString(savitar_scene).encode('utf-8') + + archive.writestr(model_file, scene_string) archive.writestr(content_types_file, b' \n' + ET.tostring(content_types)) archive.writestr(relations_file, b' \n' + ET.tostring(relations_element)) except Exception as e: From 3d01d7bc548476003351ee6aa50c43862aceaa54 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 6 Feb 2017 14:26:02 +0100 Subject: [PATCH 17/37] Removed unneeded bytearray to string conversion --- plugins/3MFWriter/ThreeMFWriter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index f7ea04ed0d..00bb8d9942 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -156,7 +156,7 @@ class ThreeMFWriter(MeshWriter): savitar_scene.addSceneNode(savitar_node) parser = Savitar.ThreeMFParser() - scene_string = parser.sceneToString(savitar_scene).encode('utf-8') + scene_string = parser.sceneToString(savitar_scene) archive.writestr(model_file, scene_string) archive.writestr(content_types_file, b' \n' + ET.tostring(content_types)) From 7681261b03f29e95e2b7055d05fc2b20e5041c4a Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Tue, 7 Feb 2017 09:55:15 +0000 Subject: [PATCH 18/37] Added anchor_skin_shrink_distance. Also, renamed anchor_skin_distance to anchor_skin_expand_distance. The idea behind the shrink distance is that when the slope of the model surface is steep, very slim skin areas are created close to the wall and if they are expanded we end up with skin inside the infill that isn't required. So by shrinking the skin polygons slightly first, the very slim areas are removed before the skin is expanded. The amount to shrink defaults to half the wall width which appears to work OK but may as well make it a setting so that it can be tweaked if required. --- resources/definitions/fdmprinter.def.json | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index bbb9d14e8d..a45a80b544 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1270,9 +1270,9 @@ "enabled": "anchor_skins_in_infill", "settable_per_mesh": true }, - "anchor_skin_distance": + "anchor_skin_expand_distance": { - "label": "Anchor Skin Distance", + "label": "Anchor Skin Expand Distance", "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", "unit": "mm", "type": "float", @@ -1281,6 +1281,18 @@ "minimum_value": "0", "enabled": "anchor_skins_in_infill", "settable_per_mesh": true + }, + "anchor_skin_shrink_distance": + { + "label": "Anchor Skin Shrink Distance", + "description": "The distance the skins are shrunk before they are expanded. Shrinking the skins slightly first removes the very narrow skin areas that are created when the model surface has a slope close to the vertical.", + "unit": "mm", + "type": "float", + "default_value": 0, + "value": "wall_thickness * 0.5", + "minimum_value": "0", + "enabled": "anchor_skins_in_infill", + "settable_per_mesh": true } } } From 3e8789ae48247bb45a17d103059b656ac98a818e Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Thu, 9 Feb 2017 11:35:54 +0000 Subject: [PATCH 19/37] Renamed anchor_skin settings to equivalent expand_skins settings. Expand skins describes the operation better, the fact that the skins end up getting anchored in the infill is just one benefit of the expansion. --- resources/definitions/fdmprinter.def.json | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index a45a80b544..ce9cd7a0c5 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1241,57 +1241,57 @@ "default_value": 0, "settable_per_mesh": true }, - "anchor_skins_in_infill": + "expand_skins_into_infill": { - "label": "Anchor Skins In Infill", + "label": "Expand Skins Into Infill", "description": "Expand skin areas into the infill behind walls. By default, skins stop under the wall lines that surround infill but this can lead to holes appearing when the infill density is low. This setting extends the skins beyond the wall lines so that the skins become anchored in the infill.", "type": "bool", "default_value": false, "settable_per_mesh": true, "children": { - "anchor_upper_skin_in_infill": + "expand_upper_skins": { - "label": "Anchor Upper Skin In Infill", + "label": "Expand Upper Skins", "description": "Expand upper skin areas (areas with air above) so that they are anchored by the infill layers above and below.", "type": "bool", "default_value": false, - "value": "anchor_skins_in_infill", - "enabled": "anchor_skins_in_infill", + "value": "expand_skins_into_infill", + "enabled": "expand_skins_into_infill", "settable_per_mesh": true }, - "anchor_lower_skin_in_infill": + "expand_lower_skins": { - "label": "Anchor Lower Skin In Infill", + "label": "Expand Lower Skins", "description": "Expand lower skin areas (areas with air below) so that they are anchored by the infill layers above and below.", "type": "bool", "default_value": false, - "value": "anchor_skins_in_infill", - "enabled": "anchor_skins_in_infill", + "value": "expand_skins_into_infill", + "enabled": "expand_skins_into_infill", "settable_per_mesh": true }, - "anchor_skin_expand_distance": + "expand_skins_expand_distance": { - "label": "Anchor Skin Expand Distance", + "label": "Expand Distance", "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", "unit": "mm", "type": "float", "default_value": 1.0, "value": "infill_line_distance * 1.4", "minimum_value": "0", - "enabled": "anchor_skins_in_infill", + "enabled": "expand_skins_into_infill", "settable_per_mesh": true }, - "anchor_skin_shrink_distance": + "expand_skins_shrink_distance": { - "label": "Anchor Skin Shrink Distance", + "label": "Shrink Distance", "description": "The distance the skins are shrunk before they are expanded. Shrinking the skins slightly first removes the very narrow skin areas that are created when the model surface has a slope close to the vertical.", "unit": "mm", "type": "float", "default_value": 0, "value": "wall_thickness * 0.5", "minimum_value": "0", - "enabled": "anchor_skins_in_infill", + "enabled": "expand_skins_into_infill", "settable_per_mesh": true } } From c1a770877fe3d834f4370ad6b0d18784aa54ae98 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Sun, 12 Feb 2017 17:48:11 +0000 Subject: [PATCH 20/37] Add "Skin " prefix to "Expand Distance" and "Shrink Distance" labels. It's useful to know what is being expanded/shrunk when those labels are cited (for example if you are switching profiles without saving changes). --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index ce9cd7a0c5..9fe25d7066 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1272,7 +1272,7 @@ }, "expand_skins_expand_distance": { - "label": "Expand Distance", + "label": "Skin Expand Distance", "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", "unit": "mm", "type": "float", @@ -1284,7 +1284,7 @@ }, "expand_skins_shrink_distance": { - "label": "Shrink Distance", + "label": "Skin Shrink Distance", "description": "The distance the skins are shrunk before they are expanded. Shrinking the skins slightly first removes the very narrow skin areas that are created when the model surface has a slope close to the vertical.", "unit": "mm", "type": "float", From 58e15848ebf3bf356c4b042eec2dc6c0ce60357e Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Mon, 20 Feb 2017 13:44:55 +0100 Subject: [PATCH 21/37] feat: machine_nozzle_temp_enabled; refactor: let settings depend on it (rather than on gcode flavor) (CURA-3101) --- resources/definitions/fdmprinter.def.json | 38 ++++++++++++++++------- resources/definitions/ultimaker2.def.json | 3 ++ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 68f8040df9..100bbcfa07 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -93,6 +93,7 @@ "description": "Whether to wait until the nozzle temperature is reached at the start.", "default_value": true, "type": "bool", + "enabled": "machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": false, "settable_per_meshgroup": false @@ -103,6 +104,7 @@ "description": "Whether to include nozzle temperature commands at the start of the gcode. When the start_gcode already contains nozzle temperature commands Cura frontend will automatically disable this setting.", "default_value": true, "type": "bool", + "enabled": "machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": false, "settable_per_meshgroup": false @@ -249,6 +251,17 @@ "settable_per_extruder": true, "settable_per_meshgroup": false }, + "machine_nozzle_temp_enabled": + { + "label": "Enable Nozzle Temperature Control", + "description": "Whether to control temperature from Cura. Turn this off to control nozzle temperature from outside of Cura.", + "default_value": true, + "value": "machine_gcode_flavor != \"UltiGCode\"", + "type": "bool", + "settable_per_mesh": false, + "settable_per_extruder": true, + "settable_per_meshgroup": false + }, "machine_nozzle_heat_up_speed": { "label": "Heat up speed", @@ -256,6 +269,7 @@ "default_value": 2.0, "unit": "°C/s", "type": "float", + "enabled": "machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -266,6 +280,7 @@ "default_value": 2.0, "unit": "°C/s", "type": "float", + "enabled": "machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -276,6 +291,7 @@ "default_value": 50.0, "unit": "s", "type": "float", + "enabled": "machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1260,7 +1276,7 @@ "description": "Change the temperature for each layer automatically with the average flow speed of that layer.", "type": "bool", "default_value": false, - "enabled": "False", + "enabled": "machine_nozzle_temp_enabled and False", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1271,14 +1287,14 @@ "unit": "°C", "type": "float", "default_value": 210, - "enabled": false, + "enabled": "machine_nozzle_temp_enabled", "settable_per_extruder": true, "minimum_value": "-273.15" }, "material_print_temperature": { "label": "Printing Temperature", - "description": "The temperature used for printing. If this is 0, the extruder will not heat up for this print.", + "description": "The temperature used for printing.", "unit": "°C", "type": "float", "default_value": 210, @@ -1286,7 +1302,7 @@ "minimum_value": "-273.15", "minimum_value_warning": "0", "maximum_value_warning": "260", - "enabled": "not (material_flow_dependent_temperature) and machine_gcode_flavor != \"UltiGCode\"", + "enabled": "machine_nozzle_temp_enabled and not (material_flow_dependent_temperature)", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1301,7 +1317,7 @@ "minimum_value": "-273.15", "minimum_value_warning": "0", "maximum_value_warning": "260", - "enabled": "machine_gcode_flavor != \"UltiGCode\"", + "enabled": "machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1316,7 +1332,7 @@ "minimum_value": "-273.15", "minimum_value_warning": "material_standby_temperature", "maximum_value_warning": "material_print_temperature", - "enabled": "machine_gcode_flavor != \"UltiGCode\"", + "enabled": "machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1331,7 +1347,7 @@ "minimum_value": "-273.15", "minimum_value_warning": "material_standby_temperature", "maximum_value_warning": "material_print_temperature", - "enabled": "machine_gcode_flavor != \"UltiGCode\"", + "enabled": "machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1342,8 +1358,7 @@ "unit": "[[mm³,°C]]", "type": "str", "default_value": "[[3.5,200],[7.0,240]]", - "enabled": "False", - "comments": "old enabled function: material_flow_dependent_temperature", + "enabled": "False and machine_nozzle_temp_enabled and material_flow_dependent_temperature", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1357,8 +1372,7 @@ "minimum_value": "0", "maximum_value_warning": "10.0", "maximum_value": "machine_nozzle_heat_up_speed", - "enabled": "False", - "comments": "old enabled function: material_flow_dependent_temperature or machine_extruder_count > 1", + "enabled": "material_flow_dependent_temperature or (machine_extruder_count > 1 and material_final_print_temperature != material_print_temperature)", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1565,7 +1579,7 @@ "minimum_value": "-273.15", "minimum_value_warning": "0", "maximum_value_warning": "260", - "enabled": "machine_extruder_count > 1 and machine_gcode_flavor != \"UltiGCode\"", + "enabled": "machine_extruder_count > 1 and machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": true }, diff --git a/resources/definitions/ultimaker2.def.json b/resources/definitions/ultimaker2.def.json index 84e09113f3..a52075fe5e 100644 --- a/resources/definitions/ultimaker2.def.json +++ b/resources/definitions/ultimaker2.def.json @@ -100,6 +100,9 @@ }, "machine_acceleration": { "default_value": 3000 + }, + "machine_nozzle_temp_enabled": { + "default_value": false } } } From c0fc8287c023e733b1a02e6c5ccb11c2480eccbc Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Wed, 1 Mar 2017 14:47:56 +0000 Subject: [PATCH 22/37] Rename expand_skins_shrink_distance setting to min_skin_width_for_expansion. --- resources/definitions/fdmprinter.def.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 6bab81ae84..9b89f07bff 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1285,10 +1285,10 @@ "enabled": "expand_skins_into_infill", "settable_per_mesh": true }, - "expand_skins_shrink_distance": + "min_skin_width_for_expansion": { - "label": "Skin Shrink Distance", - "description": "The distance the skins are shrunk before they are expanded. Shrinking the skins slightly first removes the very narrow skin areas that are created when the model surface has a slope close to the vertical.", + "label": "Minimum Skin Width For Expansion", + "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", "unit": "mm", "type": "float", "default_value": 0, From d6bed392e4d3f6acc408f64cf75a3f90e4086e11 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Thu, 2 Mar 2017 07:46:55 +0000 Subject: [PATCH 23/37] Disable skin_angles setting when top_bottom_pattern is concentric. --- resources/definitions/fdmprinter.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index a802ea1ca6..133c0b0dfb 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -914,6 +914,7 @@ "description": "A list of integer line directions to use when the top/bottom layers use the lines or zig zag pattern. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees).", "type": "[int]", "default_value": "[ ]", + "enabled": "top_bottom_pattern != 'concentric'", "settable_per_mesh": true }, "wall_0_inset": From aef39991a2e78c4f05731be0eb618349593a1871 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Thu, 2 Mar 2017 07:47:41 +0000 Subject: [PATCH 24/37] Disable infill_angles setting when infill_pattern is concentric, concentric_3d or cubicsubdiv. --- resources/definitions/fdmprinter.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 133c0b0dfb..a79ac58547 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1104,6 +1104,7 @@ "description": "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees for the lines and zig zag patterns and 45 degrees for all other patterns).", "type": "[int]", "default_value": "[ ]", + "enabled": "infill_pattern != 'concentric' and infill_pattern != 'concentric_3d' and infill_pattern != 'cubicsubdiv'", "settable_per_mesh": true }, "sub_div_rad_mult": From 3a92bf73a8c4080626e5dd2bae45e107b9e04c4a Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 3 Mar 2017 12:37:06 +0100 Subject: [PATCH 25/37] JSON fix: moved expand_skins_expand_distance and min_skin_width_for_expansion out of illegitimate parent (CURA-3440) --- resources/definitions/fdmprinter.def.json | 48 +++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index d1ef90ab6a..c0f4536eb0 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1272,32 +1272,32 @@ "value": "expand_skins_into_infill", "enabled": "expand_skins_into_infill", "settable_per_mesh": true - }, - "expand_skins_expand_distance": - { - "label": "Skin Expand Distance", - "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", - "unit": "mm", - "type": "float", - "default_value": 1.0, - "value": "infill_line_distance * 1.4", - "minimum_value": "0", - "enabled": "expand_skins_into_infill", - "settable_per_mesh": true - }, - "min_skin_width_for_expansion": - { - "label": "Minimum Skin Width For Expansion", - "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", - "unit": "mm", - "type": "float", - "default_value": 0, - "value": "wall_thickness * 0.5", - "minimum_value": "0", - "enabled": "expand_skins_into_infill", - "settable_per_mesh": true } } + }, + "expand_skins_expand_distance": + { + "label": "Skin Expand Distance", + "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", + "unit": "mm", + "type": "float", + "default_value": 1.0, + "value": "infill_line_distance * 1.4", + "minimum_value": "0", + "enabled": "expand_skins_into_infill", + "settable_per_mesh": true + }, + "min_skin_width_for_expansion": + { + "label": "Minimum Skin Width For Expansion", + "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", + "unit": "mm", + "type": "float", + "default_value": 0, + "value": "wall_thickness * 0.5", + "minimum_value": "0", + "enabled": "expand_skins_into_infill", + "settable_per_mesh": true } } }, From 5550dbf53f605afa8ae8cc69a8ff6e017a5e5f13 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 3 Mar 2017 12:41:14 +0100 Subject: [PATCH 26/37] JSON fix: don't expand bottom skins by default (CURA-3440) --- resources/definitions/fdmprinter.def.json | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index c0f4536eb0..cadbc55f38 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1269,7 +1269,6 @@ "description": "Expand lower skin areas (areas with air below) so that they are anchored by the infill layers above and below.", "type": "bool", "default_value": false, - "value": "expand_skins_into_infill", "enabled": "expand_skins_into_infill", "settable_per_mesh": true } From a7e08f10a40ddd21779f68d942e3424e37a4a0ec Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 3 Mar 2017 12:41:54 +0100 Subject: [PATCH 27/37] JSON fix: only enable skin expansion settings when we have it enabled (CURA-3440) --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index cadbc55f38..0fd49ee446 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1283,7 +1283,7 @@ "default_value": 1.0, "value": "infill_line_distance * 1.4", "minimum_value": "0", - "enabled": "expand_skins_into_infill", + "enabled": "expand_upper_skins or expand_lower_skins", "settable_per_mesh": true }, "min_skin_width_for_expansion": @@ -1295,7 +1295,7 @@ "default_value": 0, "value": "wall_thickness * 0.5", "minimum_value": "0", - "enabled": "expand_skins_into_infill", + "enabled": "expand_upper_skins or expand_lower_skins", "settable_per_mesh": true } } From 4878a50b6164c4f7d4e8fb4d6a8f9aa074138657 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 3 Mar 2017 14:50:46 +0100 Subject: [PATCH 28/37] JSON refactor: skin expansion descriptions, defaults and new min_skin_angle_for_expansion settings (CURA-3440) --- resources/definitions/fdmprinter.def.json | 38 ++++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 0fd49ee446..1d4b549059 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1247,7 +1247,7 @@ "expand_skins_into_infill": { "label": "Expand Skins Into Infill", - "description": "Expand skin areas into the infill behind walls. By default, skins stop under the wall lines that surround infill but this can lead to holes appearing when the infill density is low. This setting extends the skins beyond the wall lines so that the skins become anchored in the infill.", + "description": "Expand skin areas of top and/or bottom skin of flat surfaces. By default, skins stop under the wall lines that surround infill but this can lead to holes appearing when the infill density is low. This setting extends the skins beyond the wall lines so that the infill on the next layer rests on skin.", "type": "bool", "default_value": false, "settable_per_mesh": true, @@ -1256,11 +1256,10 @@ "expand_upper_skins": { "label": "Expand Upper Skins", - "description": "Expand upper skin areas (areas with air above) so that they are anchored by the infill layers above and below.", + "description": "Expand upper skin areas (areas with air above) so that they support infill above.", "type": "bool", "default_value": false, "value": "expand_skins_into_infill", - "enabled": "expand_skins_into_infill", "settable_per_mesh": true }, "expand_lower_skins": @@ -1269,7 +1268,6 @@ "description": "Expand lower skin areas (areas with air below) so that they are anchored by the infill layers above and below.", "type": "bool", "default_value": false, - "enabled": "expand_skins_into_infill", "settable_per_mesh": true } } @@ -1280,23 +1278,39 @@ "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", "unit": "mm", "type": "float", - "default_value": 1.0, + "default_value": 2.8, "value": "infill_line_distance * 1.4", "minimum_value": "0", "enabled": "expand_upper_skins or expand_lower_skins", "settable_per_mesh": true }, - "min_skin_width_for_expansion": + "min_skin_angle_for_expansion": { - "label": "Minimum Skin Width For Expansion", - "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", - "unit": "mm", + "label": "Minimum Skin Angle for Expansion", + "description": "Top and or bottom surfaces of your object with an angle larger than this setting, won't have their top/bottom skin expanded. This avoids expanding the narrow skin areas that are created when the model surface has a near vertical slope.", + "unit": "°", "type": "float", - "default_value": 0, - "value": "wall_thickness * 0.5", "minimum_value": "0", + "maximum_value": "90", + "maximum_value_warning": "45", + "default_value": 20, "enabled": "expand_upper_skins or expand_lower_skins", - "settable_per_mesh": true + "settable_per_mesh": true, + "children": + { + "min_skin_width_for_expansion": + { + "label": "Minimum Skin Width for Expansion", + "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", + "unit": "mm", + "type": "float", + "default_value": 2.24, + "value": "top_layers * layer_height / math.tan(math.radians(min_skin_angle_for_expansion))", + "minimum_value": "0", + "enabled": "expand_upper_skins or expand_lower_skins", + "settable_per_mesh": true + } + } } } }, From 54c1c995eddb70aeaad2093a4bfb5d7ec352ea93 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 3 Mar 2017 12:37:06 +0100 Subject: [PATCH 29/37] JSON fix: moved expand_skins_expand_distance and min_skin_width_for_expansion out of illegitimate parent (CURA-3440) --- resources/definitions/fdmprinter.def.json | 48 +++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 9b89f07bff..bd7ecfd672 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1272,32 +1272,32 @@ "value": "expand_skins_into_infill", "enabled": "expand_skins_into_infill", "settable_per_mesh": true - }, - "expand_skins_expand_distance": - { - "label": "Skin Expand Distance", - "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", - "unit": "mm", - "type": "float", - "default_value": 1.0, - "value": "infill_line_distance * 1.4", - "minimum_value": "0", - "enabled": "expand_skins_into_infill", - "settable_per_mesh": true - }, - "min_skin_width_for_expansion": - { - "label": "Minimum Skin Width For Expansion", - "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", - "unit": "mm", - "type": "float", - "default_value": 0, - "value": "wall_thickness * 0.5", - "minimum_value": "0", - "enabled": "expand_skins_into_infill", - "settable_per_mesh": true } } + }, + "expand_skins_expand_distance": + { + "label": "Skin Expand Distance", + "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", + "unit": "mm", + "type": "float", + "default_value": 1.0, + "value": "infill_line_distance * 1.4", + "minimum_value": "0", + "enabled": "expand_skins_into_infill", + "settable_per_mesh": true + }, + "min_skin_width_for_expansion": + { + "label": "Minimum Skin Width For Expansion", + "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", + "unit": "mm", + "type": "float", + "default_value": 0, + "value": "wall_thickness * 0.5", + "minimum_value": "0", + "enabled": "expand_skins_into_infill", + "settable_per_mesh": true } } }, From 016a25ce35c0851cd2bd5727f4d5c642c6f34874 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 3 Mar 2017 12:41:14 +0100 Subject: [PATCH 30/37] JSON fix: don't expand bottom skins by default (CURA-3440) --- resources/definitions/fdmprinter.def.json | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index bd7ecfd672..8a5424a7a7 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1269,7 +1269,6 @@ "description": "Expand lower skin areas (areas with air below) so that they are anchored by the infill layers above and below.", "type": "bool", "default_value": false, - "value": "expand_skins_into_infill", "enabled": "expand_skins_into_infill", "settable_per_mesh": true } From e5090f70aad39f237864160ed0b740fe356d158c Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 3 Mar 2017 12:41:54 +0100 Subject: [PATCH 31/37] JSON fix: only enable skin expansion settings when we have it enabled (CURA-3440) --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8a5424a7a7..cc5d147b98 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1283,7 +1283,7 @@ "default_value": 1.0, "value": "infill_line_distance * 1.4", "minimum_value": "0", - "enabled": "expand_skins_into_infill", + "enabled": "expand_upper_skins or expand_lower_skins", "settable_per_mesh": true }, "min_skin_width_for_expansion": @@ -1295,7 +1295,7 @@ "default_value": 0, "value": "wall_thickness * 0.5", "minimum_value": "0", - "enabled": "expand_skins_into_infill", + "enabled": "expand_upper_skins or expand_lower_skins", "settable_per_mesh": true } } From 396198797e8a0120d69dbd43c99a5063d819d743 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 3 Mar 2017 14:50:46 +0100 Subject: [PATCH 32/37] JSON refactor: skin expansion descriptions, defaults and new min_skin_angle_for_expansion settings (CURA-3440) --- resources/definitions/fdmprinter.def.json | 38 ++++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index cc5d147b98..870f5ba7ff 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1247,7 +1247,7 @@ "expand_skins_into_infill": { "label": "Expand Skins Into Infill", - "description": "Expand skin areas into the infill behind walls. By default, skins stop under the wall lines that surround infill but this can lead to holes appearing when the infill density is low. This setting extends the skins beyond the wall lines so that the skins become anchored in the infill.", + "description": "Expand skin areas of top and/or bottom skin of flat surfaces. By default, skins stop under the wall lines that surround infill but this can lead to holes appearing when the infill density is low. This setting extends the skins beyond the wall lines so that the infill on the next layer rests on skin.", "type": "bool", "default_value": false, "settable_per_mesh": true, @@ -1256,11 +1256,10 @@ "expand_upper_skins": { "label": "Expand Upper Skins", - "description": "Expand upper skin areas (areas with air above) so that they are anchored by the infill layers above and below.", + "description": "Expand upper skin areas (areas with air above) so that they support infill above.", "type": "bool", "default_value": false, "value": "expand_skins_into_infill", - "enabled": "expand_skins_into_infill", "settable_per_mesh": true }, "expand_lower_skins": @@ -1269,7 +1268,6 @@ "description": "Expand lower skin areas (areas with air below) so that they are anchored by the infill layers above and below.", "type": "bool", "default_value": false, - "enabled": "expand_skins_into_infill", "settable_per_mesh": true } } @@ -1280,23 +1278,39 @@ "description": "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient.", "unit": "mm", "type": "float", - "default_value": 1.0, + "default_value": 2.8, "value": "infill_line_distance * 1.4", "minimum_value": "0", "enabled": "expand_upper_skins or expand_lower_skins", "settable_per_mesh": true }, - "min_skin_width_for_expansion": + "min_skin_angle_for_expansion": { - "label": "Minimum Skin Width For Expansion", - "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", - "unit": "mm", + "label": "Minimum Skin Angle for Expansion", + "description": "Top and or bottom surfaces of your object with an angle larger than this setting, won't have their top/bottom skin expanded. This avoids expanding the narrow skin areas that are created when the model surface has a near vertical slope.", + "unit": "°", "type": "float", - "default_value": 0, - "value": "wall_thickness * 0.5", "minimum_value": "0", + "maximum_value": "90", + "maximum_value_warning": "45", + "default_value": 20, "enabled": "expand_upper_skins or expand_lower_skins", - "settable_per_mesh": true + "settable_per_mesh": true, + "children": + { + "min_skin_width_for_expansion": + { + "label": "Minimum Skin Width for Expansion", + "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", + "unit": "mm", + "type": "float", + "default_value": 2.24, + "value": "top_layers * layer_height / math.tan(math.radians(min_skin_angle_for_expansion))", + "minimum_value": "0", + "enabled": "expand_upper_skins or expand_lower_skins", + "settable_per_mesh": true + } + } } } }, From c9254a3095ad4fc7654cf8dc3a628912c7186668 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 6 Mar 2017 12:15:58 +0100 Subject: [PATCH 33/37] CURA-3397 Enable/disable "keep" and "discard" buttons according to the choice --- .../qml/DiscardOrKeepProfileChangesDialog.qml | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/resources/qml/DiscardOrKeepProfileChangesDialog.qml b/resources/qml/DiscardOrKeepProfileChangesDialog.qml index 4c88801bb0..ed720adafa 100644 --- a/resources/qml/DiscardOrKeepProfileChangesDialog.qml +++ b/resources/qml/DiscardOrKeepProfileChangesDialog.qml @@ -146,7 +146,25 @@ UM.Dialog ] width: 300 currentIndex: UM.Preferences.getValue("cura/choice_on_profile_override") - onCurrentIndexChanged: UM.Preferences.setValue("cura/choice_on_profile_override", currentIndex) + onCurrentIndexChanged: + { + UM.Preferences.setValue("cura/choice_on_profile_override", currentIndex) + if (currentIndex == 1) { + // 1 == "Discard and never ask again", so only enable the "Discard" button + discardButton.enabled = true + keepButton.enabled = false + } + else if (currentIndex == 2) { + // 2 == "Keep and never ask again", so only enable the "Keep" button + keepButton.enabled = true + discardButton.enabled = false + } + else { + // 0 == "Always ask me this", so show both + keepButton.enabled = true + discardButton.enabled = true + } + } } } From 1c15d24e5bc1d650c27467a8852e3012741f6994 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 6 Mar 2017 12:37:29 +0100 Subject: [PATCH 34/37] CURA-3397 Reduce tableView height to show buttons --- resources/qml/DiscardOrKeepProfileChangesDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/DiscardOrKeepProfileChangesDialog.qml b/resources/qml/DiscardOrKeepProfileChangesDialog.qml index ed720adafa..26c343ad5c 100644 --- a/resources/qml/DiscardOrKeepProfileChangesDialog.qml +++ b/resources/qml/DiscardOrKeepProfileChangesDialog.qml @@ -64,7 +64,7 @@ UM.Dialog anchors.margins: UM.Theme.getSize("default_margin").width anchors.left: parent.left anchors.right: parent.right - height: base.height - 130 + height: base.height - 200 id: tableView Component { From 356d4f9288b85622d99657bd89f1bd93c6f56350 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 6 Mar 2017 14:41:33 +0100 Subject: [PATCH 35/37] Heated bed timeout time now hides correctly if time ran out CURA-3360 --- cura/PrinterOutputDevice.py | 8 ++++++-- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 7f0b7c4c07..f411190fd5 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -47,8 +47,8 @@ class PrinterOutputDevice(QObject, OutputDevice): self._job_name = "" self._error_text = "" self._accepts_commands = True - self._preheat_bed_timeout = 900 #Default time-out for pre-heating the bed, in seconds. - self._preheat_bed_timer = QTimer() #Timer that tracks how long to preheat still. + self._preheat_bed_timeout = 900 # Default time-out for pre-heating the bed, in seconds. + self._preheat_bed_timer = QTimer() # Timer that tracks how long to preheat still. self._preheat_bed_timer.setSingleShot(True) self._preheat_bed_timer.timeout.connect(self.cancelPreheatBed) @@ -232,11 +232,15 @@ class PrinterOutputDevice(QObject, OutputDevice): # \return The duration of the time-out to pre-heat the bed, formatted. @pyqtProperty(str, notify = preheatBedRemainingTimeChanged) def preheatBedRemainingTime(self): + if not self._preheat_bed_timer.isActive(): + return "" period = self._preheat_bed_timer.remainingTime() if period <= 0: return "" minutes, period = divmod(period, 60000) #60000 milliseconds in a minute. seconds, _ = divmod(period, 1000) #1000 milliseconds in a second. + if minutes <= 0 and seconds <= 0: + return "" return "%d:%02d" % (minutes, seconds) ## Time the print has been printing. diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index a7223128b4..ea8917ed9f 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -558,7 +558,6 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): self._preheat_bed_timer.stop() self.preheatBedRemainingTimeChanged.emit() - def close(self): Logger.log("d", "Closing connection of printer %s with ip %s", self._key, self._address) self._updateJobState("") From 38a9df9d76a83e966110bfa1bf20302c8863715f Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Mon, 6 Mar 2017 14:42:11 +0100 Subject: [PATCH 36/37] fix: more lenient int-list validator parsing (CURA-3275) allow for empty integers allow the brackets to be omitted --- resources/qml/Settings/SettingTextField.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index 05c99d7e25..ce376e1c77 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -100,7 +100,7 @@ SettingItem maximumLength: (definition.type == "[int]") ? 20 : 10; - validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[(\s*-?[0-9]+\s*,)*(\s*-?[0-9]+)\s*\]$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ } // definition.type property from parent loader used to disallow fractional number entry + validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[?(\s*-?[0-9]{0,9}\s*,)*(\s*-?[0-9]{0,9})\s*\]?$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ } // definition.type property from parent loader used to disallow fractional number entry Binding { From 8a77dd66fc1408dc5c7929fa0b5a2e3f64b73759 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Mon, 6 Mar 2017 17:24:53 +0100 Subject: [PATCH 37/37] Properly handle CMake options that are enabled but not "ON" Contributes to CURA-2787 --- CMakeLists.txt | 3 +++ cura/CuraVersion.py.in | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab08a4d624..8105b677ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,9 @@ add_custom_target(tests) add_custom_command(TARGET tests POST_BUILD COMMAND "PYTHONPATH=${CMAKE_SOURCE_DIR}/../Uranium/:${CMAKE_SOURCE_DIR}" ${PYTHON_EXECUTABLE} -m pytest -r a --junitxml=${CMAKE_BINARY_DIR}/junit.xml ${CMAKE_SOURCE_DIR} || exit 0) option(CURA_DEBUGMODE "Enable debug dialog and other debug features" OFF) +if(CURA_DEBUGMODE) + set(_cura_debugmode "ON") +endif() set(CURA_VERSION "master" CACHE STRING "Version name of Cura") set(CURA_BUILDTYPE "" CACHE STRING "Build type of Cura, eg. 'PPA'") diff --git a/cura/CuraVersion.py.in b/cura/CuraVersion.py.in index 8a4d13e526..fb66275395 100644 --- a/cura/CuraVersion.py.in +++ b/cura/CuraVersion.py.in @@ -3,4 +3,4 @@ CuraVersion = "@CURA_VERSION@" CuraBuildType = "@CURA_BUILDTYPE@" -CuraDebugMode = True if "@CURA_DEBUGMODE@" == "ON" else False +CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False