From 5da6d7016389a2948011b916a94d7c141e4e2d04 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 29 Aug 2016 15:28:09 +0200 Subject: [PATCH 01/31] Fixed duplicate material. CURA-1969 --- .../XmlMaterialProfile/XmlMaterialProfile.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 77f775ee27..0dd41c2e79 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -52,9 +52,9 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): def setReadOnly(self, read_only): super().setReadOnly(read_only) - basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. + basefile = self.getMetaDataEntry("base_file", self._id) # if basefile is self.id, this is a basefile. for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): - container._read_only = read_only + container._read_only = read_only # prevent loop instead of calling setReadOnly ## Overridden from InstanceContainer def setMetaDataEntry(self, key, value): @@ -63,7 +63,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): super().setMetaDataEntry(key, value) - basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. + basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is self.id, this is a basefile. # Update all containers that share GUID and basefile for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): container.setMetaData(copy.deepcopy(self._metadata)) @@ -89,15 +89,15 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): container.setName(new_name) ## Overridden from InstanceContainer - def setProperty(self, key, property_name, property_value, container = None): - if self.isReadOnly(): - return - - super().setProperty(key, property_name, property_value) - - basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. - for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): - container._dirty = True + # def setProperty(self, key, property_name, property_value, container = None): + # if self.isReadOnly(): + # return + # + # super().setProperty(key, property_name, property_value) + # + # basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is self.id, this is a basefile. + # for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): + # container._dirty = True ## Overridden from InstanceContainer def serialize(self): From 2db8e5c16653d149101c41cff865b05e919a5ad5 Mon Sep 17 00:00:00 2001 From: jack Date: Wed, 31 Aug 2016 12:53:46 +0200 Subject: [PATCH 02/31] Changelog: typo --- plugins/ChangeLogPlugin/ChangeLog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ChangeLogPlugin/ChangeLog.txt b/plugins/ChangeLogPlugin/ChangeLog.txt index 08e89dca33..ad09470ccd 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.txt +++ b/plugins/ChangeLogPlugin/ChangeLog.txt @@ -1,7 +1,7 @@ [2.3.0] *Speed improvements -The first thing you will notice iss the speed. STL loading is now 10 to 20 times faster, layer time is significantly faster and slicing speed is slightly improved. +The first thing you will notice is the speed. STL loading is now 10 to 20 times faster, layer time is significantly faster and slicing speed is slightly improved. *Multi Extrusion Support Machines with multiple extruders are now supported. If you’ve got the Ultimaker Original with the dual extrusion upgrade kit, we’ve got you covered. From ad22cf486137265a068124239ded641192922fe0 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 31 Aug 2016 17:18:33 +0200 Subject: [PATCH 03/31] XML material profile merging is now far less naive. It's still a work in progress, as it doesn't succeed in all cases just yet. CURA-2108 --- .../XmlMaterialProfile/XmlMaterialProfile.py | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 9b670a7e8d..15f022d539 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -277,24 +277,50 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): self._combineElement(result, second) return result + def _createKey(self, element): + key = element.tag.split("}")[-1] + if "key" in element.attrib: + key += " key:" + element.attrib["key"] + if "manufacturer" in element.attrib: + key += " manufacturer:" + element.attrib["manufacturer"] + if "product" in element.attrib: + key += " product:" + element.attrib["product"] + if key == "machine": + for item in element: + if "machine_identifier" in item.tag: + key += " " + item.attrib["product"] + return key + # Recursively merges XML elements. Updates either the text or children if another element is found in first. # If it does not exist, copies it from second. def _combineElement(self, first, second): # Create a mapping from tag name to element. - mapping = {el.tag: el for el in first} - for el in second: - if len(el): # Check if element has children. + + mapping = {} + for element in first: + key = self._createKey(element) + mapping[key] = element + for element in second: + key = self._createKey(element) + if len(element): # Check if element has children. try: - self._combineElement(mapping[el.tag], el) # Multiple elements, handle those. + if "setting " in key: + # Setting can have points in it. In that case, delete all values and override them. + for child in list(mapping[key]): + mapping[key].remove(child) + for child in element: + mapping[key].append(child) + else: + self._combineElement(mapping[key], element) # Multiple elements, handle those. except KeyError: - mapping[el.tag] = el - first.append(el) + mapping[key] = element + first.append(element) else: try: - mapping[el.tag].text = el.text + mapping[key].text = element.text except KeyError: # Not in the mapping, so simply add it - mapping[el.tag] = el - first.append(el) + mapping[key] = element + first.append(element) ## Overridden from InstanceContainer def deserialize(self, serialized): @@ -305,7 +331,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): # TODO: Add material verfication self.addMetaDataEntry("status", "unknown") - #for inherit in data.findall("./um:inherits", self.__namespaces): + inherits = data.find("./um:inherits", self.__namespaces) if inherits is not None: inherited = self._resolveInheritance(inherits.text) From 28cc10edaf68dc5f9f4a9a2632e3343b4c508403 Mon Sep 17 00:00:00 2001 From: Barry Stump Date: Wed, 31 Aug 2016 14:58:46 -0700 Subject: [PATCH 04/31] update Printrbot Simple definition * Add platform mesh * Default nozzle size is 0.4mm * Updated start gcode to correct bed origin after auto-level --- resources/definitions/printrbot_simple.def.json | 7 ++++--- .../meshes/printrbot_simple_metal_platform.stl | Bin 0 -> 33284 bytes 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 resources/meshes/printrbot_simple_metal_platform.stl diff --git a/resources/definitions/printrbot_simple.def.json b/resources/definitions/printrbot_simple.def.json index a1963fe20e..255259df5a 100644 --- a/resources/definitions/printrbot_simple.def.json +++ b/resources/definitions/printrbot_simple.def.json @@ -8,6 +8,7 @@ "author": "Calvindog717", "manufacturer": "PrintrBot", "category": "Other", + "platform": "printrbot_simple_metal_platform.stl", "file_formats": "text/x-gcode" }, @@ -17,7 +18,7 @@ "machine_height": { "default_value": 150 }, "machine_depth": { "default_value": 140 }, "machine_center_is_zero": { "default_value": false }, - "machine_nozzle_size": { "default_value": 0.3 }, + "machine_nozzle_size": { "default_value": 0.4 }, "material_diameter": { "default_value": 1.75 }, "machine_nozzle_heat_up_speed": { "default_value": 2 }, "machine_nozzle_cool_down_speed": { "default_value": 2 }, @@ -33,10 +34,10 @@ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG29 ; auto bed-levelling\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..." + "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;home X/Y\nG28 Z0 ;home Z\nG92 E0 ;zero the extruded length\nG29 ;initiate auto bed leveling sequence\nG92 X132.4 Y20 ;correct bed origin (G29 changes it)" }, "machine_end_gcode": { - "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning" + "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nM106 S0 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit\nG1 Z+1 E-5 F9000 ;move Z up a bit and retract even more\nG28 X0 Y0 ;home X/Y, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning" } } } diff --git a/resources/meshes/printrbot_simple_metal_platform.stl b/resources/meshes/printrbot_simple_metal_platform.stl new file mode 100644 index 0000000000000000000000000000000000000000..717d224f1fd75ed6b9e95cf9ffb71d496eb8aae1 GIT binary patch literal 33284 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 Date: Thu, 1 Sep 2016 11:18:15 +0200 Subject: [PATCH 05/31] Machines are now flattened before merging them This ensures that machines are overwritten correctly CURA-2108 --- .../XmlMaterialProfile/XmlMaterialProfile.py | 37 ++++++++++++++++++- ...maker_pla_silver-metallic.xml.fdm_material | 8 ++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 15f022d539..58a948c17b 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -272,9 +272,44 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): self._inherited_files.append(path) return ET.fromstring(contents) + # The XML material profile can have specific settings for machines. + # Some machines share profiles, so they are only created once. + # This function duplicates those elements so that each machine tag only has one identifier. + def _flattenMachinesXML(self, element): + settings_element = element.find("./um:settings", self.__namespaces) + machines = settings_element.iterfind("./um:machine", self.__namespaces) + machines_to_add = [] + machines_to_remove = [] + for machine in machines: + identifiers = list(machine.iterfind("./um:machine_identifier", self.__namespaces)) + has_multiple_identifiers = len(identifiers) > 1 + if has_multiple_identifiers: + # Multiple identifiers found. We need to create a new machine element and copy all it's settings there. + for identifier in identifiers: + new_machine = copy.deepcopy(machine) + # Create list of identifiers that need to be removed from the copied element. + other_identifiers = [self._createKey(other_identifier) for other_identifier in identifiers if other_identifier is not identifier] + # As we can only remove by exact object reference, we need to look through the identifiers of copied machine. + new_machine_identifiers = list(new_machine.iterfind("./um:machine_identifier", self.__namespaces)) + for new_machine_identifier in new_machine_identifiers: + key = self._createKey(new_machine_identifier) + # Key was in identifiers to remove, so this element needs to be purged + if key in other_identifiers: + new_machine.remove(new_machine_identifier) + machines_to_add.append(new_machine) + machines_to_remove.append(machine) + else: + pass # Machine only has one identifier. Nothing to do. + # Remove & add all required machines. + for machine_to_remove in machines_to_remove: + settings_element.remove(machine_to_remove) + for machine_to_add in machines_to_add: + settings_element.append(machine_to_add) + return element + def _mergeXML(self, first, second): result = copy.deepcopy(first) - self._combineElement(result, second) + self._combineElement(self._flattenMachinesXML(result), self._flattenMachinesXML(second)) return result def _createKey(self, element): diff --git a/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material b/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material index fd829abf6c..2f250e8e31 100644 --- a/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material +++ b/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material @@ -3,6 +3,7 @@ Automatically generated PLA profile. Data in this file may not be not correct. --> + generic_pla Ultimaker @@ -36,16 +37,15 @@ Automatically generated PLA profile. Data in this file may not be not correct. - 150 - - + + - 150 + 180 From aa689dc2fb1fc1cd8207b8d2b54768d6c02b9979 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 1 Sep 2016 13:34:18 +0200 Subject: [PATCH 06/31] Fix layerview for grouped objects The "ghosts" would be rendered over grouped objects, thereby making them not visible. Note that this quick fix comes at the price of slightly "muddying" all the layerview colors. A better fix was proposed here (but it is not yet working correctly): https://github.com/Ultimaker/Cura/pull/906 CURA-2246 --- plugins/LayerView/LayerView.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 791ca0e153..801f4797dd 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -86,7 +86,7 @@ class LayerView(View): if not self._ghost_shader: self._ghost_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader")) - self._ghost_shader.setUniformValue("u_color", Color(0, 0, 0, 72)) + self._ghost_shader.setUniformValue("u_color", Color(0, 0, 0, 64)) for node in DepthFirstIterator(scene.getRoot()): # We do not want to render ConvexHullNode as it conflicts with the bottom layers. @@ -98,10 +98,10 @@ class LayerView(View): if node.getMeshData() and node.isVisible(): renderer.queueNode(node, shader = self._ghost_shader, - state_setup_callback = lambda gl: gl.glDepthMask(gl.GL_FALSE), - state_teardown_callback = lambda gl: gl.glDepthMask(gl.GL_TRUE) - ) + type = RenderBatch.RenderType.Transparent ) + for node in DepthFirstIterator(scene.getRoot()): + if type(node) is SceneNode: if node.getMeshData() and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: From a2f478f2ad9df16e62f40406cf913957d3fac3f1 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Thu, 1 Sep 2016 13:48:46 +0200 Subject: [PATCH 07/31] Fix for "Creating two profiles causes the names to become messed up" CURA-2220 --- cura/Settings/ContainerManager.py | 17 +++-- resources/qml/Cura.qml | 2 +- resources/qml/Preferences/ProfilesPage.qml | 74 ++++++++++++++++------ 3 files changed, 67 insertions(+), 26 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index e220a5f2f1..1e0ac3338f 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -423,8 +423,8 @@ class ContainerManager(QObject): # stack and clear the user settings. # # \return \type{bool} True if the operation was successfully, False if not. - @pyqtSlot(result = bool) - def createQualityChanges(self): + @pyqtSlot(str, result = bool) + def createQualityChanges(self, base_name): global_stack = UM.Application.getInstance().getGlobalContainerStack() if not global_stack: return False @@ -436,7 +436,9 @@ class ContainerManager(QObject): self._machine_manager.blurSettings.emit() - unique_name = self._container_registry.uniqueName(active_quality_name) + if base_name is None: + base_name = active_quality_name + unique_name = self._container_registry.uniqueName(base_name) # Go through the active stacks and create quality_changes containers from the user containers. for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): @@ -540,8 +542,8 @@ class ContainerManager(QObject): # \param quality_name The name of the quality to duplicate. # # \return A string containing the name of the duplicated containers, or an empty string if it failed. - @pyqtSlot(str, result = str) - def duplicateQualityOrQualityChanges(self, quality_name): + @pyqtSlot(str, str, result = str) + def duplicateQualityOrQualityChanges(self, quality_name, base_name): global_stack = UM.Application.getInstance().getGlobalContainerStack() if not global_stack or not quality_name: return "" @@ -551,7 +553,10 @@ class ContainerManager(QObject): UM.Logger.log("d", "Unable to duplicate the quality %s, because it doesn't exist.", quality_name) return "" - new_name = self._container_registry.uniqueName(quality_name) + if base_name is None: + base_name = quality_name + + new_name = self._container_registry.uniqueName(base_name) container_type = containers[0].getMetaDataEntry("type") if container_type == "quality": diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 5ba0c82f00..34dbcf1b67 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -463,7 +463,7 @@ UM.MainWindow target: Cura.Actions.addProfile onTriggered: { - Cura.ContainerManager.createQualityChanges(); + Cura.ContainerManager.createQualityChanges(null); preferences.setPage(4); preferences.show(); diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 4a0d87b812..15e46a9dda 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -61,6 +61,10 @@ UM.ManagementPage return -1; } + function canCreateProfile() { + return base.currentItem && (base.currentItem.id == Cura.MachineManager.activeQualityId) && Cura.MachineManager.hasUserSettings; + } + buttons: [ Button { @@ -69,26 +73,39 @@ UM.ManagementPage enabled: base.currentItem != null ? base.currentItem.id != Cura.MachineManager.activeQualityId : false; onClicked: Cura.MachineManager.setActiveQuality(base.currentItem.id) }, + + // Create button Button { - text: base.currentItem && (base.currentItem.id == Cura.MachineManager.activeQualityId) && Cura.MachineManager.hasUserSettings ? catalog.i18nc("@label", "Create") : catalog.i18nc("@label", "Duplicate") + text: catalog.i18nc("@label", "Create") + enabled: base.canCreateProfile() + visible: base.canCreateProfile() iconName: "list-add"; onClicked: { - var selectedContainer; - if (base.currentItem.id == Cura.MachineManager.activeQualityId && Cura.MachineManager.hasUserSettings) { - selectedContainer = Cura.ContainerManager.createQualityChanges(); - } else { - selectedContainer = Cura.ContainerManager.duplicateQualityOrQualityChanges(base.currentItem.name); - } - base.selectContainer(selectedContainer); - - renameDialog.removeWhenRejected = true; - renameDialog.open(); - renameDialog.selectText(); + newNameDialog.object = base.currentItem != null ? base.currentItem.name : ""; + newNameDialog.open(); + newNameDialog.selectText(); } }, + + // Duplicate button + Button + { + text: catalog.i18nc("@label", "Duplicate") + enabled: ! base.canCreateProfile() + visible: ! base.canCreateProfile() + iconName: "list-add"; + + onClicked: + { + newDuplicateNameDialog.object = base.currentItem.name; + newDuplicateNameDialog.open(); + newDuplicateNameDialog.selectText(); + } + }, + Button { text: catalog.i18nc("@action:button", "Remove"); @@ -103,7 +120,6 @@ UM.ManagementPage enabled: base.currentItem != null ? !base.currentItem.readOnly : false; onClicked: { - renameDialog.removeWhenRejected = false; renameDialog.open(); renameDialog.selectText(); } @@ -249,24 +265,44 @@ UM.ManagementPage objectList.currentIndex = -1 //Reset selection. } } + UM.RenameDialog { id: renameDialog; object: base.currentItem != null ? base.currentItem.name : "" - property bool removeWhenRejected: false onAccepted: { Cura.ContainerManager.renameQualityChanges(base.currentItem.name, newName) objectList.currentIndex = -1 //Reset selection. } - onRejected: + } + + // Dialog to request a name when creating a new profile + UM.RenameDialog + { + id: newNameDialog; + object: ""; + onAccepted: { - if(removeWhenRejected) - { - Cura.ContainerManager.removeQualityChanges(base.currentItem.name) - } + var selectedContainer = Cura.ContainerManager.createQualityChanges(newName); + base.selectContainer(selectedContainer); + objectList.currentIndex = -1 //Reset selection. } } + + // Dialog to request a name when duplicating a new profile + UM.RenameDialog + { + id: newDuplicateNameDialog; + object: ""; + onAccepted: + { + var selectedContainer = Cura.ContainerManager.duplicateQualityOrQualityChanges(base.currentItem.name, newName); + base.selectContainer(selectedContainer); + objectList.currentIndex = -1 //Reset selection. + } + } + MessageDialog { id: messageDialog From a68e112060e4cf63a69a853c7dac30732590589b Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 1 Sep 2016 14:44:29 +0200 Subject: [PATCH 08/31] Fixed resolvement not being overwritten by user changes --- plugins/CuraEngineBackend/StartSliceJob.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index c7cedc92ca..4d40da899d 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -206,7 +206,14 @@ class StartSliceJob(Job): # Use resolvement value if available, or take the value resolved_value = stack.getProperty(key, "resolve") if resolved_value is not None: - settings[key] = resolved_value + # There is a resolvement value. Check if we need to use it. + user_container = stack.findContainer({"type": "user"}) + quality_changes_container = stack.findContainer({"type": "quality_changes"}) + if user_container.hasProperty(key,"value") or quality_changes_container.hasProperty(key,"value"): + # Normal case + settings[key] = stack.getProperty(key, "value") + else: + settings[key] = resolved_value else: # Normal case settings[key] = stack.getProperty(key, "value") From 7961104a0c9fb0d4fea3d9ddf5085a6fcd3ef324 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 1 Sep 2016 15:39:24 +0200 Subject: [PATCH 09/31] Disable material/variant combinations we have no profile for CURA-2236 --- resources/materials/generic_cpe_plus.xml.fdm_material | 4 +++- resources/materials/generic_tpu.xml.fdm_material | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/resources/materials/generic_cpe_plus.xml.fdm_material b/resources/materials/generic_cpe_plus.xml.fdm_material index b688db30fb..f234d7cb45 100644 --- a/resources/materials/generic_cpe_plus.xml.fdm_material +++ b/resources/materials/generic_cpe_plus.xml.fdm_material @@ -28,7 +28,9 @@ Generic CPE+ profile. Serves as an example file, data in this file is not correc yes - + + no + diff --git a/resources/materials/generic_tpu.xml.fdm_material b/resources/materials/generic_tpu.xml.fdm_material index 1a099af9cf..455e7b89be 100644 --- a/resources/materials/generic_tpu.xml.fdm_material +++ b/resources/materials/generic_tpu.xml.fdm_material @@ -31,7 +31,9 @@ Generic TPU 95A profile. Serves as an example file, data in this file is not cor - + + no + From 7d8b3dfa515b44e5f4abb899ce19a1420ae846ca Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 1 Sep 2016 15:41:23 +0200 Subject: [PATCH 10/31] One at a time now uses correct shapes to push free again CURA-403 --- cura/PlatformPhysics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 2a42765d3f..c9afb4ccbd 100644 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -102,11 +102,11 @@ class PlatformPhysics: # Get the overlap distance for both convex hulls. If this returns None, there is no intersection. head_hull = node.callDecoration("getConvexHullHead") if head_hull: - overlap = head_hull.intersectsPolygon(other_node.callDecoration("getConvexHullHead")) + overlap = head_hull.intersectsPolygon(other_node.callDecoration("getConvexHull")) if not overlap: other_head_hull = other_node.callDecoration("getConvexHullHead") if other_head_hull: - overlap = node.callDecoration("getConvexHullHead").intersectsPolygon(other_head_hull) + overlap = node.callDecoration("getConvexHull").intersectsPolygon(other_head_hull) else: own_convex_hull = node.callDecoration("getConvexHull") other_convex_hull = other_node.callDecoration("getConvexHull") From 3f5d7b0f53ba4e100e4fea179023ab1f57b975e4 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 1 Sep 2016 15:42:00 +0200 Subject: [PATCH 11/31] One at a time mode now adds platform adhesion to convex hulls CURA-403 --- cura/BuildVolume.py | 6 +++++- cura/ConvexHullDecorator.py | 12 ++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index a91a85f406..ca4c8e7b34 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -280,7 +280,7 @@ class BuildVolume(SceneNode): self._height = self._global_container_stack.getProperty("machine_height", "value") rebuild_me = True - if setting_key in self._skirt_settings or setting_key in self._prime_settings or setting_key in self._tower_settings: + if setting_key in self._skirt_settings or setting_key in self._prime_settings or setting_key in self._tower_settings or setting_key == "print_sequence": self._updateDisallowedAreas() rebuild_me = True @@ -383,6 +383,10 @@ class BuildVolume(SceneNode): def _getBedAdhesionSize(self, container_stack): skirt_size = 0.0 + # If we are printing one at a time, we need to add the bed adhesion size to the disallowed areas of the objects + if container_stack.getProperty("print_sequence", "value") == "one_at_a_time": + return 0.1 # Return a very small value, so we do draw disallowed area's near the edges. + adhesion_type = container_stack.getProperty("adhesion_type", "value") if adhesion_type == "skirt": skirt_distance = container_stack.getProperty("skirt_gap", "value") diff --git a/cura/ConvexHullDecorator.py b/cura/ConvexHullDecorator.py index 5185579633..770ed42a9f 100644 --- a/cura/ConvexHullDecorator.py +++ b/cura/ConvexHullDecorator.py @@ -56,6 +56,7 @@ class ConvexHullDecorator(SceneNodeDecorator): if self._global_stack and self._node: if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self._node.getParent().callDecoration("isGroup"): hull = hull.getMinkowskiHull(Polygon(numpy.array(self._global_stack.getProperty("machine_head_polygon", "value"), numpy.float32))) + hull = self._add2DAdhesionMargin(hull) return hull ## Get the convex hull of the node with the full head size @@ -229,17 +230,16 @@ class ConvexHullDecorator(SceneNodeDecorator): machine_head_coords = numpy.array( self._global_stack.getProperty("machine_head_with_fans_polygon", "value"), numpy.float32) - head_y_size = abs(machine_head_coords).min() # safe margin to take off in all directions if adhesion_type == "raft": - extra_margin = max(0, self._global_stack.getProperty("raft_margin", "value") - head_y_size) + extra_margin = max(0, self._global_stack.getProperty("raft_margin", "value")) elif adhesion_type == "brim": - extra_margin = max(0, self._global_stack.getProperty("brim_width", "value") - head_y_size) + extra_margin = max(0, self._global_stack.getProperty("brim_line_count", "value") * self._global_stack.getProperty("skirt_brim_line_width", "value")) elif adhesion_type == "skirt": extra_margin = max( 0, self._global_stack.getProperty("skirt_gap", "value") + - self._global_stack.getProperty("skirt_line_count", "value") * self._global_stack.getProperty("skirt_brim_line_width", "value") - - head_y_size) + self._global_stack.getProperty("skirt_line_count", "value") * self._global_stack.getProperty("skirt_brim_line_width", "value")) + # adjust head_and_fans with extra margin if extra_margin > 0: # In Cura 2.2+, there is a function to create this circle-like polygon. @@ -288,4 +288,4 @@ class ConvexHullDecorator(SceneNodeDecorator): _affected_settings = [ "adhesion_type", "raft_base_thickness", "raft_interface_thickness", "raft_surface_layers", "raft_surface_thickness", "raft_airgap", "raft_margin", "print_sequence", - "skirt_gap", "skirt_line_count", "skirt_brim_line_width", "skirt_distance"] + "skirt_gap", "skirt_line_count", "skirt_brim_line_width", "skirt_distance", "brim_line_count"] From a2d74cc9849db438b2532bf040970aea587d6471 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 1 Sep 2016 16:23:06 +0200 Subject: [PATCH 12/31] Fix documentation --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 58a948c17b..a3bbb474d1 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -87,7 +87,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): super().setName(new_name) - basefile = self.getMetaDataEntry("base_file", self._id) # if basefile is none, this is a basefile. + basefile = self.getMetaDataEntry("base_file", self._id) # if basefile is self.id, this is a basefile. # Update the basefile as well, this is actually what we're trying to do # Update all containers that share GUID and basefile containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile) From 697329f5d27e11cae64ab0193fff426fd1e8abf4 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 1 Sep 2016 16:43:40 +0200 Subject: [PATCH 13/31] Fixed review issues CURA-2108 --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 58a948c17b..5382dd8b01 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -275,7 +275,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): # The XML material profile can have specific settings for machines. # Some machines share profiles, so they are only created once. # This function duplicates those elements so that each machine tag only has one identifier. - def _flattenMachinesXML(self, element): + def _expandMachinesXML(self, element): settings_element = element.find("./um:settings", self.__namespaces) machines = settings_element.iterfind("./um:machine", self.__namespaces) machines_to_add = [] @@ -309,7 +309,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): def _mergeXML(self, first, second): result = copy.deepcopy(first) - self._combineElement(self._flattenMachinesXML(result), self._flattenMachinesXML(second)) + self._combineElement(self._expandMachinesXML(result), self._expandMachinesXML(second)) return result def _createKey(self, element): @@ -339,7 +339,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): key = self._createKey(element) if len(element): # Check if element has children. try: - if "setting " in key: + if "setting" in element.tag and not "settings" in element.tag: # Setting can have points in it. In that case, delete all values and override them. for child in list(mapping[key]): mapping[key].remove(child) From 7451e9d6ae4c7f5a1a663d9656f67398c1f0a986 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 09:19:55 +0200 Subject: [PATCH 14/31] Removed auto-temp from changelog We didn't actually finish it, so it shouldn't be in changelog --- plugins/ChangeLogPlugin/ChangeLog.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/ChangeLogPlugin/ChangeLog.txt b/plugins/ChangeLogPlugin/ChangeLog.txt index ad09470ccd..a0ae842081 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.txt +++ b/plugins/ChangeLogPlugin/ChangeLog.txt @@ -59,9 +59,6 @@ Set the travel speed of the initial layer(s) to reduce risk of extruder pulling *Support Bottoms This new feature duplicates the Support Roofs feature in the places where the support rests on the model. -*Auto Temperature -Automatically change the temperature of a layer based on the average flow of material in the layer. - *Bug fixes & minor changes Deleting grouped objects works as intended again. Duplicating groups works as intended again. From 6c6ced404867806510d760514a0b9744a0c0a956 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 10:10:54 +0200 Subject: [PATCH 15/31] Undo changes made for debugging --- .../ultimaker_pla_silver-metallic.xml.fdm_material | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material b/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material index 2f250e8e31..2b7fbaac46 100644 --- a/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material +++ b/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material @@ -3,7 +3,6 @@ Automatically generated PLA profile. Data in this file may not be not correct. --> - generic_pla Ultimaker @@ -38,14 +37,14 @@ Automatically generated PLA profile. Data in this file may not be not correct. - - + + - 180 + 150 From d7d18043196734ae98da57ea24033b34cd485765 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 10:16:11 +0200 Subject: [PATCH 16/31] Added correct exception handling for .curaprofile importing CURA-2252 --- plugins/CuraProfileReader/CuraProfileReader.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/CuraProfileReader/CuraProfileReader.py b/plugins/CuraProfileReader/CuraProfileReader.py index 8007a8e696..772b11890b 100644 --- a/plugins/CuraProfileReader/CuraProfileReader.py +++ b/plugins/CuraProfileReader/CuraProfileReader.py @@ -26,7 +26,11 @@ class CuraProfileReader(ProfileReader): # not be read or didn't contain a valid profile, \code None \endcode is # returned. def read(self, file_name): - archive = zipfile.ZipFile(file_name, "r") + try: + archive = zipfile.ZipFile(file_name, "r") + except Exception: + # zipfile doesn't give proper exceptions, so we can only catch broad ones + return [] results = [] for profile_id in archive.namelist(): # Create an empty profile. From 3df1eb00da1a4d0fa746b2489df0250d4c4b67b8 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 10:56:27 +0200 Subject: [PATCH 17/31] Added some extra checks when changing quality profiles Contributes to ultimaker/cura#960 --- cura/Settings/MachineManager.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 91cfd5e811..ccd14fcb1d 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -614,9 +614,16 @@ class MachineManager(QObject): stack_quality_changes = self._empty_quality_changes_container old_quality = stack.findContainer(type = "quality") - old_quality.nameChanged.disconnect(self._onQualityNameChanged) + if old_quality: + old_quality.nameChanged.disconnect(self._onQualityNameChanged) + else: + Logger.log("w", "Could not find old quality while changing active quality.") + old_changes = stack.findContainer(type = "quality_changes") - old_changes.nameChanged.disconnect(self._onQualityNameChanged) + if old_changes: + old_changes.nameChanged.disconnect(self._onQualityNameChanged) + else: + Logger.log("w", "Could not find old quality_changes while changing active quality.") stack.replaceContainer(stack.getContainerIndex(old_quality), stack_quality) stack.replaceContainer(stack.getContainerIndex(old_changes), stack_quality_changes) From 266f46ed55df2ba8d00ff0d7354bef6968fca187 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 11:30:50 +0200 Subject: [PATCH 18/31] Rename dialog shows again when creating new profile from current settings CURA-2220 --- resources/qml/Preferences/ProfilesPage.qml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 15e46a9dda..aa6e230d66 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -144,7 +144,6 @@ UM.ManagementPage signal showProfileNameDialog() onShowProfileNameDialog: { - renameDialog.removeWhenRejected = true; renameDialog.open(); renameDialog.selectText(); } @@ -161,7 +160,7 @@ UM.ManagementPage Label { id: profileName - text: base.currentItem ? base.currentItem.name : "" + text: base.currentItem ? base.currentItem.name r: "" font: UM.Theme.getFont("large") width: parent.width elide: Text.ElideRight From 1a78aee46ce77b9c56135c7b3231515a5f1fee0b Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 11:37:54 +0200 Subject: [PATCH 19/31] fix typo --- resources/qml/Preferences/ProfilesPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index aa6e230d66..56d8bd41a4 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -160,7 +160,7 @@ UM.ManagementPage Label { id: profileName - text: base.currentItem ? base.currentItem.name r: "" + text: base.currentItem ? base.currentItem.name: "" font: UM.Theme.getFont("large") width: parent.width elide: Text.ElideRight From 73b9a142d2e00bc1baa53e66582c2f4000ff9491 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 11:42:14 +0200 Subject: [PATCH 20/31] Auto generate name now works if base_name is empty string CURA-2220 --- cura/Settings/ContainerManager.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 1e0ac3338f..40e036eba5 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -435,8 +435,7 @@ class ContainerManager(QObject): return False self._machine_manager.blurSettings.emit() - - if base_name is None: + if base_name is None or base_name == "": base_name = active_quality_name unique_name = self._container_registry.uniqueName(base_name) From 6c9b04182c4319e41e56ef25ff448b6d2c88448d Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 13:06:10 +0200 Subject: [PATCH 21/31] Minor text change in changelog CURA-2218 --- plugins/ChangeLogPlugin/ChangeLog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ChangeLogPlugin/ChangeLog.txt b/plugins/ChangeLogPlugin/ChangeLog.txt index a0ae842081..8041bbb171 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.txt +++ b/plugins/ChangeLogPlugin/ChangeLog.txt @@ -1,7 +1,7 @@ [2.3.0] *Speed improvements -The first thing you will notice is the speed. STL loading is now 10 to 20 times faster, layer time is significantly faster and slicing speed is slightly improved. +The first thing you will notice is the speed. STL loading is now 10 to 20 times faster, layerview is significantly faster and slicing speed is slightly improved. *Multi Extrusion Support Machines with multiple extruders are now supported. If you’ve got the Ultimaker Original with the dual extrusion upgrade kit, we’ve got you covered. From d610a30ccbe641e9d9008eec5beea9ba38ad2189 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 2 Sep 2016 13:17:31 +0200 Subject: [PATCH 22/31] Fix overhang display if the overhang angle is set to its default value --- plugins/SolidView/SolidView.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 3e3501a83f..3b56ac1881 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -47,7 +47,9 @@ class SolidView(View): if global_container_stack: if Preferences.getInstance().getValue("view/show_overhang"): angle = global_container_stack.getProperty("support_angle", "value") - if angle is not None and global_container_stack.getProperty("support_angle", "validationState") == ValidatorState.Valid: + # Make sure the overhang angle is valid before passing it to the shader + # Note: if the overhang angle is set to its default value, it does not need to get validated (validationState = None) + if angle is not None and global_container_stack.getProperty("support_angle", "validationState") in [None, ValidatorState.Valid]: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - angle))) else: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) #Overhang angle of 0 causes no area at all to be marked as overhang. From 405d3d920a6afb62249cb13a8bd7820789997ef2 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 13:31:29 +0200 Subject: [PATCH 23/31] Prime tower can no longer be printed outside build volume Note that it doesn't take disallowed area's into account CURA-2234 --- resources/definitions/fdmprinter.def.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index ce406dc923..a219347f10 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3310,6 +3310,8 @@ "default_value": 200, "minimum_value_warning": "-1000", "maximum_value_warning": "1000", + "maximum_value": "machine_width - 0.5 * prime_tower_size", + "minimum_value": "0.5 * prime_tower_size", "settable_per_mesh": false, "settable_per_extruder": false }, @@ -3323,6 +3325,8 @@ "default_value": 200, "minimum_value_warning": "-1000", "maximum_value_warning": "1000", + "maximum_value": "machine_depth - 0.5 * prime_tower_size", + "minimum_value": "0.5 * prime_tower_size", "settable_per_mesh": false, "settable_per_extruder": false }, From aa83b6834b4a9bd2c92abab792cabc6e7a7444d1 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 13:43:28 +0200 Subject: [PATCH 24/31] Removed unused decorator --- cura/CuraApplication.py | 3 --- cura/MultiMaterialDecorator.py | 11 ----------- 2 files changed, 14 deletions(-) delete mode 100644 cura/MultiMaterialDecorator.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 80bd4eb9a9..6da64452c6 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -36,7 +36,6 @@ from . import BuildVolume from . import CameraAnimation from . import PrintInformation from . import CuraActions -from . import MultiMaterialDecorator from . import ZOffsetDecorator from . import CuraSplashScreen from . import CameraImageProvider @@ -792,8 +791,6 @@ class CuraApplication(QtApplication): except Exception as e: Logger.log("d", "mergeSelected: Exception:", e) return - multi_material_decorator = MultiMaterialDecorator.MultiMaterialDecorator() - group_node.addDecorator(multi_material_decorator) # Compute the center of the objects when their origins are aligned. object_centers = [node.getMeshData().getCenterPosition().scale(node.getScale()) for node in group_node.getChildren()] diff --git a/cura/MultiMaterialDecorator.py b/cura/MultiMaterialDecorator.py deleted file mode 100644 index 5fee777309..0000000000 --- a/cura/MultiMaterialDecorator.py +++ /dev/null @@ -1,11 +0,0 @@ -from UM.Scene.SceneNodeDecorator import SceneNodeDecorator - -class MultiMaterialDecorator(SceneNodeDecorator): - def __init__(self): - super().__init__() - - def isMultiMaterial(self): - return True - - def __deepcopy__(self, memo): - return MultiMaterialDecorator() \ No newline at end of file From bbcd43ef018b85686a0355be8ca5eeaa86fcdfe5 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 14:23:05 +0200 Subject: [PATCH 25/31] Reset all translations now ensures that model is right on top of buildplate CURA-2233 --- cura/CuraApplication.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 6da64452c6..b366738a68 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -23,6 +23,7 @@ from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation from UM.Operations.GroupedOperation import GroupedOperation from UM.Operations.SetTransformOperation import SetTransformOperation +from UM.Operations.TranslateOperation import TranslateOperation from cura.SetParentOperation import SetParentOperation from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType @@ -699,8 +700,7 @@ class CuraApplication(QtApplication): op = GroupedOperation() for node in nodes: node.removeDecorator(ZOffsetDecorator.ZOffsetDecorator) - op.addOperation(SetTransformOperation(node, Vector(0,0,0))) - + op.addOperation(SetTransformOperation(node, Vector(0, node.getWorldPosition().y - node.getBoundingBox().bottom, 0))) op.push() ## Reset all transformations on nodes with mesh data. From dd1effdb8135ce67677a4673571a01ec88949e97 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 14:27:18 +0200 Subject: [PATCH 26/31] Reset all transformations now also resets object above buildplate CURA-2233 --- cura/CuraApplication.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index b366738a68..aa843bccdb 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -723,7 +723,8 @@ class CuraApplication(QtApplication): for node in nodes: # Ensure that the object is above the build platform node.removeDecorator(ZOffsetDecorator.ZOffsetDecorator) - op.addOperation(SetTransformOperation(node, Vector(0,0,0), Quaternion(), Vector(1, 1, 1))) + + op.addOperation(SetTransformOperation(node, Vector(0, node.getMeshData().getCenterPosition().y, 0), Quaternion(), Vector(1, 1, 1))) op.push() From 2c82f5a177e774c1b53072b7ee85888dc8303857 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 2 Sep 2016 16:36:49 +0200 Subject: [PATCH 27/31] Instead of writing quality + user to g-code, we now write quality_changes + user --- plugins/GCodeWriter/GCodeWriter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index c2a932b68c..c15b079097 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -89,17 +89,17 @@ class GCodeWriter(MeshWriter): prefix = ";SETTING_" + str(GCodeWriter.version) + " " # The prefix to put before each line. prefix_length = len(prefix) - container_with_profile = stack.findContainer({"type": "quality"}) + container_with_profile = stack.findContainer({"type": "quality_changes"}) if not container_with_profile: Logger.log("e", "No valid quality profile found, not writing settings to GCode!") return "" - flat_global_container = self._createFlattenedContainerInstance(stack.getTop(),container_with_profile) + flat_global_container = self._createFlattenedContainerInstance(stack.getTop(), container_with_profile) serialized = flat_global_container.serialize() data = {"global_quality": serialized} for extruder in ExtruderManager.getInstance().getMachineExtruders(stack.getId()): - extruder_quality = extruder.findContainer({"type": "quality"}) + extruder_quality = extruder.findContainer({"type": "quality_changes"}) if not extruder_quality: Logger.log("w", "No extruder quality profile found, not writing quality for extruder %s to file!", extruder.getId()) continue From 67636d6f3c8d0f6f10d986b0591d9ed71a3d53bd Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 5 Sep 2016 12:01:05 +0200 Subject: [PATCH 28/31] _updateMaterial container now correctly returns generic material CURA-2236 --- cura/Settings/MachineManager.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index ccd14fcb1d..a2f4e4abdc 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -547,6 +547,7 @@ class MachineManager(QObject): preferred_material = None if old_material: preferred_material_name = old_material.getName() + self.setActiveMaterial(self._updateMaterialContainer(self._global_container_stack.getBottom(), containers[0], preferred_material_name).id) else: Logger.log("w", "While trying to set the active variant, no variant was found to replace.") @@ -806,11 +807,11 @@ class MachineManager(QObject): if containers: return containers[0] - if "name" in search_criteria or "id" in search_criteria: + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) + if "variant" in search_criteria or "id" in search_criteria: # If a material by this name can not be found, try a wider set of search criteria - search_criteria.pop("name", None) + search_criteria.pop("variant", None) search_criteria.pop("id", None) - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) if containers: return containers[0] @@ -858,7 +859,7 @@ class MachineManager(QObject): # We still weren't able to find a quality for this specific material. # Try to find qualities for a generic version of the material. - material_search_criteria = { "type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic" } + material_search_criteria = { "type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic"} if definition.getMetaDataEntry("has_machine_quality"): if material_container: material_search_criteria["definition"] = material_container.getDefinition().id From 51d653beba4e9876922d5f608c58b606aacf6842 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 5 Sep 2016 12:40:38 +0200 Subject: [PATCH 29/31] Added logging if material container was not found CURA-2236 --- cura/Settings/MachineManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index a2f4e4abdc..f957df2c9b 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -815,7 +815,7 @@ class MachineManager(QObject): containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) if containers: return containers[0] - + Logger.log("w", "Unable to find a material container with provided criteria, returning an empty one instead.") return self._empty_material_container def _updateQualityContainer(self, definition, variant_container, material_container = None, preferred_quality_name = None): From 3227507297fec4e782efb69436d7d325edd1a917 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 5 Sep 2016 13:31:36 +0200 Subject: [PATCH 30/31] An empty quality container will now give a "not supported" warning CURA-2236 --- cura/CuraApplication.py | 1 + cura/Settings/MachineManager.py | 7 ++++--- resources/qml/SidebarHeader.qml | 2 +- resources/themes/cura/styles.qml | 17 ++++++++++++++++- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index aa843bccdb..e6dda417ff 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -180,6 +180,7 @@ class CuraApplication(QtApplication): ContainerRegistry.getInstance().addContainer(empty_material_container) empty_quality_container = copy.deepcopy(empty_container) empty_quality_container._id = "empty_quality" + empty_quality_container.setName("Not supported") empty_quality_container.addMetaDataEntry("type", "quality") ContainerRegistry.getInstance().addContainer(empty_quality_container) empty_quality_changes_container = copy.deepcopy(empty_container) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index f957df2c9b..bf82a95f1a 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -7,7 +7,7 @@ from PyQt5.QtWidgets import QMessageBox from UM.Application import Application from UM.Preferences import Preferences from UM.Logger import Logger - +from UM.Message import Message from UM.Settings.SettingRelation import RelationType import UM.Settings @@ -856,7 +856,6 @@ class MachineManager(QObject): containers = container_registry.findInstanceContainers(**search_criteria) if containers: return containers[0] - # We still weren't able to find a quality for this specific material. # Try to find qualities for a generic version of the material. material_search_criteria = { "type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic"} @@ -873,7 +872,6 @@ class MachineManager(QObject): material_search_criteria["variant"] = variant_container.id else: material_search_criteria["definition"] = "fdmprinter" - material_containers = container_registry.findInstanceContainers(**material_search_criteria) if material_containers: search_criteria["material"] = material_containers[0].getId() @@ -891,6 +889,9 @@ class MachineManager(QObject): if containers: return containers[0] + # Notify user that we were unable to find a matching quality + message = Message(catalog.i18nc("@info:status", "Unable to find a quality profile for this combination, using an empty one instead.")) + message.show() return self._empty_quality_container ## Finds a quality-changes container to use if any other container diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index 3350ebeb7b..c9c0e722eb 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -277,7 +277,7 @@ Column height: UM.Theme.getSize("setting_control").height tooltip: Cura.MachineManager.activeQualityName style: UM.Theme.styles.sidebar_header_button - + property var valueWarning: Cura.MachineManager.activeQualityId == "empty_quality" menu: ProfileMenu { } UM.SimpleButton diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml index 8d813bc2b5..3cfb4514ee 100644 --- a/resources/themes/cura/styles.qml +++ b/resources/themes/cura/styles.qml @@ -11,7 +11,22 @@ QtObject { property Component sidebar_header_button: Component { ButtonStyle { background: Rectangle { - color: control.enabled ? Theme.getColor("setting_control") : Theme.getColor("setting_control_disabled") + color: + { + if(control.enabled) + { + if(control.valueWarning) + { + return Theme.getColor("setting_validation_warning"); + } else + { + return Theme.getColor("setting_control"); + } + } else { + return Theme.getColor("setting_control_disabled"); + } + } + border.width: Theme.getSize("default_lining").width border.color: !control.enabled ? Theme.getColor("setting_control_disabled_border") : control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border") From 1b1be138188e3ffe886eedbcca15c72c304420f1 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 5 Sep 2016 13:47:19 +0200 Subject: [PATCH 31/31] Added normal quality_type to empty container so switching quality_changes works again CURA-2236 --- cura/CuraApplication.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index e6dda417ff..2091eff5ed 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -181,6 +181,7 @@ class CuraApplication(QtApplication): empty_quality_container = copy.deepcopy(empty_container) empty_quality_container._id = "empty_quality" empty_quality_container.setName("Not supported") + empty_quality_container.addMetaDataEntry("quality_type", "normal") empty_quality_container.addMetaDataEntry("type", "quality") ContainerRegistry.getInstance().addContainer(empty_quality_container) empty_quality_changes_container = copy.deepcopy(empty_container)