From 5da6d7016389a2948011b916a94d7c141e4e2d04 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 29 Aug 2016 15:28:09 +0200 Subject: [PATCH 1/8] 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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 fa3464901ee2476c3e2eeb0cb650cbe1a7d976fe Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 1 Sep 2016 13:03:50 +0200 Subject: [PATCH 6/8] Only show prime tower disabled area when the prime tower is enabled CURA-2152 --- cura/BuildVolume.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 2acdd053bb..a91a85f406 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -303,7 +303,7 @@ class BuildVolume(SceneNode): machine_depth = self._global_container_stack.getProperty("machine_depth", "value") # Add prime tower location as disallowed area. - if self._global_container_stack.getProperty("prime_tower_enable", "value"): + if self._global_container_stack.getProperty("prime_tower_enable", "value") == True: prime_tower_size = self._global_container_stack.getProperty("prime_tower_size", "value") prime_tower_x = self._global_container_stack.getProperty("prime_tower_position_x", "value") - machine_width / 2 prime_tower_y = - self._global_container_stack.getProperty("prime_tower_position_y", "value") + machine_depth / 2 From aa689dc2fb1fc1cd8207b8d2b54768d6c02b9979 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 1 Sep 2016 13:34:18 +0200 Subject: [PATCH 7/8] 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 8/8] 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