From a998d596936e1d0a38c360729ae6a913d7faee6b Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 7 Sep 2016 15:38:27 +0200 Subject: [PATCH 1/8] Fix setting heated bed upgrade option A new variant was created, but the property was set on the old variant. CURA-2253 --- plugins/UltimakerMachineActions/UMOUpgradeSelection.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/UltimakerMachineActions/UMOUpgradeSelection.py b/plugins/UltimakerMachineActions/UMOUpgradeSelection.py index 64c9ae1180..b92dc30c68 100644 --- a/plugins/UltimakerMachineActions/UMOUpgradeSelection.py +++ b/plugins/UltimakerMachineActions/UMOUpgradeSelection.py @@ -31,7 +31,7 @@ class UMOUpgradeSelection(MachineAction): if variant: if variant.getId() == "empty_variant": variant_index = global_container_stack.getContainerIndex(variant) - self._createVariant(global_container_stack, variant_index) + variant = self._createVariant(global_container_stack, variant_index) variant.setProperty("machine_heated_bed", "value", heated_bed) self.heatedBedChanged.emit() @@ -41,4 +41,5 @@ class UMOUpgradeSelection(MachineAction): new_variant.addMetaDataEntry("type", "variant") new_variant.setDefinition(global_container_stack.getBottom()) UM.Settings.ContainerRegistry.getInstance().addContainer(new_variant) - global_container_stack.replaceContainer(variant_index, new_variant) \ No newline at end of file + global_container_stack.replaceContainer(variant_index, new_variant) + return new_variant \ No newline at end of file From ee55e03911e1ef765b565317f5bfe964b5e7c90e Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 7 Sep 2016 15:46:12 +0200 Subject: [PATCH 2/8] Added max size to prime tower CURA-2234 --- resources/definitions/fdmprinter.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index e76d277b0c..bbf4df56d8 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3297,6 +3297,7 @@ "default_value": 15, "value": "15 if prime_tower_enable else 0", "minimum_value": "0", + "maximum_value": "min(0.5 * machine_width, 0.5 * machine_depth)", "maximum_value_warning": "20", "settable_per_mesh": false, "settable_per_extruder": false From 15101ec53dc285e4a02f59fc96c05cff94cc49a6 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 7 Sep 2016 15:51:08 +0200 Subject: [PATCH 3/8] Fix showing material options for 3rd party printers CURA-2287 --- resources/definitions/fdmprinter.def.json | 1 + resources/definitions/ultimaker2.def.json | 1 + 2 files changed, 2 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index bbf4df56d8..1116506886 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -10,6 +10,7 @@ "manufacturer": "Ultimaker", "file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj;application/x3g", "visible": false, + "has_materials": true, "preferred_material": "*generic_pla*", "preferred_quality": "*normal*", "machine_extruder_trains": diff --git a/resources/definitions/ultimaker2.def.json b/resources/definitions/ultimaker2.def.json index 81723ae10d..a0ead36bff 100644 --- a/resources/definitions/ultimaker2.def.json +++ b/resources/definitions/ultimaker2.def.json @@ -14,6 +14,7 @@ "platform": "ultimaker2_platform.obj", "platform_texture": "Ultimaker2backplate.png", "platform_offset": [9, 0, 0], + "has_materials": false, "supported_actions":["UpgradeFirmware"] }, "overrides": { From b7c2a77277bba3f9b3c88461445cea7f074bd878 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 7 Sep 2016 15:58:01 +0200 Subject: [PATCH 4/8] Code style: Use double quotes for strings Contributes to issue CURA-2252. --- plugins/CuraProfileReader/CuraProfileReader.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/CuraProfileReader/CuraProfileReader.py b/plugins/CuraProfileReader/CuraProfileReader.py index 4f5bb324c0..c8d39b7a78 100644 --- a/plugins/CuraProfileReader/CuraProfileReader.py +++ b/plugins/CuraProfileReader/CuraProfileReader.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. import configparser @@ -53,10 +53,10 @@ class CuraProfileReader(ProfileReader): parser.read_string(serialized) if not "general" in parser: - Logger.log('w', "Missing required section 'general'.") + Logger.log("w", "Missing required section 'general'.") return None if not "version" in parser["general"]: - Logger.log('w', "Missing required 'version' property") + Logger.log("w", "Missing required 'version' property") return None version = int(parser["general"]["version"]) From cab5f4d823c8094274207e98aa3507177b2d629d Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 7 Sep 2016 16:06:42 +0200 Subject: [PATCH 5/8] Fix "Reset all model transformations" for groups CURA-2291 --- cura/CuraApplication.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 892440cba0..32c5191c7c 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -693,17 +693,17 @@ class CuraApplication(QtApplication): continue # Node that doesnt have a mesh and is not a group. if node.getParent() and node.getParent().callDecoration("isGroup"): continue # Grouped nodes don't need resetting as their parent (the group) is resetted) - nodes.append(node) if nodes: op = GroupedOperation() for node in nodes: + # Ensure that the object is above the build platform node.removeDecorator(ZOffsetDecorator.ZOffsetDecorator) op.addOperation(SetTransformOperation(node, Vector(0, node.getWorldPosition().y - node.getBoundingBox().bottom, 0))) op.push() - - ## Reset all transformations on nodes with mesh data. + + ## Reset all transformations on nodes with mesh data. @pyqtSlot() def resetAll(self): Logger.log("i", "Resetting all scene transformations") @@ -719,15 +719,17 @@ class CuraApplication(QtApplication): if nodes: op = GroupedOperation() - for node in nodes: # Ensure that the object is above the build platform node.removeDecorator(ZOffsetDecorator.ZOffsetDecorator) - - op.addOperation(SetTransformOperation(node, Vector(0, node.getMeshData().getCenterPosition().y, 0), Quaternion(), Vector(1, 1, 1))) - + center_y = 0 + if node.callDecoration("isGroup"): + center_y = node.getWorldPosition().y - node.getBoundingBox().bottom + else: + center_y = node.getMeshData().getCenterPosition().y + op.addOperation(SetTransformOperation(node, Vector(0, center_y, 0), Quaternion(), Vector(1, 1, 1))) op.push() - + ## Reload all mesh data on the screen from file. @pyqtSlot() def reloadAll(self): From dc282dc2634171cab1eb4ec1641c25d4e8f4fcfc Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 7 Sep 2016 16:51:03 +0200 Subject: [PATCH 6/8] Fix Per Model Settings crash when switching to multiextrusion printer CURA-2228 --- .../PerObjectSettingsTool.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py index b5c4c0f22c..5c52c89416 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py @@ -7,6 +7,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Application import Application from UM.Preferences import Preferences from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator +from cura.Settings.ExtruderManager import ExtruderManager ## This tool allows the user to add & change settings per node in the scene. @@ -71,11 +72,17 @@ class PerObjectSettingsTool(Tool): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: self._multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 + + # Ensure that all extruder data is reset if not self._multi_extrusion: - # Ensure that all extruder data is reset - root_node = Application.getInstance().getController().getScene().getRoot() - for node in DepthFirstIterator(root_node): - node.callDecoration("setActiveExtruder", global_container_stack.getId()) + default_stack_id = global_container_stack.getId() + else: + default_stack_id = ExtruderManager.getInstance().getExtruderStack(0).getId() + + root_node = Application.getInstance().getController().getScene().getRoot() + for node in DepthFirstIterator(root_node): + node.callDecoration("setActiveExtruder", default_stack_id) + self._updateEnabled() def _updateEnabled(self): From 35168ddd5a7ce0cf2b974d3f377c58fac876a8bd Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 7 Sep 2016 16:54:52 +0200 Subject: [PATCH 7/8] Prime tower disallowed area is now drawn seperate from others if it colissions with others CURA-2234 --- cura/BuildVolume.py | 52 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index ca4c8e7b34..6ecb33fc78 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -67,6 +67,9 @@ class BuildVolume(SceneNode): self._disallowed_areas = [] self._disallowed_area_mesh = None + self._prime_tower_area = None + self._prime_tower_area_mesh = None + self.setCalculateBoundingBox(False) self._volume_aabb = None @@ -110,6 +113,10 @@ class BuildVolume(SceneNode): if self._disallowed_area_mesh: renderer.queueNode(self, mesh = self._disallowed_area_mesh, shader = self._shader, transparent = True, backface_cull = True, sort = -9) + if self._prime_tower_area_mesh: + renderer.queueNode(self, mesh = self._prime_tower_area_mesh, shader = self._shader, transparent=True, + backface_cull=True, sort=-8) + return True ## Recalculates the build volume & disallowed areas. @@ -184,6 +191,24 @@ class BuildVolume(SceneNode): else: self._disallowed_area_mesh = None + if self._prime_tower_area: + mb = MeshBuilder() + color = Color(1.0, 0.0, 0.0, 0.5) + points = self._prime_tower_area.getPoints() + first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, + self._clamp(points[0][1], min_d, max_d)) + previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, + self._clamp(points[0][1], min_d, max_d)) + for point in points: + new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, + self._clamp(point[1], min_d, max_d)) + mb.addFace(first, previous_point, new_point, color=color) + previous_point = new_point + + self._prime_tower_area_mesh = mb.build() + else: + self._prime_tower_area_mesh = None + 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)) @@ -301,14 +326,21 @@ class BuildVolume(SceneNode): machine_width = self._global_container_stack.getProperty("machine_width", "value") machine_depth = self._global_container_stack.getProperty("machine_depth", "value") - + self._prime_tower_area = None # Add prime tower location as disallowed area. if self._global_container_stack.getProperty("prime_tower_enable", "value") == True: prime_tower_size = self._global_container_stack.getProperty("prime_tower_size", "value") prime_tower_x = self._global_container_stack.getProperty("prime_tower_position_x", "value") - machine_width / 2 prime_tower_y = - self._global_container_stack.getProperty("prime_tower_position_y", "value") + machine_depth / 2 - disallowed_areas.append([ + '''disallowed_areas.append([ + [prime_tower_x - prime_tower_size, prime_tower_y - prime_tower_size], + [prime_tower_x, prime_tower_y - prime_tower_size], + [prime_tower_x, prime_tower_y], + [prime_tower_x - prime_tower_size, prime_tower_y], + ])''' + + self._prime_tower_area = Polygon([ [prime_tower_x - prime_tower_size, prime_tower_y - prime_tower_size], [prime_tower_x, prime_tower_y - prime_tower_size], [prime_tower_x, prime_tower_y], @@ -344,6 +376,9 @@ class BuildVolume(SceneNode): areas.append(poly) + if self._prime_tower_area: + self._prime_tower_area = self._prime_tower_area.getMinkowskiHull(Polygon(approximatedCircleVertices(bed_adhesion_size))) + # Add the skirt areas around the borders of the build plate. if bed_adhesion_size > 0: half_machine_width = self._global_container_stack.getProperty("machine_width", "value") / 2 @@ -377,6 +412,19 @@ class BuildVolume(SceneNode): [half_machine_width - bed_adhesion_size, -half_machine_depth + bed_adhesion_size] ], numpy.float32))) + # Check if the prime tower area intersects with any of the other areas. + # If this is the case, keep the polygon seperate, so it can be drawn in red. + # If not, add it back to disallowed area's, so it's rendered as normal. + collision = False + if self._prime_tower_area: + for area in areas: + if self._prime_tower_area.intersectsPolygon(area) is not None: + collision = True + break + if not collision: + areas.append(self._prime_tower_area) + self._prime_tower_area = None + self._disallowed_areas = areas ## Convenience function to calculate the size of the bed adhesion in directions x, y. From 9a84deb14ece77de330ddd7dfac39ab22cf63015 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 7 Sep 2016 17:19:20 +0200 Subject: [PATCH 8/8] If buildplate has errors, slicing is not possible CURA-2234 --- cura/BuildVolume.py | 9 +++++++-- plugins/CuraEngineBackend/StartSliceJob.py | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 6ecb33fc78..a25604d165 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -85,6 +85,8 @@ class BuildVolume(SceneNode): ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged) self._onActiveExtruderStackChanged() + self._has_errors = False + def setWidth(self, width): if width: self._width = width @@ -316,10 +318,13 @@ class BuildVolume(SceneNode): if rebuild_me: self.rebuild() + def hasErrors(self): + return self._has_errors + def _updateDisallowedAreas(self): if not self._global_container_stack: return - + self._has_errors = False # Reset. disallowed_areas = copy.deepcopy( self._global_container_stack.getProperty("machine_disallowed_areas", "value")) areas = [] @@ -424,7 +429,7 @@ class BuildVolume(SceneNode): if not collision: areas.append(self._prime_tower_area) self._prime_tower_area = None - + self._has_errors = collision self._disallowed_areas = areas ## Convenience function to calculate the size of the bed adhesion in directions x, y. diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 4d40da899d..fc26bd086b 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -78,6 +78,10 @@ class StartSliceJob(Job): self.setResult(StartJobResult.SettingError) return + if Application.getInstance().getBuildVolume().hasErrors(): + self.setResult(StartJobResult.SettingError) + return + # Don't slice if there is a per object setting with an error value. for node in DepthFirstIterator(self._scene.getRoot()): if type(node) is not SceneNode or not node.isSelectable():