From bea67f0536b066494e15cae0b29aaf177f044654 Mon Sep 17 00:00:00 2001 From: Thomas-Karl Pietrowski Date: Fri, 8 Jul 2016 13:07:24 +0200 Subject: [PATCH 01/64] CURA-1445: Using getDurationInISOFormat in SliceInfo I think this is the way YouMagine expects the data to be sent. --- plugins/SliceInfoPlugin/SliceInfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index d3b93aacac..85d26a0b93 100644 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -90,7 +90,7 @@ class SliceInfo(Extension): "settings": global_container_stack.serialize(), # global_container with references on used containers "version": Application.getInstance().getVersion(), "modelhash": "None", - "printtime": print_information.currentPrintTime.getDisplayString(), + "printtime": print_information.currentPrintTime.getDurationInISOFormat(), "filament": material_used, "language": Preferences.getInstance().getValue("general/language"), "materials_profiles ": {} From 19c60ee5844bcf8e120f82432f89d2625773ed0c Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Jul 2016 09:34:03 +0200 Subject: [PATCH 02/64] Group delet checking is more explicit CURA-1891 --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 29c1f086b4..689ef2c783 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -583,7 +583,7 @@ class CuraApplication(QtApplication): op.push() if group_node: - if len(group_node.getChildren()) == 1: + if len(group_node.getChildren()) == 1 and group_node.callDecoration("isGroup"): group_node.getChildren()[0].setParent(group_node.getParent()) op = RemoveSceneNodeOperation(group_node) op.push() From aed033674f54e555d992848eb2205664dbf06745 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Jul 2016 09:39:19 +0200 Subject: [PATCH 03/64] Changed some warnings into errors CURA-1706 --- resources/definitions/fdmextruder.def.json | 4 ++-- resources/definitions/fdmprinter.def.json | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/definitions/fdmextruder.def.json b/resources/definitions/fdmextruder.def.json index 7ce44b77b0..bde24ee684 100644 --- a/resources/definitions/fdmextruder.def.json +++ b/resources/definitions/fdmextruder.def.json @@ -153,7 +153,7 @@ "unit": "mm", "default_value": 0, "minimum_value_warning": "0", - "maximum_value_warning": "machine_height", + "maximum_value": "machine_height", "settable_per_mesh": false, "settable_per_extruder": true } @@ -175,7 +175,7 @@ "unit": "mm", "default_value": 0, "minimum_value_warning": "machine_nozzle_offset_x", - "maximum_value_warning": "machine_width", + "maximum_value": "machine_width", "settable_per_mesh": false, "settable_per_extruder": true, "enabled": false diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index d4933be5bb..8f435c1e5c 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -342,7 +342,7 @@ "unit": "mm", "default_value": 0, "minimum_value_warning": "0", - "maximum_value_warning": "machine_height", + "maximum_value": "machine_height", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -706,7 +706,7 @@ "default_value": 0.8, "minimum_value": "0", "minimum_value_warning": "0.6", - "maximum_value_warning": "machine_height", + "maximum_value": "machine_height", "type": "float", "settable_per_mesh": true, "children": @@ -718,7 +718,7 @@ "unit": "mm", "default_value": 0.8, "minimum_value": "0", - "maximum_value_warning": "machine_height", + "maximum_value": "machine_height", "type": "float", "value": "top_bottom_thickness", "settable_per_mesh": true, @@ -746,7 +746,7 @@ "minimum_value": "0", "type": "float", "value": "top_bottom_thickness", - "maximum_value_warning": "machine_height", + "maximum_value": "machine_height", "settable_per_mesh": true, "children": { From bb4d4e78077c4ff07251e5e6203d1585e107e0b0 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Jul 2016 11:01:38 +0200 Subject: [PATCH 04/64] Moved viewmode in order so the tooltip is displayed over per-object settings panel CURA-1651 --- resources/qml/Cura.qml | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index c449b4c83e..d0870991d2 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -321,23 +321,7 @@ UM.MainWindow sourceSize.height: height; } - Button - { - id: viewModeButton - anchors - { - top: toolbar.bottom; - topMargin: UM.Theme.getSize("window_margin").height; - left: parent.left; - } - text: catalog.i18nc("@action:button","View Mode"); - iconSource: UM.Theme.getIcon("viewmode"); - - style: UM.Theme.styles.tool_button; - tooltip: ''; - menu: ViewMenu { } - } Toolbar { @@ -367,6 +351,24 @@ UM.MainWindow width: UM.Theme.getSize("sidebar").width; } + Button + { + id: viewModeButton + + anchors + { + top: toolbar.bottom; + topMargin: UM.Theme.getSize("window_margin").height; + left: parent.left; + } + text: catalog.i18nc("@action:button","View Mode"); + iconSource: UM.Theme.getIcon("viewmode"); + + style: UM.Theme.styles.tool_button; + tooltip: ''; + menu: ViewMenu { } + } + Rectangle { id: viewportOverlay From b69388525f2f6efc8670873c1536463ba642b872 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Jul 2016 11:06:26 +0200 Subject: [PATCH 05/64] Fixed uncaught exception on first run --- cura/PlatformPhysics.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 191f7b0e27..23de74b80e 100644 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -48,7 +48,13 @@ class PlatformPhysics: bbox = node.getBoundingBox() # Ignore intersections with the bottom - build_volume_bounding_box = self._build_volume.getBoundingBox().set(bottom=-9001) + build_volume_bounding_box = self._build_volume.getBoundingBox() + if build_volume_bounding_box: + build_volume_bounding_box.set(bottom=-9001) + else: + # No bounding box. This is triggered when running Cura from command line with a model for the first time + # In that situation there is a model, but no machine (and therefore no build volume. + return node._outside_buildarea = False # Mark the node as outside the build volume if the bounding box test fails. From 79f640e344967714839c30c4c028d764f360a34c Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 20 Jul 2016 11:12:44 +0200 Subject: [PATCH 06/64] Fixed simple sidebar infill label font. CURA-1824 --- resources/qml/SidebarSimple.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index a393500fb7..04b93e7d2a 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -125,6 +125,7 @@ Item } Label{ id: infillLabel + font: UM.Theme.getFont("default") anchors.top: infillIconLining.bottom anchors.horizontalCenter: infillIconLining.horizontalCenter color: infillListView.activeIndex == index ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_border") From 923e4de4ed95236a09e41e9b3effd024861fd37e Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Jul 2016 11:13:24 +0200 Subject: [PATCH 07/64] Stack changes now also ensure that validation state change signal is emitted CURA-1890 --- 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 2b2135e4a3..0c435ba2b9 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -233,7 +233,7 @@ class MachineManager(QObject): self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged) self._global_container_stack.propertyChanged.connect(self._onGlobalPropertyChanged) self._global_stack_valid = not self._checkStackForErrors(self._global_container_stack) - + self.globalValidationChanged.emit() material = self._global_container_stack.findContainer({"type": "material"}) material.nameChanged.connect(self._onMaterialNameChanged) From 612bb39680bf763931236e09c0d352a2003812c1 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 20 Jul 2016 11:36:32 +0200 Subject: [PATCH 08/64] Compensated build volume bbox and scale_to_max_bounds with raft_thickness. Rework of CURA-1707 --- cura/BuildVolume.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 1709a67dd5..e5bd037f1b 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -191,7 +191,9 @@ class BuildVolume(SceneNode): else: self._disallowed_area_mesh = None - self._volume_aabb = AxisAlignedBox(minimum = Vector(min_w, min_h - 1.0, min_d), maximum = Vector(max_w, max_h, max_d)) + self._volume_aabb = AxisAlignedBox( + minimum = Vector(min_w, min_h - 1.0, min_d), + maximum = Vector(max_w, max_h - self._raft_thickness, max_d)) skirt_size = 0.0 @@ -204,7 +206,7 @@ class BuildVolume(SceneNode): # The +1 and -1 is added as there is always a bit of extra room required to work properly. scale_to_max_bounds = AxisAlignedBox( minimum = Vector(min_w + skirt_size + 1, min_h, min_d + disallowed_area_size - skirt_size + 1), - maximum = Vector(max_w - skirt_size - 1, max_h, max_d - disallowed_area_size + skirt_size - 1) + maximum = Vector(max_w - skirt_size - 1, max_h - self._raft_thickness, max_d - disallowed_area_size + skirt_size - 1) ) Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds From 6ec69d523b2bea433f5fc94d7a21669bc9744d25 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Jul 2016 13:05:45 +0200 Subject: [PATCH 09/64] Fixed reloading meshes for 3mf CURA-1622 --- cura/CuraApplication.py | 6 +++++- plugins/3MFReader/ThreeMFReader.py | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 4715ff6009..361facc30c 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -851,7 +851,11 @@ class CuraApplication(QtApplication): def _reloadMeshFinished(self, job): # TODO; This needs to be fixed properly. We now make the assumption that we only load a single mesh! - job._node.setMeshData(job.getResult().getMeshData()) + mesh_data = job.getResult().getMeshData() + if mesh_data: + job._node.setMeshData(job.getResult().getMeshData()) + else: + Logger.log("w", "Could not find a mesh in reloaded node.") def _openFile(self, file): job = ReadMeshJob(os.path.abspath(file)) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 2a51e442da..57d76b2783 100644 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -111,6 +111,8 @@ class ThreeMFReader(MeshReader): if len(objects) > 1: group_decorator = GroupDecorator() result.addDecorator(group_decorator) + elif len(objects) == 1: + result = result.getChildren()[0] # Only one object found, return that. except Exception as e: Logger.log("e", "exception occured in 3mf reader: %s", e) From cbbf62106d90ac154384f62d3eb45797cf93c9d3 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 20 Jul 2016 13:25:05 +0200 Subject: [PATCH 10/64] Fix moving objects through bottom. --- cura/PlatformPhysics.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 23de74b80e..d2a848dd72 100644 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -50,7 +50,8 @@ class PlatformPhysics: # Ignore intersections with the bottom build_volume_bounding_box = self._build_volume.getBoundingBox() if build_volume_bounding_box: - build_volume_bounding_box.set(bottom=-9001) + # It's over 9000! + build_volume_bounding_box = build_volume_bounding_box.set(bottom=-9001) else: # No bounding box. This is triggered when running Cura from command line with a model for the first time # In that situation there is a model, but no machine (and therefore no build volume. From 77c5d25e70f42c403d6b271d61f34c172d290e35 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Jul 2016 14:11:16 +0200 Subject: [PATCH 11/64] Cutoff point for convex hull is now a bit below 0 to prevent rounding issues. CURA-1608 --- cura/ConvexHullDecorator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/ConvexHullDecorator.py b/cura/ConvexHullDecorator.py index f8d1a1e12e..3ccb9481f9 100644 --- a/cura/ConvexHullDecorator.py +++ b/cura/ConvexHullDecorator.py @@ -157,7 +157,7 @@ class ConvexHullDecorator(SceneNodeDecorator): vertex_data = mesh.getConvexHullTransformedVertices(world_transform) # Don't use data below 0. # TODO; We need a better check for this as this gives poor results for meshes with long edges. - vertex_data = vertex_data[vertex_data[:,1] >= 0] + vertex_data = vertex_data[vertex_data[:,1] >= -0.01] if len(vertex_data) >= 4: # Round the vertex data to 1/10th of a mm, then remove all duplicate vertices From f8a9fa1a660279e7c35fcaea158771830345074a Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Jul 2016 14:44:44 +0200 Subject: [PATCH 12/64] Deleting objects from groups no longer cause position changes CURA-1891 --- cura/CuraApplication.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 361facc30c..79bb21cd15 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -583,6 +583,7 @@ class CuraApplication(QtApplication): op.push() if group_node: if len(group_node.getChildren()) == 1 and group_node.callDecoration("isGroup"): + group_node.getChildren()[0].translate(group_node.getPosition()) group_node.getChildren()[0].setParent(group_node.getParent()) op = RemoveSceneNodeOperation(group_node) op.push() From 33313ddb707b6f83a0e14c3589c1c84ecd6d5308 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Jul 2016 15:15:16 +0200 Subject: [PATCH 13/64] Fixed some imports for USB printing --- plugins/USBPrinting/USBPrinterOutputDevice.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index da3dfa2bde..6b5fe22fcf 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -8,14 +8,12 @@ import time import queue import re import functools -import os.path from UM.Application import Application from UM.Logger import Logger -from UM.PluginRegistry import PluginRegistry from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState +from UM.Message import Message -from PyQt5.QtQml import QQmlComponent, QQmlContext from PyQt5.QtCore import QUrl, pyqtSlot, pyqtSignal from UM.i18n import i18nCatalog @@ -137,7 +135,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice): # \param gcode_list List with gcode (strings). def printGCode(self, gcode_list): if self._progress or self._connection_state != ConnectionState.connected: - self._error_message = Message(i18n_catalog.i18nc("@info:status", "Printer is busy or not connected. Unable to start a new job.")) + self._error_message = Message(catalog.i18nc("@info:status", "Printer is busy or not connected. Unable to start a new job.")) self._error_message.show() Logger.log("d", "Printer is busy or not connected, aborting print") self.writeError.emit(self) From 8eef34ac4587630cfecbe6efee5f5f8123150c86 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 21 Jul 2016 10:30:22 +0200 Subject: [PATCH 14/64] USB printer connection is now reset when print is completed CURA-1822 --- plugins/USBPrinting/USBPrinterOutputDevice.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index 6b5fe22fcf..7bd5b66cc2 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -502,6 +502,13 @@ class USBPrinterOutputDevice(PrinterOutputDevice): # It will be normalized (based on max_progress) to range 0 - 100 def setProgress(self, progress, max_progress = 100): self._progress = (progress / max_progress) * 100 # Convert to scale of 0-100 + if self._progress == 100: + # Printing is done, reset progress + self._gcode_position = 0 + self.setProgress(0) + self._is_printing = False + self._is_paused = False + self._updateJobState("ready") self.progressChanged.emit() ## Cancel the current print. Printer connection wil continue to listen. From 6602177102ab3a0b10c3155b4f584b767dded342 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 21 Jul 2016 13:20:37 +0200 Subject: [PATCH 15/64] Removed unneeded getMeshData call CURA-1622 --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 79bb21cd15..82cc769172 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -854,7 +854,7 @@ class CuraApplication(QtApplication): # TODO; This needs to be fixed properly. We now make the assumption that we only load a single mesh! mesh_data = job.getResult().getMeshData() if mesh_data: - job._node.setMeshData(job.getResult().getMeshData()) + job._node.setMeshData(mesh_data) else: Logger.log("w", "Could not find a mesh in reloaded node.") From 121cd19e83be480d590d5fef48bfbed3087124f0 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 16 Jul 2016 13:10:50 +0200 Subject: [PATCH 16/64] Disable the settings in the global tab CURA-1758 --- cura/Settings/ExtruderManager.py | 6 ++++++ resources/qml/Settings/SettingView.qml | 19 ++++++++++--------- resources/qml/SidebarHeader.qml | 2 ++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 744a6811c5..987b161776 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -41,6 +41,12 @@ class ExtruderManager(QObject): except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong. return None + @pyqtProperty(int, notify = extrudersChanged) + def extruderCount(self): + if not UM.Application.getInstance().getGlobalContainerStack(): + return 0 # No active machine, so no extruders. + return len(self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]) + ## The instance of the singleton pattern. # # It's None if the extruder manager hasn't been created yet. diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 39f0f833b8..faa7bf94cb 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -34,14 +34,7 @@ ScrollView expanded: Printer.expandedCategories onExpandedChanged: Printer.setExpandedCategories(expanded) - filter: - { - if(ExtruderManager.activeExtruderStackId) - { - return { "settable_per_extruder": true } - } - return { } - } + filter: {} } delegate: Loader @@ -53,7 +46,15 @@ ScrollView Behavior on height { NumberAnimation { duration: 100 } } opacity: provider.properties.enabled == "True" ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 100 } } - enabled: provider.properties.enabled == "True" + enabled: + { + if(!ExtruderManager.activeExtruderStackId && ExtruderManager.extruderCount > 0) + { + // disable all controls on the global tab, except categories + return model.type == "category" + } + return provider.properties.enabled == "True" + } property var definition: model property var settingDefinitionsModel: definitionsModel diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index aa6f2c0067..e6c3e8a86c 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -258,6 +258,8 @@ Column { id: globalProfileSelection text: Cura.MachineManager.activeQualityName + enabled: !extrudersList.visible || base.currentExtruderIndex > -1 + width: parent.width * 0.55 + UM.Theme.getSize("default_margin").width height: UM.Theme.getSize("setting_control").height tooltip: Cura.MachineManager.activeQualityName From 8537c5a0e21ada157e1dd8483d6b7b1df4738956 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 16 Jul 2016 13:14:04 +0200 Subject: [PATCH 17/64] Introduce a property that says which extruder the global stack should get its value from. CURA-1758 --- cura/CuraApplication.py | 1 + resources/definitions/fdmprinter.def.json | 37 +++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 82cc769172..5ba22002bb 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -97,6 +97,7 @@ class CuraApplication(QtApplication): SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True) + SettingDefinition.addSupportedProperty("global_inherits_stack", DefinitionPropertyType.Function, default = "0") SettingDefinition.addSettingType("extruder", int, str, Validator) ## Add the 4 types of profiles to storage. diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8f435c1e5c..e6f7766600 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -629,6 +629,7 @@ "type": "float", "enabled": "support_enable", "value": "line_width", + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": false }, @@ -643,6 +644,7 @@ "type": "float", "enabled": "support_roof_enable", "value": "line_width", + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": false }, @@ -1442,6 +1444,7 @@ "maximum_value_warning": "150", "default_value": 60, "value": "speed_print", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false, @@ -1458,6 +1461,7 @@ "maximum_value": "299792458000", "maximum_value_warning": "150", "value": "speed_support", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false @@ -1474,6 +1478,7 @@ "maximum_value_warning": "150", "enabled": "support_roof_enable and support_enable", "value": "speed_support / 1.5", + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": false } @@ -1644,6 +1649,7 @@ "maximum_value_warning": "10000", "default_value": 3000, "value": "acceleration_print", + "global_inherits_stack": "support_extruder_nr", "enabled": "acceleration_enabled and support_enable", "settable_per_mesh": false, "settable_per_extruder": false, @@ -1655,6 +1661,7 @@ "type": "float", "default_value": 3000, "value": "acceleration_support", + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0.1", "minimum_value_warning": "100", "maximum_value_warning": "10000", @@ -1669,6 +1676,7 @@ "type": "float", "default_value": 3000, "value": "acceleration_support", + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0.1", "minimum_value_warning": "100", "maximum_value_warning": "10000", @@ -1832,6 +1840,7 @@ "maximum_value_warning": "50", "default_value": 20, "value": "jerk_print", + "global_inherits_stack": "support_extruder_nr", "enabled": "jerk_enabled and support_enable", "settable_per_mesh": false, "settable_per_extruder": false, @@ -1843,6 +1852,7 @@ "type": "float", "default_value": 20, "value": "jerk_support", + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0.1", "minimum_value_warning": "5", "maximum_value_warning": "50", @@ -1857,6 +1867,7 @@ "type": "float", "default_value": 20, "value": "jerk_support", + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0.1", "minimum_value_warning": "5", "maximum_value_warning": "50", @@ -2121,6 +2132,7 @@ "description": "Enable support structures. These structures support parts of the model with severe overhangs.", "type": "bool", "default_value": false, + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": true }, "support_type": @@ -2134,6 +2146,7 @@ "everywhere": "Everywhere" }, "default_value": "everywhere", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false @@ -2147,6 +2160,7 @@ "minimum_value": "0", "maximum_value": "90", "default_value": 50, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2164,6 +2178,7 @@ "zigzag": "Zig Zag" }, "default_value": "zigzag", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false @@ -2174,6 +2189,7 @@ "description": "Connect the ZigZags. This will increase the strength of the zig zag support structure.", "type": "bool", "default_value": true, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable and (support_pattern == \"zigzag\")", "settable_per_mesh": false, "settable_per_extruder": false @@ -2187,6 +2203,7 @@ "minimum_value": "0", "maximum_value_warning": "100", "default_value": 15, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false, @@ -2201,6 +2218,7 @@ "default_value": 2.66, "enabled": "support_enable", "value": "(support_line_width * 100) / support_infill_rate * (2 if support_pattern == \"grid\" else (3 if support_pattern == \"triangles\" else 1))", + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": false } @@ -2215,6 +2233,7 @@ "minimum_value": "0", "maximum_value_warning": "10", "default_value": 0.15, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true, "children": @@ -2230,6 +2249,7 @@ "type": "float", "enabled": "support_enable", "value": "support_z_distance", + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": true }, "support_bottom_distance": @@ -2241,6 +2261,7 @@ "maximum_value_warning": "10", "default_value": 0.1, "value": "0.1 if support_type == 'everywhere' else 0", + "global_inherits_stack": "support_extruder_nr", "type": "float", "enabled": "support_enable and support_type == 'everywhere'", "settable_per_mesh": true @@ -2256,6 +2277,7 @@ "minimum_value": "0", "maximum_value_warning": "10", "default_value": 0.7, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2268,6 +2290,7 @@ "z_overrides_xy": "Z overrides X/Y" }, "default_value": "z_overrides_xy", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2280,6 +2303,7 @@ "maximum_value_warning": "10", "default_value": 0.2, "value": "machine_nozzle_size / 2", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable and support_xy_overrides_z=='z_overrides_xy'", "settable_per_mesh": true }, @@ -2290,6 +2314,7 @@ "unit": "mm", "type": "float", "default_value": 0.3, + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "1.0", "enabled": "support_enable", @@ -2302,6 +2327,7 @@ "unit": "mm", "type": "float", "default_value": 2.0, + "global_inherits_stack": "support_extruder_nr", "minimum_value_warning": "0", "maximum_value_warning": "10", "enabled": "support_enable", @@ -2314,6 +2340,7 @@ "unit": "mm", "type": "float", "default_value": 0.2, + "global_inherits_stack": "support_extruder_nr", "minimum_value_warning": "-0.5", "maximum_value_warning": "5.0", "enabled": "support_enable", @@ -2326,6 +2353,7 @@ "unit": "mm", "type": "float", "default_value": 0.6, + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "1.0", "enabled": "support_enable", @@ -2337,6 +2365,7 @@ "description": "Generate a dense top skin at the top of the support on which the model is printed.", "type": "bool", "default_value": false, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2348,6 +2377,7 @@ "type": "float", "default_value": 1, "minimum_value": "0", + "global_inherits_stack": "support_extruder_nr", "maximum_value_warning": "10", "enabled": "support_roof_enable and support_enable", "settable_per_mesh": true @@ -2359,6 +2389,7 @@ "unit": "%", "type": "float", "default_value": 100, + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "100", "enabled":"support_roof_enable and support_enable", @@ -2375,6 +2406,7 @@ "default_value": 0.4, "minimum_value": "0", "value": "0 if support_roof_density == 0 else (support_roof_line_width * 100) / support_roof_density * (2 if support_roof_pattern == \"grid\" else (3 if support_roof_pattern == \"triangles\" else 1))", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_roof_enable and support_enable", "settable_per_mesh": false, "settable_per_extruder": false @@ -2395,6 +2427,7 @@ "zigzag": "Zig Zag" }, "default_value": "concentric", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_roof_enable and support_enable", "settable_per_mesh": false, "settable_per_extruder": false @@ -2405,6 +2438,7 @@ "description": "Use specialized towers to support tiny overhang areas. These towers have a larger diameter than the region they support. Near the overhang the towers' diameter decreases, forming a roof.", "type": "bool", "default_value": true, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2415,6 +2449,7 @@ "unit": "mm", "type": "float", "default_value": 3.0, + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "10", "enabled": "support_enable and support_use_towers", @@ -2427,6 +2462,7 @@ "unit": "mm", "type": "float", "default_value": 3.0, + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "10", "maximum_value": "support_tower_diameter", @@ -2442,6 +2478,7 @@ "minimum_value": "0", "maximum_value": "90", "default_value": 65, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable and support_use_towers", "settable_per_mesh": true } From 2387da1a28fb874a947be7a7967c14e249f026c4 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 16 Jul 2016 13:16:27 +0200 Subject: [PATCH 18/64] Make the global stack value mirror the stack value appropriate for this setting CURA-1758 --- cura/Settings/MachineManager.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 0c435ba2b9..f1b093ba27 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -198,6 +198,12 @@ class MachineManager(QObject): def _onGlobalPropertyChanged(self, key, property_name): if property_name == "value": self.globalValueChanged.emit() + + if self._active_container_stack and self._active_container_stack != self._global_container_stack: + # Make the global stack value mirror the stack value appropriate for this setting + if self._active_container_stack.getProperty("extruder_nr", "value") == int(self._active_container_stack.getProperty(key, "global_inherits_stack")): + self._global_container_stack.getTop().setProperty(key, "value", self._active_container_stack.getProperty(key, "value")) + if property_name == "validationState": if self._global_stack_valid: changed_validation_state = self._active_container_stack.getProperty(key, property_name) From 97b3dd8f706559faee20a6e91310457d89babecd Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Jul 2016 10:35:36 +0200 Subject: [PATCH 19/64] Copy values of global-only setting values to all extruders CURA-1758 --- cura/Settings/ExtruderManager.py | 13 ++++++++++--- cura/Settings/MachineManager.py | 7 +++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 987b161776..78468acbcb 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -112,8 +112,11 @@ class ExtruderManager(QObject): for extruder_train in extruder_trains: self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train - # Ensure that the extruder train stacks are linked to global stack. - extruder_train.setNextStack(UM.Application.getInstance().getGlobalContainerStack()) + # Make sure the next stack is a stack that contains only the machine definition + if not extruder_train.getNextStack(): + shallowStack = UM.Settings.ContainerStack(machine_id + "_shallow") + shallowStack.addContainer(machine_definition) + extruder_train.setNextStack(shallowStack) changed = True if changed: self.extrudersChanged.emit(machine_id) @@ -226,7 +229,11 @@ class ExtruderManager(QObject): container_registry.addContainer(user_profile) container_stack.addContainer(user_profile) - container_stack.setNextStack(UM.Application.getInstance().getGlobalContainerStack()) + # Make sure the next stack is a stack that contains only the machine definition + if not container_stack.getNextStack(): + shallowStack = UM.Settings.ContainerStack(machine_id + "_shallow") + shallowStack.addContainer(machine_definition) + container_stack.setNextStack(shallowStack) container_registry.addContainer(container_stack) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index f1b093ba27..b20f9da843 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -204,6 +204,13 @@ class MachineManager(QObject): if self._active_container_stack.getProperty("extruder_nr", "value") == int(self._active_container_stack.getProperty(key, "global_inherits_stack")): self._global_container_stack.getTop().setProperty(key, "value", self._active_container_stack.getProperty(key, "value")) + # Global-only setting values should be set on all extruders at once + if not self._global_container_stack.getProperty(key, "settable_per_extruder"): + extruder_stacks = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()) + for extruder_stack in extruder_stacks: + if extruder_stacks != self._active_container_stack: + extruder_stack.getTop().setProperty(key, "value", self._active_container_stack.getProperty(key, "value")) + if property_name == "validationState": if self._global_stack_valid: changed_validation_state = self._active_container_stack.getProperty(key, property_name) From 7302baa7daf69ba0f96ad46da8f141dce7a4fb88 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Jul 2016 13:20:37 +0200 Subject: [PATCH 20/64] Add icon to settings that can only be set globally (for all extruders) CURA-1758 --- .../PerObjectSettingsPanel.qml | 1 + resources/qml/Settings/SettingItem.qml | 23 +- resources/qml/Settings/SettingView.qml | 2 +- resources/themes/cura/icons/link.svg | 43 + resources/themes/cura/icons/reset.svg | 10365 ---------------- 5 files changed, 67 insertions(+), 10367 deletions(-) create mode 100644 resources/themes/cura/icons/link.svg diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 546b7086e6..54783f02b0 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -181,6 +181,7 @@ Item { onLoaded: { settingLoader.item.showRevertButton = false settingLoader.item.showInheritButton = false + settingLoader.item.showLinkedSettingIcon = false settingLoader.item.doDepthIndentation = false } diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index a7bdabb3c5..1609e30080 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -21,10 +21,12 @@ Item { property var showRevertButton: true property var showInheritButton: true + property var showLinkedSettingIcon: true property var doDepthIndentation: true // Create properties to put property provider stuff in (bindings break in qt 5.5.1 otherwise) property var state: propertyProvider.properties.state + property var settablePerExtruder: propertyProvider.properties.settable_per_extruder property var stackLevels: propertyProvider.stackLevels property var stackLevel: stackLevels[0] @@ -131,6 +133,26 @@ Item { verticalCenter: parent.verticalCenter } + UM.SimpleButton + { + id: linkedSettingIcon; + + visible: base.settablePerExtruder != "True" && base.showLinkedSettingIcon + + height: parent.height; + width: height; + + backgroundColor: UM.Theme.getColor("setting_control"); + hoverBackgroundColor: UM.Theme.getColor("setting_control") + color: UM.Theme.getColor("setting_control_button") + hoverColor: UM.Theme.getColor("setting_control_button") + + iconSource: UM.Theme.getIcon("link") + + onEntered: { hoverTimer.stop(); base.showTooltip(catalog.i18nc("@label", "This setting is always shared between all extruders. Changing it here will change the value for all extruders")) } + onExited: base.showTooltip(base.tooltipText); + } + UM.SimpleButton { id: revertButton; @@ -231,7 +253,6 @@ Item { onEntered: { hoverTimer.stop(); base.showTooltip(catalog.i18nc("@label", "This setting is normally calculated, but it currently has an absolute value set.\n\nClick to restore the calculated value.")) } onExited: base.showTooltip(base.tooltipText); } - } Item diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index faa7bf94cb..a2aa5be197 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -95,7 +95,7 @@ ScrollView containerStackId: ExtruderManager.activeExtruderStackId ? ExtruderManager.activeExtruderStackId : Cura.MachineManager.activeMachineId key: model.key ? model.key : "" - watchedProperties: [ "value", "enabled", "state", "validationState" ] + watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder" ] storeIndex: 0 } diff --git a/resources/themes/cura/icons/link.svg b/resources/themes/cura/icons/link.svg new file mode 100644 index 0000000000..7cc2778846 --- /dev/null +++ b/resources/themes/cura/icons/link.svg @@ -0,0 +1,43 @@ + +image/svg+xml \ No newline at end of file diff --git a/resources/themes/cura/icons/reset.svg b/resources/themes/cura/icons/reset.svg index fae303d2a1..4772d446d7 100644 --- a/resources/themes/cura/icons/reset.svg +++ b/resources/themes/cura/icons/reset.svg @@ -27,10369 +27,4 @@ c-1.128,0.65-2.448,0.967-3.679,1.439C-0.113,107.552-0.113,69.744-0.113,31.935z"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 3923d435672e3459c3bfd7d1befa1b305f33e0dd Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Jul 2016 14:58:48 +0200 Subject: [PATCH 21/64] Disable simple mode controls on global tab CURA-1758 --- resources/qml/SidebarSimple.qml | 46 +++++++++++++++++++++++++++----- resources/themes/cura/theme.json | 2 +- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 04b93e7d2a..2b7ed7e3cd 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -19,6 +19,7 @@ Item property Action configureSettings; property variant minimumPrintTime: PrintInformation.minimumPrintTime; property variant maximumPrintTime: PrintInformation.maximumPrintTime; + property bool settingsEnabled: ExtruderManager.activeExtruderStackId || ExtruderManager.extruderCount == 0 Component.onCompleted: PrintInformation.enabled = true Component.onDestruction: PrintInformation.enabled = false @@ -81,7 +82,11 @@ Item height: width border.color: { - if(infillListView.activeIndex == index) + if(!base.settingsEnabled) + { + return UM.Theme.getColor("setting_control_disabled_border") + } + else if(infillListView.activeIndex == index) { return UM.Theme.getColor("setting_control_selected") } @@ -92,7 +97,17 @@ Item return UM.Theme.getColor("setting_control_border") } border.width: UM.Theme.getSize("default_lining").width - color: infillListView.activeIndex == index ? UM.Theme.getColor("setting_control_selected") : "transparent" + color: { + if(infillListView.activeIndex == index) + { + if(!base.settingsEnabled) + { + return UM.Theme.getColor("setting_control_disabled_text") + } + return UM.Theme.getColor("setting_control_selected") + } + return "transparent" + } UM.RecolorImage { id: infillIcon @@ -102,13 +117,24 @@ Item sourceSize.width: width sourceSize.height: width source: UM.Theme.getIcon(model.icon); - color: (infillListView.activeIndex == index) ? UM.Theme.getColor("text_white") : UM.Theme.getColor("text") + color: { + if(infillListView.activeIndex == index) + { + return UM.Theme.getColor("text_reversed") + } + if(!base.settingsEnabled) + { + return UM.Theme.getColor("setting_control_disabled_text") + } + return UM.Theme.getColor("text") + } } MouseArea { id: infillMouseArea anchors.fill: parent hoverEnabled: true + enabled: base.settingsEnabled onClicked: { if (infillListView.activeIndex != index) { @@ -206,13 +232,15 @@ Item //: Setting enable skirt adhesion checkbox text: catalog.i18nc("@option:check", "Print Brim"); style: UM.Theme.styles.checkbox; + enabled: base.settingsEnabled - checked: platformAdhesionType.properties.value == "brim" + checked: {print(platformAdhesionType.properties.value); return platformAdhesionType.properties.value == "brim"} MouseArea { id: brimMouseArea anchors.fill: parent hoverEnabled: true + enabled: base.settingsEnabled onClicked: { platformAdhesionType.setPropertyValue("value", !parent.checked ? "brim" : "skirt") @@ -254,12 +282,14 @@ Item //: Setting enable support checkbox text: catalog.i18nc("@option:check", "Print Support Structure"); style: UM.Theme.styles.checkbox; + enabled: base.settingsEnabled checked: supportEnabled.properties.value == "True" MouseArea { id: supportMouseArea anchors.fill: parent hoverEnabled: true + enabled: base.settingsEnabled onClicked: { supportEnabled.setPropertyValue("value", !parent.checked) @@ -288,6 +318,7 @@ Item width: parent.width / 100 * 45 style: UM.Theme.styles.combobox + enabled: base.settingsEnabled property alias _hovered: supportExtruderMouseArea.containsMouse currentIndex: supportEnabled.properties.value == "True" ? parseFloat(supportExtruderNr.properties.value) + 1 : 0 @@ -303,6 +334,7 @@ Item id: supportExtruderMouseArea anchors.fill: parent hoverEnabled: true + enabled: base.settingsEnabled acceptedButtons: Qt.NoButton onEntered: { @@ -382,7 +414,7 @@ Item { id: platformAdhesionType - containerStackId: Cura.MachineManager.activeMachineId + containerStackId: Cura.MachineManager.activeStackId key: "adhesion_type" watchedProperties: [ "value" ] storeIndex: 0 @@ -392,7 +424,7 @@ Item { id: supportEnabled - containerStackId: Cura.MachineManager.activeMachineId + containerStackId: Cura.MachineManager.activeStackId key: "support_enable" watchedProperties: [ "value" ] storeIndex: 0 @@ -412,7 +444,7 @@ Item { id: supportExtruderNr - containerStackId: Cura.MachineManager.activeMachineId + containerStackId: Cura.MachineManager.activeStackId key: "support_extruder_nr" watchedProperties: [ "value" ] storeIndex: 0 diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index 053e5e3d84..69fc2c2c71 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -56,7 +56,7 @@ "text_inactive": [174, 174, 174, 255], "text_hover": [70, 84, 113, 255], "text_pressed": [12, 169, 227, 255], - "text_white": [255, 255, 255, 255], + "text_reversed": [255, 255, 255, 255], "text_subtext": [70, 84, 113, 255], "error": [255, 140, 0, 255], From 64c870a3cf841822f9fe7eb3be394684b51e2614 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Jul 2016 15:03:55 +0200 Subject: [PATCH 22/64] Disable setting support_enable per extruder This prevents a lot of confusion with setting the support_extruder_nr to an extruder which then has support_enable set to False (resulting in no support). It is still possible to print some objects with no support using the Per Object Settings tool. CURA-1758 --- resources/definitions/fdmprinter.def.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index e6f7766600..a4a3e93f44 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2133,7 +2133,8 @@ "type": "bool", "default_value": false, "global_inherits_stack": "support_extruder_nr", - "settable_per_mesh": true + "settable_per_mesh": true, + "settable_per_extruder": false }, "support_type": { From efa2099912c72830fb5a7c4899aa78a095b29f7c Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Jul 2016 15:07:48 +0200 Subject: [PATCH 23/64] Remove stray debug code CURA-1758 --- resources/qml/SidebarSimple.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 2b7ed7e3cd..0e1b04cdeb 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -234,7 +234,7 @@ Item style: UM.Theme.styles.checkbox; enabled: base.settingsEnabled - checked: {print(platformAdhesionType.properties.value); return platformAdhesionType.properties.value == "brim"} + checked: platformAdhesionType.properties.value == "brim" MouseArea { id: brimMouseArea From a48b3b73983524149d2a099ae6f2dd0a4a810874 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Jul 2016 15:15:10 +0200 Subject: [PATCH 24/64] Select first extruder when switching to a printer The days of the global tab are numbered CURA-1758 --- cura/Settings/ExtruderManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 78468acbcb..bfbf8247f8 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -22,7 +22,7 @@ class ExtruderManager(QObject): def __init__(self, parent = None): super().__init__(parent) self._extruder_trains = { } #Per machine, a dictionary of extruder container stack IDs. - self._active_extruder_index = -1 + self._active_extruder_index = 0 UM.Application.getInstance().globalContainerStackChanged.connect(self.__globalContainerStackChanged) self._addCurrentMachineExtruders() From 8a6f41d7e784303773903e6cd2eb439081de4ef3 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Jul 2016 15:50:01 +0200 Subject: [PATCH 25/64] Initialise multiextrusion global stacks to empty profiles CURA-1758 --- cura/Settings/MachineManager.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index b20f9da843..58cc722d5e 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -206,10 +206,11 @@ class MachineManager(QObject): # Global-only setting values should be set on all extruders at once if not self._global_container_stack.getProperty(key, "settable_per_extruder"): + new_value = self._active_container_stack.getProperty(key, "value") extruder_stacks = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()) for extruder_stack in extruder_stacks: - if extruder_stacks != self._active_container_stack: - extruder_stack.getTop().setProperty(key, "value", self._active_container_stack.getProperty(key, "value")) + if extruder_stack != self._active_container_stack: + extruder_stack.getTop().setProperty(key, "value", new_value) if property_name == "validationState": if self._global_stack_valid: @@ -290,9 +291,15 @@ class MachineManager(QObject): new_global_stack.addMetaDataEntry("type", "machine") UM.Settings.ContainerRegistry.getInstance().addContainer(new_global_stack) - variant_instance_container = self._updateVariantContainer(definition) - material_instance_container = self._updateMaterialContainer(definition, variant_instance_container) - quality_instance_container = self._updateQualityContainer(definition, material_instance_container) + if definition.getProperty("machine_extruder_count", "value") == 1: + variant_instance_container = self._updateVariantContainer(definition) + material_instance_container = self._updateMaterialContainer(definition, variant_instance_container) + quality_instance_container = self._updateQualityContainer(definition, material_instance_container) + else: + # Initialise multiextrusion global stacks to empty profiles; all settings go in the user profile + variant_instance_container = self._empty_variant_container + material_instance_container = self._empty_material_container + quality_instance_container = self._empty_quality_container current_settings_instance_container = UM.Settings.InstanceContainer(name + "_current_settings") current_settings_instance_container.addMetaDataEntry("machine", name) From a31ffc4ebf277965089b50a31d62cf9b1f6b739b Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Jul 2016 16:19:37 +0200 Subject: [PATCH 26/64] Select first extruder when switching to a printer (continued) The days of the global tab are numbered CURA-1758 --- resources/qml/SidebarHeader.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index e6c3e8a86c..ba7c94b079 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -91,8 +91,8 @@ Column target: Cura.MachineManager onGlobalContainerChanged: { - base.currentExtruderIndex = -1; - forceActiveFocus() + forceActiveFocus() // Changing focus applies the currently-being-typed values so it can change the displayed setting values. + base.currentExtruderIndex = (machineExtruderCount.properties.value == 1) ? -1 : 0; ExtruderManager.setActiveExtruderIndex(base.currentExtruderIndex); } } @@ -110,7 +110,7 @@ Column onClicked: { - forceActiveFocus() //Changing focus applies the currently-being-typed values so it can change the displayed setting values. + forceActiveFocus() // Changing focus applies the currently-being-typed values so it can change the displayed setting values. base.currentExtruderIndex = index; ExtruderManager.setActiveExtruderIndex(index); } From 5d613bd22e1e237ab5ce00110f85c88b1756fc3e Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Jul 2016 18:46:54 +0200 Subject: [PATCH 27/64] Make sure _active_container_stack is properly initiated CURA-1758 --- cura/Settings/MachineManager.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 58cc722d5e..7abd5b102b 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -58,7 +58,9 @@ class MachineManager(QObject): if active_machine_id != "": # An active machine was saved, so restore it. self.setActiveMachine(active_machine_id) - pass + if self._global_container_stack.getProperty("machine_extruder_count", "value") > 1: + # Make sure _active_container_stack is properly initiated + ExtruderManager.getInstance().setActiveExtruderIndex(0) self._auto_change_material_hotend_flood_window = 10 # The minimum number of seconds between asking if the material or hotend on the machine should be used self._auto_change_material_hotend_flood_time = 0 # The last timestamp (in seconds) when the user was asked about changing the material or hotend to whatis loaded on the machine From 16315b6e1d5807a513cabb61fe753f2b27d27a80 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 19 Jul 2016 08:50:03 +0200 Subject: [PATCH 28/64] Fix reset value icon on non-per-extruder-settable settings CURA-1758 --- cura/Settings/MachineManager.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7abd5b102b..644c7d7843 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -206,13 +206,22 @@ class MachineManager(QObject): if self._active_container_stack.getProperty("extruder_nr", "value") == int(self._active_container_stack.getProperty(key, "global_inherits_stack")): self._global_container_stack.getTop().setProperty(key, "value", self._active_container_stack.getProperty(key, "value")) - # Global-only setting values should be set on all extruders at once + # Global-only setting values should be set on all extruders and the global stack if not self._global_container_stack.getProperty(key, "settable_per_extruder"): new_value = self._active_container_stack.getProperty(key, "value") - extruder_stacks = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()) - for extruder_stack in extruder_stacks: + active_stack_has_user_value = self._active_container_stack.getTop().getInstance(key) != None + + for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()): if extruder_stack != self._active_container_stack: - extruder_stack.getTop().setProperty(key, "value", new_value) + if active_stack_has_user_value: + extruder_stack.getTop().setProperty(key, "value", new_value) + else: + # Remove from the value from the other stacks as well, unless the + # resulting value from the other stacklevels is different + extruder_stack.getTop().removeInstance(key) + if extruder_stack.getProperty(key, "value") != new_value: + extruder_stack.getTop().setProperty(key, "value", new_value) + self._global_container_stack.getTop().setProperty(key, "value", new_value) if property_name == "validationState": if self._global_stack_valid: From 81f9467ca0d14efc9e86c79f145c0d587be7ce99 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 19 Jul 2016 16:28:24 +0200 Subject: [PATCH 29/64] Update the global value when the "global_inherits_stack" value changes CURA-1758 --- cura/Settings/MachineManager.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 644c7d7843..d97748dfb3 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -223,6 +223,17 @@ class MachineManager(QObject): extruder_stack.getTop().setProperty(key, "value", new_value) self._global_container_stack.getTop().setProperty(key, "value", new_value) + if property_name == "global_inherits_stack": + if self._active_container_stack and self._active_container_stack != self._global_container_stack: + # Update the global user value when the "global_inherits_stack" function points to a different stack + stack_index = int(self._active_container_stack.getProperty(key, property_name)) + extruder_stacks = [stack for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())] + + if len(extruder_stacks) > stack_index: + new_value = extruder_stacks[stack_index].getProperty(key, "value") + if self._global_container_stack.getProperty(key, "value") != new_value: + self._global_container_stack.getTop().setProperty(key, "value", new_value) + if property_name == "validationState": if self._global_stack_valid: changed_validation_state = self._active_container_stack.getProperty(key, property_name) From 2e75430d0ed804ab64ba2890ca373e652cc3e184 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 21 Jul 2016 08:18:49 +0200 Subject: [PATCH 30/64] Update the global container when switching variant/material/quality profiles CURA-1758 --- cura/Settings/MachineManager.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index d97748dfb3..8d907ad8af 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -221,7 +221,8 @@ class MachineManager(QObject): extruder_stack.getTop().removeInstance(key) if extruder_stack.getProperty(key, "value") != new_value: extruder_stack.getTop().setProperty(key, "value", new_value) - self._global_container_stack.getTop().setProperty(key, "value", new_value) + if self._global_container_stack.getProperty(key, "value") != new_value: + self._global_container_stack.getTop().setProperty(key, "value", new_value) if property_name == "global_inherits_stack": if self._active_container_stack and self._active_container_stack != self._global_container_stack: @@ -290,6 +291,31 @@ class MachineManager(QObject): def _onInstanceContainersChanged(self, container): container_type = container.getMetaDataEntry("type") + + if self._active_container_stack and self._active_container_stack != self._global_container_stack: + global_container = self._global_container_stack.findContainer({"type": container_type}) + if global_container: + # rebuild the global equivalent of the changed container + global_container.clear() + + # get the keys from the containers of this type from all stacks + stacks = [stack for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())] + keys = [] + for extruder_stack in stacks: + if extruder_stack == self._active_container_stack: + extruder_container = container + else: + extruder_container = extruder_stack.findContainer({"type": container_type}) + if extruder_container: + keys += extruder_container.getAllKeys() + keys = list(set(keys)) + + # set the value of the global container to the value of the inherit stack - if any + for key in keys: + inherit_stack_index = int(self._active_container_stack.getProperty(key, "global_inherits_stack")) + if stacks[inherit_stack_index].hasProperty(key, "value"): + global_container.setProperty(key, "value", stacks[inherit_stack_index].getProperty(key, "value")) + if container_type == "material": self.activeMaterialChanged.emit() elif container_type == "variant": From fa8b58844d6fd9146b1fa9060bb451ce4c51d7d3 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 21 Jul 2016 09:42:33 +0200 Subject: [PATCH 31/64] Initialise multiextrusion global stacks to new empty profiles _EmptyInstanceContainer does not allow setting properties and does not emit signals CURA-1758 --- cura/Settings/MachineManager.py | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 8d907ad8af..6820cbcd2c 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -331,29 +331,48 @@ class MachineManager(QObject): @pyqtSlot(str, str) def addMachine(self, name, definition_id): - definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id = definition_id) + container_registry = UM.Settings.ContainerRegistry.getInstance() + definitions = container_registry.findDefinitionContainers(id = definition_id) if definitions: definition = definitions[0] name = self._createUniqueName("machine", "", name, definition.getName()) new_global_stack = UM.Settings.ContainerStack(name) new_global_stack.addMetaDataEntry("type", "machine") - UM.Settings.ContainerRegistry.getInstance().addContainer(new_global_stack) + container_registry.addContainer(new_global_stack) if definition.getProperty("machine_extruder_count", "value") == 1: variant_instance_container = self._updateVariantContainer(definition) material_instance_container = self._updateMaterialContainer(definition, variant_instance_container) quality_instance_container = self._updateQualityContainer(definition, material_instance_container) else: - # Initialise multiextrusion global stacks to empty profiles; all settings go in the user profile - variant_instance_container = self._empty_variant_container - material_instance_container = self._empty_material_container - quality_instance_container = self._empty_quality_container + # Initialise multiextrusion global stacks to new empty profiles + # These will mirror values from the extruder stacks + variant_instance_container = UM.Settings.InstanceContainer(name + "_global_variant") + variant_instance_container.addMetaDataEntry("machine", name) + variant_instance_container.addMetaDataEntry("type", "variant") + variant_instance_container.setDefinition(definitions[0]) + variant_instance_container.setName("global") + container_registry.addContainer(variant_instance_container) + + material_instance_container = UM.Settings.InstanceContainer(name + "_global_material") + material_instance_container.addMetaDataEntry("machine", name) + material_instance_container.addMetaDataEntry("type", "material") + material_instance_container.setDefinition(definitions[0]) + material_instance_container.setName("global") + container_registry.addContainer(material_instance_container) + + quality_instance_container = UM.Settings.InstanceContainer(name + "_global_quality") + quality_instance_container.addMetaDataEntry("machine", name) + quality_instance_container.addMetaDataEntry("type", "quality") + quality_instance_container.setDefinition(definitions[0]) + quality_instance_container.setName("global") + container_registry.addContainer(quality_instance_container) current_settings_instance_container = UM.Settings.InstanceContainer(name + "_current_settings") current_settings_instance_container.addMetaDataEntry("machine", name) current_settings_instance_container.addMetaDataEntry("type", "user") current_settings_instance_container.setDefinition(definitions[0]) - UM.Settings.ContainerRegistry.getInstance().addContainer(current_settings_instance_container) + container_registry.addContainer(current_settings_instance_container) # If a definition is found, its a list. Should only have one item. new_global_stack.addContainer(definition) From 89b601791d106780c7655371a34d1ef70a5c53cc Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 21 Jul 2016 09:55:08 +0200 Subject: [PATCH 32/64] Fix possible error when a printer fails to load CURA-1758 --- 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 6820cbcd2c..9fe60f3ef1 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -58,7 +58,7 @@ class MachineManager(QObject): if active_machine_id != "": # An active machine was saved, so restore it. self.setActiveMachine(active_machine_id) - if self._global_container_stack.getProperty("machine_extruder_count", "value") > 1: + if self._global_container_stack and self._global_container_stack.getProperty("machine_extruder_count", "value") > 1: # Make sure _active_container_stack is properly initiated ExtruderManager.getInstance().setActiveExtruderIndex(0) From 0857017ac6730d26d8aac5a5f49f175f6e243c53 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 21 Jul 2016 11:21:35 +0200 Subject: [PATCH 33/64] Add a context-menu item to copy a value to all extruders. CURA-1758 --- cura/Settings/MachineManager.py | 13 ++++++++++ resources/qml/Settings/SettingView.qml | 36 +++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 9fe60f3ef1..50d390dabc 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -505,6 +505,19 @@ class MachineManager(QObject): return True return containers[0].isReadOnly() + ## Copy the value of the setting of the current extruder to all other extruders as well as the global container. + @pyqtSlot(str) + def copyValueToExtruders(self, key): + if not self._active_container_stack or self._global_container_stack.getProperty("machine_extruder_count", "value") <= 1: + return + + new_value = self._active_container_stack.getProperty(key, "value") + stacks = [stack for stack in self._extruder_manager.getMachineExtruders(self._global_container_stack.getId())] + stacks.append(self._global_container_stack) + for extruder_stack in stacks: + if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: + extruder_stack.getTop().setProperty(key, "value", new_value) + @pyqtSlot(result = str) def newQualityContainerFromQualityAndUser(self): new_container_id = self.duplicateContainer(self.activeQualityId) diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index a2aa5be197..7551ec2345 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -102,7 +102,12 @@ ScrollView Connections { target: item - onContextMenuRequested: { contextMenu.key = model.key; contextMenu.popup() } + onContextMenuRequested: + { + contextMenu.key = model.key; + contextMenu.provider = provider + contextMenu.popup(); + } onShowTooltip: base.showTooltip(delegate, { x: 0, y: delegate.height / 2 }, text) onHideTooltip: base.hideTooltip() } @@ -134,9 +139,24 @@ ScrollView Menu { - id: contextMenu; + id: contextMenu - property string key; + property string key + property var provider + + MenuItem + { + //: Settings context menu action + text: catalog.i18nc("@action:menu", "Copy value to all extruders") + visible: machineExtruderCount.properties.value > 1 + enabled: contextMenu.provider.properties.settable_per_extruder != "False" + onTriggered: Cura.MachineManager.copyValueToExtruders(contextMenu.key) + } + + MenuSeparator + { + visible: machineExtruderCount.properties.value > 1 + } MenuItem { @@ -152,5 +172,15 @@ ScrollView onTriggered: Cura.Actions.configureSettingVisibility.trigger(contextMenu); } } + + UM.SettingPropertyProvider + { + id: machineExtruderCount + + containerStackId: Cura.MachineManager.activeMachineId + key: "machine_extruder_count" + watchedProperties: [ "value" ] + storeIndex: 0 + } } } From baf9d81e471e266dc2ea27c8d3c9da507c66f2a7 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 21 Jul 2016 14:09:49 +0200 Subject: [PATCH 34/64] Massively simplify the strategy This removes the *_global_variant, *_global_material and *_global_quality profiles and instead uses the same profiles for the global stack as for extrude 0. CURA-1758 --- cura/Settings/MachineManager.py | 76 +++++++++------------------------ 1 file changed, 21 insertions(+), 55 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 50d390dabc..b444be27a5 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -202,9 +202,10 @@ class MachineManager(QObject): self.globalValueChanged.emit() if self._active_container_stack and self._active_container_stack != self._global_container_stack: - # Make the global stack value mirror the stack value appropriate for this setting + # Make the global current settings mirror the stack values appropriate for this setting if self._active_container_stack.getProperty("extruder_nr", "value") == int(self._active_container_stack.getProperty(key, "global_inherits_stack")): - self._global_container_stack.getTop().setProperty(key, "value", self._active_container_stack.getProperty(key, "value")) + new_value = self._active_container_stack.getProperty(key, "value") + self._global_container_stack.getTop().setProperty(key, "value", new_value) # Global-only setting values should be set on all extruders and the global stack if not self._global_container_stack.getProperty(key, "settable_per_extruder"): @@ -217,10 +218,17 @@ class MachineManager(QObject): extruder_stack.getTop().setProperty(key, "value", new_value) else: # Remove from the value from the other stacks as well, unless the - # resulting value from the other stacklevels is different - extruder_stack.getTop().removeInstance(key) - if extruder_stack.getProperty(key, "value") != new_value: - extruder_stack.getTop().setProperty(key, "value", new_value) + # top value from the other stacklevels is different than the new value + for container in extruder_stack.getContainers(): + if container == extruder_stack.getTop(): + continue + if container.__class__ == UM.Settings.InstanceContainer and container.getInstance(key) != None: + if container.getProperty(key, "value") != new_value: + extruder_stack.getTop().setProperty(key, "value", new_value) + else: + extruder_stack.getTop().removeInstance(key) + break + if self._global_container_stack.getProperty(key, "value") != new_value: self._global_container_stack.getTop().setProperty(key, "value", new_value) @@ -292,29 +300,11 @@ class MachineManager(QObject): def _onInstanceContainersChanged(self, container): container_type = container.getMetaDataEntry("type") - if self._active_container_stack and self._active_container_stack != self._global_container_stack: + if self._active_container_stack and int(self._active_container_stack.getProperty("extruder_nr", "value")) == 0: global_container = self._global_container_stack.findContainer({"type": container_type}) - if global_container: - # rebuild the global equivalent of the changed container - global_container.clear() - - # get the keys from the containers of this type from all stacks - stacks = [stack for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())] - keys = [] - for extruder_stack in stacks: - if extruder_stack == self._active_container_stack: - extruder_container = container - else: - extruder_container = extruder_stack.findContainer({"type": container_type}) - if extruder_container: - keys += extruder_container.getAllKeys() - keys = list(set(keys)) - - # set the value of the global container to the value of the inherit stack - if any - for key in keys: - inherit_stack_index = int(self._active_container_stack.getProperty(key, "global_inherits_stack")) - if stacks[inherit_stack_index].hasProperty(key, "value"): - global_container.setProperty(key, "value", stacks[inherit_stack_index].getProperty(key, "value")) + if global_container and global_container != container: + container_index = self._global_container_stack.getContainerIndex(global_container) + self._global_container_stack.replaceContainer(container_index, container) if container_type == "material": self.activeMaterialChanged.emit() @@ -340,33 +330,9 @@ class MachineManager(QObject): new_global_stack.addMetaDataEntry("type", "machine") container_registry.addContainer(new_global_stack) - if definition.getProperty("machine_extruder_count", "value") == 1: - variant_instance_container = self._updateVariantContainer(definition) - material_instance_container = self._updateMaterialContainer(definition, variant_instance_container) - quality_instance_container = self._updateQualityContainer(definition, material_instance_container) - else: - # Initialise multiextrusion global stacks to new empty profiles - # These will mirror values from the extruder stacks - variant_instance_container = UM.Settings.InstanceContainer(name + "_global_variant") - variant_instance_container.addMetaDataEntry("machine", name) - variant_instance_container.addMetaDataEntry("type", "variant") - variant_instance_container.setDefinition(definitions[0]) - variant_instance_container.setName("global") - container_registry.addContainer(variant_instance_container) - - material_instance_container = UM.Settings.InstanceContainer(name + "_global_material") - material_instance_container.addMetaDataEntry("machine", name) - material_instance_container.addMetaDataEntry("type", "material") - material_instance_container.setDefinition(definitions[0]) - material_instance_container.setName("global") - container_registry.addContainer(material_instance_container) - - quality_instance_container = UM.Settings.InstanceContainer(name + "_global_quality") - quality_instance_container.addMetaDataEntry("machine", name) - quality_instance_container.addMetaDataEntry("type", "quality") - quality_instance_container.setDefinition(definitions[0]) - quality_instance_container.setName("global") - container_registry.addContainer(quality_instance_container) + variant_instance_container = self._updateVariantContainer(definition) + material_instance_container = self._updateMaterialContainer(definition, variant_instance_container) + quality_instance_container = self._updateQualityContainer(definition, material_instance_container) current_settings_instance_container = UM.Settings.InstanceContainer(name + "_current_settings") current_settings_instance_container.addMetaDataEntry("machine", name) From a64e0fa8e8f6fe0e433b059be17e2c17bce0b635 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 21 Jul 2016 14:13:35 +0200 Subject: [PATCH 35/64] Fix copyValueToExtruders (rebase-accident) CURA-1758 --- 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 b444be27a5..3d59b7b1c7 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -478,7 +478,7 @@ class MachineManager(QObject): return new_value = self._active_container_stack.getProperty(key, "value") - stacks = [stack for stack in self._extruder_manager.getMachineExtruders(self._global_container_stack.getId())] + stacks = [stack for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())] stacks.append(self._global_container_stack) for extruder_stack in stacks: if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: From caa202e3d62a27438160a90834d93b174939480f Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 21 Jul 2016 15:28:10 +0200 Subject: [PATCH 36/64] Make sure values from loaded profile permeate to other stacks CURA-1758 --- cura/Settings/MachineManager.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 3d59b7b1c7..73b350d75f 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -300,11 +300,16 @@ class MachineManager(QObject): def _onInstanceContainersChanged(self, container): container_type = container.getMetaDataEntry("type") - if self._active_container_stack and int(self._active_container_stack.getProperty("extruder_nr", "value")) == 0: - global_container = self._global_container_stack.findContainer({"type": container_type}) - if global_container and global_container != container: - container_index = self._global_container_stack.getContainerIndex(global_container) - self._global_container_stack.replaceContainer(container_index, container) + if self._active_container_stack and self._active_container_stack != self._global_container_stack: + if int(self._active_container_stack.getProperty("extruder_nr", "value")) == 0: + global_container = self._global_container_stack.findContainer({"type": container_type}) + if global_container and global_container != container: + container_index = self._global_container_stack.getContainerIndex(global_container) + self._global_container_stack.replaceContainer(container_index, container) + + for key in container.getAllKeys(): + # Make sure the values in this profile are distributed to other stacks if necessary + self._onGlobalPropertyChanged(key, "value") if container_type == "material": self.activeMaterialChanged.emit() From d4744735c6fd5352a966dc176ba3988050d72671 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 21 Jul 2016 15:33:35 +0200 Subject: [PATCH 37/64] Remove global inheritance for most settings CURA-1758 --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 5ba22002bb..a6d0a3b827 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -97,7 +97,7 @@ class CuraApplication(QtApplication): SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True) - SettingDefinition.addSupportedProperty("global_inherits_stack", DefinitionPropertyType.Function, default = "0") + SettingDefinition.addSupportedProperty("global_inherits_stack", DefinitionPropertyType.Function, default = "-1") SettingDefinition.addSettingType("extruder", int, str, Validator) ## Add the 4 types of profiles to storage. From dd78561e25cfb33fcbb2e196c96bedd84c8cc62e Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 21 Jul 2016 15:35:20 +0200 Subject: [PATCH 38/64] Remove global tab CURA-1758 --- resources/qml/SidebarHeader.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index ba7c94b079..1f7fa00b54 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -84,7 +84,7 @@ Column orientation: ListView.Horizontal - model: Cura.ExtrudersModel { id: extrudersModel; addGlobal: true } + model: Cura.ExtrudersModel { id: extrudersModel; addGlobal: false } Connections { From 4346d5a233f5cecb49ed682feaec38d405e059d1 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 21 Jul 2016 20:54:02 +0200 Subject: [PATCH 39/64] Settings now point to the right extruder stack CURA-1758 --- cura/Settings/ExtruderManager.py | 4 +++ resources/qml/Settings/SettingView.qml | 38 +++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index bfbf8247f8..5afa8f0346 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -47,6 +47,10 @@ class ExtruderManager(QObject): return 0 # No active machine, so no extruders. return len(self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]) + @pyqtProperty("QVariantList", notify=extrudersChanged) + def extruderIds(self): + return [self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()][extruder].getId() for extruder in self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]] + ## The instance of the singleton pattern. # # It's None if the extruder manager hasn't been created yet. diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 7551ec2345..9f7a74be1d 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -60,6 +60,8 @@ ScrollView property var settingDefinitionsModel: definitionsModel property var propertyProvider: provider + property var stackId: ExtruderManager.activeExtruderStackId ? ExtruderManager.activeExtruderStackId : Cura.MachineManager.activeMachineId + //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989 //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes, //causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely. @@ -89,11 +91,45 @@ ScrollView } } + // Binding to ensure that the right containerstack ID is set for the provider. + // This ensures that if a setting has a global_inherits_stack id (for instance; Support speed points to the + // extruder that actually prints the support, as that is the setting we need to use to calculate the value) + Binding + { + target: provider + property: "containerStackId" + value: + { + if(inheritStackProvider.properties.global_inherits_stack == -1 || inheritStackProvider.properties.global_inherits_stack == null) + { + if( ExtruderManager.activeExtruderStackId) + { + return ExtruderManager.activeExtruderStackId + } + else + { + return Cura.MachineManager.activeMachineId + } + } + return ExtruderManager.extruderIds[inheritStackProvider.properties.global_inherits_stack] + } + } + + // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events + // so we bypass that to make a dedicated provider. + UM.SettingPropertyProvider + { + id: inheritStackProvider + containerStackId: Cura.MachineManager.activeMachineId + key: model.key + watchedProperties: [ "global_inherits_stack"] + } + UM.SettingPropertyProvider { id: provider - containerStackId: ExtruderManager.activeExtruderStackId ? ExtruderManager.activeExtruderStackId : Cura.MachineManager.activeMachineId + containerStackId: delegate.stackId key: model.key ? model.key : "" watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder" ] storeIndex: 0 From 568d30d17b85dc1fd5bd4ab784e750ac237cdb39 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 21 Jul 2016 21:19:25 +0200 Subject: [PATCH 40/64] Commented out 2 lines of code that caused issues with reset The documentation doesn't mention why the code is there, so i've commented them out for the time beeing CURA-1758 --- 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 73b350d75f..7d3efc2560 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -199,6 +199,7 @@ class MachineManager(QObject): def _onGlobalPropertyChanged(self, key, property_name): if property_name == "value": + self.globalValueChanged.emit() if self._active_container_stack and self._active_container_stack != self._global_container_stack: @@ -211,7 +212,6 @@ class MachineManager(QObject): if not self._global_container_stack.getProperty(key, "settable_per_extruder"): new_value = self._active_container_stack.getProperty(key, "value") active_stack_has_user_value = self._active_container_stack.getTop().getInstance(key) != None - for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()): if extruder_stack != self._active_container_stack: if active_stack_has_user_value: @@ -220,15 +220,16 @@ class MachineManager(QObject): # Remove from the value from the other stacks as well, unless the # top value from the other stacklevels is different than the new value for container in extruder_stack.getContainers(): - if container == extruder_stack.getTop(): - continue + # Commented out this line for a bit. Don't know why it's here, but it is causing + # issues with reset button. + #if container == extruder_stack.getTop(): + # continue if container.__class__ == UM.Settings.InstanceContainer and container.getInstance(key) != None: if container.getProperty(key, "value") != new_value: extruder_stack.getTop().setProperty(key, "value", new_value) else: extruder_stack.getTop().removeInstance(key) break - if self._global_container_stack.getProperty(key, "value") != new_value: self._global_container_stack.getTop().setProperty(key, "value", new_value) From 87b9b17f98f5eac19fa00843f9ce5c7441643bf4 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 21 Jul 2016 21:42:02 +0200 Subject: [PATCH 41/64] Now the right extruder is actually used (instead of randomly mixing it up) CURA-1758 --- cura/Settings/ExtruderManager.py | 7 +++++-- resources/qml/Settings/SettingView.qml | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 5afa8f0346..47359a5e97 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -47,9 +47,12 @@ class ExtruderManager(QObject): return 0 # No active machine, so no extruders. return len(self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]) - @pyqtProperty("QVariantList", notify=extrudersChanged) + @pyqtProperty("QVariantMap", notify=extrudersChanged) def extruderIds(self): - return [self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()][extruder].getId() for extruder in self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]] + map = {} + for position in self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]: + map[position] = self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()][position].getId() + return map ## The instance of the singleton pattern. # diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 9f7a74be1d..cef5f86b33 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -111,7 +111,7 @@ ScrollView return Cura.MachineManager.activeMachineId } } - return ExtruderManager.extruderIds[inheritStackProvider.properties.global_inherits_stack] + return ExtruderManager.extruderIds[String(inheritStackProvider.properties.global_inherits_stack)] } } From 7e48b6ad4c732fc0edecedd87f2ce7c6c29690c3 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 22 Jul 2016 09:03:14 +0200 Subject: [PATCH 42/64] Removed global_inherit_stack from support enable and support type CURA-1758 --- resources/definitions/fdmprinter.def.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index a4a3e93f44..e7e5ffb5d3 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2132,7 +2132,6 @@ "description": "Enable support structures. These structures support parts of the model with severe overhangs.", "type": "bool", "default_value": false, - "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": true, "settable_per_extruder": false }, @@ -2147,7 +2146,6 @@ "everywhere": "Everywhere" }, "default_value": "everywhere", - "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false From 8307dba643c01efef8b37f9ce14d83da6981a950 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 22 Jul 2016 09:33:44 +0200 Subject: [PATCH 43/64] Revert "Commented out 2 lines of code that caused issues with reset" This reverts commit 568d30d17b85dc1fd5bd4ab784e750ac237cdb39. Turned out this causes recursion issue when changing materials --- cura/Settings/MachineManager.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7d3efc2560..73b350d75f 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -199,7 +199,6 @@ class MachineManager(QObject): def _onGlobalPropertyChanged(self, key, property_name): if property_name == "value": - self.globalValueChanged.emit() if self._active_container_stack and self._active_container_stack != self._global_container_stack: @@ -212,6 +211,7 @@ class MachineManager(QObject): if not self._global_container_stack.getProperty(key, "settable_per_extruder"): new_value = self._active_container_stack.getProperty(key, "value") active_stack_has_user_value = self._active_container_stack.getTop().getInstance(key) != None + for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()): if extruder_stack != self._active_container_stack: if active_stack_has_user_value: @@ -220,16 +220,15 @@ class MachineManager(QObject): # Remove from the value from the other stacks as well, unless the # top value from the other stacklevels is different than the new value for container in extruder_stack.getContainers(): - # Commented out this line for a bit. Don't know why it's here, but it is causing - # issues with reset button. - #if container == extruder_stack.getTop(): - # continue + if container == extruder_stack.getTop(): + continue if container.__class__ == UM.Settings.InstanceContainer and container.getInstance(key) != None: if container.getProperty(key, "value") != new_value: extruder_stack.getTop().setProperty(key, "value", new_value) else: extruder_stack.getTop().removeInstance(key) break + if self._global_container_stack.getProperty(key, "value") != new_value: self._global_container_stack.getTop().setProperty(key, "value", new_value) From cafb46cb1dbd485dca449976309d9a309a062ec4 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 22 Jul 2016 10:43:26 +0200 Subject: [PATCH 44/64] First container is now updated withouth recursion possible We now use a set of keys that we are handling in order to prevent the lock CURA-1758 --- cura/Settings/MachineManager.py | 10 +++++++--- resources/qml/Settings/SettingView.qml | 2 -- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 73b350d75f..58906be9d6 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -50,6 +50,8 @@ class MachineManager(QObject): Preferences.getInstance().addPreference("cura/active_machine", "") + self._global_event_keys = set() + active_machine_id = Preferences.getInstance().getValue("cura/active_machine") self._printer_output_devices = [] @@ -199,6 +201,10 @@ class MachineManager(QObject): def _onGlobalPropertyChanged(self, key, property_name): if property_name == "value": + ## We can get recursion issues. So we store a list of keys that we are still handling to prevent this. + if key in self._global_event_keys: + return + self._global_event_keys.add(key) self.globalValueChanged.emit() if self._active_container_stack and self._active_container_stack != self._global_container_stack: @@ -220,8 +226,6 @@ class MachineManager(QObject): # Remove from the value from the other stacks as well, unless the # top value from the other stacklevels is different than the new value for container in extruder_stack.getContainers(): - if container == extruder_stack.getTop(): - continue if container.__class__ == UM.Settings.InstanceContainer and container.getInstance(key) != None: if container.getProperty(key, "value") != new_value: extruder_stack.getTop().setProperty(key, "value", new_value) @@ -231,6 +235,7 @@ class MachineManager(QObject): if self._global_container_stack.getProperty(key, "value") != new_value: self._global_container_stack.getTop().setProperty(key, "value", new_value) + self._global_event_keys.remove(key) if property_name == "global_inherits_stack": if self._active_container_stack and self._active_container_stack != self._global_container_stack: @@ -254,7 +259,6 @@ class MachineManager(QObject): if not has_errors: self._global_stack_valid = True self.globalValidationChanged.emit() - def _onGlobalContainerChanged(self): if self._global_container_stack: self._global_container_stack.nameChanged.disconnect(self._onMachineNameChanged) diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index cef5f86b33..957a68b94c 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -60,8 +60,6 @@ ScrollView property var settingDefinitionsModel: definitionsModel property var propertyProvider: provider - property var stackId: ExtruderManager.activeExtruderStackId ? ExtruderManager.activeExtruderStackId : Cura.MachineManager.activeMachineId - //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989 //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes, //causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely. From df46a61d38cf6f6f3da056006fd079b0b9459ced Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 22 Jul 2016 11:44:37 +0200 Subject: [PATCH 45/64] Active stack should no longer influence changing of targeted settings CURA-1758 --- cura/Settings/MachineManager.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 58906be9d6..4afcd325f1 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -210,17 +210,23 @@ class MachineManager(QObject): if self._active_container_stack and self._active_container_stack != self._global_container_stack: # Make the global current settings mirror the stack values appropriate for this setting if self._active_container_stack.getProperty("extruder_nr", "value") == int(self._active_container_stack.getProperty(key, "global_inherits_stack")): + new_value = self._active_container_stack.getProperty(key, "value") self._global_container_stack.getTop().setProperty(key, "value", new_value) # Global-only setting values should be set on all extruders and the global stack if not self._global_container_stack.getProperty(key, "settable_per_extruder"): - new_value = self._active_container_stack.getProperty(key, "value") - active_stack_has_user_value = self._active_container_stack.getTop().getInstance(key) != None - - for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()): - if extruder_stack != self._active_container_stack: - if active_stack_has_user_value: + extruder_stacks = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())) + target_stack_position = int(self._active_container_stack.getProperty(key, "global_inherits_stack")) + if target_stack_position == -1: # Prevent -1 from selecting wrong stack. + target_stack = self._active_container_stack + else: + target_stack = extruder_stacks[target_stack_position] + new_value = target_stack.getProperty(key, "value") + target_stack_has_user_value = target_stack.getTop().getInstance(key) != None + for extruder_stack in extruder_stacks: + if extruder_stack != target_stack: + if target_stack_has_user_value: extruder_stack.getTop().setProperty(key, "value", new_value) else: # Remove from the value from the other stacks as well, unless the @@ -232,7 +238,6 @@ class MachineManager(QObject): else: extruder_stack.getTop().removeInstance(key) break - if self._global_container_stack.getProperty(key, "value") != new_value: self._global_container_stack.getTop().setProperty(key, "value", new_value) self._global_event_keys.remove(key) From 83ec6e849ab040d23ab6e74e3ecb67065c9bebc5 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 22 Jul 2016 13:16:35 +0200 Subject: [PATCH 46/64] Multiple changes when quality profiles have different values should no longer break the link CURA-1758 --- cura/Settings/MachineManager.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 4afcd325f1..79f0020603 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -236,7 +236,9 @@ class MachineManager(QObject): if container.getProperty(key, "value") != new_value: extruder_stack.getTop().setProperty(key, "value", new_value) else: - extruder_stack.getTop().removeInstance(key) + # Check if we really need to remove something. + if extruder_stack.getProperty(key, "value") != new_value: + extruder_stack.getTop().removeInstance(key) break if self._global_container_stack.getProperty(key, "value") != new_value: self._global_container_stack.getTop().setProperty(key, "value", new_value) From 1f53ce0d4d916a7e89fdbd568260d363edf47a01 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 22 Jul 2016 13:43:26 +0200 Subject: [PATCH 47/64] Fix weight calculation CURA-1038 --- cura/PrintInformation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 4dedf9db16..096170ba22 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -95,7 +95,7 @@ class PrintInformation(QObject): else: # Machine with no extruder stacks density = Application.getInstance().getGlobalContainerStack().getMetaDataEntry("properties", {}).get("density", 0) - self._material_weights.append(float(amount) * float(density)) + self._material_weights.append(float(amount) * float(density) / 1000) self._material_lengths.append(round((amount / (math.pi * r ** 2)) / 1000, 2)) self.materialLengthsChanged.emit() self.materialWeightsChanged.emit() From 9171908c8bc578a393183b53b4e842adb013df85 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 22 Jul 2016 13:44:45 +0200 Subject: [PATCH 48/64] Show weights as well as lengths CURA-1038 --- resources/qml/JobSpecs.qml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index 8e14241741..9064c4835f 100644 --- a/resources/qml/JobSpecs.qml +++ b/resources/qml/JobSpecs.qml @@ -195,15 +195,21 @@ Rectangle { color: UM.Theme.getColor("text_subtext") text: { - var amounts = []; + var lengths = []; + var weights = []; if(base.printMaterialLengths) { for(var index = 0; index < base.printMaterialLengths.length; index++) { - amounts.push(base.printMaterialLengths[index].toFixed(2)); + if(base.printMaterialLengths[index] > 0) { + lengths.push(base.printMaterialLengths[index].toFixed(2)); + weights.push(String(Math.floor(base.printMaterialWeights[index]))); + } } - } else { - amounts = ["0.00"]; } - return catalog.i18nc("@label", "%1 m").arg(amounts.join(" + ")); + if(lengths.length == 0) { + lengths = ["0.00"]; + weights = ["0"]; + } + return catalog.i18nc("@label", "%1 m / %2 g").arg(lengths.join(" + ")).arg(weights.join(" + ")); } } } From a2972e26f5e2711df6157af3615b464cc921fccc Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 22 Jul 2016 13:45:53 +0200 Subject: [PATCH 49/64] Remove the "from" convert_function for extruder settings Fixes CURA-1974 --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 82cc769172..a97522389a 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -97,7 +97,7 @@ class CuraApplication(QtApplication): SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True) - SettingDefinition.addSettingType("extruder", int, str, Validator) + SettingDefinition.addSettingType("extruder", None, str, Validator) ## Add the 4 types of profiles to storage. Resources.addStorageType(self.ResourceTypes.QualityInstanceContainer, "quality") From fa61a9e3f0a0f6efb220fa7b843717350d482322 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 22 Jul 2016 14:04:35 +0200 Subject: [PATCH 50/64] Removed bunch of unneeded global inheritance stuff CURA-1758 --- resources/definitions/fdmprinter.def.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index e7e5ffb5d3..511be7780c 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2177,7 +2177,6 @@ "zigzag": "Zig Zag" }, "default_value": "zigzag", - "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false @@ -2188,7 +2187,6 @@ "description": "Connect the ZigZags. This will increase the strength of the zig zag support structure.", "type": "bool", "default_value": true, - "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable and (support_pattern == \"zigzag\")", "settable_per_mesh": false, "settable_per_extruder": false @@ -2202,7 +2200,6 @@ "minimum_value": "0", "maximum_value_warning": "100", "default_value": 15, - "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false, @@ -2217,7 +2214,6 @@ "default_value": 2.66, "enabled": "support_enable", "value": "(support_line_width * 100) / support_infill_rate * (2 if support_pattern == \"grid\" else (3 if support_pattern == \"triangles\" else 1))", - "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": false } @@ -2388,7 +2384,6 @@ "unit": "%", "type": "float", "default_value": 100, - "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "100", "enabled":"support_roof_enable and support_enable", @@ -2405,7 +2400,6 @@ "default_value": 0.4, "minimum_value": "0", "value": "0 if support_roof_density == 0 else (support_roof_line_width * 100) / support_roof_density * (2 if support_roof_pattern == \"grid\" else (3 if support_roof_pattern == \"triangles\" else 1))", - "global_inherits_stack": "support_extruder_nr", "enabled": "support_roof_enable and support_enable", "settable_per_mesh": false, "settable_per_extruder": false @@ -2426,7 +2420,6 @@ "zigzag": "Zig Zag" }, "default_value": "concentric", - "global_inherits_stack": "support_extruder_nr", "enabled": "support_roof_enable and support_enable", "settable_per_mesh": false, "settable_per_extruder": false From 6cc6e79e65b522000df63ac359c7db730714b455 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 22 Jul 2016 14:24:52 +0200 Subject: [PATCH 51/64] Stripe objects that are outside the build volume This way they can not be confused with objects that are rendered with a (future) grey materialcolor. --- plugins/SolidView/SolidView.py | 7 +-- resources/shaders/striped.shader | 84 ++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 resources/shaders/striped.shader diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 15cf25e65e..96f60fb7cf 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -34,9 +34,10 @@ class SolidView(View): self._enabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "overhang.shader")) if not self._disabled_shader: - self._disabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "overhang.shader")) - self._disabled_shader.setUniformValue("u_diffuseColor", [0.68, 0.68, 0.68, 1.0]) - self._disabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) + self._disabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "striped.shader")) + self._disabled_shader.setUniformValue("u_diffuseColor1", [1.0, 0.28, 0.28, 1.0]) + self._disabled_shader.setUniformValue("u_diffuseColor2", [0.68, 0.68, 0.68, 1.0]) + self._disabled_shader.setUniformValue("u_width", 50.0) if Application.getInstance().getGlobalContainerStack(): if Preferences.getInstance().getValue("view/show_overhang"): diff --git a/resources/shaders/striped.shader b/resources/shaders/striped.shader new file mode 100644 index 0000000000..0114f0b2cb --- /dev/null +++ b/resources/shaders/striped.shader @@ -0,0 +1,84 @@ +[shaders] +vertex = + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewProjectionMatrix; + uniform highp mat4 u_normalMatrix; + + attribute highp vec4 a_vertex; + attribute highp vec4 a_normal; + attribute highp vec2 a_uvs; + + varying highp vec3 v_position; + varying highp vec3 v_vertex; + varying highp vec3 v_normal; + + void main() + { + vec4 world_space_vert = u_modelMatrix * a_vertex; + gl_Position = u_viewProjectionMatrix * world_space_vert; + + v_position = gl_Position.xyz; + v_vertex = world_space_vert.xyz; + v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + } + +fragment = + uniform mediump vec4 u_ambientColor; + uniform mediump vec4 u_diffuseColor1; + uniform mediump vec4 u_diffuseColor2; + uniform mediump vec4 u_specularColor; + uniform highp vec3 u_lightPosition; + uniform mediump float u_shininess; + uniform highp vec3 u_viewPosition; + + uniform mediump float u_width; + + varying highp vec3 v_position; + varying highp vec3 v_vertex; + varying highp vec3 v_normal; + + void main() + { + mediump vec4 finalColor = vec4(0.0); + mediump vec4 diffuseColor = (mod((-v_position.x + v_position.y), u_width) < (u_width / 2.)) ? u_diffuseColor1 : u_diffuseColor2; + + /* Ambient Component */ + finalColor += u_ambientColor; + + highp vec3 normal = normalize(v_normal); + highp vec3 lightDir = normalize(u_lightPosition - v_vertex); + + /* Diffuse Component */ + highp float NdotL = clamp(abs(dot(normal, lightDir)), 0.0, 1.0); + finalColor += (NdotL * diffuseColor); + + /* Specular Component */ + /* TODO: We should not do specularity for fragments facing away from the light.*/ + highp vec3 reflectedLight = reflect(-lightDir, normal); + highp vec3 viewVector = normalize(u_viewPosition - v_vertex); + highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0); + finalColor += pow(NdotR, u_shininess) * u_specularColor; + + gl_FragColor = finalColor; + gl_FragColor.a = 1.0; + } + +[defaults] +u_ambientColor = [0.3, 0.3, 0.3, 1.0] +u_diffuseColor1 = [1.0, 0.5, 0.5, 1.0] +u_diffuseColor2 = [0.5, 0.5, 0.5, 1.0] +u_specularColor = [0.4, 0.4, 0.4, 1.0] +u_shininess = 20.0 +u_width = 5.0 + +[bindings] +u_modelMatrix = model_matrix +u_viewProjectionMatrix = view_projection_matrix +u_normalMatrix = normal_matrix +u_viewPosition = view_position +u_lightPosition = light_0_position +u_diffuseColor = diffuse_color + +[attributes] +a_vertex = vertex +a_normal = normal From be252fb84f49fa185ae44fb19c92e7f59a4e9e7e Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 22 Jul 2016 15:31:37 +0200 Subject: [PATCH 52/64] We now check if a setting can also be removed to get the same state THis should prevent the reset buttons from showing up when there is nothing going on. CURA-1758 --- cura/Settings/MachineManager.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 79f0020603..d5ccfea88e 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -234,7 +234,27 @@ class MachineManager(QObject): for container in extruder_stack.getContainers(): if container.__class__ == UM.Settings.InstanceContainer and container.getInstance(key) != None: if container.getProperty(key, "value") != new_value: - extruder_stack.getTop().setProperty(key, "value", new_value) + # It could be that the setting needs to be removed instead of updated. + temp = extruder_stack + containers = extruder_stack.getContainers() + # Ensure we have the entire 'chain' + while temp.getNextStack(): + temp = temp.getNextStack() + containers.extend(temp.getContainers()) + instance_needs_removal = False + + if len(containers) > 1: + for index in range(1, len(containers)): + deeper_container = containers[index] + if deeper_container.getProperty(key, "value") == new_value: + # Removal will result in correct value, so do that. + # We do this to prevent the reset from showing up unneeded. + instance_needs_removal = True + break + if instance_needs_removal: + extruder_stack.getTop().removeInstance(key) + else: + extruder_stack.getTop().setProperty(key, "value", new_value) else: # Check if we really need to remove something. if extruder_stack.getProperty(key, "value") != new_value: From cb4c1fd08c01d40cdc3e5608018a5db9b986a0c9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 22 Jul 2016 16:45:11 +0200 Subject: [PATCH 53/64] Rename skirt_speed to skirt_brim_speed Also updated the description. Because this concerns not only the skirt, but also the brim. Contributes to issue CURA-1678. --- .../VersionUpgrade21to22/VersionUpgrade21to22.py | 4 ++++ resources/definitions/bq_hephestos_2.def.json | 2 +- resources/definitions/bq_witbox_2.def.json | 2 +- resources/definitions/fdmprinter.def.json | 6 +++--- resources/definitions/maker_starter.def.json | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py index 2493e23405..7cf3d0915e 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py @@ -31,6 +31,7 @@ _setting_name_translations = { "remove_overlapping_walls_enabled": "travel_compensate_overlapping_walls_enabled", "remove_overlapping_walls_x_enabled": "travel_compensate_overlapping_walls_x_enabled", "retraction_hop": "retraction_hop_enabled", + "skirt_speed": "skirt_brim_speed", "speed_support_lines": "speed_support_infill" } @@ -157,6 +158,9 @@ class VersionUpgrade21to22(VersionUpgrade): elif key == "retraction_hop": #Setting key was changed. del settings[key] settings["retraction_hop_enabled"] = value + elif key == "skirt_speed": #Setting key was changed. + del settings[key] + settings["skirt_brim_speed"] = value elif key == "speed_support_lines": #Setting key was changed. del settings[key] settings["speed_support_infill"] = value diff --git a/resources/definitions/bq_hephestos_2.def.json b/resources/definitions/bq_hephestos_2.def.json index 51777ff83e..920c5f5e9b 100644 --- a/resources/definitions/bq_hephestos_2.def.json +++ b/resources/definitions/bq_hephestos_2.def.json @@ -38,7 +38,7 @@ "speed_wall_0": { "default_value": 30 }, "speed_infill": { "default_value": 80 }, "speed_topbottom": { "default_value": 35 }, - "skirt_speed": { "default_value": 35 }, + "skirt_brim_speed": { "default_value": 35 }, "skirt_line_count": { "default_value": 4 }, "skirt_minimal_length": { "default_value": 30 }, "skirt_gap": { "default_value": 6 }, diff --git a/resources/definitions/bq_witbox_2.def.json b/resources/definitions/bq_witbox_2.def.json index b9d9b497cd..73dff97eeb 100644 --- a/resources/definitions/bq_witbox_2.def.json +++ b/resources/definitions/bq_witbox_2.def.json @@ -89,7 +89,7 @@ "speed_topbottom": { "default_value": 35 }, - "skirt_speed": { + "skirt_brim_speed": { "default_value": 35 }, "skirt_line_count": { diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8f435c1e5c..e8831e27cd 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1520,9 +1520,9 @@ "maximum_value_warning": "300", "settable_per_mesh": true }, - "skirt_speed": { - "label": "Skirt Speed", - "description": "The speed at which the skirt and brim are printed. Normally this is done at the initial layer speed, but sometimes you might want to print the skirt at a different speed.", + "skirt_brim_speed": { + "label": "Skirt/Brim Speed", + "description": "The speed at which the skirt and brim are printed. Normally this is done at the initial layer speed, but sometimes you might want to print the skirt or brim at a different speed.", "unit": "mm/s", "type": "float", "default_value": 30, diff --git a/resources/definitions/maker_starter.def.json b/resources/definitions/maker_starter.def.json index a26ca058f0..4d3f6e06b7 100644 --- a/resources/definitions/maker_starter.def.json +++ b/resources/definitions/maker_starter.def.json @@ -94,7 +94,7 @@ "speed_layer_0": { "default_value": 20 }, - "skirt_speed": { + "skirt_brim_speed": { "default_value": 15 }, "speed_slowdown_layers": { From 23f643aabc5a14a9202ef9e2fa709bca7ee62b39 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 22 Jul 2016 16:49:31 +0200 Subject: [PATCH 54/64] Rename setting acceleration_skirt to acceleration_skirt_brim Also updated the description. Because this concerns not only the skirt, but also the brim. Contributes to issue CURA-1678. --- 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 e8831e27cd..caaefa8d5a 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1719,9 +1719,9 @@ "enabled": "acceleration_enabled", "settable_per_mesh": true }, - "acceleration_skirt": { - "label": "Skirt Acceleration", - "description": "The acceleration with which the skirt and brim are printed. Normally this is done with the initial layer acceleration, but sometimes you might want to print the skirt at a different acceleration.", + "acceleration_skirt_brim": { + "label": "Skirt/Brim Acceleration", + "description": "The acceleration with which the skirt and brim are printed. Normally this is done with the initial layer acceleration, but sometimes you might want to print the skirt or brim at a different acceleration.", "unit": "mm/s²", "type": "float", "default_value": 3000, From 5e2f1688b47c978a27fbb40a6b1fa4732a1de17f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 22 Jul 2016 16:53:41 +0200 Subject: [PATCH 55/64] Rename setting jerk_skirt to jerk_skirt_brim Because it concerns not only the skirt, but also the brim. Contributes to issue CURA-1678. --- 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 caaefa8d5a..b433fa0725 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1907,8 +1907,8 @@ "enabled": "jerk_enabled", "settable_per_mesh": true }, - "jerk_skirt": { - "label": "Skirt Jerk", + "jerk_skirt_brim": { + "label": "Skirt/Brim Jerk", "description": "The maximum instantaneous velocity change with which the skirt and brim are printed.", "unit": "mm/s", "type": "float", From d4f96ab62daa4e573c3ec53e224cfed8d3f912dd Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 22 Jul 2016 17:00:30 +0200 Subject: [PATCH 56/64] Rename setting skirt_line_width to skirt_brim_line_width Also updated the description. Because this concerns not only the skirt, but also the brim. Contributes to issue CURA-1678. --- cura/BuildVolume.py | 6 +++--- .../VersionUpgrade21to22/VersionUpgrade21to22.py | 4 ++++ resources/definitions/fdmprinter.def.json | 8 ++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index e5bd037f1b..66428b7cba 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -364,9 +364,9 @@ class BuildVolume(SceneNode): if adhesion_type == "skirt": skirt_distance = container_stack.getProperty("skirt_gap", "value") skirt_line_count = container_stack.getProperty("skirt_line_count", "value") - skirt_size = skirt_distance + (skirt_line_count * container_stack.getProperty("skirt_line_width", "value")) + skirt_size = skirt_distance + (skirt_line_count * container_stack.getProperty("skirt_brim_line_width", "value")) elif adhesion_type == "brim": - skirt_size = container_stack.getProperty("brim_line_count", "value") * container_stack.getProperty("skirt_line_width", "value") + skirt_size = container_stack.getProperty("brim_line_count", "value") * container_stack.getProperty("skirt_brim_line_width", "value") elif adhesion_type == "raft": skirt_size = container_stack.getProperty("raft_margin", "value") @@ -381,5 +381,5 @@ class BuildVolume(SceneNode): def _clamp(self, value, min_value, max_value): return max(min(value, max_value), min_value) - _skirt_settings = ["adhesion_type", "skirt_gap", "skirt_line_count", "skirt_line_width", "brim_width", "brim_line_count", "raft_margin", "draft_shield_enabled", "draft_shield_dist", "xy_offset"] + _skirt_settings = ["adhesion_type", "skirt_gap", "skirt_line_count", "skirt_brim_line_width", "brim_width", "brim_line_count", "raft_margin", "draft_shield_enabled", "draft_shield_dist", "xy_offset"] _raft_settings = ["adhesion_type", "raft_base_thickness", "raft_interface_thickness", "raft_surface_layers", "raft_surface_thickness", "raft_airgap"] diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py index 7cf3d0915e..a429a7e64c 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py @@ -31,6 +31,7 @@ _setting_name_translations = { "remove_overlapping_walls_enabled": "travel_compensate_overlapping_walls_enabled", "remove_overlapping_walls_x_enabled": "travel_compensate_overlapping_walls_x_enabled", "retraction_hop": "retraction_hop_enabled", + "skirt_line_width": "skirt_brim_line_width", "skirt_speed": "skirt_brim_speed", "speed_support_lines": "speed_support_infill" } @@ -158,6 +159,9 @@ class VersionUpgrade21to22(VersionUpgrade): elif key == "retraction_hop": #Setting key was changed. del settings[key] settings["retraction_hop_enabled"] = value + elif key == "skirt_line_width": #Setting key was changed. + del settings[key] + settings["skirt_brim_line_width"] = value elif key == "skirt_speed": #Setting key was changed. del settings[key] settings["skirt_brim_speed"] = value diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b433fa0725..5f3bb57789 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -603,10 +603,10 @@ "value": "line_width", "settable_per_mesh": true }, - "skirt_line_width": + "skirt_brim_line_width": { - "label": "Skirt Line Width", - "description": "Width of a single skirt line.", + "label": "Skirt/Brim Line Width", + "description": "Width of a single skirt or brim line.", "unit": "mm", "minimum_value": "0.0001", "minimum_value_warning": "0.2", @@ -2557,7 +2557,7 @@ "default_value": 20, "minimum_value": "0", "maximum_value_warning": "300", - "value": "math.ceil(brim_width / skirt_line_width)", + "value": "math.ceil(brim_width / skirt_brim_line_width)", "enabled": "adhesion_type == \"brim\"", "settable_per_mesh": false, "settable_per_extruder": true From 3042b6af5fc464c3f339f954925eceb9d534e7b5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 22 Jul 2016 17:06:35 +0200 Subject: [PATCH 57/64] Rename skirt size to bed adhesion size Because it concerns not only the skirt, but also the brim and raft (and X/Y offset but I didn't include that in the name). Contributes to issue CURA-1678. --- cura/BuildVolume.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 66428b7cba..03ae28e275 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -195,18 +195,18 @@ class BuildVolume(SceneNode): minimum = Vector(min_w, min_h - 1.0, min_d), maximum = Vector(max_w, max_h - self._raft_thickness, max_d)) - skirt_size = 0.0 + bed_adhesion_size = 0.0 container_stack = Application.getInstance().getGlobalContainerStack() if container_stack: - skirt_size = self._getSkirtSize(container_stack) + bed_adhesion_size = self._getBedAdhesionSize(container_stack) # As this works better for UM machines, we only add the disallowed_area_size for the z direction. # This is probably wrong in all other cases. TODO! # The +1 and -1 is added as there is always a bit of extra room required to work properly. scale_to_max_bounds = AxisAlignedBox( - minimum = Vector(min_w + skirt_size + 1, min_h, min_d + disallowed_area_size - skirt_size + 1), - maximum = Vector(max_w - skirt_size - 1, max_h - self._raft_thickness, max_d - disallowed_area_size + skirt_size - 1) + minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + disallowed_area_size - bed_adhesion_size + 1), + maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness, max_d - disallowed_area_size + bed_adhesion_size - 1) ) Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds @@ -311,53 +311,53 @@ class BuildVolume(SceneNode): [prime_x - PRIME_CLEARANCE, prime_y + PRIME_CLEARANCE], ]) - skirt_size = self._getSkirtSize(self._active_container_stack) + bed_adhesion_size = self._getBedAdhesionSize(self._active_container_stack) if disallowed_areas: # Extend every area already in the disallowed_areas with the skirt size. for area in disallowed_areas: poly = Polygon(numpy.array(area, numpy.float32)) - poly = poly.getMinkowskiHull(Polygon(approximatedCircleVertices(skirt_size))) + poly = poly.getMinkowskiHull(Polygon(approximatedCircleVertices(bed_adhesion_size))) areas.append(poly) # Add the skirt areas around the borders of the build plate. - if skirt_size > 0: + if bed_adhesion_size > 0: half_machine_width = self._active_container_stack.getProperty("machine_width", "value") / 2 half_machine_depth = self._active_container_stack.getProperty("machine_depth", "value") / 2 areas.append(Polygon(numpy.array([ [-half_machine_width, -half_machine_depth], [-half_machine_width, half_machine_depth], - [-half_machine_width + skirt_size, half_machine_depth - skirt_size], - [-half_machine_width + skirt_size, -half_machine_depth + skirt_size] + [-half_machine_width + bed_adhesion_size, half_machine_depth - bed_adhesion_size], + [-half_machine_width + bed_adhesion_size, -half_machine_depth + bed_adhesion_size] ], numpy.float32))) areas.append(Polygon(numpy.array([ [half_machine_width, half_machine_depth], [half_machine_width, -half_machine_depth], - [half_machine_width - skirt_size, -half_machine_depth + skirt_size], - [half_machine_width - skirt_size, half_machine_depth - skirt_size] + [half_machine_width - bed_adhesion_size, -half_machine_depth + bed_adhesion_size], + [half_machine_width - bed_adhesion_size, half_machine_depth - bed_adhesion_size] ], numpy.float32))) areas.append(Polygon(numpy.array([ [-half_machine_width, half_machine_depth], [half_machine_width, half_machine_depth], - [half_machine_width - skirt_size, half_machine_depth - skirt_size], - [-half_machine_width + skirt_size, half_machine_depth - skirt_size] + [half_machine_width - bed_adhesion_size, half_machine_depth - bed_adhesion_size], + [-half_machine_width + bed_adhesion_size, half_machine_depth - bed_adhesion_size] ], numpy.float32))) areas.append(Polygon(numpy.array([ [half_machine_width, -half_machine_depth], [-half_machine_width, -half_machine_depth], - [-half_machine_width + skirt_size, -half_machine_depth + skirt_size], - [half_machine_width - skirt_size, -half_machine_depth + skirt_size] + [-half_machine_width + bed_adhesion_size, -half_machine_depth + bed_adhesion_size], + [half_machine_width - bed_adhesion_size, -half_machine_depth + bed_adhesion_size] ], numpy.float32))) self._disallowed_areas = areas ## Convenience function to calculate the size of the bed adhesion in directions x, y. - def _getSkirtSize(self, container_stack): + def _getBedAdhesionSize(self, container_stack): skirt_size = 0.0 adhesion_type = container_stack.getProperty("adhesion_type", "value") From 54685e8898dd82f9cf8248f7b59fa8582f2436e9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 22 Jul 2016 17:12:34 +0200 Subject: [PATCH 58/64] Rename setting skirt_minimal_length to skirt_brim_minimal_length Also updated the description and made it a bit more accurate. Because this concerns not only the skirt, but also the brim. Contributes to issue CURA-1678. --- plugins/LegacyProfileReader/DictionaryOfDoom.json | 2 +- .../VersionUpgrade21to22/VersionUpgrade21to22.py | 4 ++++ resources/definitions/bq_hephestos_2.def.json | 2 +- resources/definitions/bq_witbox_2.def.json | 2 +- resources/definitions/fdmprinter.def.json | 6 +++--- resources/definitions/mankati_fullscale_xt_plus.def.json | 2 +- resources/definitions/rigidbot.def.json | 2 +- resources/definitions/rigidbot_big.def.json | 2 +- 8 files changed, 13 insertions(+), 9 deletions(-) diff --git a/plugins/LegacyProfileReader/DictionaryOfDoom.json b/plugins/LegacyProfileReader/DictionaryOfDoom.json index 9dd0c04a05..471604ddbc 100644 --- a/plugins/LegacyProfileReader/DictionaryOfDoom.json +++ b/plugins/LegacyProfileReader/DictionaryOfDoom.json @@ -47,7 +47,7 @@ "adhesion_type": "\"skirt\" if (platform_adhesion == \"None\") else platform_adhesion.lower()", "skirt_line_count": "skirt_line_count", "skirt_gap": "skirt_gap", - "skirt_minimal_length": "skirt_minimal_length", + "skirt_brim_minimal_length": "skirt_minimal_length", "brim_line_count": "brim_line_count", "raft_margin": "raft_margin", "raft_airgap": "float(raft_airgap_all) + float(raft_airgap)", diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py index a429a7e64c..64ea1ac665 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py @@ -32,6 +32,7 @@ _setting_name_translations = { "remove_overlapping_walls_x_enabled": "travel_compensate_overlapping_walls_x_enabled", "retraction_hop": "retraction_hop_enabled", "skirt_line_width": "skirt_brim_line_width", + "skirt_minimal_length": "skirt_brim_minimal_length", "skirt_speed": "skirt_brim_speed", "speed_support_lines": "speed_support_infill" } @@ -159,6 +160,9 @@ class VersionUpgrade21to22(VersionUpgrade): elif key == "retraction_hop": #Setting key was changed. del settings[key] settings["retraction_hop_enabled"] = value + elif key == "skirt_minimal_length": #Setting key was changed. + del settings[key] + settings["skirt_brim_minimal_length"] = value elif key == "skirt_line_width": #Setting key was changed. del settings[key] settings["skirt_brim_line_width"] = value diff --git a/resources/definitions/bq_hephestos_2.def.json b/resources/definitions/bq_hephestos_2.def.json index 920c5f5e9b..e49e7163e8 100644 --- a/resources/definitions/bq_hephestos_2.def.json +++ b/resources/definitions/bq_hephestos_2.def.json @@ -40,7 +40,7 @@ "speed_topbottom": { "default_value": 35 }, "skirt_brim_speed": { "default_value": 35 }, "skirt_line_count": { "default_value": 4 }, - "skirt_minimal_length": { "default_value": 30 }, + "skirt_brim_minimal_length": { "default_value": 30 }, "skirt_gap": { "default_value": 6 }, "cool_fan_full_at_height": { "default_value": 0.4 } } diff --git a/resources/definitions/bq_witbox_2.def.json b/resources/definitions/bq_witbox_2.def.json index 73dff97eeb..e47d082d0f 100644 --- a/resources/definitions/bq_witbox_2.def.json +++ b/resources/definitions/bq_witbox_2.def.json @@ -95,7 +95,7 @@ "skirt_line_count": { "default_value": 4 }, - "skirt_minimal_length": { + "skirt_brim_minimal_length": { "default_value": 30 }, "skirt_gap": { diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 5f3bb57789..6f8168d4ae 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2521,10 +2521,10 @@ "settable_per_mesh": false, "settable_per_extruder": true }, - "skirt_minimal_length": + "skirt_brim_minimal_length": { - "label": "Skirt Minimum Length", - "description": "The minimum length of the skirt. If this length is not reached by the skirt line count, more skirt lines will be added until the minimum length is reached. Note: If the line count is set to 0 this is ignored.", + "label": "Skirt/Brim Minimum Length", + "description": "The minimum length of the skirt or brim. If this length is not reached by all skirt or brim lines together, more skirt or brim lines will be added until the minimum length is reached. Note: If the line count is set to 0 this is ignored.", "unit": "mm", "type": "float", "default_value": 250, diff --git a/resources/definitions/mankati_fullscale_xt_plus.def.json b/resources/definitions/mankati_fullscale_xt_plus.def.json index 57742696fb..eb8b99aaf9 100644 --- a/resources/definitions/mankati_fullscale_xt_plus.def.json +++ b/resources/definitions/mankati_fullscale_xt_plus.def.json @@ -61,6 +61,6 @@ "cool_fan_speed": { "default": 0 }, "skirt_line_count": { "default": 3 }, "skirt_gap": { "default": 4 }, - "skirt_minimal_length": { "default": 200 } + "skirt_brim_minimal_length": { "default": 200 } } } diff --git a/resources/definitions/rigidbot.def.json b/resources/definitions/rigidbot.def.json index ace8300d5d..fb8112a582 100644 --- a/resources/definitions/rigidbot.def.json +++ b/resources/definitions/rigidbot.def.json @@ -94,7 +94,7 @@ "default_value": 4, "enabled": "adhesion_type == \"Skirt\"" }, - "skirt_minimal_length": { + "skirt_brim_minimal_length": { "default_value": 200, "enabled": "adhesion_type == \"Skirt\"" } diff --git a/resources/definitions/rigidbot_big.def.json b/resources/definitions/rigidbot_big.def.json index ce27d36745..7026df646b 100644 --- a/resources/definitions/rigidbot_big.def.json +++ b/resources/definitions/rigidbot_big.def.json @@ -97,7 +97,7 @@ "default_value": 4, "enabled": "adhesion_type == \"Skirt\"" }, - "skirt_minimal_length": { + "skirt_brim_minimal_length": { "default_value": 200, "enabled": "adhesion_type == \"Skirt\"" } From 4e9bfc657398c3f2ac14271fe4cb0c41eb19a422 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 22 Jul 2016 17:23:03 +0200 Subject: [PATCH 59/64] Display some skirt/brim settings if skirt/brim enabled Some needed to be updated because they concern both skirt and brim. Others missed the check entirely. Contributes to issue CURA-1678. --- resources/definitions/fdmprinter.def.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 6f8168d4ae..024d679315 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -614,6 +614,7 @@ "default_value": 0.4, "type": "float", "value": "line_width", + "enabled": "adhesion_type == \"skirt\" or adhesion_type == \"brim\"", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1530,6 +1531,7 @@ "maximum_value": "299792458000", "maximum_value_warning": "300", "value": "speed_layer_0", + "enabled": "adhesion_type == \"skirt\" or adhesion_type == \"brim\"", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -2531,7 +2533,7 @@ "minimum_value": "0", "minimum_value_warning": "25", "maximum_value_warning": "2500", - "enabled": "adhesion_type == \"skirt\"", + "enabled": "adhesion_type == \"skirt\" or adhesion_type == \"brim\"", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -2597,7 +2599,7 @@ "value": "raft_airgap / 2", "minimum_value": "0", "maximum_value_warning": "layer_height", - "enabled": "adhesion_type == 'raft'", + "enabled": "adhesion_type == \"raft\"", "settable_per_mesh": false, "settable_per_extruder": true }, From 000c4d5f41ea377265a13b29f76019d0d0c8a7d0 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 25 Jul 2016 09:58:33 +0200 Subject: [PATCH 60/64] Fixed issue where changing a setting would cause mismatch between stacks CURA-1758 --- cura/Settings/MachineManager.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index d5ccfea88e..9f51591a58 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -246,11 +246,16 @@ class MachineManager(QObject): if len(containers) > 1: for index in range(1, len(containers)): deeper_container = containers[index] + if deeper_container.getProperty(key, "value") is None: + continue # Deeper container does not have the value, so continue. if deeper_container.getProperty(key, "value") == new_value: # Removal will result in correct value, so do that. # We do this to prevent the reset from showing up unneeded. instance_needs_removal = True break + else: + # Container has the value, but it's not the same. Stop looking. + break if instance_needs_removal: extruder_stack.getTop().removeInstance(key) else: From 374ec8e577071c7622142d73f430d682cfedd868 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 25 Jul 2016 11:30:30 +0200 Subject: [PATCH 61/64] Don't show user/quality emphasis on Per Object Settings --- plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml | 1 + resources/qml/Settings/SettingItem.qml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 546b7086e6..7695bea821 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -182,6 +182,7 @@ Item { settingLoader.item.showRevertButton = false settingLoader.item.showInheritButton = false settingLoader.item.doDepthIndentation = false + settingLoader.item.doQualityUserSettingEmphasis = false } sourceComponent: diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index a7bdabb3c5..4911bf37a4 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -22,6 +22,7 @@ Item { property var showRevertButton: true property var showInheritButton: true property var doDepthIndentation: true + property var doQualityUserSettingEmphasis: true // Create properties to put property provider stuff in (bindings break in qt 5.5.1 otherwise) property var state: propertyProvider.properties.state @@ -115,7 +116,7 @@ Item { color: UM.Theme.getColor("setting_control_text"); // emphasize the setting if it has a value in the user or quality profile - font: base.stackLevel != undefined && base.stackLevel <= 1 ? UM.Theme.getFont("default_italic") : UM.Theme.getFont("default") + font: base.doQualityUserSettingEmphasis && base.stackLevel != undefined && base.stackLevel <= 1 ? UM.Theme.getFont("default_italic") : UM.Theme.getFont("default") } Row From 87abed39f02674769753bfeb2dae16383db1f9a9 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 25 Jul 2016 11:41:54 +0200 Subject: [PATCH 62/64] Fix two warnings on startup CURA-1758 --- resources/qml/Settings/SettingView.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 957a68b94c..009dbf09a9 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -33,8 +33,6 @@ ScrollView exclude: ["machine_settings"] expanded: Printer.expandedCategories onExpandedChanged: Printer.setExpandedCategories(expanded) - - filter: {} } delegate: Loader @@ -183,7 +181,7 @@ ScrollView //: Settings context menu action text: catalog.i18nc("@action:menu", "Copy value to all extruders") visible: machineExtruderCount.properties.value > 1 - enabled: contextMenu.provider.properties.settable_per_extruder != "False" + enabled: contextMenu.provider != undefined && contextMenu.provider.properties.settable_per_extruder != "False" onTriggered: Cura.MachineManager.copyValueToExtruders(contextMenu.key) } From d9839ee41de81005636973903c873fa524f6e315 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Mon, 25 Jul 2016 13:40:19 +0200 Subject: [PATCH 63/64] SliceInfo: Using getDisplayString(ISO8601) instead --- plugins/SliceInfoPlugin/SliceInfo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 85d26a0b93..0337aee02c 100644 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -10,6 +10,7 @@ from UM.Message import Message from UM.i18n import i18nCatalog from UM.Logger import Logger from UM.Platform import Platform +from UM.Qt.Duration import DurationFormat import collections import json @@ -90,7 +91,7 @@ class SliceInfo(Extension): "settings": global_container_stack.serialize(), # global_container with references on used containers "version": Application.getInstance().getVersion(), "modelhash": "None", - "printtime": print_information.currentPrintTime.getDurationInISOFormat(), + "printtime": print_information.currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601), "filament": material_used, "language": Preferences.getInstance().getValue("general/language"), "materials_profiles ": {} @@ -127,4 +128,4 @@ class SliceInfo(Extension): except: # We really can't afford to have a mistake here, as this would break the sending of g-code to a device # (Either saving or directly to a printer). The functionality of the slice data is not *that* important. - pass \ No newline at end of file + pass From f51cffdf2e6e57fbd223ed869fb7ec4ad073b4dc Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 25 Jul 2016 13:50:47 +0200 Subject: [PATCH 64/64] We now ask the stack for the position (instead of definition) --- cura/Settings/ExtrudersModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index 15e80d3f6b..cbe127d511 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -120,7 +120,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): material = extruder.findContainer({ "type": "material" }) if material: extruder_name = "%s (%s)" % (material.getName(), extruder_name) - position = extruder.getBottom().getMetaDataEntry("position", default = "0") #Position in the definition. + position = extruder.getMetaDataEntry("position", default = "0") # Get the position try: position = int(position) except ValueError: #Not a proper int.