From 8ae49c317cbd317cf96a0f90c7a7f37e23a4904d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 29 Jun 2017 15:03:49 +0200 Subject: [PATCH 01/10] Emit metaDataChanged when changing properties Properties is a dictionary inside the metadata dictionary. If you change one of the properties, it'll check afterwards if the dictionary is different from what it was before, but since the dictionary is passed by reference all the time, it'll think that the dictionary didn't change: The reference is still the same, so the thing it checks against is updated along. This solution is a bit ugly but it does notice when the metadata changed inside the properties and then emits a change signal. Contributes to issue CURA-2822. --- cura/Settings/ContainerManager.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 9a2282c8c0..aee9eccdd7 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -218,6 +218,7 @@ class ContainerManager(QObject): entries = entry_name.split("/") entry_name = entries.pop() + sub_item_changed = False if entries: root_name = entries.pop(0) root = container.getMetaDataEntry(root_name) @@ -226,12 +227,16 @@ class ContainerManager(QObject): for entry in entries: item = item.get(entries.pop(0), { }) + if item[entry_name] != entry_value: + sub_item_changed = True item[entry_name] = entry_value entry_name = root_name entry_value = root container.setMetaDataEntry(entry_name, entry_value) + if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed. + container.metaDataChanged.emit(container) return True From 034686e9facc7fb64fff45657ea50028e6b709d8 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 29 Jun 2017 15:09:50 +0200 Subject: [PATCH 02/10] Don't modify list you're iterating over It doesn't give a problem right now since we're only iterating over lists of length 1 here, but in the future this could cause weird bugs. Contributes to issue CURA-2822. --- cura/Settings/ContainerManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index aee9eccdd7..0d776aec20 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -224,7 +224,7 @@ class ContainerManager(QObject): root = container.getMetaDataEntry(root_name) item = root - for entry in entries: + for _ in range(len(entries)): item = item.get(entries.pop(0), { }) if item[entry_name] != entry_value: From b3e49f0c12f5c0153acfecb0224705f3fa611efe Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 29 Jun 2017 16:28:01 +0200 Subject: [PATCH 03/10] Fix getting the old approximate diameter The properties.approximate_diameter gets updated later via signals, so at this point it's not correct yet. Contributes to issue CURA-2822. --- resources/qml/Preferences/MaterialView.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 39f2db0695..23e81067ed 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -169,7 +169,7 @@ TabView // This does not use a SettingPropertyProvider, because we need to make the change to all containers // which derive from the same base_file var old_diameter = Cura.ContainerManager.getContainerProperty(base.containerId, "material_diameter", "value").toString(); - base.setMetaDataEntry("approximate_diameter", properties.approximate_diameter, Math.round(value).toString()); + base.setMetaDataEntry("approximate_diameter", Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"), Math.round(value).toString()); base.setMetaDataEntry("properties/diameter", properties.diameter, value); if (Cura.MachineManager.filterMaterialsByMachine && properties.approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) { From 27bcb11dc92a4d4a7ffb55c8ac6261769604e573 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 29 Jun 2017 16:41:24 +0200 Subject: [PATCH 04/10] Store old approximate diameter in variable Shorter line, easier to read. Contributes to issue CURA-2822. --- resources/qml/Preferences/MaterialView.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 23e81067ed..7183a3d926 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -169,7 +169,8 @@ TabView // This does not use a SettingPropertyProvider, because we need to make the change to all containers // which derive from the same base_file var old_diameter = Cura.ContainerManager.getContainerProperty(base.containerId, "material_diameter", "value").toString(); - base.setMetaDataEntry("approximate_diameter", Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"), Math.round(value).toString()); + var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); + base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, Math.round(value).toString()); base.setMetaDataEntry("properties/diameter", properties.diameter, value); if (Cura.MachineManager.filterMaterialsByMachine && properties.approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) { From b8b23055ba60211f5890c955b3b4490a1319aa17 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 29 Jun 2017 16:50:15 +0200 Subject: [PATCH 05/10] Fix getting new material diameter Same problem, it's not been updated yet at this point. Contributes to issue CURA-2822. --- resources/qml/Preferences/MaterialView.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 7183a3d926..39692a9f84 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -172,7 +172,8 @@ TabView var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, Math.round(value).toString()); base.setMetaDataEntry("properties/diameter", properties.diameter, value); - if (Cura.MachineManager.filterMaterialsByMachine && properties.approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) + var new_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); + if (Cura.MachineManager.filterMaterialsByMachine && new_approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) { Cura.MaterialManager.showMaterialWarningMessage(base.containerId, old_diameter); } From bb79e33ad55a4736f193ba8baf2d142c9f136720 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 29 Jun 2017 16:55:47 +0200 Subject: [PATCH 06/10] Don't forget to update approximate diameter after resetting actual diameter The approximate diameter needs to be in a static field because the list model filters on that field. The filter function is not clever enough to be able to filter on values being in some kind of range or rounded, so instead the decision was made that the rounded value needs to be set in a separate field so that the static filter can filter on it. Contributes to issue CURA-2822. --- cura/Settings/MaterialManager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/Settings/MaterialManager.py b/cura/Settings/MaterialManager.py index abfafc5f9f..8bb7b525f8 100644 --- a/cura/Settings/MaterialManager.py +++ b/cura/Settings/MaterialManager.py @@ -49,6 +49,8 @@ class MaterialManager(QObject): if button == "Undo": container_manager = ContainerManager.getInstance() container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "properties/diameter", self._material_diameter_warning_message.previous_diameter) + approximate_previous_diameter = str(round(float(self._material_diameter_warning_message.previous_diameter))) + container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "approximate_diameter", approximate_previous_diameter) message.hide() else: Logger.log("w", "Unknown button action for material diameter warning message: {action}".format(action = button)) \ No newline at end of file From f8b99b2bff3298e58eec5a5a6a9fb6c71dd39d9d Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 29 Jun 2017 18:02:07 +0200 Subject: [PATCH 07/10] Update README.md Removed old plugin (it's no longer needed, cura can do it on it's own) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index a3e7f9c0d5..c1ebb0993b 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,6 @@ Please checkout [cura-build](https://github.com/Ultimaker/cura-build) Third party plugins ------------- -* [Print Cost Calculator](https://github.com/nallath/PrintCostCalculator): Calculates weight and monetary cost of your print. * [Post Processing Plugin](https://github.com/nallath/PostProcessingPlugin): Allows for post-processing scripts to run on g-code. * [Barbarian Plugin](https://github.com/nallath/BarbarianPlugin): Simple scale tool for imperial to metric. * [X3G Writer](https://github.com/Ghostkeeper/X3GWriter): Adds support for exporting X3G files. From adb93507c81ab55eca102a8dc6bce11dd2ddd5f3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 30 Jun 2017 08:42:39 +0200 Subject: [PATCH 08/10] Set material_diameter setting in approximate material diameter test Instead of the metadata entry, which was a previous implementation of the function. This is essentially just an update of the test. Contributes to issue CURA-2822. --- tests/Settings/TestGlobalStack.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index 3cac17fa3a..df9f31dc64 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -12,6 +12,7 @@ from UM.Settings.InstanceContainer import InstanceContainer #To test against the from UM.Settings.SettingInstance import InstanceState import UM.Settings.ContainerRegistry import UM.Settings.ContainerStack +import UM.Settings.SettingDefinition #To add settings to the definition. ## Fake container registry that always provides all containers you ask of. @pytest.yield_fixture() @@ -100,7 +101,9 @@ def test_addExtruder(global_stack): ]) def test_approximateMaterialDiameter(diameter, approximate_diameter, global_stack): global_stack.definition = DefinitionContainer(container_id = "TestDefinition") - global_stack.definition._metadata["material_diameter"] = str(diameter) + material_diameter = UM.Settings.SettingDefinition.SettingDefinition(key = "material_diameter", container = global_stack.definition) + material_diameter.addSupportedProperty("value", UM.Settings.SettingDefinition.DefinitionPropertyType.Any, default = diameter) + global_stack.definition.definitions.append(material_diameter) assert float(global_stack.approximateMaterialDiameter) == approximate_diameter ## Tests getting the material diameter when there is no material diameter. From 3e278cbd0a7a62898f339396490c4e67e7549126 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 30 Jun 2017 08:47:49 +0200 Subject: [PATCH 09/10] Add test for very large material diameters Shouldn't matter with Python, but you never know. Contributes to issue CURA-2822. --- tests/Settings/TestGlobalStack.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index df9f31dc64..c6491d574c 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -97,7 +97,8 @@ def test_addExtruder(global_stack): #Exceptional cases. (0, 0), (-10.1, -10), - (-1, -1) + (-1, -1), + (9000.1, 9000) ]) def test_approximateMaterialDiameter(diameter, approximate_diameter, global_stack): global_stack.definition = DefinitionContainer(container_id = "TestDefinition") From 71c146f4379c24af2e05ffadd690c3b24e5ed4eb Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 30 Jun 2017 13:04:09 +0200 Subject: [PATCH 10/10] Always send not-printed objects to slicer regardless of build volume Objects that aren't printed, such as infill meshes, can simply be sent to the slicer regardless of whether they are inside or outside the build volume, because they don't generate g-code in their own volume. This way you can have a model that is partially outside the build volume that still does its anti-overhang task or whatever. Contributes to issue CURA-3951. --- plugins/CuraEngineBackend/StartSliceJob.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index c83ffb655d..f2e9cb7db2 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -44,6 +44,14 @@ class GcodeStartEndFormatter(Formatter): ## Job class that builds up the message of scene data to send to CuraEngine. class StartSliceJob(Job): + ## Meshes that are sent to the engine regardless of being outside of the + # build volume. + # + # If these settings are True for any mesh, the build volume is ignored. + # Note that Support Mesh is not in here because it actually generates + # g-code in the volume of the mesh. + _not_printed_mesh_settings = {"anti_overhang_mesh", "infill_mesh", "cutting_mesh"} + def __init__(self, slice_message): super().__init__() @@ -132,7 +140,8 @@ class StartSliceJob(Job): temp_list = [] for node in DepthFirstIterator(self._scene.getRoot()): if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None: - if not getattr(node, "_outside_buildarea", False): + if not getattr(node, "_outside_buildarea", False)\ + or (node.callDecoration("getStack") and any(node.callDecoration("getStack").getProperty(setting, "value") for setting in self._not_printed_mesh_settings)): temp_list.append(node) Job.yieldThread()